개발하는 두부

Spring @RequestParam vs. @RequestPart

by 뚜부니

API를 개발하다가 @RequestParam@RequestPart 차이가 갑자기 궁금하더라고요. 그래서 애노테이션 소스 코드를 열어봤는데 소스가 되게 비슷하더라고요..?! 🤔 이거 찾아봐야겠다 하는 생각이 들어서 찾아본 김에 정리해서 공유드려요 😊

 

1. 애노테이션 소스 코드 분석

먼저 애노테이션 소스 코드 분석을 해봤어요. 소스코드가 진짜 비슷하게 생겼거든요. 아마 이거 먼저 보시면 '엇..? 이게 뭐지?' 하는 생각이 드실 수도 있어요. 참고로, 공통 메타 애노테이션인 @Target, @Retention, @Documented 설명은 생략하고 소스만 분석했어요.

1.1. @RequestPart 소스 코드

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestPart {
    @AliasFor("name")
    String value() default "";

    @AliasFor("value")
    String name() default "";

    boolean required() default true;
}
  • value와 name
    • @AliasFor("name") 또는 @AliasFor("value") 라고 되어 있는 것은 서로 같은 속성을 가리킨다는 의미입니다.
    • 즉, value를 설정하면 내부적으로 name이 같은 값으로 설정되며, name을 설정하면 value가 동일하게 설정됩니다.
    • e.g.) @RequestPart("file")와 @RequestPart(name = "file")는 동일하게 동작합니다.
  • required
    • 기본 값은 true로, 해당 파라미터에 반드시 요청이 포함되어야 함을 뜻합니다.

1.2. @RequestParam 소스 코드

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
    @AliasFor("name")
    String value() default "";

    @AliasFor("value")
    String name() default "";

    boolean required() default true;

    String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";
}
  • value와 name, required는 @RequestPart와 동일합니다.
  • defaultValue
    • 파라미터가 없거나 빈 문자열로 넘어왔을 때 해당 값이 기본 값으로 설정됩니다.
    • 소스 코드에 보이는 "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n"는 특별한 문자열(센티넬 값)로, 사용자가 defaultValue를 지정하지 않았음을 구분하기 위한 내부 처리용입니다.
    • e.g. 
@GetMapping("/search")
public String search(
    @RequestParam(defaultValue = "Spring") String keyword
) {
    // keyword 파라미터가 없으면 "Spring"이 기본값으로 매핑
    return "결과";
}

 

 

내부 애노테이션만 보면 유사한데, 사용하는 목적이나 데이터 변환 방식에 차이가 있는 것 같더라고요. 어떤 특징을 가지는지 하나씩 좀 더 자세하게 살펴볼게요.

 

 

2. @RequestParam

@RequestParam은 별도 설정 없이 문자열, 숫자 등의 자동 변환이 이뤄지고, key-value 형식에 쉽게 매핑할 수 있어요.

@GetMapping("/search")
public String search(@RequestParam String keyword) {
    // ?keyword=Hello 와 같은 파라미터를 쉽게 매핑
    return "결과";
}

 

@RequestParam은 주로 다음과 같은 상황에 사용해요.

 

  • 쿼리 파라미터(Query Parameter): 예) ?keyword=Spring
  • Form Data: 전형적인 application/x-www-form-urlencoded 형식
  • 파일이 아닌 단순 텍스트 필드: multipart/form-data에서 파일을 제외한 다른 필드

 

 

3. @RequestPart

@RequestPart는 Multipart 형식에서 파일뿐만 아니라, JSON이나 일반 텍스트도 파트 단위로 분리해 매핑하며, 내부적으로 HttpMessageConverter를 통해 변환이 이뤄지므로, JSON DTO로 매핑하는 것도 가능해요.

@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public String upload(
    @RequestPart("file") MultipartFile file,
    @RequestPart("metadata") String metadata
) {
    // 파일 파트와 메타데이터(문자열 혹은 JSON)를 각각 별도의 파라미터로 매핑
    return "업로드 성공";
}

 

@RequestPart는 주로 multipart/form-data 형식에서 파일 업로드나 JSON/텍스트 등 복합 데이터를 "파트(part)" 단위로 받는 경우 사용해요.

 

 

4. @RequestParam vs. @RequestPart 차이점 정리

@RequestParam과 @RequestPart에 대한 차이점을 좀 더 눈에 잘 들어오게 표로 정리해 봤어요.

  @RequestParam @RequestPart
주 사용 목적 - Query Parameter
- Form Data (x-www-form-urlencoded)
- Multipart의 단순 텍스트 필드
- Multipart/Form-Data 내 파일 업로드
- Multipart/Form-Data 내 JSON, 텍스트 (파트 단위)
HTTP 요청 형식 - 일반 쿼리 스트링 파라미터 또는 폼 데이터 - multipart/form-data
데이터 변환 - 주로 단순 String, Number 변환
- 필요하면 Converter 이용 가능
- HttpMessageConverter를 통해 파일, JSON 등 복합 형식 처리 가능
주 사용 예시 - @RequestParam("keyword") String keyword - @RequestPart("file") MultipartFile file
- @RequestPart("jsonData") DTO dto

 

 

참고

 

블로그의 정보

개발하는 두부

뚜부니

활동하기