⚠️ 에러 사항
Contoller에서 @RequestBody
를 통해 DTO 클래스로 데이터를 받아와서 사용하는중 DTO클래스의 필드가 null으로 오류가 발생하는 상황
AuthContoller
@RestController
@RequiredArgsConstructor
@RequestMapping("api/v1/user/auth")
public class AuthController {
private final UserAuthService userAuthService;
┅
@PostMapping("/reissue")
public ResponseEntity<?> reissue(@RequestBody RefreshTokenDto refreshTokenDto) {
return ResponseEntity.status(HttpStatus.OK)
.body(new DefaultResponse<>(200, "reissue access token", userAuthService.reIssue(refreshTokenDto)));
}
}
RefreshTokenDto
@Builder
@Getter
public class RefreshTokenDto {
private String refreshToken;
}
오류가 발생한 코드는 위와 같다.
평소와 같이 DTO 클래스에는 @Builder
, @Getter
어노테이션만 작성하고 사용했는데 해당 컨트롤러로 요청을 했을때 refreshToken이 null이라는 오류가 발생해서 원하는 동작이 하지 않았다.
왜 다른 DTO 클래스들은 필드가 null이라는 오류가 발생하지 않는데 해당 DTO 클래스는 필드가 null이라는 오류가 발생할까?
@RequestBody
어노테이션이 JSON Request를 처리하는 방법을 알면 필드가 null인 이유에 대해서 알 수 있다.
@RequestBody
어노테이션이 JSON Request를 처리하는 방법
@RequestBody
어노테이션은 JSON -> Java 객체
로 바꾸어 객체의 형태로 사용할 수 있다.
JSON -> Java 객체
의 행위를 역직렬화(Deserializion) 라고 한다.
Spring Boot에서 직렬화, 역직렬화를 진행하는 방법
Spring은 Jackson 라이브러리 안에 있는 ObjectMapper를 사용하여 Java 객체 -> JSON
으로 직렬화 혹은 JSON -> Java 객체
로 역직렬화를 진행한다.
직렬화의 조건
직렬화화의 조건은 각 필드에 대한 Getter 메소드를 정의 하는것이다.
역직렬화의 조건
역직렬화를 하기 위한 조건은 기본생성자를 만들어 줘야한다. 그렇다면 이때까지 DTO를 만들어서 @RequestBody
를 사용했을때는 오류가 발생하지 않았을까?
필드가 두개 이상인 클래스에서는 jackson-module-parameter-names
모듈에서(Spring Boot 2.x 이후 버전에서는 자동으로 등록이 되어 있음)ParameterNamesModule
클래스가 JsonCreator
를 사용해 기본생성자가 없는 객체도 역직렬화가 가능하게 설정해준다.
필드가 하나인 경우에는 JsonCreator
의 Mode를 어떤 것을 설정하지 정하지 못해서 오류가 발생한다. (Delegating 생성자인지, Property-based creator인지 구분할 수 없다.)
✅ 해결
@Builder
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class RefreshTokenDto {
private String refreshToken;
}
DTO 클래스에 기본생성자를 만들어서 사용을 하면 @RequestBody
를 이용한 역직렬화를 성공적으로 진행을 한다.
Spring Boot를 사용하지 않았다면 필드가 두 개 이상인 클래스에서도 역직렬화 관련 문제가 발생했을 것이다. 반드시 역직렬화를 하기 위해서는 기본생성자를 만들어줘야 한다.
Reference
Spring에서의 직렬화
Spring은 ObjectMapper라는 클래스를 사용해 Json값을 Spring의 자바 객체로 변환한다. spring-boot-starter-web을 gradle에 의존성으로 추가하면 jackson이라는 라이브러리도 함께 가져오는데, jackson안에 ObjectMa
velog.io
https://dukcode.github.io/spring/spring-dto/#spring-boot-autoconfiguration
[개발고민] Spring DTO는 어떻게 작성하고 변환해야 할까?
💡 개발고민은 개발을 공부하며 했던 저의 생각들 입니다. 정답이 아니며 정답을 찾아가는 과정이라고 봐주시면 감사하겠습니다. Github Repository Spring DTO는 어떻게 작성하고 변환해야 할까?
dukcode.github.io