카테고리 없음

[Spring Boot] DTO 역직렬화 오류와 해결법 – @JsonCreator vs @NoArgsConstructor

책다니엘 2025. 5. 8. 13:52

서론: 단위 테스트 중 발생한 500 에러의 정체

백엔드 프로젝트의 단위 테스트를 작성하던 중, 예상치 못한 500 Internal Server Error가 발생했다. 컨트롤러에서 204 No Content 응답을 기대했지만, 실제 테스트 결과는 아래와 같았다.

java.lang.AssertionError: Status expected:<204> but was:<500>

 

콘솔 로그를 확인해보니, 문제는 DTO 역직렬화에서 발생하고 있었다.

Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: 
Cannot construct instance of `ProductStatusUpdateRequestDto` 
(no Creators, like default constructor, exist): 
cannot deserialize from Object value (no delegate- or property-based Creator)

즉, Jackson이 JSON을 자바 객체로 변환하는 과정에서 생성자를 찾지 못해 실패했던 것이다.


문제 코드

@Getter
@AllArgsConstructor
public class ProductStatusUpdateRequestDto {
    
    @NotNull(message = "상품 상태를 입력해주세요.")
    private ProductStatus status;
}

이 DTO에는 @AllArgsConstructor만 존재했고, 기본 생성자 없이 Jackson이 역직렬화를 시도하면서 오류가 발생했다.


본론: DTO 역직렬화 문제 해결 방법 2가지

✅ 방법 1: @JsonCreator + 명시적 생성자 선언

@Getter
public class ProductStatusUpdateRequestDto {

    @NotNull
    private final ProductStatus status;

    @JsonCreator
    public ProductStatusUpdateRequestDto(@JsonProperty("status") ProductStatus status) {
        this.status = status;
    }
}
  • 장점: 불변 객체 유지 가능 (final 필드 사용)
  • 단점: 생성자가 많아지면 코드가 길어짐, 테스트에서 객체 생성 불편

✅ 방법 2: @NoArgsConstructor + @AllArgsConstructor

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class ProductStatusUpdateRequestDto {

    @NotNull
    private ProductStatus status;
}
  • 장점: Jackson 역직렬화에 적합하고 테스트에서도 편리하게 사용 가능
  • 단점: final 필드 불가 → 객체 불변성 보장 어려움, 상태 일관성 주의 필요

🧩 두 방법 비교 요약

 

항목 @JsonCreator 방식 @NoArgsConstructor 방식
Jackson 역직렬화 지원 ✅ (직접 제어) ✅ (기본 생성자 활용)
테스트 코드 활용 ❌ (생성자 호출 불편) ✅ (유연하게 객체 생성 가능)
불변 객체 생성 ✅ (final 사용 가능) ❌ (final 불가)
실수 방지 ✅ (강제 초기화) ❌ (null 객체 생성 가능)
유지보수 용이성 높음 (직관적)
 

결론: 이번 경우엔 실용성과 유연성을 선택했다

이번 상품 상태 변경 요청 DTO는 단순히 상태 값을 받아 컨트롤러에 전달하는 역할만 수행한다.
불변성이 중요한 객체도 아니고, 테스트에서 직접 값을 세팅하는 경우도 자주 발생한다.

따라서 복잡한 생성자 제어 없이 @NoArgsConstructor + @AllArgsConstructor 조합으로 구현하는 것이 가장 실용적이라고 판단했다.


💬 마무리

이런 역직렬화 오류는 테스트에서 예외 메시지를 확인하지 않으면 지나치기 쉽다.
하지만 원리를 이해하고 Jackson의 객체 생성 방식을 알게 되면, 문제 해결뿐 아니라 더 깔끔한 DTO 설계도 가능해진다.

DTO의 목적과 사용 맥락에 따라 가장 적합한 생성자 구조를 선택하자!