Builder Pattern은 객체를 단계적으로 생성하는 디자인 패턴이다.
Spring Boot와 JPA에서는 엔티티(Entity)나 DTO 객체를 생성할 때 가장 많이 사용하는 패턴 중 하나이다.
객체의 필드가 많아질수록 생성자(Constructor)나 Setter를 사용하는 방식에는 여러 문제가 발생한다.
Builder Pattern은 이러한 문제를 해결하기 위해 사용된다.
예를 들어 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()
);
이처럼 매개변수의 순서를 실수해도 잘못된 객체가 생성될 수 있다.
Setter를 사용하면 다음과 같이 객체를 생성할 수 있다.
Member member = new Member();
member.setUsername("kim");
member.setPassword("1234");
member.setNickname("김승호");
하지만 객체가 생성되는 도중 예외가 발생하면
Member member = new Member();
member.setUsername("kim");
// 예외 발생
비밀번호도 없고 닉네임도 없는 불완전한 객체가 만들어질 수 있다.
또한 JPA에서는 Entity의 Setter를 무분별하게 사용하는 것을 권장하지 않는다.
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();
순서를 바꿔도 동일한 객체가 생성된다.
Builder는 객체를 바로 생성하지 않는다.
Member.builder()
를 호출하면 Builder 객체가 생성된다.
.username("kim")
.password("1234")
.nickname("김승호")
를 호출하면서 Builder 내부에 값만 저장한다.
마지막에
.build()
를 호출하면 저장된 값들을 이용해 Member 객체를 생성한다.
즉,
builder()
↓
Builder 객체 생성
↓
필드 값 저장
↓
build()
↓
Member 객체 생성
이라는 순서로 동작한다.
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 저장
Spring Boot와 JPA에서는 Entity나 DTO를 생성할 때 Builder Pattern을 많이 사용한다.
Builder Pattern은 객체를 단계적으로 생성하여 가독성, 안정성, 유지보수성을 높여주는 패턴이며, 실무에서도 가장 많이 사용하는 객체 생성 방식 중 하나이다.