주의: 패턴 중독

패턴을 과도하게 도입하지 않도록 주의하자

프로젝트 전반에 걸쳐 불필요하게 패턴으로 도배하는 것은 엔지니어링 관점에서 도가 지나친 것입니다. 디자인 패턴들은 마술이 아니며, 솔루션이 좋은 디자인이라고 자동적으로 보장해 주지도 않습니다. 디자인 패턴들은 단지 되풀이되는 문제들에 대한 재사용 가능한 솔루션들입니다. 다른 사람들이 그것을 발견하고 문서화해옴으로써 우리가 이미 발명된 바퀴를 찾고 있음을 깨닫게 해줍니다. 문제가 발생할 때 이러한 솔루션으로 해결될 수 있는 문제를 가려내고, 디자인 패턴을 적절하게 적용하는 것이 우리가 할 일입니다. 디자인 패턴에 대한 지식을 과시하려는 여러분의 욕구가 실용주의적인 시각을 가리지 않도록 하십시오. 여러분의 시야를 효과적인 비즈니스 솔루션을 제공하는 시스템을 설계하는 데 초점을 맞추고, 패턴은 각 패턴이 언급하는 문제를 해결하는 데 사용하십시오.

– 소프트웨어 아키텍트가 알아야 할 97가지. 110쪽.

숙련자라도 패턴중독에 빠질 수 있다

패턴 중독의 폐해는 초보 프로그래머에만 국한된 것이 아니다. 중급 또는 고급 프로그래머 역시 패턴 중독으로부터 자유롭지 못하고, 세련된 패턴 책이나 글을 본 후라면 더욱 그렇다. 예를 들어 내가 개발을 돕던 시스템에서 Closure 패턴을 구현한 코드를 발견한 적이 있었는데, 나중에 알고 보니 그 프로젝트의 어느 프로그래머가 얼마 전에 어떤 위키 페이지1에서 Closure 패턴을 보고 배웠다는 것이었다.

코드를 살펴봤지만 Closure 패턴의 사용을 정당화할 만한 이유를 찾을 수가 없었다. Closure 패턴은 불필요했다. 따라서 나는 리팩터링을 통해 Closure 패턴을 제거하고, 그 자리를 보다 단순한 코드로 대체했다. 작업을 끝낸 후 그 팀의 프로그래머들에게 새로 바꾼 코드가 Closure를 사용하는 것보다 단순하다고 생각하지 않느냐 물었다. 그들은 코드가 더 단순해졌다고 대답했다. 결국 그 코드의 작성자도 리팩터링된 코드가 더 단순하다는 것을 인정했다.

패턴을 배우는 과정에서 패턴 중독을 피하기는 아마 거의 불가능할 것이다. 사실 우리는 대부분 실수를 통해 배운다. 나역시 여러 경우에서 패턴 중독에 빠져 있었다.

패턴의 진정한 성과는 패턴을 현명하게 사용할 때 나타난다. 리팩터링은 중복을 제거하고, 코드를 단순화하고, 코드가 그 의도를 잘 드러내도록 하는 데에 우리의 주의를 집중하도록 함으로써, 패턴을 현명하게 사용하도록 도와준다. 리팩터링을 통해 점진적으로 패턴을 도입하면, 패턴으로 인한 과도한 설계가 발생할 기회도 줄어든다. 그리고 리팩터링을 더 잘 이해할수록 패턴이 주는 즐거움을 이해할 확률도 높아진다.

– 패턴을 활용한 리팩터링. 3장. 60쪽.

패턴을 구현하는 방법은 다양하다

요점은, 하나의 패턴도 여러 가지 방법으로 구현할 수 있다는 것이다.

불행히도, 프로그래머들은 [Design Patterns]의 각 패턴에 제시된 구조 다이어그램만을 보고 그것이 해당 패턴을 구현하는 유일한 방법이라는 결론을 내려버리는 경우가 종종 있다. 프로그래머들이 구현 노트를 주의 깊게 읽었더라면, 그러지 않을 것이다. 그러나 많은 프로그래머들이 [Design Patterns]를 펼쳐 구조 다이어그램을 확인한 다음, 바로 코딩을 시작한다. 그 결과로 나온 코드는 당장의 필요에 가장 잘 맞는 패턴 구현이 아니라, 구조 다이어그램을 그대로 구현한 것일 뿐이다.

