책정리/GoF 디자인 패턴

PART 1. 소프트웨어 개발과 디자인 패턴

GONII 2015. 4. 3. 12:27

CHAPTER 1. 소프트웨어 개발과 WHAT-WHY-HOW 생각 모델

소프트웨어 개발

원하는 목적(Goal)을 달성하기 위해 기준이 되는 개념이나 철학(Paradigm)을 바탕으로 특정한 과정(Process)을 거쳐 소프트웨어적인 해결책(Solution)을 만들어내는 것

   

  • 소프트웨어 개발 개념 또는 철학

    크게 구조적(Structured), 객체지향적(Object Oriented)으로 나뉨

비교항목

구조적 (Structured)

객체지향적 (Object Oriented)

주요 관점

기능(Function 또는 Process) 위주

데이터(Data) 위주

접근 방법

하향식 (Top Down)

분할 정복 (Divide and Qonquer)

상향식 (Bottom Up)

상호 관계 정의

산출물 구조

트리(Tree) 구조

그래프나 네트워크 구조

장점

  • 처음부터 원하는 목적을 수행할 기능을 위주로 생각하믐로 해결책을 구하기가 쉽다.
  • 개발기간이 짧아질 수 있다. 특히 요구 사항을 잘 알고 있는 상태에서 시급히 개발이 필요할 경우 적합하다.
  • 개발된 해결책의 유지보수 및 재사용이 편리하다.
  • 요구 사항의 변화에 쉽게 대처할 수 있다.
  • 분석과 설계 단계에서 사용되는 모델이 동일하므로, 분석에서 설계로 전이가 편리하다.
  • 기존의 프로그램이나 상용 패키지를 상속(Inheritance)하여 재사용하는 것이 쉽다.
  • 설계를 강요한다.

단점

  • 요구 사항 변화에 취약하여, 이로 인해 유지, 보수, 관리가 힘들다.
  • 분석 결과로부터 설계로의 전이 과정이 매끄럽지 못하다.
  • 알고리즘이나 기능을 중심으로 한 접근 방법이기 때문에 잦은 변경이 불가피하고, 한 부분의 변경에 의해 영향 받는 범위를 구분짓기 힘들다.
  • 대형 시스템의 경우, 상속 구조나 객체간의 상호 작용이 너무 복잡해질 수 있으며, 다루어야 할 객체도 너무 많아질 수 있다.
  • 서브 시스템의 정의 방법이 아직 제대로 정립되지 않았다.
  • 아직까지 시스템 전반적인 기능이나 행위 분석 방법이 제안된 것이 거의 없고, 적절한 객체를 정의하는 것도 힘들다.

실세계와 개념적 대응 용이성

기능 위주이므로 실세계와의 개념적 대응이 힘들다.

객체를 통한 실세계와의 개념적 대응이 비교적 쉽다.

주요 응용 분야

계산이나 복잡한 알고리즘 중심의 응용 분야(과학기술, 실시간 시스템 등)

커뮤니케이션이 많은 분야 또는 시뮬레이션, 비즈니스 응용 분야

   

  • 소프트웨어 개발 과정

개발단계

주요 작업

주요 산출물

요구 사항 명세

  • 요구 사항의 정확한 이해 및 유도
  • 과다하거나 불필요한 요구 사항에 대한 협상 및 조율
  • 요구 사항의 적합성 검토 및 향후 예측
  • 전반적인 업무 흐름도
  • 요구 사항(상세) 기술서
  • 요구 사항 검토 의견서

요구 사항 분석

  • 요구 사항에 대한 체계적이고 구체적인 분석
  • 실제 실행 환경에 대한 분석
  • 기능, 행위, 데이터 측면의 요구 사항 분석 명세서
  • 실행 환경 분석 보고서

기본 설계

  • 시스템 아키텍쳐 설계
  • 데이터베이스 설계
  • 시스템 구성요소간 프로토콜 설계
  • 사용자 인터페이스 설계
  • 시스템 아키텍쳐 설계도
  • 데이터베이스 스키마
  • 프로토코 ㄹ설계도
  • UI 설계 결과물

상세 설계

  • 상세 자료구조 설계
  • 상세 알고리즘 설계
  • 자료구조 설계도(클래스 다이어그램)
  • 알고리즘 명세서(가상 코드 등)

구현

  • 구현 언어 및 개발 환경 선정

    EX) 운영체제, 표준 라이브러리 등

  • 프로그램 코딩
  • 프로그램 소스코드

