공부하는 블로그

#10 - 정말 큰 문제들 해결하기 본문

design patterns

#10 - 정말 큰 문제들 해결하기

devtimothy 2019. 4. 11. 20:11

본 블로깅은 Head first OOAD: 세상을 설계하는 객체지향 방법론 (한빛미디어) 책을 Typescript 문법으로 전환하며 공부하는 글입니다.
글을 읽기 전에, 광고 배너 한번씩만 클릭 부탁드립니다. 블로그 운영에 큰 보탬이 됩니다 :)

그동안 소프트웨어 디자인을 함께 공부했지만, 사실 실제 프로젝트는 5~10개 정도의 클래스로는 어림도 없다. 거대한 프로그램을 만드려면 어떻게 해야할까? 작은 문제를 풀어가는 방식과 마찬가지로, 큰 문제도 해결할 수 있다.

우리는 앞서 좋은 프로그램을 만드는 3단계를 배웠다. 이는 규모가 작건 적건 동일하게 적용된다.

  1. 나의 SW가 고객이 원하는 기능을 하게 하라
  2. 객체지향의 기본 원리를 적용해 SW를 유연하게 하라
  3. 유지보수와 재사용이 쉬운 디자인을 위해 노력하라

큰 문제를 어떻게 바라보는가

큰 문제를 바라보는 가장 좋은 시각은 여러 기능의 조각들로 나누어 보는 것이다. 각 조각들을 풀어야 할 개별 문제로 바라볼 수도 있고, 크기가 작은 개별 문제에는 이미 알고 있는 도구들을 적용할 수 있다.

사실 우리는 이미 소프트웨어 문제 해결에 중요한 여러가지를 배웠다.

  1. 변하는 것을 캡슐화하여 프로그램을 더 유연하고 변경하기 쉽게 만든다.
  2. 구현에 맞춰 코딩하기보다는 인터페이스에 맞춰 코딩하면 소프트웨어 확장이 더 쉬워진다.
  3. 좋은 요구 사항을 얻는 가장 좋은 방법은 시스템이 해야 하는 일을 이해하는 것이다.
  4. 좋은 소프트웨어는 변경과 확장이 쉽고 고객이 원하는 일을 한다.
  5. 분석은 시스템이 실세계에서 잘 동작하도록 만드는 데 도움이 된다.

게리 게임즈의 비전 기술서

게리 게임즈는 게임 디자이너들이 턴 기반 전략 보드게임을 만드는데 사용할 프레임웍을 제공한다. 아케이드 방식의 슈팅 게임이나 뛰어난 오디오, 비디오를 제공하는 게임과는 달리, 우리의 게임들은 전략과 전술에 관한 기술적 세부 내용에 중점을 두고 있습니다. 우리의 프레임웍은 게임 디자인에 필요한 반복적 코딩 작업을 없애고, 개별 게임을 쉽게 만드는 데 필요한 게임 관리 도구를 제공합니다.

게임 시스템 프레임웍은 게리 게임즈에서 만드는 모든 게임들의 핵심 모듈을 제공할 것입니다. 프레임웍은 회사 내의 게임 개발 프로젝트 팀들이 모두 사용할 수 있게 잘 정의된 API 형태의 라이브러리로 제공될 것입니다. 프레임웍이 제공할 기능은 다음과 같습니다.

  • 보드의 환경을 정의, 표현한다.
  • 부대를 정의하고 군대 또는 다른 전투 유닛들의 환경을 설정한다.
  • 보드에서 유닛들을 이동시킨다.
  • 유닛의 이동이 가능한 지를 판별한다.
  • 전투를 수행한다.
  • 유닛의 정보를 제공한다.

게임 시스템 프레임웍은 턴 기반 전략 보드게임의 개발 작업을 단순화하여 프레임웍 사용자들이 실제 게임의 내용을 구현하는 데에 노력과 시간을 들이도록 할 것입니다.


위의 비전 기술서를 보면서 가장 먼저 우리가 해야 할 일은 무엇일까? 요구사항과 유스케이스를 먼저 작성할까? 시스템이 해야 할 일을 알 수 있고, 리스트의 순서대로 기능을 하나씩 추가할 수 있어서 좋은 방법이다. 여러개의 작은 문제들을 해결해나가며 하나의 큰 문제를 해결하는 방법이다.

그러나 우리가 시스템에 대해 얼마나 알고 있을까? 고작 비전 기술서 하나뿐이다. 시스템이 해야할 일에 대해서는 우리가 기술서만으로는 알 수 없다.

