[Practice-2] 객체 생성: 빌더 패턴과 정적 팩터리 메서드

2025. 9. 2. 12:46·Spring/Core

Spring(Java)으로 개발하다 보면 객체를 생성하는 다양한 방법을 마주하게 됩니다. 그중 가장 대표적인 것이 빌더 패턴(Builder Pattern)과 정적 팩터리 메서드(Static Factory Method)입니다.

 

많은 개발자들이 자연스럽게 "Entity에는 빌더 패턴, DTO에는 정적 팩터리 메서드"라는 규칙을 따르곤 합니다. 왜 이런 관행이 생겼을까요? 단순히 파라미터 개수 때문일까요? 이 글에서는 두 패턴의 핵심적인 차이와 각자의 역할에 가장 적합한 사용 기준을 명확하게 알아보겠습니다.


빌더 패턴 (Builder Pattern): "어떻게(How) 만들 것인가?" 🧱

빌더 패턴은 복잡한 객체를 생성할 때, 그 과정을 단계별로 명확하게 표현하는 데 중점을 둡니다. 여러 데이터를 '조립'하여 하나의 완전한 객체를 만드는 그림을 상상하면 쉽습니다.

언제 사용할까? 생성 시점에 필요한 파라미터가 많고, 그중 다수가 선택적일 때 매우 유용합니다.

장점

  • 가독성: .field(value) 형태의 메서드 체이닝을 통해 어떤 필드에 어떤 값이 설정되는지 명확하게 알 수 있습니다.
  • 유연성: 필요한 필드만 선택적으로 설정할 수 있습니다.
  • 불변성 확보: .build() 메서드를 호출하기 전까지 객체가 생성되지 않아, 생성 시점의 일관성을 유지하기 좋습니다.

주요 사용처: 엔티티 (Entity) 엔티티는 데이터베이스 테이블과 매핑되며 다양한 필드를 가집니다. 특히 여러 소스에서 온 데이터를 합쳐야 하는 경우가 많습니다.

  • title, contents → 클라이언트 요청 (Request DTO)
  • userEntity → 인증 정보 (SecurityContext)
  • imageUrl → 파일 업로드 결과 (Service)

이처럼 여러 조각을 모아 하나의 완전한 객체를 '조립'하는 상황에서는 빌더 패턴이 각 구성 요소를 명확하게 보여주어 가장 적합합니다.

// UserEntity.java
UserEntity newUser = UserEntity.builder()
    .username("testuser")
    .password("encoded_password")
    .isLock(false)
    .isSocial(false)
    .roleType(UserRoleType.USER)
    .nickname("테스트유저")
    .email("test@example.com")
    .build(); // 필요한 값을 명확히 지정하여 객체 생성

정적 팩터리 메서드 (Static Factory Method): "무엇을(What) 만들 것인가?" ✨

정적 팩터리 메서드는 생성자 대신, 의도를 명확히 드러내는 이름을 가진 정적 메서드를 통해 객체를 생성하는 방식입니다. 특정 객체를 다른 형태로 '변환'하는 목적이 강합니다.

언제 사용할까? 객체 생성의 목적이 명확할 때, 특히 다른 객체로부터 변환하여 생성할 때 매우 효과적입니다.

장점

  • 의미 있는 이름: of(), from(), newInstance() 등 메서드 이름을 통해 생성 의도를 명확히 전달할 수 있습니다.
  • 로직 캡슐화: 객체 생성에 필요한 복잡한 로직을 메서드 내부에 숨길 수 있습니다.
  • 유연한 반환 타입: 명시된 반환 타입의 하위 타입 객체를 반환할 수도 있어 유연합니다.

주요 사용처: DTO (Data Transfer Object) DTO는 대부분 "엔티티를 API 응답 형식으로 변환"하는 명확한 목적을 가집니다. 즉, PostEntity라는 단 하나의 소스를 PostResponseDto라는 형태로 '변환'하는 것이죠.

필드가 여러 개라도, 이 값들은 모두 단일 소스 객체(PostEntity)로부터 나옵니다. 생성의 목적이 '조립'이 아니라 '변환'이므로, 이 과정을 from()이라는 메서드 안에 캡슐화하는 것이 훨씬 간결하고 의도가 잘 드러납니다.

