나도 확실한 개념을 정립하고 있진 못하지만 "Head First Design Patterns" 란 책을 통해 접하고 있다.
조금씩 패턴에 대해 알아가면서 아하! 하고 무릎을 탁치기도 하고 패턴을 적용해 보고 싶은 맘도 든다.
그리고 자바 API를 보면서 무슨 패턴을 적용한거군 하고 알게 되기도 하고 흥미롭다.
마소컬럼중에 아키텍처 패턴이야기가 있어서 퍼오게 되었다.^^
<출처: http://www.imaso.co.kr/?doc=bbs/gnuboard.php&bo_table=article&wr_id=33149 >
패턴을 대하기 이전의 마음가짐 - 유연성, 확장성
초창기 객체 지향(80년대)에서 가장 중요시 여기던 패러다임은 ‘Reuse(재사용)’이었다. 그래서 Component와 같은 이상적인 패러다임이 나오기도 했다. 마치 레고(Lego)와 같이 조립만 하면 만들어지는 레고웨어(Legoware)를 꿈꾸어 오면서…. 하지만 현재 소프트웨어는 어떠한가? 빈번하게 바뀌는 고객의 요구사항, 몇 명이서는 결코 만들 수 없을 만큼 거대해진 규모, 길어진 소프트웨어 생명주기를 가진 녀석들이 대부분이다. 그렇기 때문에 소프트웨어가 가져야 할 중요한 설계 방향으로 재사용성보다는 쉽게 변화를 수용할 수 있는 유연성(Flexibility)과 확장성(Extensibility)이 대두되었다. 만약 여러분이 유연성과 확장성에 초점을 맞춘 설계에 관심이 있다면, 패턴은 좋은 도구가 된다. 하지만, 최적화나 성능 개선이 목적이라면 패턴보다는 알고리즘을 공부하는 것이 더 낫다. 그리고 패턴을 쉽사리 적용하지 못하는 여러 가지 장벽들이 곳곳에 존재한다. 패턴에 대한 불신들이다. 지면상의 제약으로 이 모든 내용을 언급하기는 어려우므로, 예전에 필자가 마소 2007년 8월호에 기고한 ‘미워도 다시 보는 패턴 이야기’를 꼭 읽어보길 권한다. 이 글에서는 패턴의 정의, 원칙, 참고할 만한 설계구조도 설명하고 있다. 패턴은 올바른 아키텍팅을 하기 위한 전술
간략히 패턴에서 전술의 예를 든다면 분산 객체의 마샬링(marshaling) 정책을 들 수 있다. Loosely Coupling하게 마샬링하기 위해 프로토콜 기반의 설계를 사용함으로써 확정성이나 관리의 용이성을 획득하지만, 응답속도나 처리량을 포기해야 한다. 반면에 Tightly Coupling하게 마샬링하기 위해서는 Simple Object를 만들어서 사용하는 방법이 있는데, 시스템에 종속적이고 변화에 유연하지 못한 단점이 있는 반면에 응답속도나 처리량이 더 뛰어나다. 흔히 Web Service(전자인 경우 - SOAP에 의한 프로토콜 전송 방식)과 COM+(후자인 경우 - Simple Object)의 데이터를 주고받는 경우라고 할 수 있다. 만약 여러분이 패턴을 통해 이러한 전략을 습득하고 있다면, 아키텍팅을 수립하는 데 겪는 많은 시행착오를 줄일 수 있다. 패턴의 시작은 GoF부터? GoF 책은 1990년대 후반부에 쓰인 터라, 1990년 중반부에 사용되는 애플리케이션을 예로 들어 설명했고, C++의 이해를 수반으로 하고 있으므로 현재 우리가 관심을 가지고 있는 애플리케이션과는 약간 범위가 다르며 자바나 C#에 익숙한 초보 개발자에게는 난해할 수 있다. 그래서 2000년대에 이슈인 데이터베이스 프로그래밍과 같이 누구나 쉽게 이해할 수 있는 수준으로 설명한 책이 『Design Pattern Explained』였고 국내에서는 ‘알기 쉬운 디자인 패턴’이라고 번역되어 있다. 불과 4년 전 만해도 초보자를 위한 디자인 패턴 책은 이것밖에 없었다. 하지만 현재는 뇌공학을 연계로 해서 쉽게 개념을 파악할 수 있는 좋은 서적이 나왔다(『Head First Design Patterns』, 『알기 쉬운 디자인 패턴』 등). 다음 단계 서적으로는, 구체적으로 하나의 언어를 정해 언어별 특성을 파악하며 패턴을 살펴볼 필요가 있다. 여러분이 자바에 관심이 많다면 『Java 언어로 배우는 디자인 패턴 입문』을 추천하며 C++에 관심 있는 개발자라면 『GoF 디자인 패턴! 이렇게 활용한다』를 권하고 싶다. 그 이후에 GoF 서적을 보면 한결 수월하게 읽을 수 있을 것이다. GoF 패턴을 충분히 이해했지만, 프로그래밍에 바로 적용하는 사람은 그다지 많지 않을 것이다. 왜 그럴까? GoF 패턴은 패턴의 가장 기본인 Micro Pattern일 뿐이다. GoF 패턴은 단지 시작에 불과하다. 가족을 이루는 패턴 군을 파악하라
이 책을 탐독하면 자연스럽게 패턴 군(Compound Pattern)들이 눈에 보이게 된다(물론 GoF 패턴이 밑단에 전체적으로 깔려 있다). 즉 패턴 하나가 혼자 쓰이지 않고 같이 잘 엮여 사용되는 패턴들이 보이기 시작할 것이다. 바로 이러한 패턴 군을 많이 습득하는 것이 패턴을 습득하는 올바른 방법이다. 그럼 소프트웨어 기본 구조에서 볼 수 있는 간략한 사례를 들어 패턴 군을 설명해 본다. 소프트웨어는 <그림 1>처럼 크게 세 가지 요소로 구성되는데 각각 공용부, 가변부, 설정부이다. 공용부는 소프트웨어의 많은 Feature에서 공통적으로 사용하는 부분으로 log, transaction, security와 같은 모듈을 말하며, 요즘 Aspect와 같은 기술들로 구성하는 것이 추세다. 우리가 눈여겨봐야 할 것은 설정부와 가변부이다. 그럼 하나하나씩 살펴보자. Component Configurator Pattern
<리스트 1>과 <리스트 2>는 Component Configurator 패턴의 간단한 샘플이다. 설정 파일(<리스트 1>)의 프로토콜이 HTTP면 그 정보를 읽어 HTTP 프로토콜로 메시지를 전송하고 FTP 프로토콜로 설정되어 있다면 FTP 프로토콜로 메시지를 전송할 수 있다. 이렇게 함으로써 런타임시에 객체의 속성을 정의해 변화에 유연하게 대처할 수 있다. 하지만. 새로운 프로토콜이나 로깅 정책이 추가되어야 한다면 <리스트 2>의 코드도 변경될 수밖에 없다. 이러한 문제를 해결하기 위해 Component Configurator 패턴은 Reflection 패턴과 병행해 사용해야 한다. Reflection은 런타임시에 객체를 생성하는 패턴으로, 이미 닷넷(.NET)과 자바 플랫폼에서 지원하고 있다. 여기서 Component Configuration을 통해 객체 정보를 읽어와 생성하는 Factory를 만들면, 객체를 생성하는 클라이언트 입장에는 별 걱정 없이 객체를 생성할 수 있다. Template Method Pattern
<그림 1>을 다시 한 번 보도록 하자. 이제 전체적인 그림이 이해가 갈 것이다. 설정부에 객체의 속성을 Component Confi gurator를 통해 정의해 놓는다. 그 후 객체가 생성되는 시점에서 Factory가 현재의 상황을 고려해 적합한 객체를 선택한 후, 메모리에 로딩한다. 단 가변부에 있는 객체는 쉽게 교체할 수 있어야 하므로, Template Method나 Strategy와 같이 동일한 계약 상황(인터페이스를 구현하거나 Abstract를 상속하는 형태)을 유지해야 한다. 눈치 있는 독자는 이 구조를 어디서 많이 보았다고 생각할 것이다. 바로 스프링(Spring)과 같은 Dependency Injection Con tainer를 설명한 것이다. 좀 더 자세한 설명을 원한다면 필자의 블로그(종속성을 관리하는 방법 - http://arload.wordpress.co m/2008/12/07/dependency_managment/)를 방문하길 바란다. 아키텍팅의 핵심 SoC, 그리고 문제 중심으로 바라보기
여러 가지 측면들을 동시에 생각하기는 힘드니, 잘 나누어 각각의 요소에 한 가지 관점만을 적용해 바라보겠다는 의미다. 흔히 분할 후 정복(Divide and Conquer)과 일맥상통하는 말이라 할 수 있다. 다양한 이해 당사자의 요구, 프로젝트의 특수한 상황, 잘못 설계된 아키텍처로 인해, 하나가 바뀌면 연쇄적으로 다른 곳에 변화가 발생하는 파문 효과(Ripple Effect)를 종종 만나게 된다. 이때 우리가 특히 중점을 두어 관리해야 하는 것이 종속성(Dependency)인데, 이러한 종속성이 유발시키는 강결합을 무너뜨리는 좋은 가이드라인을 제시하는 것이 바로 패턴이다. SoC를 얼마나 잘하느냐가 아키텍팅의 성공과 실패를 결정하므로, 패턴 기반의 좋은 참조 아키텍처(Reference Architecture), 특히 패턴 기반으로 구축된 시스템을 평소에 틈틈이 공부할 필요가 있다. 그 이유는 패턴은 군을 이뤄 사용되기 때문이다. 특히 도메인에 한정될수록 사용되는 패턴 군들은 더 제한적이다. 어느 날 갑자기 여러분의 상사가, 모든 환경에서 좋은 성능을 보이는 웹 서버를 설계(SoC)하라고 한다면 어떻게 해야 될까? 먼저 비슷한 선례, 즉 참조할 만한 아키텍처가 있는지 찾아볼 것이다. 유명한 TAO/ACE의 창시자인 Douglas C. Schmidt 박사는 이에 대한 대답으로 주고받는 파일이 사이즈, 클라이언트의 다양한 요청 속성(예를 들면 요청 빈도, 요청시 얼마나 오랫동안 세션을 맺고 있는지 등), 고객의 웹사이트 접근 경로 등을 고려해 환경에 맞게 적절한 전략을 변경할 수 있는 웹서버 JAWS의 소스 코드와 아키텍처를 공유했다(필자의 JAWS 아키텍처 동영상 강의- http://www.devpia.com/net2/EvaCast/Lecture/ ?cu=view&r=11 참조). 이렇게 괜찮은 참조 아키텍처를 발견했다고 하더라도, 왜 이렇게 아키텍처가 구축되었는지에 대한 문제 상황의 깊은 이해가 요구된다. 어떤 부분에는 유연성을 중심으로 설계했고, 또 다른 부분은 유연성보다는 성능을 중심적으로 설계했다. 왜 이렇게 결정했을까? 결국 이렇게 구축한 시스템의 의도를 잘 파악하기 위해서는 패턴을 하나의 해결책으로 바라보는 것이 아니라, 패턴의 의도와 다루는 문제들을 중심적으로 바라볼 필요가 있다. 특히 아키텍처가 거대해질수록 이러한 접근법은 더 효율적이다. 현재 발표된 다양한 패턴 서적들을 소개하니 여러분의 프로젝트나 관심 분야 서적들을 골라 읽어보길 바란다. ● PLoPD 시리즈 ● POAD(Pattern Oriented Anaysis Design) ● Holub on Patterns(실전 코드로 배우는 실용주의 디자인 패턴) ● Remoting Patterns ● xUnit Test Patterns ● Patterns For Fault Tolerant Software(耐고장성 소프트웨어를 위한 패턴) ● PEAA(Patterns for Enterprise Application Architecture) ● Enterprise Integration Patterns ● Real-Time Design Patterns ● Refactoring to Patterns ● Architecting Enterprise Solutions 끝나지 않는 패턴 이야기-PLoP
관심 있는 독자는 지난 10년간 발표된 패턴들을 끊임없이 학습하길 권하며 이 글을 마친다. 그 이외에도 다양한 패턴 학회가 존재하지만, 언어적인 제약이나 자료 수집의 어려움 때문에 일부만 소개한다.
참고자료 |