시스템을 분석해보면서, 먼저는 공통점과 차이점을 분석해보도록 한다. (사실 나는 기술서를 보면서 처음에 코에이의 삼국지 영걸전 시리즈가 먼저 생각이 났다.)

고객과의 대화

고객과의 대화를 통해 알아낸 내용은 아래와 같다.

  • 고객은 Zork 라는 게임을 예로 들었다.
  • 고객은 그래픽 게임이 아닌 텍스트 기반 게임을 좋아한다. (대체 왜)
  • 남북전쟁, 1차 세계대전, 우주전쟁 등...
  • 다양한 시대적 배경, 유닛 타입, 유닛의 유니폼 등을 지원한다.
  • RISK, Stratego 라는 게임 (턴 기반 전쟁 게임)
  • 사각형 보드를 만들어 보드를 타일로 채운다.
  • 게임 디자이너는 몇 개의 타일을 사용할 지 선택할 수 있다.
  • 타일의 높이와 너비를 선택할 수 있다.
  • 지형 종류: 산맥, 강, 평야, 분화구, 소행성, 해초, 점토 등.
  • 유닛 이동 규칙 등의 고려사항 (무거운 것 들고 있으면 이동거리 짧아짐) -> 이는 게임 디자이너가 활용할 수 있게 함.

특징 찾아내기(feature)

위 내용에서 굵은 글씨로 적은 것들이 일종의 특징(feature)이다. 특징은 해야 할 일을 추상적으로 나타낸 것인데, 고객과 대화하며 시스템의 특징을 알아낸다. 대개 하나의 특징에 여러가지 요구 사항들이 나온다. 시스템 특징을 알아내는 것은 요구사항을 얻는 좋은 방법이다.

특히 규모가 큰 프로젝트의 경우 시스템의 특징부터 시작하는 것이 도움이 된다.

특징(feature)

  • 다양한 타입의 지형을 지원한다.
    • 요구 사항(개발자용)
      • 타일은 지형의 타입과 관련있다.
      • 게임 디자이너는 원하는 지형 타입을 만들 수 있다.
      • 각 지형은 유닛들의 움직임에 영향을 주는 특성이 있다.
  • 게임의 특성에 맞는 여러 타입의 부대들 또는 유닛들을 지원한다
  • 각 게임은 사각형의 타일들로 구성된 보드를 가지고 있고, 각 타일은 지형 타입을 가지고 있다.
  • 공상 과학 소설이나 판타지 소설에 등장하는 가상의 시대를 포함한 다양한 시대를 지원한다.
  • 새로운 작전 수행이나 전쟁 시나리오를 위한 추가 모듈을 지원한다.
  • 프레임웍은 누구의 차례인지에 대한 정보를 유지하고 유닛들의 기본적인 움직임을 관장한다.

특징과 요구 사항의 차이점에 얽매이지 말라.

feature와 requirement를 여러가지 의미로 사용하니 용어에 얽매이진 말자. (많은 사람들이 feature와 requirement를 구분하지 않는다.) feature는 requirement를 아우르는 큰 개념이라고 생각하자.

세부 내용은 늦출 수 있을 때까지 최대한 늦추라

유스케이스는 개발 시스템 전체의 큰 그림을 보는 데 도움이 되지 않는다. 처음부터 너무 자세한 것을 살펴보다가 큰 그림을 까먹게 된다. 아직 우리는 세세한 부분을 다룰 준비가 덜 되어 있다. 지금 시점에서는 프레임웍이 실제 무엇인지를 알아내는 단계이다. 유스케이스 작성을 할 수도 있겠지만, 이는 큰 그림을 그려볼 때 도움이 되지 않는 작업이다.

아직 우리는 여전히 시스템이 무엇을 해야하는지를 먼저 파악해야 한다. 세세한 부분은 피하며 시스템 전체의 큰 그림에 중점을 두자.

유스케이스 다이어그램