// UserResponseDto.java
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class PostResponseDto {
    private Long postId;
    private String authorNickname;
    private String title;
    // ... 기타 필드

    // 생성자를 private으로 막아 외부에서 직접 생성을 제한
    private PostResponseDto(PostEntity postEntity) {
        this.postId = postEntity.getId();
        this.authorNickname = postEntity.getUserEntity().getNickname();
        this.title = postEntity.getTitle();
        // ...
    }

    // "PostEntity로부터 PostResponseDto를 만든다"는 의도를 명확히 보여줌
    public static PostResponseDto from(PostEntity postEntity) {
        return new PostResponseDto(postEntity);
    }
}

핵심 기준: 조립(Build) vs 변환(Transform)

"파라미터가 3~4개 이상이면 빌더를 쓴다"는 규칙은 표면적인 기준일 뿐입니다. 더 중요한 핵심 기준은 객체 생성의 '목적'과 '의도'입니다.

  • 빌더 패턴: 여러 출처의 데이터를 조립(Assembly)하여 복잡한 객체를 만들 때 사용합니다. (Entity)
  • 정적 팩터리 메서드: 단일 소스 객체를 다른 형태의 객체로 변환(Transformation)할 때 사용합니다. (DTO)
구분 빌더 패턴 (Builder Pattern)
정적 팩터리 메서드 (Static Factory Method)
핵심 목적 🧩 조립 (Assembly)
🔄 변환 (Transformation)
데이터 소스 여러 곳 (DTO, SecurityContext, Service 등)
단일 객체 (e.g., Entity)
주요 사용처 ✅ 엔티티(Entity), 복잡한 객체
✅ DTO, 간단한 객체

'Spring > Core' 카테고리의 다른 글

[Basic-3] 관심사의 분리와 의존관계 주입(DI)  (0) 2025.12.30
[Basic-2] 순수 자바 예제로 이해하는 DIP와 OCP 위반  (0) 2025.12.30
[Basic-1] 객체 지향 설계와 스프링의 탄생 배경  (0) 2025.12.30
[Practice-3] Spring Core: 깔끔하고 확장성 있는 예외 처리  (1) 2025.12.16
[Practice-1] ResponseEntity<>  (0) 2025.08.27
'Spring/Core' 카테고리의 다른 글
  • [Basic-2] 순수 자바 예제로 이해하는 DIP와 OCP 위반
  • [Basic-1] 객체 지향 설계와 스프링의 탄생 배경
  • [Practice-3] Spring Core: 깔끔하고 확장성 있는 예외 처리
  • [Practice-1] ResponseEntity<>
h6bro
h6bro
백엔드 개발자의 기술 블로그
  • h6bro
    Jun's Tech Blog
    h6bro
  • 전체
    오늘
    어제
    • 분류 전체보기 (241) N
      • Java (18)
        • Core (9)
        • Design Pattern (9)
      • Spring (80)
        • Core (24)
        • MVC (6)
        • DB (10)
        • JPA (26)
        • Monitoring (3)
        • Security (11)
        • WebSocket (0)
      • Database (33)
        • Redis (15)
        • MySQL (18)
      • MSA (16)
        • MSA 기본 (11)
        • MSA 아키텍처 (5)
      • Kafka (30) N
        • Core (18) N
        • Connect (12)
      • ElasticSearch (11)
        • Search (11)
        • Logging (0)
      • Test (4)
        • k6 (4)
      • Docker (9)
      • CI&CD (10)
        • GitHub Actions (6)
        • ArgoCD (4)
      • Kubernetes (18)
        • Core (12)
        • Ops (6)
      • Cloud Engineering (4)
        • AWS Infrastructure (3)
        • AWS EKS (1)
        • Terraform (0)
      • Project (8)
        • LinkFolio (1)
        • Secondhand Market (7)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

    • Cloud Engineering 포스팅 정리
  • 인기 글

  • 태그

    ㅈ
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
h6bro
[Practice-2] 객체 생성: 빌더 패턴과 정적 팩터리 메서드
상단으로

티스토리툴바