Spring Boot JSON 역직렬화Spring DTO 설계 방법Jackson 역직렬화 오류 해결Spring Boot DTO 불변 객체backend

Spring Boot DTO 설계 및 JSON 역직렬화 가이드

KUKJIN LEE
KUKJIN LEE
2025년 4월 1일
1871

Spring Boot에서는 클라이언트가 보내는 JSON 데이터를 Java 객체(DTO)로 자동 변환하여 처리합니다. 이 과정을 JSON 역직렬화(deserialization)라고 합니다. 기본적으로 Spring Boot는 Jackson 라이브러리를 사용하여 이 작업을 수행합니다.

 

문제 상황: 역직렬화 오류

Spring Boot 애플리케이션에서 JSON 데이터를 DTO로 변환할 때 다음과 같은 오류가 발생

Cannot construct instance of `com.example.dto.SignIn`: no default constructor found.

이 오류의 원인은 다음 두 가지입니다:

  • DTO 클래스에 기본 생성자가 없음

  • DTO 클래스의 필드가 final로 선언되어 Jackson이 기본 생성자를 생성하지 못함

 

역직렬화의 기본 작동 방식

Spring Boot는 요청된 JSON 데이터를 다음과 같은 과정으로 Java 객체로 변환

  1. JSON 데이터를 읽고 분석(parse)

  2. 분석한 데이터를 바탕으로 DTO 객체의 인스턴스를 생성

  3. 생성된 객체의 필드에 JSON 데이터 값을 매핑

이때, 객체 생성을 위해 기본 생성자(No-Args Constructor)를 사용합니다. 따라서 DTO 설계 시 주의

 

올바른 DTO 설계를 위한 가이드라인

방법 1: 기본적인 DTO 설계

가장 간단한 방법으로, DTO 클래스에 기본 생성자를 제공하고 final 필드를 사용하지 않는 방식

@Getter
@NoArgsConstructor // 기본 생성자 추가
@AllArgsConstructor
public class SignIn {
    private String userId;
    private String password;
    private String remember;
}

장점: 구현이 간단하고 명확합니다.
단점: 객체의 불변성을 보장하지 못합니다.

 

final 필드는 Java에서 초기화 이후 값을 변경할 수 없는 필드. 즉, 객체가 한번 생성되면 그 값이 고정되어 변경이 불가능한(불변, immutable) 상태

setter로 값을 바꿀 수 없다는 게 final 필드의 핵심

 

방법 2: 불변성 유지 및 역직렬화 지원 (@JsonCreator 사용)

DTO 객체의 불변성을 유지하면서 역직렬화를 지원하려면 Jackson의 @JsonCreator@JsonProperty를 명시적으로 사용

@Getter
public class SignIn {
    private final String userId;
    private final String password;
    private final String remember;

    @JsonCreator
    public SignIn(
        @JsonProperty("userId") String userId,
        @JsonProperty("password") String password,
        @JsonProperty("remember") String remember
    ) {
        this.userId = userId;
        this.password = password;
        this.remember = remember;
    }
}

장점: 객체 불변성을 유지할 수 있습니다.
단점: JSON 속성을 생성자 파라미터와 정확히 매칭시켜야 합니다.

 

Spring Boot에서 DTO 클래스를 설계할 때 JSON 역직렬화 요구 사항을 항상 고려해야 합니다. 다음의 핵심 원칙을 기억하세요:

  • DTO 클래스에는 기본 생성자를 제공하거나 명시적 생성자(@JsonCreator)를 사용합니다.

  • 불변성을 유지하려면 final 필드를 사용하되, 이 경우 반드시 @JsonCreator@JsonProperty를 명시합니다.

  • Lombok 사용 시 final 필드와 기본 생성자의 충돌을 주의합니다.

관련 글

[SQL 입문] 필요한 데이터만 콕 집어 가져올 수 있는 WHERE 절

사용자는 테이블에 있는 모든 데이터를 다 보고 싶어 하지는 않습니다. 오히려 특정 항목에 대한 데이터만 가져오고 싶을 때가 훨씬 많습니다. 예를 들어, 어떤 사용자의 이메일이나 ID는 알고 있는데, 그 사람이 언제 우리 앱에 가입했는지 확인하고 싶다고 가정해 봅시다...

2026년 1월 27일10

SQL에서 SELECT란 무엇인가?

데이터베이스를 거대한 서류 보관함이라고 생각하면 됩니다. 보관함 안에는 수많은 데이터가 차곡차곡 쌓입니다. SELECT는 이 보관함에서 "내가 원하는 정보를 찾아줘!"라고 요청하는 명령어입니다. 이 과정을 전문 용어로 '쿼리(Query)'라고 부릅니다. &nbs...

2026년 1월 26일10

[SQL 기초] "언제 하나씩 다 넣어?" 데이터 한 번에 넣기

개발을 하다 보면 데이터베이스(DB)에 샘플 데이터를 대량으로 넣어야 할 때가 있습니다. 메뉴 100개를 추가해야 하는데 INSERT 문을 100번 쓰고 있다면? 너무 비효율적이죠! 오늘은 SQL에서 여러 데이터를 한 번에 넣는 '다중 삽입(Multiple Inse...

2026년 1월 21일13

SQL 데이터 삽입하기

데이터가 없는 데이터베이스는 연료 없는 로켓과 같습니다. 이제 'Missions' 테이블에 새로운 행(row)을 추가하는 방법을 알아보겠습니다. "삽입(Inserting)"은 '데이터 추가'를 의미합니다. 기존 Missions 테이블 ...

2026년 1월 20일12