다이어그램은 자세하진 않지만 시스템이 할 모든 내용을 간단하고 읽기 쉽게 알려준다. 이는 우리가 큰 그림을 볼 수 있게 도와준다. 특징 리스트를 사용해서 유스케이스 다이어그램에 빠진 것이 없게 만들라.


  1. 액터: 액터는 시스템과 상호작용을 한다. 액터는 게임 디자이너이다.
  2. 시스템
    1. 새 게임 만들기
      • 프레임웍은 타일들로 구성된 보드를 제공하고, 타일은 지형 타입을 가지고 있다.
      • 프레임웍은 다양한 타입의 지형을 지원한다.
      • 프레임웍은 다양한 시대를 지원한다.
      • 프레임웍은 다양한 유닛 타입들을 지원한다.
      • 프레임웍은 추가 모듈을 지원한다.
    2. 기존 게임 변경하기
    3. 게임 배치하기

위에 기술했던 특징을 함께 연결지어 놓았는데, 한가지가 눈에 밟힌다. 프레임웍은 누구의 차례인지에 대한 정보를 유지하고 유닛들의 기본적인 움직임을 관장한다. 라는 내용인데, 이 특징은 어디에 연결지을수 있을까? 다이어그램에는 넣을 수 없을듯 하고, 유스케이스가 무언가 빠진 건 아닐까? 우리에게는 작은 액터가 하나 숨어 있다.


작은 액터

우리는 게임 프레임웍을 만들고 있다. 게임 디자이너가 게임을 만들게 하기 위해서이다. 게임 디자이너는 액터이며, 프레임웍을 이용해서 게임을 설계한다. 게임과 프레임웍은 같지 않다. 왜냐하면 게임은 완성본이고, 게임을 즐길 수 있다. 프레임웍은 게임을 만드는 기반을 제공한다.

프레임웍은 게임 디자이너를 위한 도구라고 볼 수 있을까? 그렇지만은 않다. 유스케이스 다이어그램을 그리다가 막힌 부분이 프레임웍이 각 게임에 대해 제공하는 서비스와 관련된 특징이다. 프레임웍은 게임의 일부이며, 게임의 기본 서비스 제공하는 하위레벨 모듈과 같은 것이다. 게임은 프레임웍 위에 올려져 있고, 실제 그것을 사용한다. 그렇다면… 게임은 액터이다!

리틀 리스퍼 형식의 문답을 하며 우리는 게임이 액터라는 사실을 추론했다.


  1. 게임 디자이너
    1. 시스템
      1. 새 게임 만들기
        • 프레임웍은 타일들로 구성된 보드를 제공하고, 타일은 지형 타입을 가지고 있다.
        • 프레임웍은 다양한 타입의 지형을 지원한다.
        • 프레임웍은 다양한 시대를 지원한다.
        • 프레임웍은 다양한 유닛 타입들을 지원한다.
        • 프레임웍은 추가 모듈을 지원한다.
      2. 기존 게임 변경하기
      3. 게임 배치하기
  2. 게임
    1. 시스템
      1. 보드 만들기
      2. 유닛 이동
        1. 프레임웍은 누구의 차례인지에 대한 정보를 유지하고 유닛들의 기본적인 움직임을 관장한다.
      3. 유닛 추가/삭제

위에서 보다시피 액터가 꼭 사람일 필요는 없다. 예전에 코드스피츠에서 강의 들을 때, 양놈들의 사고방식을 설명들으며 JS에게는 브라우저가 OS일 수 있고, 브라우저에게는 윈도우가 OS일 수도 있다는 설명을 들었는데… 비슷한 내용이 아닌가 싶다.

저 굵은 글씨로 써놓은 것이 이제 들어갈 곳을 찾았다. 그러나 여전히 찜찜하다. 누가 이동할 차례인지에 대한 정보 유지는 어쩌지? 다이어그램에 무언가 아직 빠져있는듯 하다.

자 그렇다면...


  1. 게임 디자이너
    1. 시스템
      1. 새 게임 만들기
        • 프레임웍은 타일들로 구성된 보드를 제공하고, 타일은 지형 타입을 가지고 있다.
        • 프레임웍은 다양한 타입의 지형을 지원한다.
        • 프레임웍은 다양한 시대를 지원한다.
        • 프레임웍은 다양한 유닛 타입들을 지원한다.
        • 프레임웍은 추가 모듈을 지원한다.
      2. 기존 게임 변경하기
      3. 게임 배치하기
  2. 게임
    1. 시스템
      1. 보드 만들기
      2. 유닛 이동
        1. 유닛들의 기본적인 움직임을 관장한다.
      3. 유닛 추가/삭제
      4. 차례 바꾸기
        1. 프레임웍은 누구의 차례인지에 대한 정보를 유지한다.

위와 같이 차례 바꾸기 유스 케이스를 추가하여 특징을 쪼갰다.

