디자인패턴

01.1.1 유래

패턴이란 사전적인 의미로 일정한 형태나 양식 또는 유형으로 반복이 되는 것을 말합니다. 이러한 반복되는 패턴의 원리를 공학적인 측면에서 개념을 도입한 것이 디자인 패턴의 시작입니다.

공학 분야에서 처음으로 패턴의 개념을 도입한 분야는 건축공학입니다. 대표적인 건축가 크리스토퍼 알렉산더(Christopher Alexander)는 패턴의 개념을 이용하여 반복적이고 복잡한 일들을 건축 공학에 적용하여 해결을 하기 시작을 하였습니다.

01.1.2 창발

패턴은 발명이 되는 것이 아니라 발견입니다. 처음 건축학에서 도입된 패턴도 발명이 아닌 발견에서부터 시작이 되었습니다.

실생활에서 어떠한 것을 발견을 하기 위해서는 수많은 관찰이 필요로 합니다. 지속적 관찰을 통하여 특정한 패턴을 발견하게 됩니다. 이러한 발견을 창발(energence)이라 합니다.

01.1.3 비슷한것

발견된 패턴들을 확인해 보면 서로 비슷한 부분이 많은 것을 알 수 있습니다. 발견된 패턴을 면밀하게 살펴보면, 특정한 문제를 해결해 나아가는 것이 유사하다는 것입니다.

패턴은 문제를 해결해 가는 과정을 일반화한 것이라 할 수 있습니다. 또한, 하나의 패턴이 또다른 패턴에 중복적으로 사용되는 것도 발견을 할 수 있습니다.

디자인 패턴을 구별하는 기준은 각각의 패턴이 어떠한 관심사를 가지고 문제를 해결할려고 하는 것인지 입니다. 패턴은 의도와 목적에 따라서 달라집니다. 적절한 패턴을 적용하기 위해서는 의도와 목적을 잘 파악하는 것이 중요하다.

01.2 소프트웨어 공학

이러한 패턴의 원리는 소프트웨어 공학 분야에도 도입이 되기 시작하였습니다. 소프트웨어적인 어떠한 문제를 코드로 구현을 할때, 해결하였던 방법들을 패턴화로 정리한 것 입니다.

01.2.1 객체지향

처음으로 소프트웨어 공학에 도입된 파트는 객체지향 개발 입니다. 객체지향 개발은 1980년대 오래전 부터 있었던 소프트웨어 개발 방법론 이었습니다.

최근들어 객체지향 코드를 작성할 수 있는 언어가 많아 지고 있습니다. 개체지향 언어의 종류로는 전형적인 SmallTalk, C++, Java 외에도 웹 개발언어인 PHP가 있습니다.

객체지향 기반으로 개발을 하면서 가장 어려운 부분은 각각의 코드들이 재사용이 가능한 형태의 코드로 작성하는 것입니다. 인터페이스, 상속, 객체의 관계를 정의하는 것입니다.

01.2.2 패턴 발견

객체지향은 큰 프로젝트의 개발과, 유지보수를 보다 쉽게 하기 위해서 도입된 개발 방법론입니다. 최근들어 프로그램들이 대형화, 분업화 되면서 절차지향적 개발방법론에서 객체지향 방법론으로 빠르게 이동을 하고 있습니다.

객체지향 개발 방법이 인기를 얻게 되면서 함께 디자인 패턴 또한 많은 각광을 받게 되었습니다. 소프트웨어 분야에서도 많은 프로그래머들이 특정 문제를 유사한 유형으로 해결을 하는 것을 발견 하였습니다.

소흘하게 여겨져 왔는 객체지향의 구현 문제점들을 해결하기 위해서 패턴을 도입하게 됩니다. 그리고 이러한 해결 과정들 속에서 발견된 방법들을 패턴화 하여 규정을 하게 됩니다. 패턴은 향후 발생되는 유사한 문제점들을 보다 쉽게 해결할 수 있게 되었습니다. 즉, 패턴은 해결 방법들을 재사용 하는 것입니다.

01.2.3 해결책

객체지향 개발에서 디자인패턴이 해결하는 주요 문제들은 객체간 관계와 소통을 처리하는 것입니다

디자인 패턴은 객체지향 프로그램 코드를 통하여 문제를 해결하기 위한 일련된 해결책들 입니다. 따라서, 디자인 패턴을 응용하기 위해서는 객체지향적인 코드를 작성이 가능한 프로그래밍 언어 이어야 합니다.

