실전 디자인 패턴과 기타 패턴
- 6.1 패턴의 정의와 분류
- 6.2 패턴으로 생각하기
- 6.3 안티 패턴
- 6.4 브리지, 빌더, 책임 연쇄 패턴
- 6.5 플라이웨이트, 인터프리터, 중재자 패턴
- 6.6 메멘토, 프로토타입, 비지터 패턴
패턴을 아는 것보다 중요한 건 언제 쓰고 언제 안 쓸지 아는 것, 그리고 나머지 패턴들의 존재를 아는 것이야.
GoF가 정의한 패턴은 "특정 컨텍스트에서 주어진 문제의 해결책"이야. 컨텍스트(반복되는 상황), 문제(목표와 제약), 해결책(일반적 설계) — 이 세 요소가 있어야 패턴이지. 생성/구조/행동이라는 세 카테고리로 분류되고, 각 패턴의 **의도(intent)**를 기억해두면 문제 상황에서 적절한 패턴을 떠올릴 수 있어. 하지만 패턴을 아는 것보다 더 중요한 건 언제 안 쓸지 아는 것이야. "이 문제에 옵저버를 쓸 수 있을까?"가 아니라 "어떻게 가장 간단하게 해결할까?"부터 생각해야 해. 패턴은 도구이지 목표가 아니거든. 처음 설계할 때부터 넣으려 하지 말고, 코드가 발전하면서 필요해지는 시점에 리팩토링으로 도입하는 게 맞아.
패턴의 숨겨진 가치는 공유 어휘에 있어. "여기에 옵저버 패턴 적용했어"라고 하면, 팀원이 코드를 안 봐도 구조를 이해하잖아. 패턴 이름 하나가 설계 의도를 압축적으로 전달하는 거야. 반대로 안티 패턴 — 자주 쓰이지만 나쁜 결과를 초래하는 해결책 — 도 알아둬야 해. 하나의 기술로 모든 걸 해결하려는 골든 해머, 완벽한 설계를 찾느라 개발을 못 시작하는 분석 마비. 자기가 빠져 있다는 걸 인식해야 빠져나올 수 있으니까.
이제 앞에서 다루지 않은 나머지 9개 패턴을 빠르게 훑어보자. 브리지는 추상화와 구현을 분리해서 리모컨과 TV가 독립적으로 확장되게 해. 빌더는 addHotel(), addFlight() 같은 단계별 메소드로 복잡한 객체를 점진적으로 생성하고, 같은 과정으로 일반 여행이든 럭셔리 여행이든 다른 표현을 만들어낼 수 있어. 책임 연쇄는 이메일 필터처럼 요청을 처리할 수 있는 객체들을 체인으로 연결해서, 보내는 쪽이 누가 처리할지 몰라도 되게 만들지.
플라이웨이트는 문서 편집기에서 'a' 객체를 하나만 만들고 모든 'a'가 공유하듯, 내재 상태(공유 가능)와 외재 상태(위치, 크기)를 분리해서 대량의 객체를 효율적으로 다뤄. 인터프리터는 간단한 언어의 문법을 정의하고 해석하는 패턴이고, 중재자는 공항 관제탑처럼 객체들 사이의 상호작용을 캡슐화하는 중간자를 둬서 결합을 줄여. 메멘토는 게임 세이브처럼 캡슐화를 유지하면서 객체 상태를 저장하고 복원하고, 프로토타입은 기존 객체를 복제해서 새 객체를 만들고, 비지터는 accept(Visitor)와 더블 디스패치로 객체 구조를 건드리지 않고 새로운 연산을 추가해. 각 패턴에는 트레이드오프가 있어 — 중재자는 결합을 줄이지만 자체가 비대해질 수 있고, 비지터는 연산 추가는 쉽지만 새 요소 타입 추가는 어렵지. 이름과 한 줄 설명만 기억해둬도, 필요한 순간에 "아 그런 패턴이 있었지" 하고 찾아볼 수 있어.
정리
6장 읽고 기억할 거 세 가지:
- 패턴은 도구이지 목표가 아니야 — 가장 단순한 설계가 최선이야. 필요할 때 리팩토링으로 도입하고, 안티 패턴에 빠지지 않도록 경계하자.
- 패턴의 진짜 가치는 공유 어휘에 있어 — 패턴 이름 하나로 설계 의도를 팀 전체에 전달할 수 있어.
- GoF 23개 패턴의 존재를 알아두자 — 다 외울 필요 없지만, 이름과 한 줄 설명만 기억해도 필요한 순간에 찾아볼 수 있어.