[Design Patterns]가 출간된 지 몇 년 후, 공동 저자 중 한 명인 John Vlissides는 다음과 같은 글을 썼다.

패턴의 구조 다이어그램은 명세가 아니라 단지 예제일 뿐이라는 것은 아무리 강조해도 지나치지 않을 것 같다. 구조 다이어그램은 우리가 가장 자주 본 구현을 나타낼 뿐이다. 이런 구조 다이어그램이 자기 자신의 구현과 많은 공통점이 있을 수도 있겠지만, 차이가 생기는 것은 피할 수 없고, 사실은 차이가 있는 것이 바람직하다고까지 할 수 있다. 최소한 구성 요소의 이름은 자신의 도메인에 맞게 바꿀 것이다. 구현상의 트레이드오프trade-off는 경우에 따라 다르고, 자신의 구현은 구조 다이어그램과 상당히 다르게 보일 수 있다.

– 패턴을 활용한 리팩터링. 3장. 63쪽.

From: 크리스토퍼 알렉산더

'디자인 방법론'에 있어 학문 분야는 성장하였다. 필자는 디자인 방법론이라 부르는 분야에서 대표주자 중 한 사람으로 언급되기에 이르렀다. 이러한 사실에 유감을 표한다. 그리고 학문의 주제로 디자인 방법론의 전체 사고에 대해 거부하고자 한다. 디자인의 실체에서 디자인을 하는 방법을 분리하는 것은 어리석다고 필자는 생각하기 때문이다. 실제로 디자인의 실체를 경험하지 않고 디자인 방법론을 배우는 사람은 디자이너에 대해 잘못된 생각을 가질 것이다. 실제 형태로 나타날 디자인을 갖지 못하게 될 가능성이 높아지는 것이다(Alexander 1971).

– 뷰티풀 아키텍처. 14장. 497쪽.

From: 임백준

패턴을 다루는 책이나 웹사이트는 많다. 그리고 그들 사이에 존재하는 하나의 공통점은 패턴을 마치 상품의 목록을 연상시키는 카탈로그(catalog)의 형태로 제공한다는 점이다. 그와 같은 카탈로그가 프로그래머들을 자주 잘못된 '학습패턴'으로 몰고 갔다는 사실은 흥미롭다. 프로그래밍에서 '패턴'은 여러 프로그램에서 반복적으로 나타나는 문제를 해결하기 위한 공통의 방법을 찾으려는 노력에서 탄생했다. 따라서 패턴을 공부하는데 있어서 중요한 것은 패턴 자체가 아니라 프로그래밍에서 반복적으로 나타나는 문제의 유형을 정확하게 이해하려고 노력하는 것이다.

그런데 프로그래머 중에서 많은 사람이 패턴을 공부하는 것을 문제의 본질을 이해하는 것이 아니라 카탈로그를 암기하는 것으로 착각한다. 그런 사람들은 "그러니까 브리지(bridge) 패턴이 구조적 패턴일까 아니면 행위 패턴일까"라는 식의 쓸모없는 질문을 지적(知的)인 프로그래밍 문제로 착각한다. 새 프로그래머를 채용하기 위한 인터뷰를 하다보면 패턴에 대한 질문을 받았을 때 생성 패턴, 구조 패턴, 행위 패턴 등의 카탈로그 목록을 앵무새처럼 외우는 사람들을 자주 만나게 된다. 솔직히 필자는 그런 사람들을 신뢰하기 어려웠다. 중요한 것은 주어진 상황이 맞닥뜨린 문제를 구체적으로 이해하려는 노력이지 카탈로그를 외우는지 여부가 아니기 때문이다.

– 소프트웨어 산책. 49쪽.

패턴과 이디엄

