Spring

[Lombok] @Builder, DTO 접근제한자 적절한 설정 방법

공부하고 기억하는 공간 2025. 3. 11. 07:40
728x90
반응형
SMALL

@AllArgsConstructor 및 @NoArgsConstructor의 접근 제한 설정 방법

 

MSA(Microservices Architecture) 환경에서는 각 서비스가 독립적으로 동작하며, 데이터 및 객체의 무분별한 생성 및 변경을 방지하는 것이 중요하다. 따라서 @AllArgsConstructor@NoArgsConstructor의 접근 제한자를 적절히 설정하여 객체의 생성 및 변경을 제어해야 한다.

 


1. @AllArgsConstructor (모든 필드를 포함하는 생성자)

@AllArgsConstructor(access = AccessLevel.PROTECTED)

설정 이유

1. 엔티티 객체의 직접적인 변경 방지

엔티티는 무분별하게 생성되거나 수정되어서는 안 되므로 **protected**로 설정하여 내부에서만 사용할 수 있도록 제한.

2. Spring Data JPA 및 ORM 사용을 고려

JPA에서는 엔티티를 조회할 때 프록시 객체를 생성하는데, public 생성자가 없으면 객체를 생성할 수 없다.

하지만 외부에서 직접 엔티티를 생성하는 것은 지양해야 하므로 protected 수준으로 접근을 제한.

 

📌 적용 예시

@Getter
@Entity
@AllArgsConstructor(access = AccessLevel.PROTECTED)
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private int price;
}

🛠 사용 예

// 잘못된 사용 (제한된 생성자 호출 불가)
// Product product = new Product(1L, "스마트폰", 1000); ❌

// 올바른 사용 (팩토리 메서드 또는 빌더 사용)
Product product = Product.createProduct("스마트폰", 1000);

 

 


2. @NoArgsConstructor (기본 생성자)

@NoArgsConstructor(access = AccessLevel.PROTECTED)

 설정 이유

1. JPA의 프록시 객체 생성을 허용해야 함

JPA에서는 기본 생성자가 필요하므로 반드시 제공해야 하지만, 외부에서 직접 호출되는 것은 막아야 함.

따라서 @NoArgsConstructor(access = AccessLevel.PROTECTED)를 설정하여 엔티티 외부에서는 기본 생성자를 호출할 수 없도록 제한.

2. DTO 변환 및 직렬화(Serialization) 고려

Jackson(JSON 변환 라이브러리)이나 Kafka 메시지 처리 시 기본 생성자가 필요할 수 있음.

하지만 엔티티의 경우, JSON 직렬화를 위한 DTO를 따로 만들어 사용하는 것이 일반적이므로 엔티티에 public 기본 생성자를 두지 않는 것이 좋음.

 

 적용 예시

@Getter
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private int price;
}

🛠 사용 예

// JPA가 기본 생성자를 사용하여 객체를 생성할 수 있음 (사용자 호출은 불가능)
Product product = new Product(); // ❌ (protected라서 외부에서 직접 호출 불가)

// JPA 내부에서는 사용 가능 (Spring이 프록시 객체를 만들 때 필요)

 

 


3. DTO 및 Service에서의 객체 생성 제한

 

DTO의 경우 public 생성자 허용

DTO는 데이터를 담는 용도이므로 제한 없이 public 생성자를 허용하는 것이 일반적이다.

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class ProductDto {
    private Long id;
    private String name;
    private int price;
}

엔티티 객체의 직접 생성 방지

엔티티는 @AllArgsConstructor@NoArgsConstructorprotected로 제한하고,

팩토리 메서드 또는 @Builder를 이용하여 생성하는 방식이 바람직함.

@Getter
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PROTECTED)
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private int price;

    // 객체 생성을 위한 팩토리 메서드
    public static Product createProduct(String name, int price) {
        return new Product(null, name, price);
    }
}

🛠 사용 예

Product product = Product.createProduct("스마트폰", 1000); // ✅ 올바른 사용 방식

 

 


4. @Builder와 함께 사용할 경우

 

빌더 사용 시 생성자 접근 제한 설정

@Builder@AllArgsConstructor를 필요로 하지만, 엔티티가 직접 생성되는 것을 막아야 하므로 protected로 제한해야 한다.

@Getter
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@Builder
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private int price;
}

🛠 사용 예

Product product = Product.builder()
                         .name("스마트폰")
                         .price(1000)
                         .build(); // ✅ 빌더를 통해서만 객체 생성 가능

 

 


5. 정리: MSA 환경에서 생성자 접근 제한 기준

적용 대상생성자 접근 제한 방식설정 이유

엔티티 클래스 (@Entity) @NoArgsConstructor(access = AccessLevel.PROTECTED) JPA 프록시 객체 생성을 허용하면서 외부 사용을 제한
  @AllArgsConstructor(access = AccessLevel.PROTECTED) 직접 객체 생성을 방지하고, 빌더 또는 팩토리 메서드 사용 유도
DTO 클래스 @NoArgsConstructor(access = AccessLevel.PUBLIC) JSON 변환 및 직렬화 지원
  @AllArgsConstructor(access = AccessLevel.PUBLIC) DTO의 직렬화 및 데이터 전달 용도로 사용
빌더 패턴 사용 (@Builder) @AllArgsConstructor(access = AccessLevel.PROTECTED) 직접 객체 생성을 방지하고 빌더 패턴 사용 강제
팩토리 메서드 제공 public static 메서드로 생성 객체 생성 로직을 캡슐화

 

 


결론

 

MSA 환경에서는 무분별한 객체 생성을 방지하고, 올바른 방식으로 객체를 초기화할 수 있도록 접근 제한을 설정하는 것이 중요하다.

엔티티 클래스(@Entity)

@NoArgsConstructor(access = AccessLevel.PROTECTED) → JPA를 위한 기본 생성자는 허용하지만, 외부 사용은 제한.

@AllArgsConstructor(access = AccessLevel.PROTECTED) → 직접 객체 생성을 방지.

@Builder 활용 시 생성자 호출을 막고 빌더만 사용 가능하도록 설정.

DTO 클래스

public 생성자 허용 (@NoArgsConstructor, @AllArgsConstructor) → JSON 변환 및 직렬화를 위해 필요.

팩토리 메서드 또는 @Builder 사용 권장

직접 객체 생성이 필요할 경우 public static 팩토리 메서드 제공.

 

이를 통해 MSA 환경에서 객체의 일관성을 유지하고, 올바른 방식으로 객체를 관리할 수 있도록 설계하는 것이 바람직하다. 🚀

728x90
반응형
SMALL