빌더 패턴
- 동일한 프로세스를 거쳐 다양한 구성의 인스턴스를 만드는 방법
- 복잡한 객체의 생성 과정과 표현 방식을 분리하여 동일한 생성 절차에서 서로 다른 표현 결과를 만들 수 있게 지원
- 특히 생성해야 하는 객체가 복잡하고, 생성 과정이 여러 단계로 나누어져 있을 때 유용
- 복잡한 객체를 만드는 프로세스를 독립적으로 분리할 수 있음

주요 구성 요소
1. Builder 인터페이스
- 객체 생성을 위한 추상 메서드 정의
- 인스턴스를 생성하는 방법들을 단계 별로 만들 수 있도록 메서드 제공 (위 UML에서 buildXXX 메서드들)
- 최종 Product를 받아올 수 있는 메서드 제공 (위 UML에서 getResult 메서드)
2. Concrete Builder
- Builder 인터페이스 구현체
- 특정한 타입의 복잡한 객체 생성을 위한 구체적인 구현을 담당
- 생성할 객체를 내부적으로 유지하면서 단계별로 객체를 생성
- 원한다면 다른 ConcreteBuilder를 만들어 다양한 방식으로 객체를 생성하는 빌더들을 구상할 수 있음
3. Director
- Director 안에 반복적으로 호출되는 빌더 호출 스택을 은닉
- Product는 Director를 통해 Builder 사용함에 따라 비교적 간단하게 인스턴스를 받아다 사용
- Builder 인터페이스를 사용하는 객체 생성의 절차를 관리하여 Director는 Builder에 객체 생성을 요청하며, Builder가 반환된 객체를 받음
4. Product
- 최종적으로 생성된 객체
- Builder와 Concrete Builder는 해당 Product를 생성
빌더 패턴 구현 예시
1. Product 정의
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Setter | |
@ToString | |
public class Product { | |
private String partA; | |
private String partB; | |
} |
2. Builder 인터페이스 및 Concrete Builder 정의
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface Builder { | |
Builder buildPartA(String s); | |
Builder buildPartB(String s); | |
Product getProduct(); | |
} | |
public class ConcreteBuilder implements Builder { | |
private Product product; | |
public ConcreteBuilder() { | |
product = new Product(); | |
} | |
@Override | |
public Builder buildPartA(String s) { | |
product.setPartA(s); | |
return this; | |
} | |
@Override | |
public Builder buildPartB(String s) { | |
product.setPartB(s); | |
return this; | |
} | |
@Override | |
public Product getProduct() { | |
return product; | |
} | |
} |
3. Director 정의
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Director { | |
private Builder builder; | |
public Director(Builder builder) { | |
this.builder = builder; | |
} | |
public Product construct() { | |
return builder.buildPartA("파트 A") | |
.buildPartB("파트 B") | |
.getProduct(); | |
} | |
} |
4. Client 코드 예시
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Client { | |
public static void main(String[] args) { | |
Builder builder = new ConcreteBuilder(); | |
Director director = new Director(builder); | |
Product product = director.construct(); | |
System.out.println(product); | |
} | |
} |

빌더 패턴 장단점
장점
- 만들기 복잡한 객체를 순차적으로 만드는 방법을 제공
- 생성자의 경우 순서라는 개념이 딱히 없으며 한 번에 다 넘겨줘야 함
- Director를 통해 복잡한 객체를 만드는 과정을 은닉할 수 있음
- 동일한 프로세스를 통해 각기 다르게 구성된 객체를 만들 수 있음 (다양한 ConcreteBuilder)
- 불완전한 객체를 사용하지 못하도록 방지 가능
- 예제 코드를 보면 getProduct()를 호출해야지만 객체가 만들어짐
단점
- 원하는 객체를 만드려면 Builder, ConcreteBuilder, 그리고 Director를 만들어야 하기 때문에 관리 포인트가 늘어남
- 클래스가 많아짐에 따라 구조가 복잡해짐
실무에서 쓰이는 빌더 패턴
1. StringBuilder
- 문자열을 만드는 일련의 과정이 빌더 패턴과 유사
- 순차적으로 문자열을 추가한 후 (append 메서드)
- toString() 메서드를 호출해야지만 String 객체가 만들어짐
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static void main(String[] args) { | |
StringBuilder stringBuilder = new StringBuilder(); | |
String result = stringBuilder // 일련의 과정이 비슷함 | |
.append("builder") | |
.append(" pattern") | |
.toString(); | |
System.out.println(result); | |
} |

