디자인 패턴
“Context–Problem–Solution 구조로 반복되는 설계 문제의 검증된 해법.”
디자인 패턴이란
디자인 패턴(Design Pattern)은 소프트웨어 설계에서 반복적으로 나타나는 문제에 대해 검증된 해법을 일정한 형식으로 정리한 설계 지식의 묶음이다. 매번 새로운 상황처럼 보이는 설계 과제도 그 본질은 이미 여러 번 풀린 적이 있는 경우가 많으며, 패턴은 그 누적된 경험을 재사용 가능한 형태로 응축한다.
따라서 패턴은 코드 조각이 아니라 특정 맥락에서 통하는 구조와 협력 방식에 대한 합의에 가깝다. 잘 알려진 패턴을 공유하면 설계 의도를 짧은 이름으로 전달할 수 있어 의사소통의 비용이 크게 줄어든다.
Context와 Problem과 Solution
패턴의 기술 형식은 맥락(Context), 문제(Problem), 해법(Solution)의 세 축으로 구성된다. 맥락은 그 해법이 의미를 갖는 상황의 전제이고, 문제는 그 맥락에서 충돌하는 힘과 제약을 드러내며, 해법은 그 힘들을 균형 있게 풀어내는 구조를 제시한다.
이 세 축을 함께 읽어야 패턴을 올바르게 쓸 수 있는데, 맥락을 무시하고 해법만 가져오면 문제를 풀기는커녕 불필요한 복잡도를 더하기 때문이다. 즉 패턴의 핵심 정보는 해법 자체보다 그 해법이 언제 유효하고 언제 부적절한가에 대한 경계 조건에 있다.
좋은 패턴 설명은 적용의 결과로 따라오는 절충까지 함께 밝힌다.
패턴의 분류 관점
널리 쓰이는 분류는 객체와 클래스를 만드는 방식을 다루는 생성 패턴, 구조를 조립하는 방식을 다루는 구조 패턴, 객체 사이의 책임과 상호작용을 다루는 행위 패턴으로 나누는 방식이다. 이 구분은 패턴을 외우기 위한 것이 아니라, 지금 겪는 문제가 어느 영역의 문제인지 분간하는 사고의 틀을 제공한다.
생성에 관한 문제인지, 결합 구조에 관한 문제인지, 협력 흐름에 관한 문제인지를 먼저 식별하면 후보 패턴의 범위가 좁혀진다. 분류는 출발점일 뿐이며, 실제 선택은 맥락에 대한 판단으로 마무리된다.
| 축 | 의미 | 역할 |
|---|---|---|
| 맥락 | 유효한 상황 전제 | 적용 경계 판단 |
| 문제 | 충돌하는 힘과 제약 | 해결 대상 식별 |
| 해법 | 힘을 푸는 구조 | 절충까지 제시 |
MSA와 아키텍처 패턴
디자인 패턴의 사고는 객체 수준을 넘어 시스템 구조 수준으로도 확장된다. 마이크로서비스 아키텍처(MSA)를 둘러싼 서비스 분리, 데이터 일관성, 장애 격리 같은 과제 역시 반복되는 문제이며, 그에 대응하는 아키텍처 패턴들이 정리되어 있다.
규모가 커질수록 개별 클래스의 설계보다 서비스 경계와 통신 방식의 패턴이 시스템의 운명을 좌우한다. 다만 적용 단위가 커진 만큼 잘못된 패턴 선택의 비용도 커지므로, 작은 코드의 패턴보다 더 신중한 맥락 분석이 요구된다.
큰 구조의 패턴일수록 되돌리기 어렵다는 점을 전제로 다뤄야 한다.
리팩토링과의 접점
패턴은 처음부터 완성된 설계로 박아 넣는 대상이 아니라, 코드가 자라는 과정에서 리팩토링을 통해 자연스럽게 드러나는 경우가 많다. 중복과 결합이 쌓여 변경이 어려워진 지점을 개선하다 보면, 그 해법이 결국 알려진 패턴의 형태로 수렴하곤 한다.
이런 방향, 즉 문제가 확인된 뒤 패턴으로 옮겨가는 흐름은 검증된 적 없는 추측을 미리 구조화하는 것보다 안전하다. 따라서 패턴은 설계의 출발점인 동시에 리팩토링의 목적지가 되며, 두 활동은 서로를 보강한다.
변경의 필요가 분명해진 뒤 패턴을 도입하는 순서가 과설계를 막는다.
오용과 과설계의 경계
패턴의 가장 흔한 실패는 문제보다 해법이 앞서는 과설계다. 패턴을 안다는 이유로 단순한 요구에까지 일괄적으로 적용하면, 추상 계층만 늘어나 읽기 어렵고 바꾸기 어려운 구조가 만들어진다.
패턴은 복잡성을 없애는 도구가 아니라 불가피한 복잡성을 다루기 좋은 자리로 옮기는 도구이며, 없는 복잡성을 들여오는 명분이 되어서는 안 된다. 따라서 모든 패턴은 그것이 해결하는 문제가 실제로 존재할 때만 가치를 가진다.
패턴의 이름을 아는 것과 그 패턴을 써야 할 순간을 분간하는 것은 전혀 다른 역량이다.
관련 용어