brunch

제4장: 빌더 패턴

복잡한 객체의 조립 설명서

by jeromeNa

주택을 구매하는 과정을 생각해 보죠. 분양 사무실에 들어가면 다양한 주택 모델이 전시되어 있습니다. 평수, 구조, 마감재, 가전제품, 조경 등 선택해야 할 옵션이 너무 많아 눈이 어지럽습니다. 하지만 주택 분양 상담사는 여러분의 취향과 예산에 맞게 차근차근 선택을 도와줍니다.


1977년 크리스토퍼 알렉산더(Christopher Alexander) 건축가의 “A Pattern Language”에서 ‘집짓기(House Building)’이라는 건축 패턴을 제안했습니다. 이를 GoF의 디자인 패턴에서 공식적으로 ‘빌더 패턴’이라고 문서화했죠. 2000년대 초반에 Joshua Bloch의 “Effective Java”책에서 ‘빌더 패턴’을 재해석합니다. 현재는 이 방식으로 구현되고 있습니다. 또한, 2010년대에 들어와서 클라우드가 성행하게 됩니다. aws의 함수형 프로그래밍인 람다(Lambda)가 인기를 끌면서 이와 결합된 ‘빌더 패턴’이 등장하게 되죠. 더 간결하고 유연한 빌더 패턴 구현이 가능해졌습니다.


이처럼 ‘빌더 패턴’은 건축에서 개념을 가져왔습니다. 복잡한 객체를 한 번에 만들기보다 부분 부분 나누어 단계적으로 구성하고, 최종적으로 완성된 결과물을 얻는 방법입니다.


복잡한 객체를 만들 때는 많은 파라미터가 필요합니다.


// 복잡한 생성자
House house = new House(150, "콘크리트", "대리석", "강화유리", "지열난방", true, 2, 3, ...);


코드에서 처럼 파라미터가 많으면 가독성이 떨어집니다. 또한 어떤 값이 어떤 속성을 나타내는지 알 수가 없습니다. 일부 값만 변경하려 해도 모든 파라미터를 넣어야 하고, 객체 생성 과정이 한 번에 이루어지기 때문에 유연성이 부족합니다.


이런 복잡한 코드를 빌더 패턴을 사용하면 우아한 코드로 바꿀 수 있습니다.


House house = new House.Builder()
.setSquareFeet(150)
.setWallMaterial("콘크리트")
.setFloorMaterial("대리석")
.setWindowType("강화유리")
.setHeatingSystem("지열난방")
.hasGarage(true)
.setBathrooms(2)
.setBedrooms(3)
.build();


앞의 코드보다 명확하고 가독성이 높아졌습니다. 필요한 속성만 설정할 수 있고, 객체 생성 과정을 단계별로 제어할 수 있습니다.


건축의 사례뿐만 아니라 패스트푸드점의 햄버거 주문을 생각해 볼 수도 있습니다. 패티, 빵, 치즈, 소스, 토핑 등 다양한 옵션을 선택해야 하죠.


Hamburger hamburger = new Hamburger.Builder("통밀빵")
.patty("소고기")
.cheese("체다치즈")
.sauce("머스타드")
.vegetable("양상추")
.vegetable("토마토")
.build();


이처럼 빌더 패턴은 단계별 구성이 필요한 복잡한 객체에 적합합니다.

최근에는 함수형 프로그래밍의 영향으로 더 유연한 빌더 패턴이 등장했습니다.


House house = HouseBuilder.create()
.with(h -> {
h.squareFeet = 150;
h.wallMaterial = "콘크리트";
h.floorMaterial = "대리석";
})
.build();


create()로 객체를 생성하는데, with에 있는 함수를 포함하여 객체를 생성합니다.


빌더 패턴은 복잡한 객체를 쉽고 명확하게 만들 수 있게 도와주는 강력한 도구입니다. 마치 레고 블록을 하나씩 조립해서 복잡한 모형을 만드는 것처럼, 복잡한 객체를 단계별로 구성할 수 있게 해 줍니다.


앞서 이야기한 패턴들과 비교해 보면, 팩토리 매서드 패턴은 한 번의 호출로 객체를 생성하지만, 빌더 패턴은 여러 단계에 걸쳐 객체를 구성합니다. 추상 팩토리는 연관된 객체들의 집합을 생성하는 반면, 빌더 패턴은 복잡한 단일 객체를 단계별로 만들어냅니다.


건축, 요리, 미술, 음악 등 모든 분야는 단계적 절차가 필요합니다. 완성품을 결코 한 번에 이루어지지 않죠. 한 단계씩 나아가는 과정을 통해 더 견고하고 아름다운 결과물을 얻을 수 있습니다. 복잡한 문제일수록 단계별로 분해해서 해결해 나가는 것이 창조의 본질이 아닐까 생각합니다.


비트겐슈타인은 “우리 언어의 한계가 곧 우리 세계의 한계”라고 말합니다. 빌더 패턴은 코드의 가독성과 의미의 명확성을 높임으로써, 사고와 소통 능력을 확장합니다. 복잡한 의도를 간결하고 명확하게 표현함으로써, 더 깊은 이해와 공감을 이끌어 낼 수 있습니다.

keyword