2. Spring Framework의 UriComponentBuilder
- URL의 구성 요소를 쉽게 조립하고 관리하기 위한 도구
- 일반적으로 URI 또는 URL을 구성할 때 다양한 부분(스킴, 호스트, 경로, 쿼리 매개변수 등)을 명확하고 체계적으로 설정할 수 있게 지원
- 복잡한 URL을 생성하는 과정을 간편하게 해주며, 특히 쿼리 매개변수를 동적으로 추가하거나 변경할 때 유용
- 프로토콜, 호스트(도메인), 포트, 경로, 쿼리 매개변수, 프래그먼트 등을 개별적으로 설정하고 조립할 수 있도록 체이닝 메서드 제공
- 복잡한 URL을 문자열로 직접 조작하는 것보다, 명확하게 메서드 호출을 통해 URL을 구성하면 코드 가독성이 크게 향상
- 쿼리 매개변수 등은 자동으로 URL 인코딩되어, 특수 문자가 포함된 데이터를 안전하게 처리할 수 있음
- 템플릿 변수 바인딩을 지원하여 동적 URI를 생성할 수 있음
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static void main(String[] args) { | |
// 기본 URI 설정 | |
UriComponents uriComponents = UriComponentsBuilder.newInstance() | |
.scheme("https") | |
.host("www.example.com") | |
.path("/search") | |
.queryParam("q", "springframework") | |
.queryParam("sort", "desc") | |
.fragment("section1") | |
.build(); | |
// URI 문자열 출력 | |
String uri = uriComponents.toUriString(); | |
System.out.println(uri); // 출력: https://www.example.com/search?q=spring+framework&sort=desc#section1 | |
// URI 템플릿 사용 | |
UriComponents uriTemplate = UriComponentsBuilder.newInstance() | |
.scheme("https") | |
.host("www.example.com") | |
.path("/users/{userId}/posts") | |
.queryParam("page", "1") | |
.buildAndExpand("123"); | |
// URI 템플릿 문자열 출력 | |
String uriWithTemplate = uriTemplate.toUriString(); | |
System.out.println(uriWithTemplate); | |
} |

3. Lombok에서 제공하는 @Builder, @SuperBuilder
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Builder | |
@ToString | |
public class User { | |
private String name; | |
private int age; | |
private String email; | |
} | |
public static void main(String[] args) { | |
User user = User.builder() | |
.name("jaimemin") | |
.age(29) | |
.email("example@example.com") | |
.build(); | |
System.out.println(user); | |
} |

참고
코딩으로 학습하는 GoF의 디자인 패턴 - 백기선 강사님
반응형
'Design Pattern' 카테고리의 다른 글
[디자인 패턴] 어댑터 패턴 (Adapter Pattern) (0) | 2024.06.22 |
---|---|
[디자인 패턴] 프로토타입 패턴 (Prototype Pattern) (0) | 2024.06.22 |
[디자인 패턴] 추상 팩토리 패턴 (Abstract Factory Pattern) (0) | 2024.06.18 |
[디자인 패턴] 팩토리 메서드 패턴 (Factory Method Pattern) (0) | 2024.06.18 |
[디자인 패턴] 싱글톤 패턴 (Singleton Pattern) (0) | 2024.06.13 |