Builder 패턴

code++·2026년 7월 14일

Builder Pattern은 객체를 단계적으로 생성하는 디자인 패턴이다.

Spring Boot와 JPA에서는 엔티티(Entity)나 DTO 객체를 생성할 때 가장 많이 사용하는 패턴 중 하나이다.


Builder Pattern을 사용하는 이유

객체의 필드가 많아질수록 생성자(Constructor)나 Setter를 사용하는 방식에는 여러 문제가 발생한다.

Builder Pattern은 이러한 문제를 해결하기 위해 사용된다.


1. 생성자의 문제점

예를 들어 Member 객체를 생성한다고 가정해보자.

Member member = new Member(
    "kim",
    "1234",
    "김승호",
    "kim@test.com",
    Role.BUYER,
    LocalDateTime.now()
);

이 코드를 보면 "1234"가 비밀번호인지, "김승호"가 닉네임인지 한눈에 알아보기 어렵다.

또한 같은 타입(String)이 여러 개라면 순서를 잘못 입력해도 컴파일 오류가 발생하지 않을 수 있다.

예를 들어

Member member = new Member(
    "kim",
    "김승호",   // password 자리에 nickname이 들어감
    "1234",
    "kim@test.com",
    Role.BUYER,
    LocalDateTime.now()
);

이처럼 매개변수의 순서를 실수해도 잘못된 객체가 생성될 수 있다.


2. Setter의 문제점

Setter를 사용하면 다음과 같이 객체를 생성할 수 있다.

Member member = new Member();

member.setUsername("kim");
member.setPassword("1234");
member.setNickname("김승호");

하지만 객체가 생성되는 도중 예외가 발생하면

Member member = new Member();

member.setUsername("kim");

// 예외 발생

비밀번호도 없고 닉네임도 없는 불완전한 객체가 만들어질 수 있다.

또한 JPA에서는 Entity의 Setter를 무분별하게 사용하는 것을 권장하지 않는다.


3. Builder Pattern 사용

Builder Pattern을 사용하면 다음과 같이 객체를 생성할 수 있다.

Member member = Member.builder()
        .username("kim")
        .password("1234")
        .nickname("김승호")
        .email("kim@test.com")
        .role(Role.BUYER)
        .build();

각 값이 어떤 필드에 들어가는지 코드만 봐도 바로 알 수 있다.

또한 필드의 순서를 자유롭게 작성할 수 있다.

Member member = Member.builder()
        .role(Role.BUYER)
        .nickname("김승호")
        .username("kim")
        .password("1234")
        .email("kim@test.com")
        .build();

순서를 바꿔도 동일한 객체가 생성된다.


build()는 무슨 역할을 할까?

Builder는 객체를 바로 생성하지 않는다.

Member.builder()

를 호출하면 Builder 객체가 생성된다.

.username("kim")
.password("1234")
.nickname("김승호")

를 호출하면서 Builder 내부에 값만 저장한다.

마지막에

.build()

를 호출하면 저장된 값들을 이용해 Member 객체를 생성한다.

즉,

builder()
    ↓
Builder 객체 생성
    ↓
필드 값 저장
    ↓
build()
    ↓
Member 객체 생성

이라는 순서로 동작한다.


Lombok의 @Builder

Lombok의 @Builder를 사용하면 Builder 클래스를 직접 작성하지 않아도 자동으로 생성해준다.

예를 들어

@Builder
public class Member {

    private String username;
    private String password;
}

만 작성하면 내부적으로 Builder 클래스가 자동 생성되어

Member.builder()
        .username("kim")
        .password("1234")
        .build();

와 같이 사용할 수 있다.


실제 프로젝트 예시

회원가입에서 Member 객체를 생성하는 코드이다.

Member member = Member.builder()
        .username(request.getUsername())
        .email(email)
        .password(passwordEncoder.encode(request.getPassword()))
        .nickname(request.getNickname())
        .role(Role.BUYER)
        .createdAt(LocalDateTime.now())
        .onboarded(true)
        .build();

memberRepository.save(member);

동작 순서는 다음과 같다.

Member.builder()
      ↓
Builder 생성
      ↓
username 저장
      ↓
email 저장
      ↓
password 저장
      ↓
nickname 저장
      ↓
role 저장
      ↓
build()
      ↓
Member 객체 생성
      ↓
memberRepository.save()
      ↓
DB 저장

Builder Pattern의 장점

  • 코드의 가독성이 좋아진다.
  • 어떤 값이 어떤 필드에 들어가는지 한눈에 알 수 있다.
  • 생성자의 매개변수 순서를 신경 쓰지 않아도 된다.
  • Setter를 남발하지 않아도 된다.
  • 불완전한 객체 생성을 방지할 수 있다.
  • 필드가 많아질수록 유지보수가 쉬워진다.

정리

Spring Boot와 JPA에서는 Entity나 DTO를 생성할 때 Builder Pattern을 많이 사용한다.

Builder Pattern은 객체를 단계적으로 생성하여 가독성, 안정성, 유지보수성을 높여주는 패턴이며, 실무에서도 가장 많이 사용하는 객체 생성 방식 중 하나이다.

profile
일상

0개의 댓글