테스팅

  • 단위 테스팅 : 단위 모듈 테스팅
  • 통합 모듈 테스팅 : 모듈간 통합 테스팅
  • 적합성 테스팅(Validation Testing) : 요구 사항과 일치성 여부 테스팅
  • 시스템 테스팅 : 시스템 복구 테스팅, 보안 테스팅, 스트레스 테스팅, 성능 테스팅
  • 테스트 계획서
  • 테스트 결과 보고서
  • 수정된 최종 소스코드

유지 보수

  • 추가, 수정 요구 사항 검토 및 반영
  • 장애 및 오류 발생 시 대처와 복구
  • 시스템 및 서비스 운영, 유지보수 보고
  • 역공학(Reverse Engineering)또는 재공학(Reengineering) 필요성 검토
  • 추가, 수정 요구 사항이 반영된 모든 개발 산출물
  • 각종 보고서
  • 역공학 또는 재공학을 위한 자료

개발 개념, 철학, 개발과정의 필요성

원하는 목적을 수행할 수 있는 수많은 해결책(Solution) 중에서 최적의 해결책(Optimal Solution)을 찾기 위함

   

  • 최적의 해결책

    왜 소프트웨어를 개발할 때 최적의 해결책을 지향하는가? 최소 비용, 최대 효율

    무엇보다도 최적의 해결책은 소프트웨어를 개발하려는 목적을 가장 잘 수행해줄 수 있기 때문이다. 여기서 소프트웨어를 개발하려는 목적은 표면적이고 추상적인 것이 아니라, 최대한 구체화 되고 세분화된 목적을 가리킨다.

    최적의 해결책을 지향하는 또 다른 이유는 구체적인 상황이나 환경에 맞추어 최소의 비용으로 최대의 효과를 보기 위해서다.

   

  • What - Why - How 생각 모델

    소프트웨어 개발

    추상화(Abstraction) 레벨을 구체화 시켜나가면서 무엇을(What) 어떻게(How) 할지를 반복해나가는 과정

    What-Why-How 생각 모델에서 강조하고 싶은 것은 무엇(What)이나 어떻게(How)보다도 왜(Why)에 해당하는 것이다. 즉, 무엇(What)을 해야 하는가도 중요하지만, 왜(Why) 그것을 해야 하는가가 더 중요하다는 것이며, 어떻게(How) 할 것인가도 중요하지만, 왜(Why) 그렇게 해야하는가가 더 중요하다는 의미다. 이때 '왜 그것을 해야 하는가'에 대한 검증 기준은 원하는 목적(Goal)이 무엇인가가 될 것이며, '왜 그렇게 해야 하는가'에 대한 검증 기준은 어떤 것이 최적(Optimization)의 방법인가가 될 것이다.

   

