logo
springboot-requestbody-dto-mapping.png

2023년 07월 05일

[SpringBoot] Request Body와 DTO의 맵핑 원리

Backend
SpringBoot
Java
Programing

Spring Boot를 사용하여 REST API를 개발할 때, Body의 값을 가져올 때마다 한번씩 값이 null로 나온 경험은 누구나 한번씩은 있을 것이다.

그렇기 때문에 Spring Boot에서 Request Body를 맵핑할 때, 어떤 방식으로 DTO에 맵핑이 되는지에 대해 정리하여 기억하기 위해 정리한 포스팅이다.

@RequestBody는 Setter를 사용하지 않는다


실제로 그런가?

간단하게 Post Controller를 만들어서 확인해 보자.

코드 작성

Dto 생성

@Getter
@ToString
@NoArgsConstructor
public class RequestDto { 
	private String name; 
	private int age;
}

Controller 생성

@RestController
public class DtoTestController {
	@PostMapping("/dto-test")
	public Object requestPost(@RequestBody RequestDto request) {
		System.out.println(request);
		return request;
	}
}

실행 결과

위와 같이 코드를 작성한 후 실행해 보면 예상과는 다르게 값이 들어가서 출력이 되는 것을 볼 수 있다.

왜 작동이 될까?

Spring 에서 Json 데이터의 형변환을 시켜주는 것은 Jackson2HttpMessageConverter를 사용한다.

때문에 실제로 변환을 진행하는 것은 ObjectMapper class의 함수인 readValue를 사용하기 때문에 Setter가 없더라도 정상적으로 값을 가져와서 반환하는 것이다.

@RequestBody 없이 Body를 가져온다면?


확인해보자

이번에는 @RequestBody를 사용하지 않고 코드를 작성해보자.

코드 작성

Dto 생성

@Getter
@ToString
@NoArgsConstructor
public class RequestDto {
	private String name;
	private int age;
}

Controller 생성

@RestController
public class DtoTestController {
	@PostMapping("/dto-test")
	public Object requestPost(RequestDto request) {
		System.out.println(request);
		return request;
	}
}

실행 결과

위와 같은 방식으로 코드를 작성하게 된다면 application/json 타입이 아닌 application/x-www-form-data 형태로 요청이 들어오게 된다.

타입을 고려하지 않고 우선 호출 결과를 보게 된다면 Body의 값은 null이 들어가 있다.

왜 그럴까?

기본적으로 @PostMapping과 같은 어노테이션이 붙은 함수의 파라미터는 @RequestParam이 붙어 있다고 보면 되는데, 이 @RequestParam이 붙은 인자의 타입이 String이 아닐 경우 Type Conversion이 자동으로 적용된다.

그런데 이 Type Conversion이 타입을 변환하는 방법이 DataBinder이다.

DataBinderJava Bean Spec을 따르기 때문에 Setter가 필요한 것이다.

Java Bean Spec

  1. 기본 생성자를 가지고 있어야 한다.
  2. 인스턴스 변수는 private 접근 지정자여야 한다.
  3. public의 gettersetter를 가지고 있어야 한다.

생성자를 통해 새로운 instance를 만들고, Setter를 통해 값을 넣어주기 때문에 @RequestParam에서는 기본 생성자와 Setter가 필요한 것이다.

잘못된 정보의 비판은 언제든 환영입니다.

댓글