-
RESTful API 설계하기이커머스 devops/국비교육 2025. 11. 16. 12:30
"RESTful하다 = HTTP 규칙(메서드, 상태코드, URI)을 잘 지켜서 자원 중심의 일관된 인터페이스를 제공하는 것"
Lombok @Builder : 클래스 vs 생성자
- @Builder는 빌더 패턴(Builder Pattern)을 자동으로 생성하여 복잡한 객체 생성을 명확하고 안전하게 만들어 준다
- @Builder는 클래스 전체 또는 특정 생성자에 붙일 수 있다
1. 클래스에 @Builder 붙이는 경우
- 가장 일반적이고 간단한 사용법
- 클래스 레벨에 @Builder를 선언하면 해당 클래스의 모든 필드를 초기화할 수 있는 빌더가 생성된다
- 동작 방식 : Lombok은 모든 필드를 파라미터로 받는 생성자(@AllArgsConstructor)를 자동으로 만들고, 이 생성자를 기반으로 빌더를 생성한다
// 코드 예제 @Getter @Builder @AllArgsConstructor // 클래스 레벨 빌더는 모든 필드 생성자를 필요로 함 @NoArgsConstructor // JSON 변환 등에서 필요할 수 있음 public class Product { private String name; private double price; private String description; @Builder.Default // 필드 초기값을 빌더에 반영하려면 @Builder.Default 사용 private boolean onSale = false; } // 사용법 Product product = Product.builder() .name("Laptop") .price(1500.00) .description("A high-performance laptop") .onSale(true) // onSale 필드도 설정 가능 .build();- 장점
- 간편함과 완전성
- 높은 유연성
- 단점 및 주의사항
- 필수 값 강제 불가 : 어떤 필드가 필수인지 빌더 수준에서 강제할 수 없다
- 필드 기본값 무시 : 필드에 직접 초기값을 주면 @Builder는 무시한다 필드 초기값을 빌더 생성 시에도 유지하려면 반드시 @Builder. Default 어노테이션을 함께 사용해야 한다
2. 생성자에 @Builder 붙이는 경우
- 특정 생성자 위에 @Builder를 선언하면 해당 생성자의 파라미터로 받은 필드들만으로 빌더 생성
- 객체 생성을 더 엄격하게 제어하고 싶을 때 사용
- 동작 방식 : Lombok은 @Builder가 붙은 생성자만을 사용하여 빌더 코드를 생성한다
// 코드 예제 @Getter public class Product { private final String name; // 필수 값 private final double price; // 필수 값 private String description; // 선택 값 @Builder // 이 생성자에 대해서만 빌더를 만듦 public Product(String name, double price) { // 생성자 내부에서 유효성 검증 로직 추가 가능 if (name == null || name.isBlank()) { throw new IllegalArgumentException("상품 이름은 필수입니다."); } this.name = name; this.price = price; // 특정 필드를 내부적으로 초기화할 수도 있음 this.description = "기본 설명"; } } // 사용법 Product product = Product.builder() .name("Laptop") .price(1500.00) // .description("...") -> 빌더에 포함되지 않아 컴파일 에러 발생 .build();- 장점
- 필수값 강제
- 초기화 로직 추가 : 생성자 내부에 유효성 검증, 다른 필드를 조합하여 새로운 값을 만드는 등 복잡한 초기화 로직을 추가할 수 있다
- 단점
- 빌더를 통해 초기화할 수 있는 필드가 제한된다
- 다른 조합의 객체를 생성하려면 별도의 생성자와 빌더를 또 만들어야 할 수 있다
사용 사례 추천 방식 이유 단순한 DTO, Response 객체 클래스에 @Builder 모든 필드를 유연하게 채워야 하고, 복잡한 생성 로직이 필요 없는 경우가 대부분이기 때문이다 엔티티, 도메인 객체 생성자에 @Builder "이름은 필수, 가격은 0이상"과 같이 필수값을 강제하고 객체가 생성될 때부터 일관된 상태를 보장해야하기 때문이다 필드에 기본값을 설정하고 싶을 때 클래스에 @Builder + @Builder.Default @Builder.Default를 사용하면 필드 초기화와 빌더의 유연함을 동시에 가져갈 수 있기 때문이다 Builder 패턴
- 복잡한 객체의 생성 과정과 최종 표현을 분리하여 객체를 단계별로 유연하고 안전하게 만들 수 있도록 한다
- 높은 가독성 : 어떤 필드에 어떤 값이 들어가는지 명확하게 알 수 있다
- 유연한 객체 생성 : 필요한 필드만 선택적으로 설정할 수 있고, 순서에 상관없이 값을 지정할 수 있다
- 불변성 확보 : setter 필요 없이 build()메서드가 호출되는 시점에 완전한 상태의 불변 객체를 생성할 수 있다
서비스 메서드 네이밍 규칙 : get vs find
- 메서드 이름은 해당 메서드의 동작 제약을 나타내는 중요한 규칙이다
- get
- 데이터가 반드시 존재함을 보장한다
- orElseThrow()를 사용하여 데이터가 없을 경우 예외를 던지는 방식
- 로직상 데이터가 반드시 존재해야만 다음 단계 진행이 가능한 경우 사용
- 예) 로그인한 사용자의 정보 조회
- find
- 데이터가 없을 수도 있음을 인정한다
- Optional<T>를 그대로 반환하여 호출한 쪽에서 데이터 존재 여부를 판단하고 처리하도록 위임
- 데이터의 존재 여부 자체가 비즈니스 로직의 중요한 분기점이 될 때 사용
- 예) 이메일 중복 확인
728x90'이커머스 devops > 국비교육' 카테고리의 다른 글
QueryDSL 기본 문법 (0) 2025.11.19 영속성 컨텍스트와 트랜잭션 & QueryDSL (0) 2025.11.16 공통 응답 처리와 예외 핸들링 (0) 2025.11.16 ORM 심화 및 데이터 로딩 전략 (0) 2025.11.15 프로젝트 기본 설정 (0) 2025.11.15