패턴에 대해 본격적으로 살펴보기에 앞서 패턴(pattern)과 이디엄(idiom)을 비교해 보기로 하자. 디자인 패턴을 매우 일상적으로 사용하게 되면 이는 패턴이 아니라 이디엄이다. 이런 상황에서는 패턴이 특별한 무엇이 아닌 '이미 그렇게 되어 있는 것'일 뿐이다. 어떤 사람들은 패턴은 정형적인 방식으로 표현되어 있는 반면 이디엄은 그렇지 않다는 식으로 패턴과 이디엄을 구분하기도 하지만, 나는 이와 같은 정의를 따르지 않는다. 이디엄은 일상적으로 사용하게 된 패턴이다.
상속은 패턴이 이디엄으로 진화해 간 훌륭한 예이다. 1980년대 초 C 언어가 왕이었을 무렵 상속은 하나의 디자인 패턴이었다. 실제 C에서 'extends' 관계를 사용하는 여러 예들을 볼 수 잇다. 구체적인 예를 하나 들자면 malloc()의 표준 구현은 헤더(부모 클래스)를 사용하는데, 이 헤더는 확장(extends)되어 새로운 구조체(자식 클래스)를 생성할 수 있고, 자식 클래스는 부모 클래스의 free() 메소드를 상속하게 된다.

추상 함수 역시 상속 패턴의 일부였다. C에서 다른 목적을 위해 다르게 초기화된 함수 포인터의 테이블을 넘기는 것은 흔한 일이었다. 그리고 이는 C++가 abstract 메소드와 인터페이스 상속을 구현하는 방식과 같지만 C 세계에서는 이를 지칭하는 이름이 없었다.
상속은 C 언어에 내장되어 있지 않았으며, 대부분의 C 프로그래머들은 상속을 이용하여 프로그래밍하지 않았다. 그러므로 상속은 프로그래밍 이디엄이 아닌 패턴이었다. C에서의 상속은 비슷한 류의 문제를 해결할 때 많은 프로그램에서 발견되는 방법이었지만, 초중급 수준의 C 프로그래머들이 이용하는 방법은 아니었다. 요즘은 상속과 인터페이스 같은 기능이 많은 언어에 내장되어 있다. 이들은 이디엄이 된 것이다.

– 실전 코드로 배우는 실용주의 디자인 패턴. 22쪽.

이디엄

이디엄(idiom)은 특정 프로그래밍 언어에만 국한된 하위 레벨 패턴(low-level pattern)이다. 이디엄은 주어진 언어의 기능을 사용해서 컴포넌트들 혹은 컴포넌트들 간 관계의 특정 측면을 구현하는 방법을 서술한다.

– 패턴 지향 소프트웨어 아키텍처 1. 1장. 15쪽.

4인방(the Gang of Four)의 책 『Design Patterns(Addison-Wesley, 1994)』에 나와 있는 것 같은 디자인 패턴이 실제로는 존재하지 않는다는 논쟁은 일리가 있죠. 4인방 책의 23번, 26번 패턴이 있다고요? 대부분은 C++의 한계 때문에 생긴 것들입니다.

– 세상을 뒤흔든 프로그래머들의 비밀. 인터뷰 11, 앤디 헌트.

참고문헌

  • 뷰티풀 아키텍처 / 디오미디스 스피넬리스, 지오지아스 고시아스 엮음 / 황재선 옮김 / 지앤선(志&嬋) / 발행: 2010년 03월 8일
  • 세상을 뒤흔든 프로그래머들의 비밀 / 에드 번즈 저 / 김도균 역 / 정보문화사 / 초판 1쇄 발행: 2010년 02월 19일 / 원제: Secrets of the Rock Star Programmers: Riding the IT Crest
  • 소프트웨어 아키텍트가 알아야 할 97가지 / Richard Monson-Haefel 저 / Eva Study 역 / 지앤선(志&嬋) / 2011년 04월 14일 / 원제 : 97 Things Every Software Architect Should Know
  • 실전 코드로 배우는 실용주의 디자인 패턴 / Allen Holub 저 / 송치형 편역 / 지앤선(志&嬋) / 2006년 07월 19일 발행 / 원제 : Holub on Patterns : Learning Design Patterns by Looking at Code
  • 임백준의 소프트웨어 산책 / 임백준 저 / 한빛미디어 / 초판발행: 2005년 05월 30일
  • 패턴 지향 소프트웨어 아키텍처 1 / Frank Buschmann 외 / 김지선 역 / 지앤선(志&嬋) / 발행 2008년 01월 18일
  • 패턴을 활용한 리팩터링 / 조슈아 케리에브스키 저 / 윤성준, 조상민 공역 / 인사이트(insight) / 신판 1쇄 발행 2011년 02월 09일 / 원제 : REFACTORING TO PATTERNS

주석