[Spring Boot] @RequestParam 과 @RequestBody 는 무슨 차이일까?

치현·2024년 5월 13일
0

Spring Boot

목록 보기
1/4

@RequestParam

공식문서에 따르면 Query Parameters, Form Data의 정보를 변수에 바인딩할 때 사용한다. 즉, URL과 Body에 전달되는 값을 읽어 적절한 변수에 바인딩한다는 것을 알 수 있다.

사용법

의도한 변수로 값이 바인딩되기 위해서는 규칙이 필요하다. 다음은 그 규칙을 위한 옵션이다.

[name 옵션]

@RequestParam(name="target") String t

파라미터 이름이 "target"인 값을 t에 바인딩한다.

@RequestParam(name="target") String target
@RequestParam String target

변수 이름과 파라미터 이름이 같다면, 이름을 생략해도 된다.

String target

String, int, Integer 등의 단순 타입이면 @RequestParam을 생략 가능하다.

[required 옵션]

@RequestParam(required=false) String target

required 옵션으로 값의 필수 여부를 결정할 수 있다. 기본 값은 True이다.
false일 경우 값이 Null로 채워진다.

[defaultValue 옵션]

@RequestParam(required = true, defaultValue = "EMPTY") String target

요청 파라미터 값이 없을 경우 "EMPTY" 문자열로 대체한다.

@RequestParam Map<string, Object> paramMap
...
paramMap.get("target");

Map을 이용해 Key, Value 형태로 값이 저장된다. 동일한 이름이 있을 경우, MultiValueMap을 사용하면 된다.

@PostMapping("/example")
public void example(@RequestParam(name="example", required=true, defaultValue="EMPTY") String example)
...

하지만, 프로그램을 개발하는 입장에서 코드가 일회성이 아닌 이상 누가 보더라도 명확한 의미를 나타내는 것이 중요하지 않을까? 그래서 최대한 어떤 의미를 담고 있는지 표현하는 것이 좋다고 생각한다.

@RequestBody

공식문서에 따르면 HttpMessageConverter를 통해 Request Body를 읽어 Object로 역직렬화 한다. 즉, Body로 전송된 JSON 형태의 데이터를 String에 JSON 형태로 받거나 정의한 클래스에 매핑할 수 있다.


@RequestBody는 @Valid, @Validated와 결합할 수 있고 값에 대한 기본적인 유효성 검사에 의해 MethodArgumentNotValidException이 400(BAD_REQUEST) 응답으로 전환된다.


다음 예제와 같이 직접 위의 에러를 핸들링 할 수도 있다. 이때, Errors 또는 BindingResult 클래스를 사용한다.

@PostMapping("/example")
public void handle(@Valid @RequestBody Example example, Errors errors or BindingResult bindingResult)

@RequestParam과 @RequestBody의 차이

분명한 차이가 있는 것 같지만, 잘 와닿지 않을 수 있을 것 같다.
직접 눈으로 보면서 이해하면 더 효율적이기 때문에 몇 가지 실험을 진행해보자.

  1. GET 방식으로 데이터를 전송했을 때 @RequestBody로 값을 받을 수 있을까?
  2. POST 방식으로 데이터를 전송했을 때 @RequestBody로 값을 받을 수 있을까?
  3. GET 방식으로 데이터를 전송했을 때 @RequestParam은 어떻게 매핑될까?
  4. POST 방식으로 데이터를 전송했을 때 @RequestParam은 어떻게 매핑될까?
  5. Query, Body에 모두 데이터가 들어있을 때 @RequestParam은 어떻게 매핑될까?

실험 환경은 다음과 같다.
Spring Boot 3.2.5
Java 17

데이터 전송에는 Post Man을 사용했다.

1. GET 방식으로 데이터를 전송했을 때 @RequestBody로 값을 받을 수 있을까?


위와 같이 구성되어있을 때 GET 방식으로 데이터를 전송해보자.

Body 데이터에 정보가 없어 변환된 400 에러를 응답하는 것을 볼 수 있다.
GET 방식으로는 값을 받을 수 없다.

2. POST 방식으로 데이터를 전송했을 때 @RequestBody로 값을 받을 수 있을까?


위와 같이 구성되어있을 때 POST 방식으로 데이터를 전송해보자.

데이터가 잘 전달되는 것을 볼 수 있다.

이번에는 직접 정의한 클래스에 매핑해보자.

String 타입의 name 변수만 필수로 받고 있는 Test 클래스이다.

위와 같이 구성된 상태에서 name 데이터를 전송했을 때 Test 객체가 잘 생성되는지 확인해보자.

잘 생성되어 값을 출력하는 것을 볼 수 있다.

3. GET 방식으로 데이터를 전송했을 때 @RequestParam은 어떻게 매핑될까?


위와 같이 구성되어있을 때 GET 방식으로 데이터를 전송해보자.

값을 잘 받은 것을 볼 수 있다.
Test 객체로 받을 수는 없을까?

위와 같이 구성하고 데이터를 보내보자.

신기하게도 객체가 생성된다. 하지만, 다음 실험의 결과를 보면 알 수 있듯이 하나의 맴버 변수 값을 가지고 있는 클래스만 객체가 생성된다.

하나의 데이터를 전송해서 두 개의 값을 가지는 객체를 생성하는 것은 불가능했다.
혹시나 해서 배열의 형태로 데이터를 전송해봤지만, 불가능 했다!

4. POST 방식으로 데이터를 전송했을 때 @RequestParam은 어떻게 매핑될까?

Query에 데이터에 정보가 없어 변환된 400 에러를 응답하는 것을 볼 수 있다.
POST 방식으로는 값을 받을 수 없다.

@RequestParam과 @RequestBody의 차이점 정리

  1. @RequestParam은 Query 데이터, @RequestBody는 Body 데이터를 바인딩한다.
  2. @RequestParam은 맴버 변수 하나를 필요로 하는 클래스에만 바인딩 될 수 있고, @RequestBody는 데이터와 클래스 사이의 매핑 정보가 일치하다면 어떠한 Object에도 바인딩 될 수 있다.
  3. @RequestParam은 전달되는 파라미터의 이름과 받고자하는 명시된 이름이 일치해야한다.
  4. @RequestBody는 String 타입으로 값을 받을 때 JSON 형태의 문자열을 받는다.

출처

https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller/ann-methods/requestparam.html
https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller/ann-methods/requestbody.html
https://dangdangee.tistory.com/entry/Spring-RequestParam-%EC%82%AC%EC%9A%A9%EB%B2%95
https://ittrue.tistory.com/243
https://ocblog.tistory.com/49
https://yuma1029.tistory.com/8

내용에 틀린 부분이 있다면, 언제든지 알려주세요!

profile
Backend Engineer

0개의 댓글