우리는 특징, 요구사항 리스트로 시스템이 해야 할 큰 일들을 알아내보았다. 유스케이스 다이어그램은 세부사항에 얽매이지 않고 우리가 만들 시스템을 나타낼 수 있게 도와주었다.

도메인 분석

이제 코드에 대한 이야기를 시작할 때가 되지는 않았나? 특징 리스트, 유스케이스 다이어그램 등을 만든다 하더라도 결국 코드가 구현이 되어야 하지 않는가? 고객은 우리가 이쯤되면 됐다 하고서 클래스가 어쩌고 하며 이야기를 하기 시작하면 당황하게 될 것이다. 그래서 도메인 분석이 필요하다. 고객이 이해할 수 있는 용어로 설명을 하는 것이다. 고객과 이야기 할 때는 클래스, 객체, 메소드가 아닌 유닛, 지형 타일에 대해 이야기하는 것이다.

도메인 분석을 통해서 디자인을 확인할 수 있고, 고객이 사용하는 용어를 사용할 수 있다.

도메인 분석은 기존 시스템과 개발 이력, 도메인 전문가들로부터 얻은 지식, 기반 이론, 그리고 도메인에서 새로 등장하는 기술을 기반으로 도메인 관련 정보를 찾아내고, 모으고, 구조화하고, 나타내는 프로세스이다.

특징

  • 시대적 배경: 다양한 지형, 유닛 타입, 무기
  • 타일: 기본 타일, 지형 타입, 유닛, 전쟁 지원
  • 지형 타입: 최소 하나의 지형 타입을 지원함. 들판, 호수, 행성 등
  • 유닛

크게 나누기

시스템의 특징들을 다루면서, 큰 문제를 여러개의 더 작고 관리하기 쉬운 기능의 조각들로 나눈다.

  • Units: 부대, 군대, 유닛 등
  • Board: 보드, 타일, 지형, 게임에서 사용될 실제 보드를 만드는 것과 이와 관련된 클래스를 가짐
  • Game: 모든 디자이너가 확장할 기본 클래스를 저장한다.
  • Utilities: 모듈간 공유하는 도구, 헬퍼 클래스들을 보관
  • Controller: 각 플레이어 순서, 기본 이동, 게임의 실제 흐름과 관련된 내용을 다룸

이게 다 정답이지는 않다. 각자 프로그램을 만들다보면 다를 수 있다.

누군가는 "이 게임 노잼인데? 그래픽도 별로고." 할수 있다. 그러나 우리의 고객은 게이머가 아니라 게임 디자이너임을 잊지말자.

디자인 패턴

우리가 나누어 본 것을 보면 MVC 패턴을 차용했음을 알 수 있다.

  • Model: Board, Units
  • View: Graphics
  • Controller: Controller
  • 기타: Game, Utilities

우리는 보통 이미 만들어진 라이브러리, 프레임웍을 이용한다. 라이브러리와 프레임웍은 컴포넌트를 찾아 연결하는 방식의 개발 모델이다. 그러나 우리 프로그램을 이해하기 쉽고, 유지보수와 유연성이 높은 방식으로 구조화하는데는 도움이 되지 않는다. 이럴 때 우리는 디자인 패턴을 이용한다.

디자인 패턴은 특정 문제를 위한 해결 방안을 디자인하는 방법이다. 디자인 패턴을 알고나면 새로운 디자인에 적용할 수 있고, 내 코드가 유연하지 않은 코드로 변질되어 갈 때도 디자인 패턴으로 다시 작업할 수 있다. 디자인 패턴을 잘 모르더라도 괜찮다. 이는 마지막 단계에 도움이 되기 때문이다.

요약

우리가 지금까지 한 내용을 살펴본다.

  • 특징들 수집
  • 도메인 분석
  • 시스템을 여러개의 모듈로 나누기
  • 시스템이 MVC 패턴을 이용한다는 것을 알기

크게는 이렇게 일을 했다.

  1. 우리는 고객의 말에 귀 기울여 들었다.
  2. 우리가 시스템을 이해하는지 확인했다. - 고객이 이해하는 용어로 설명할 수 있어야 한다.
  3. 우리가 만드는 시스템에 대한 청사진(설계도)를 그렸다. - 유스케이스 다이어그램을 사용했다.
  4. 큰 문제를 기능의 작은 조각들로 나누었다.
  5. 작은 문제들의 해결에 디자인 패턴을 적용한다.
Comments