최신의 PHP 언어는 객체지향 코드 개발을 위한 다양한 OOP 기술들이 들어가 있습니다. 많은 최신의 PHP 웹프레임워크들은 객체지향, 디자인패턴들을 이용하여 개발되고 있는 추세 입니다.

01.3 설계원칙

디자인 패턴이외에도 객체지향 코드를 개발하면서 지키면 좋은 원칙들이 있습니다. 이 원칙들의 앞자리를 모아서 SOLID라고 불리우기도 합니다.

 높은 응집도와 낮은 결합도  단일 책임의 원칙  의존관계 역전의 원칙  인터페이스 분리의 원칙  리스코프 대체 원칙  개방 폐쇄 원칙

위의 원칙들은 객체지향 코드를 작성하는데 도움을 주지만, 너무 시스템을 고려하지 않는 원칙의 적용은 불필요한 일을 만들어 낼 수도 있습니다. 각각의 원칙들을 코드의 목적에 맞게 적제 적소에 적용을 하여 사용을 해야 한다는 것입니다.

01.4 GOF

디자인 패턴을 이야기하면서 자주 듣는 말이 GOF라는 단어 입니다. GOF는 처음으로 소프트웨어 공학에서 사용되는 패턴을 정리한 사람들의 별칭을 말합니다.

GOF는 에리히 감마(Erich Gamma), 리처드 헬름(Richard Helm), 랠프 존슨(Ralph Johnson), 존 브리사이즈(john Vissides) 의 저서를 말하는 용어 입니다.

01.4.1 패턴 카탈로드

디자인 패턴들은 갑자기 생겨난 방식들이 아닙니다. 우리는 모든 일상적인 개발 작업들 속에서 자연스럽게 이미 사용을 하고 있는 방식들 입니다. 어떻게 보면 새롭다고 생각이 들지도 않을 것입니다.

GOF는 객체지향 분야에서 가지고 있었던 문제점들을 분석하여 24개의 패턴으로 분류를 하였습니다. 기존의 문제점들을 카탈로그화 하여 패턴을 정리하였습니다.

카탈로그화된 패턴은 시스템의 유지보수 문서 작성을 할 때 매우 유용합니다. 또한 객체들의 상호 작용, 설계 의도등을 쉽게 확인할 수 있습니다.

01.4.2 통일성

협업을 통하여 대규모의 프로젝트를 진행할 때 중요한 요소는 통일된 개발방식의 공유 입니다. 서로 각자가 개발을 하는 방식이 차이가 있을 경우, 최종 결과물로 통합을 하는 과정이 쉽지 않습니다.

최근들어 PHP는 코드의 가독성을 향상하기 위해서 PSR 코딩 스타일을 정의하고 있습니다. 하지만, 코딩 스타일만으로서 통일화된 개발 진행을 하기에는 다소 부족합니다.

디자인 패턴은 개발의 방법을 정의함으로써 보다 통일화된 더 좋은 코드를 작성할 수 있습니다. 디자인 패턴은 개발자들이 자신의 코드를 작성하고, 다른 사람들과 소통을 하는데 좋은 코드 가이드 입니다.

01.4.3 실체화

실체화(reification)는 “실제로 만든다”의 의미 입니다. 또한 실체화가 구현(implementation)을 의미하는 것이 아닙니다. 실체화는 코드가 아니라 디자인을 말합니다.

구조만을 통하여 패턴을 파악하는 것은 불가능 합니다. 따라서 패턴을 파악하기 위해서는 의도를 알아야 한다. 어떤 문제를 해결하기 위해서 2개 이상의 패턴을 혼합하여 사용을 하는 경우가 많습니다.

01.5 패턴의 요소

24개로 분리된 디자인 패턴들은 공통된 4가지의 요소들을 가지고 있습니다.

01.5.1 이름 (Pattern Name)

24종류의 디자인 패턴들은 각각의 고유한 이름을 가지고 있습니다.

처음에는 패턴에 대한 이름이 정해지지 않았으나, 시간이 흘러 이를 정리하면서 각각의 패턴에 대한 이름들의 명칭이 생겨나게 되었습니다. 패턴의 고유한 이름명칭을 사용하는 것은 다양한 개발자들과 패턴을 응용한 소통을 하는데 매우 중요합니다.

패턴의 이름을 통하여 패턴의 용도를 직관적으로 이해를 하실 수 있습니다. 코드 패턴의 스타일 또는 해결하고자 하는 용도에 따라서 패턴의 이름을 정하고 있습니다.

