목차
중점적으로 봐야 하는 내용
- 선택적 매개변수가 많은 클래스는 생성자나 정적 팩터리 메서드만으로 표현하기 어렵다.
- 점층적 생성자 패턴이나 자바빈즈 패턴은 유지보수성·안정성 측면에서 한계가 있다.
- 이런 경우 빌더 패턴을 사용하면 가독성과 객체 일관성 면에서 유리하다.
주요 개념 요약
빌더 패턴은 복잡한 객체를 구성할 때 필수 매개변수와 선택 매개변수를 분리하고, 단계별 설정을 가능하게 하는 설계 기법이다.
보통 클래스 내부에 정적 멤버 클래스로 Builder를 두고, 메서드 체인 방식으로 속성들을 설정한 뒤 build() 메서드로 객체를 생성한다.
장점
- 매개변수가 많은 경우 코드 가독성이 좋아진다.
- 필수 매개변수와 선택 매개변수를 명확히 구분할 수 있다.
- 메서드 체인(Fluent API)을 통해 설정이 직관적이다.
- 계층적으로 설계된 클래스에서도 공변 반환(covariant return) 등을 통해 확장이 가능하다.
단점
- 객체 하나를 만들려면 Builder 객체부터 만들어야 하므로 코드가 좀 더 장황해질 수 있다.
- 개발자가 선택 매개변수를 실수로 누락할 가능성이 있음.
- 많은 경우, 간단한 객체라면 생성자 또는 정적 팩터리를 쓸 때보다 오히려 불편할 수 있다.
실무 적용 예시
선택적 필드가 많은 DTO/Domain/Entity 클래스를 다룰 때, 특히 필드의 유효성 체크가 중요한 경우에 직접 빌더 패턴을 구현 및 도입했다.
public class UserProfile {
private final Long id; // 필수
private final String username; // 필수
private final String email; // 선택
private final String phoneNumber; // 선택
private final String address; // 선택
private UserProfile(Builder builder) {
this.id = builder.id;
this.username = builder.username;
this.email = builder.email;
this.phoneNumber = builder.phoneNumber;
this.address = builder.address;
}
public static class Builder {
private final Long id;
private final String username;
private String email = "";
private String phoneNumber = "";
private String address = "";
public Builder(Long id, String username) {
this.id = id;
this.username = username;
}
public Builder email(String email) { this.email = email; return this; }
public Builder phoneNumber(String phoneNumber) { this.phoneNumber = phoneNumber; return this; }
public Builder address(String address) { this.address = address; return this; }
public UserProfile build() {
// 필수 필드 누락 체크 가능
if (id == null || username == null) {
throw new IllegalStateException("필수 매개변수가 누락되었습니다");
}
return new UserProfile(this);
}
}
}
UserProfile profile = new UserProfile.Builder(1L, "hyedddi")
.email("hyedddi@example.com")
.phoneNumber("010-1234-5678")
.build();
그 외의 클래스에는 롬복(Lombok)의 @Builder를 활용하여 반복되는 빌더 코드를 줄였다.
나의 인사이트
- 빌더 패턴을 도입하면서 복잡한 생성자 시그니처를 피할 수 있었고, 가독성과 유지보수성이 크게 좋아졌다.
- 다만 실제로 협업 시, 선택적 매개변수를 누락하여 논리적 오류가 나는 경우가 있어서, 빌더내에서 필수 필드 검증 혹은 테스트 케이스를 꼭 넣어야 한다고 느꼈다.
- 간단한 객체나 필드가 적은 경우에는 여전히 정적 팩터리나 생성자를 사용하는 것이 더 간편하다고 판단했다.
'Language > Java' 카테고리의 다른 글
[EFFECTIVE JAVA 3/E] #1 생성자 대신 정적 팩터리 메서드를 고려하라 (0) | 2025.09.15 |
---|---|
[JAVA] HashMap이란? (0) | 2023.12.31 |
[JAVA] String constant pool이란? (0) | 2023.10.13 |
[JAVA] String 클래스의 특징 (0) | 2023.10.12 |
[JAVA] 직렬화(Serialization)란? (0) | 2023.08.20 |