Chapter02 소프트웨어 설계 및 디자인 패턴

  • 소프트웨어 설계

    소프트웨어 개발 과정 중 설계(Design)는 원하는 소프트웨어를 어떻게 만들어낼지를 결정하는 작업이다. 기본 설계와 상세 설계로 다시 나뉠 수 있으며, 근본적으로는 '여러 가능한 방법 중 어느 하나를 선택'하는 '결정(Decision)'을 내리는 것이 설계라고 할 수 있다.

    여기서 결정이란 여러 가능성 중 하나를 선택한다는 것을 뜻한다.

  • 좋은 소프트웨어 설계의 특성

    어떤 소프트웨어 설계가 더 좋은것이냐 하는 것은 구체적인 목적이나 상황, 환경에 따라 달라질 수 있다. 그럼에도 전문가에 의하면 다음과 같은 특성을 갖추어야 좋은 소프트웨어 설계라고 말한다.

    • 이해 용이성(Understandability)

      전체 소프트웨어나 개별 구성 요소에 대해 쉽게 이해할 수 있어야 한다.

    • 수정 용이성(Modifiability 또는 Flexibility)

      요구 사항의 변경에 따른 수정이 용이해야 한다.

    • 관리 용이성(Maintainability)

      소프트웨어 유지, 보수, 관리 단계에서 버그 수정이나 장애 대처, 요구 사항 변경, 성능 향상 등의 이유로 소프트웨어를 수정해야 할 경우 이를 쉽게 수행할 수 있어야 한다.

    • 재사용 용이성(Reusability)

      개발된 소프트웨어 구성 요소들을 다른 소프트웨어를 개발할 때 쉽게 재사용 가능해야 한다.

    • 테스트 용이성(Testability)

      소프트웨어가 원하는 동작이나 기능을 수행하는지 테스트하기 쉬워야 한다.

    • 높은 안정성(Reliability)

      소프트웨어가 오류없이 원하는 작업을 수행할 수 있는 확률이 충분히 높아야 한다.

    이 밖에도 소프트웨어는 기본적으로 원하는 목적을 정확히 만족시켜야 하고(Correctness), 적은 자원을 사용해서 최대한의 성능을 발휘할 수 있도록 효율적(Efficiency)이어야 하며, 상호 운영성(Interoperability) 등도 뛰어나야 한다.

    소프트웨어 설계 과정은 What-Why-How 생각 모델에 따라 구체적인 목적이나 상황에 맞추어 위 특성들 중 가장 우선해야 할 것들을 선별하고 그에 따라 설계를 하는 것이 최적은 설계(Optimal Design)를 이끌어낼 수 있는 방법이라고 할 수 있다.

  • 좋은 소프트웨어를 설계하기 위한 도구

    좋은 소프트웨어를 설계하기 위한 대원칙은 What-Why-How 생각 모델에 따라 개발하려는 소프트웨어의 구체적인 목적이나 적용할 상황을 구체화하고 좋은 소프트웨어가 갖추어야 할 특성들 중 우선해야 할 특성들을 선별해서 이를 충족할 수 있게 설계해야 한다. 이러한 원칙을 기반으로 좋은 소프트웨어를 설계하기 위해서 다음과ㅏ 같은 도구들을 사용할 수 있다.

    추상화(Abstraction)와 구체화(Refinement)

    추상화란 구체적이고 복잡한 사실을 간략화시키는 것을 의미한다. 반대로 구체화란 구체적이고 상세한 사실을 계속해서 추가해나가는 것을 가리킨다. 이 두 가지는 What-Why-How 생각 모델에서 추상화 레벨로 표현된 것으로 서로 다른 방향을 가리키는 수직선이라고 볼 수 있다.

    좋은 소프트웨어를 설계하기 위해서는 여러 관점(Viewpoint)에서 소프트웨어를 설계할 필요가 있는데 이 때 특정 관점과 무관한 사실들을 간략화시켜 생각하는 것이 편리하다. 따라서 좋은 소프트웨어를 설계하기 위해서는 추상화와ㅏ 구체화를 적절히 적용할 필요가 있다.

    모듈화(Modularization)와 계층화(Hierarchy)

    모듈화란 소프트웨어를 모듈 단위로 분할(Decomposition)시키는 것을 의미한다. 좋은 소프트웨어를 설계하기 위해서는 소프트웨어를 모듈 단위로 분할해서 구분짓는 것이 좋은데 소프트웨어를 모듈 단위로 분리해서 다루는 것이 이해하기도 쉽고, 필요에 따라 재사용하거나 수정하기도 편리하다.

    이때 모듈간 상호 연관 관계가 너무 복잡해지면 소프트웨어는 이해하기 힘들어질 뿐만 아니라, 수정, 관리, 재사용하기 어려워진다. 따라서 모듈간 상호 연관 관계는 관리 가능한 형태로 구성하는 것이 바람직하다. 이런 목적을 달성하기 위해서 사용할 수 있는 도구로는 계층화가 있을 수 있다.

    계층화란 비슷한 목적의 모듈들을 같은 계층에 배치하고, 계층과 계층간의 트리와 유사한 형태로 사용 관계를 구성해주는 것을 의미한다.

    정보은닉(Information Hiding)과 변경의 국지화(Localization of Change)

    정보 은닉이란 소프트웨어 설계 시의 상세한 결정 사항을 모듈의 내부에 숨기고 외부에는 해당 모듈을 사용할 수 있는 인터페이스(Interface)만을 공개하는 것을 의미한다. 이 같은 정보 은닉의 목적은 모듈 내부의 결정 사항에 변동이 생겼을 경우 모듈 외부에서는 그에 따른 영향을 받지 않게 하기 위한 것이다.

    이처럼 소프트웨어 설계에 정보 은닉을 적용하게 되면 요구 사항의 추가나 변동에 따라 소프트웨어의 변경이 필요할 경우 그 수정 범위를 특정 모듈 내부로 한정시킬 수 있게 된다. 왜냐하면 요구 사항의 추가나 변동에 따라 영향을 받는 것은 인터페이스보다는 모듈 내부의 결정 사항들일 가능성이 크기 때문이다. 이와 같이 소프트웨어에 변경이 필요할 경우 그 수정 범위가 한정되도록 만들어 주는 것을 변경의 국지화라고 하는데 이를 통해 소프트웨어는 수정이나 관리 및 재사용 등이 쉬워지게 된다.

    실제 프로그램에서 여러 모듈을 수정해야 한다는 것은 그만큼 많은 프로그램을 다시 분석해서 적절히 수정해야 하는 것을 의미하고 이는 시간과 노력, 즉 비용이 필요하게 된다.

    방법론(Methodology, Method) 및 지침(Guildline)

    방법론이나 지침은 말 그대로 스프트웨어의 생성부터 소멸까지 전 과정에서 수행해야 하는 일처리 방법이나 절차 등을 정리해놓은 것을 가리킨다. 따라서 소프트웨어 설계 과정에서도 이런 방법론이나 지침은 유용하다. 특히 방법론이나 지침은 수많은 경험을 바탕으로 이를 일반화시켜 놓은 것이기 때문에 좋은 소프트웨어를 설계하고자 할 때 부족한 경험을 메꿀 수 있는 좋은 도구가 될 수 있다. 또한 정형화된 방법론이나 지침은 소프트웨어 개발을 표준화 시킬 수 있게 도와준다.

  • 디자인 패턴의 정의 및 유용성

    소프트웨어 설계에 있어서 경험만큼 확실한 것은 없으나 모든 사람들이 충분한 경험을 갖고 있지 않기 때문에 많은 경험을 가진 사람들의 지식과 노하우를 공유함으로써 부족한 경험을 채울 수 있다. 그렇다면 어떻게 소프트웨어 설계에 대한 지식과 노하우를 공유할 수 있을까???

    한 가지 방법은 소프트웨어 설계 방법론과 지침을 통한 공유다. 그러나 이런 접근은 일반화되어 있기 때문에 구체적인 문제에 적용하기 위해서는 또 다른 지식이나 노하우가 필요하기 때문에 한계가 있다.

    다른 한 가지 방법은 사례를 통한 공유다. 즉, 주어진 문제를 해결하기 위한 여러 가지 설계 사례를 분석해서 지식이나 노하우를 공유하는 접근 방법이다. 그러나 이 방법 또한 사례와는 전혀 다른 유형의 문제를 해결하기 위해서는 또 다른 노력이 필요할 것이다.

    그렇다면 너무 일반적이지도, 너무 구체적이지도 않은 형태로 소프트웨어 설계를 위한 지식이나 노하우를 공유할 수 있는 방법은 무엇일까??

    이를 위해 고안된 것이 [Design Patterns: Elements of Reusable Object-Oriented Software]라는 책에서 제시한 디자인 패턴이다. 이 책은 객체 지향 개념에 따른 설계들 중 재사용할 경우 유용한 설계들을 디자인 패턴으로 정립하였는데, 여기서 디자인 패턴이란 여러 가지 문제에 대하나 설계 사례를 분석해서 서로 비슷한 문제를 해결하기 위한 설계들을 분류하고, 각 문제 유형별로 가장 적합한 설계를 일반화시켜 패턴으로 정립한 것을 의미한다.

    사실 소프트웨어는 각기 다른 목적을 가지고 있고, 구체적인 적용 상황이나 환경에 따라서도 최적의 해결책이 달라지는 만큼 일정한 틀을 가진 패턴을 여러 소프트웨어 설계에 사용한다는 것은 이해가 되지 않는 부분이 있을 수 있다. 그러나 우리는 자주 비슷한 상황, 비슷한 문제를 경험하게 된다. 특히 주어진 상황이나 문제를 세분화시켜 분류해보면 놀랍게도 많은 문제들이 전에도 경험했던 것들임을 알 수 있다. 따라서 이미 여러 사람에 의해 검증된 디자인 패턴을 잘 이해하고 활용한다면 경험이 부족하더라도 충분히 좋은 소프트웨어를 설계할 수 있을 것이다.

  • 디자인 패턴 이해와 활용을 위한 이 책의 접근 방법

    디자인 패턴이 무엇(What)을 위한 것인지를 먼저 파악하고, 그것을 달성하기 위해서 어떤(How) 방식의 설계를 해야 하는지, 또 왜(Why) 그렇게 해야 하는지를 반복적으로 생각해 보는 방식을 통해 디자인 패턴에 대한 이해를 증진시키고 쉽게 활용할 수 있도록 한다.(주입식x, 스스로 문제를 파악하고 문제를 해결하기 위한 방법을 생각 해야함)

반응형