패턴을 학습하다 보면 이름과 같이 연관되어 이해를 좀더 도울 수 있습니다.

01.5.2 문제 (Problem)

각 패턴은 해결하고자 하는 문제(Problem)를 가지고 있습니다. 그리고 이러한 문제점들은 패턴을 적용을 고려해야 되는 시점을 암시합니다.

코드에서 해결할 문제점들을 발견하고 그와 관련된 여러 배경들을 먼저 정리합니다. 그리고 이러한 문제점들을 해결할 수 있는 다양한 적용 사례들을 찾아 봅니다.

01.5.3 해법 (Solution)

문제점을 인식하였다면 해결을 합니다. 해결을 위해서 객체 요소들간의 관계를 미리 정리합니다.

문제를 해결하기 위해서 패턴들은 객체들을 추상화 하는 과정을 걸칩니다. 또한, 해결을 위한 객체들을 나열합니다.

01.5.4 결과 (Consequence)

24개의 디자인 패턴은 발견된 다양한 문제를 해결 할 수 있는 선배 개발자들의 지혜 입니다.

디자인 패턴은 알려진 여러 문제점들을 해결하는데 이로운 점들이 많이 있습니다. 하지만, 디자인 패턴을 적용한다고 해서 모든 문제를 완벽히 제거할 수는 없습니다.

모든 코드에서 디자인 패턴이 유용하다고 볼 수 는 없습니다. 좋아 지지도 않는 부분도 있습니다. 패턴은 매우 유용하나 꼭 필요한 경우를 생각하여 적절한 분배를 하여 사용해야 합니다.

01.6 유지보수

디자인패턴은 소프트웨어의 유지보수성을 개선합니다.

01.6.1 소프트웨어 수명

소프트웨어는 하드웨어와 달리 시간이 지날수록 부품이 닳거나 소모가 되지 않습니다. 한번 작성된 코드들은 시스템의 환경이 변하지 않는 기간동안에선 지속적으로 동작이 가능합니다. 하지만, 소프트웨어는 부품이 소모되는 것과 달리 기능이 추가되고, 코드의 수정이 많이 발생하게 됩니다.

디자인 패턴을 적용하여 설계를 하는 목적중 또 다른 하나는 유지보수성 입니다. 유지보수성은 향후 추가되는 코드를 수정하기 위해서 변경이 쉽도록 짜여진 코드를 말합니다. 소프트웨어의 유지보수기간은 서로 다르겠지만, 통상적으로 10년 정도로 말을 합니다.

01.6.2 방어적 설계

오랜기간동안 유지보수를 위해서는 변경이 가능한 디자인(design for change)으로 설계를 해야 합니다. 코드를 작성하면서, 향후에 수정이 가능할 것같이 예측이 되는 부분이라면 우리는 해당 기능을 방어적으로 처리가 가능하도록 코드를 설계를 해야 합니다.

방어적 설계를 위하여 소프트웨어는 지속적으로 코드를 개선해 나아가는 리펙토링 작업들을 하게 됩니다.

01.7 정리

코드를 개발할때는 유지보수성과 성능적인 부분들을 같이 감안하여 생각을 해야 합니다. 하나의 작업 코드를 지속적으로 보고 있을 경우에는 코드의 흐름을 빨리 파악을 할 수 있습니다.

하지만, 시간이 지나고 다른 사람들이 코드를 다시 보기 위해서는 이전의 코드들을 확인하는 학습시간이 필요합니다. 디자인 패턴에 익숙하여 코드를 작성을 한다면, 과거의 코드나 새로운 코드를 학습하는데 시간을 줄일 수 있습니다.

이러한 측면에서 디자인 패턴은 문제해결 방법외에도 개발 인건비용과 시간을 절약하는데 매우 유용합니다.

디자인 패턴과 처리성능은 별개의 문제입니다. 성능최적화를 위해서는 많은 함수의 호출과 객체간의 호출이 적을 수록 성능이 향상이 됩니다. 하지만, 코드의 가독성, 유지보수를 위하여 디자인 패턴에서는 객체의 메소드를 분리하고, 잦은 호출이 발생하게 됩니다. 너무 패턴을 남용하여 많이 사용하다 보면, 잦는 메소드의 호출로 인하여 성능이 저하될 수도 있습니다.

디자인 패턴을 적용하는 경우 얻게 되는 장단점등을 고려하여 적용을 하는 것이 중요합니다.