본문 바로가기

Spring Boot

[Spring Boot] Lombok과 직렬화/역직렬화

728x90

Lombok과 직렬화/역직렬화: 문제와 해결 방법

Lombok의 @Getter, @Setter, @AllArgsConstructor, @NoArgsConstructor는 코드 작성의 편리함을 제공합니다. 그러나 Java의 직렬화/역직렬화(Jackson, Gson, 기본 직렬화 등)와 함께 사용할 때 문제가 발생하기도 합니다. 이번 글에서는 이러한 문제를 다루고, 해결 방법과 설계 가이드를 제시합니다.

 

 

직렬화와 역직렬화란?

1. 직렬화(Serialization)

  • 정의: 객체를 바이트 스트림으로 변환하여 파일 저장, 네트워크 전송 등에 사용할 수 있도록 만드는 과정입니다.
  • 사용 사례:
    • 객체 데이터를 파일에 저장할 때.
    • HTTP API 응답으로 JSON 형식의 데이터를 반환할 때.

2. 역직렬화(Deserialization)

  • 정의: JSON, XML, 바이트 스트림 등을 객체로 복원하는 과정입니다.
  • 사용 사례:
    • 외부 시스템으로부터 받은 데이터를 객체로 변환할 때.
    • HTTP 요청에서 JSON 데이터를 Java 객체로 매핑할 때.

 

Lombok과 직렬화/역직렬화의 문제점과 해결 방법

1. 기본 생성자 누락 문제

  • 문제 상황:
    • 역직렬화 라이브러리(Jackson, Gson 등)는 기본 생성자를 통해 객체를 생성합니다.
    • 그러나 클래스에 @NoArgsConstructor가 없으면 기본 생성자가 없어서 역직렬화 시 InstantiationException이 발생합니다.
  • 해결 방법:
    • @NoArgsConstructor를 추가하여 기본 생성자를 제공해야 합니다.
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private String name;
    private int age;
}

 

 

2. 필드 초기화 문제

  • 문제 상황:
    • 기본 생성자로 객체를 생성한 뒤, 역직렬화 과정에서 필드 값이 제대로 설정되지 않아 null이 반환될 수 있습니다.
    • 이는 JSON 데이터를 필드에 매핑할 때, 필드 접근 권한이나 Lombok 설정이 올바르지 않을 경우 발생합니다.
  • 해결 방법:
    • 필드 접근 권한(private)을 유지하면서, @Getter 및 @Setter를 추가해 Jackson이 값에 접근할 수 있도록 설정합니다.
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private String name;
    private int age;
}

 

 

3. @AllArgsConstructor와 @NoArgsConstructor 혼용 문제

  • 문제 상황:
    • @AllArgsConstructor만 사용하면 역직렬화가 실패합니다. 이는 Jackson이 JSON 데이터를 객체로 변환할 때 기본 생성자가 필요하기 때문입니다.
    • 또한 JSON 데이터에 특정 필드가 누락되면, 해당 필드가 null로 설정될 수 있습니다.
  • 해결 방법:
    • @AllArgsConstructor와 @NoArgsConstructor를 함께 사용하여 기본 생성자와 필드 초기화 생성자를 모두 제공합니다.
    • 필요한 경우, JSON 필드 이름을 명시적으로 매핑하기 위해 Jackson의 @JsonProperty를 사용합니다.

 

@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
public class User {
    @JsonProperty("user_name")
    private String name;
    private int age;
}

 

 

4. 필드 초기화와 기본값 문제

  • 문제 상황:
    • 기본 생성자로 생성된 객체는 필드 값이 초기화되지 않아 예상치 못한 기본값(예: null, 0)으로 설정될 수 있습니다.
    • JSON 데이터를 매핑할 때도 기본값이 덮어쓰여질 위험이 있습니다.
  • 해결 방법:
    • 필드에 기본값을 명시하거나, Lombok의 @Builder를 사용하여 객체 생성 시 초기화를 강제합니다.
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
public class User {
    private String name = "Default Name";
    private int age = 18;
}

 

 

 

직렬화/역직렬화 설계 가이드

1. 직렬화/역직렬화가 모두 필요한 DTO 설계

  • 권장 어노테이션 조합:
    • @NoArgsConstructor, @AllArgsConstructor, @Getter, @Setter
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
public class UserDTO {
    private String name;
    private int age;
}

2. 직렬화만 필요한 경우

  • 권장 어노테이션 조합:
    • @AllArgsConstructor, @Getter
@AllArgsConstructor
@Getter
public class UserResponse {
    private String name;
    private int age;
}

3. 역직렬화만 필요한 경우

  • 권장 어노테이션 조합:
    • @NoArgsConstructor, @Getter, @Setter
@NoArgsConstructor
@Getter
@Setter
public class UserRequest {
    private String name;
    private int age;
}

 

 

결론

Lombok은 직렬화/역직렬화 작업을 단순화하는 데 큰 도움을 줍니다. 하지만 올바르지 못한 사용은 예상치 못한 오류를 초래할 수 있습니다. 설계 초기 단계에서 다음을 고려하세요:

  1. 기본 생성자와 모든 필드 초기화 생성자 조합:
    • @NoArgsConstructor와 @AllArgsConstructor를 함께 사용해 역직렬화 가능성을 확보하세요.
  2. 필드 초기화와 기본값 설정:
    • 필드 기본값을 명시적으로 정의하거나 @JsonProperty를 사용해 JSON 데이터 매핑을 명확히 하세요.
  3. DTO와 엔티티 분리:
    • JPA 엔티티와 JSON 직렬화/역직렬화를 위한 객체를 분리해 설계를 간결하게 유지하세요.
728x90