본문 바로가기

Homo Design

시스템 설계를 바라보는 두가지 관점

시스템 구축시 설계(Design)를 바라보는 두가지 관점이 존재한다. 하나는 시스템의 청사진을 제시하고, 이를 통해 시스템의 전반적인 구조나 역학을 보기 위함이고, 다른 하나는 산출물로써의 관점이다. 전자의 관점은 시스템의 진화의 모습을 다양한 각도를 통해서 시스템의 내부 구성이 아키텍처의 원칙과 건전성을 유지하는지를 추상화가 높은 뷰에서 보는 시도로 동일한 뷰에서 작성된 설계도는 시간축의 흐름에 따라서 변경의 모습을 가지며, 시간의 흐름에 따라서 다양한 뷰가 추가되기도 한다. 하지만, 후자는 특정 시점(통상 감리나 중간 정산을 위한 시점)에서 한 스냅샷을 유지하는 것으로 이 시점의 문서는 해당 시점 이후의 고객이나 시스템을 운영하는 사람이나 개발하는 사람에게도 크게 도움이 되지 않을 수 있다. 즉, 산출물의 현행화의 관점에서 어떻게 시간의 흐름에 보조를 맞추는가가 제일 큰 이슈이다.

Torre Marenostrum - 1/4
Torre Marenostrum - 1/4 by . SantiMB . 저작자 표시비영리변경 금지


시스템의 청사진으로써의 설계
설계 내용에 어떠한 것들을 포함시킬지에 대한 합의는 사전에 필요하다. 하지만, 시스템을 알아가는 과정으로 설계를 하는 입장에서는 이러한 내용에 구태여 구속받을 필요는 없다. 산출물이라는 것을 통해 나타나는 내용들이 특별한 형식을 지향하는 반면에 청사진으로써의 설계의 형식은 지극히 자유로울 수 밖에 없으며, 이는 설계자가 선호하거나 작업하기 좋은 형태로 그 모습을 나타날 수 있다. 설계의 초반 시점에는 분석에서 식별된 각 요소를 정제화시켜서 명세를 확정하거나 세부화시키는 작업이 주로 발생되며, 특히 각 시스템과 모듈/컴포넌트의 책임성이 더 강화되도록 그 모습을 구체화시킨다.

따라서, 분석 단계와 설계 단계에서의 각 요소들의 추적성(traceability)을 어떻게 확보할 것인가를 제일 먼저 고민해야 한다. 통상 분석 산출물에서는 기능의 묶음 단위로 각 요소들이 정리가 되며, 그 기능의 묶음은 결국 서브시스템이나 모듈/컴포넌트로 매핑이 가능하다. (이를 가능하도록 설계 단계에서는 그 방법을 모색해야 한다.) 아키텍처 요소인 레이어나 내부 구조에 대한 특성들이 설계 시점에 추가되어서 표현될 수도 있겠지만, 되도록이면 시스템에 독립적인 (system independent) 모델을 설계에서 표현하도록 한다. 시스템에 독립적인 모델은 정도의 차이가 있는 용어로 UML에서는 클래스나 인터페이스 정도로 표현될 수 있다. 이를 시스템에 종속적인 모델을 가미한다면, 클래스는 자바와 같은 경우 .java 의 형태(POJO, EJB 등)로 나타날 수 있으며, 동일한 클래스라고 하더라도 용도에 따라서 EJB 인터페이스, 스프링 인터페이스, 웹 서비스 인터페이스 등의 다양한 형태로 시스템적인 요소가 가미될 수 있다. (이 경우, 주로 stereotype을 통해 표현하기도 한다.)

설계가 청사진으로써의 역할로 사용되려면 다양한 뷰에 따라서 의미있는 설계 결과를 나타낼 수 있어야 한다. 예를 들어, 컴포넌트 관점은 그 본연의 명세 내용이 포함되는 것은 당연하며, 주로 컴포넌트 간의 관계를 표현할 수 있는 내용이 포함되어야 한다. 최소한 해당 컴포넌트를 사용하는 또 다른 컴포넌트들, 그리고, 해당 컴포넌트가 사용하는 또 다른 컴포넌트들은 반드시 표현되어야 컴포넌트의 구조를 통해서 시스템의 구성을 고려해볼 수 있다.

특히, 설계 시점에서의 각 모델 요소들이 물리적인 구현 시점의 부착 요소로의 매핑이 반드시 1:1일 필요는 없다는 것이다. 즉, 설계에서의 요소들은 논리적인 관점에서 접근할 필요가 있으며, 구현 시점에서는 이러한 논리적인 요소들이 구현의 특징에 따라서 다양한 형태로 나뉠 수 있는 시스템 종속적인 요소로 변환하게 된다. 물론, 구현 모델로의 매핑을 위해 시스템 독립적인 요소로 모델링을 한 결과를 시스템 종속적인 요소로 변환하여 표현하는 것도 한 방식이겠지만, 여기서의 매핑은 특정 표기 형태로만 한정하면 그다지 많은 표현 형태로 표현되지 않아도 충분할 수 있다.

하지만, 이와 같은 청사진이 구태여 특정 형식의 문서화 양식을 통해서 공유될 당위성도 그다지 못느낀다. 물론, 커뮤니케이션과 DDD(Domain Driven Design)에서 말하는 Ubiquitous Language로의 활용 가치를 위해서 가시화의 형태로 표현될 필요는 있지만, 이에 대한 가시화가 설계의 세부사항을 표현할 정도의 문서화를 의미하지 않는다. 동일 조직이나 같은 팀 내에서의 설계 문서는 업계에서 통용되는 공통된 양식(UML과 같은)만 알고 있다고 하면, 설계 내용을 표현하는데 그 틀 안에서 얼마든지 자유롭게 기술하면 된다. 물론 산출물에서는 이를 비공식 문서라는 또 다른 공식화된 문서로 포장을 하긴 하지만, 강제적일 필요는 없다는 것이다. 이와 같은 강제성을 띠지 않는 이유 중에 하나는 이 시점에서의 설계는 주로 '설계 사상'이라는 표현으로 만들어가는 과정의 일부이기 때문이며, 이는 서로 다른 이해관계자들과의 소통으로 인해서 정해진 문서 양식을 통해서 전달되지 않기 때문이다. 또한, 자그마한 시스템의 경우 몇명의 설계자들끼리 공유하고 이해하는 정도로 대화가 이루어지기 때문에 설계 문서를 만들지 않고 교류하기 때문이다. 설계 문서를 만들지 않았다고 해서 청사진으로써의 시스템 설계가 존재하지 않는 것은 아니다. 실용적인 관점에서 소스 코드 안에 이러한 사상이 표현될 수 있기 때문이며, 추후 설계 문서는 여기서부터 추출이 가능할 것이다. (설계 사상을 소스 코드로 구현하는 경우 round trip을 경험하게 되는데 설계가 곧 소스 코드임을 잘 나타내는 사례는 얼마든지 많다. 이와 같이 설계와 구현을 동시에 경험하게 되면 구태여 설계와 소스 코드에 같이 표현할 내용 중에서 과감하게 설계에 표현한 내용을 생략하는 경우도 많다.)

설계를 공유하지 말라는 이야기는 결코 아니다. 설계에 대한 사상은 어떤 방식으로든 공유가 되며, 한목소리를 낼 수 있을 정도로 해당 팀 구성원들이 이해하고 있어야 한다. 하지만, 이러한 설계 사상이 고정된 문서나 고정된 가이드를 통해서 한번에 공유되기 힘들며, 설계자 또한 한번에 (BDUF, Big Design Up Front) 하늘에서 떨어지듯 완성된 모든 설계 요소를 정리하기란 힘들다. 통상 감리나 품질관리 측면에서 소스 코드를 바라보는 시각을 설계 문서와 동일시하거나 설계 문서가 나오고 소스 코드를 작성해야 한다는 절차상의 하자를 이야기하는 경우가 많다. 이러한 절차가 꼭 정답이 될 수도 없으며, 이러한 절차가 문제가 될 수 있다고 말할 수도 없다. 이 부분이 기존 건축과 소프트웨어를 바라보는 큰 차이이기도 하다. 눈에 보이는 건축은 사전에 청사진이 있어야 하며, 청사진을 만드는 동안 건물을 만들 수는 없다. 청사진에서 충분히 검토 과정을 거쳐서 실제 건물을 짓는 방식의 절차를 수행할 수 밖에 없다. 하지만, 소프트웨어는 얼마든지 청사진 없이(물론 설계자/구현자의 머리 속에서는 그 청사진이 있어야 한다)구현이 가능하며, 구현된 소프트웨어에 얼마든지 수정을 가할 수도 있고 심지어 없애고 다른 소프트웨어를 만들 수도 있다. 구현과 설계의 역행을 인정하지 못한다면 그리고 이를 절차상으로 표현하지 못한다면 소프트웨어 개발은 구현 시점에 또 다른 새로운 설계 문서를 만드는 노력을 다시 해야하는 과정을 거쳐야 한다.

청사진으로써의 설계라는 표현은 건물의 청사진을 떠올리기 때문에 그리 어울리는 표현이라고 보기는 힘들다. 한번 만들어진 청사진은 소프트웨어 입장에서 얼마든지 변경이 가능하고 그 형식이 다양할 수 있기 때문이다. 어느 책에서는 설계를 음악의 악보와 같다고도 표현하기도 한다. 악보를 만드는 과정은 실제로 작곡가가 머리에 표현된 내용을 악기로 구현하기도 하고, 다시 악보를 수정하는 과정을 거쳐서 완성되어 가는 과정이기 때문에 실제 소프트웨어가 완성되어 가는 과정과도 매우 흡사하다. 이러한 과정을 공정률이나 진척률로 표현하기에는 한계가 있다. 늘상 프로젝트에서 부딪히는 문제들은 이러한 설계와 구현 과정의 잘못된 인식으로 인해서 발생되기도 한다.

산출물로써의 설계
설계를 산출물로 바라볼 때 의미있다고 생각하는 부분은 바로 청사진으로써의 설계 중에 더 이상의 진화를 하지 않을 정도로 그 사상이 굳어진 형태라고 할 수 있다. 하지만, 이 시점은 프로젝트 초반이 될 수도 있고, 프로젝트 후반 이후도 될 수 있다. 문제는 산춤물로써의 설계에 이러한 사상이 어느 수준에서 어느 범위까지 표현될 것인가이다. 검수와 중간 정산으로써의 산출물에 대한 내용은 시스템의 특화된 내용보다는 다소 비즈니스의 정리된 관점이 가장 크다고 본다. 위에서 이야기했듯이 설계와 구현 과정을 딱 잘라서 수행하기란 힘들며, 프로젝트 후반까지도 중요한 (핵심이 되는) 설계에 대해서도 진행되지 못하는 경우도 많기 때문에 설계 단계를 나누어서 진행하는 프로젝트에서 산출물로써의 설계는 비즈니스의 구획화 정도에 만족해야 하지 않을까 생각이 든다. 비즈니스 구획화에 대한 내용은 비즈니스 프로세스에서 수행한 내용이 그 토대가 될 것이며, 그러한 비즈니스가 시스템으로 전환되는 과정에서 오류에 대한 범위를 줄이는 형태로 설계가 만들어져야 한다.

산출물이라는 단어가 말하듯이 특정 양식의 문서화 작업을 필요로 하며, 이를 어떻게 정리된 형태로 구성할 것인지가 가장 큰 결정사항이기도 하다. 특히 분석 과정의 다양한 양식의 문서들을 어떻게 설계의 문서로 추적할 것인지와 설계의 구성 요소를 어떠한 단위로 세분화할 것인지가 설계 단계에서의 큰 고민거리이기도 하다. 우선은 설계의 가장 기본적인 단위를 컴포넌트로 표현하는 형태가 가장 합리적일 것이다. 패키지나 클래스 단위로 내려가면 너무나 많은 클래스와 인터페이스가 섞여서 여러 사람이 작업하기에도 상당히 어려운 점들이 있다. 특히 산출물의 종류 중에 클래스 정의서나 클래스 다이어그램을 포함하는 경우에 (컴포넌트 명세가 클래스 다이어그램으로 표현이 되긴 하지만, 산출물의 명칭을 클래스 다이어그램과 같이 정하는 것은 그리 적합하지 않다고 본다) 아무도 보지 않는 문서를 만들고 필요없는 종이를 낭비하는 결과를 가져온다.

컴포넌트가 하나의 단위가 될 경우에는 그 컴포넌트 문서에는 다양한 내용을 포함시킬 수가 있으며, 서로 다른 컴포넌트에서 성격에 따라 다른 제목의 산출물이 만들어질 수 있다. 특히, 자원이나 외부 시스템을 연결하는 컴포넌트의 경우 타 컴포넌트와 달리 자원과 외부 시스템과의 관계나 이들과의 인터페이스를 좀 더 상세하게 표현할 수 있다. 컴포넌트의 설계 내용에는 크게 명세, 의존관계, 내부설계로 나누어볼 수 있으며, 명세는 인터페이스 singnature와 책임(responsibility)과 의무(obiligation)는 되도록이면 상세하게 표현해야 한다. 명세에 어떠한 내용이 표현되어야 하는지에 대한 이론이나 문서들은 많이 있으며, 시스템 개발 수준에서 이러한 내용들을 어떻게 표현할지에 대해서는 되도록이면 다양한 경우를 같이 공유하여 일치되도록 하는 것이 좋다. 하지만, 명세에 너무 이상적인 모습만을 표현하고자 한다면 실제 구현시에 이를 실현하기에 너무나 뜬 구름같은 내용이 표현될 수도 있다. 명세 내용을 어떠한 것으로 채울 것인지에 대해서는 한번쯤은 JCP나 SUN에서 배포하는 API 명세서를 보는 것도 도움이 될 것이다.

컴포넌트를 중심으로 시스템을 구성하는 경우, 의존관계는 관리해야 할 가장 중요한 정보이다. 따라서, 제공(provided) 인터페이스와 필요(required) 인터페이스를 어떠한 방식으로든 컴포넌트 별로 표현되어야 한다. 컴포넌트 의존관계는 정적인 모델을 통해서 식별되지 않으며, 동적인 모델을 완성하면서 그 의존관계가 식별된다. 동적인 모델은 결국 비즈니스의 흐름을 다양한 용례(usage)를 통해서 분석할 수 밖에 없으며, 이는 유스케이스를 설계 단계에서도 활용할 수 밖에 없다는 것이다. 즉, 기존 유스케이스가 인터페이스/컴포넌트 식별을 위해 사용되었다면, 이제는 이 유스케이스를 각각의 특별한 경우로 구체화시켜서(인스턴스화) 컴포넌트의 인터페이스의 관계를 구체화시켜야 한다. 예를 들어, 버스카드를 통해서 결제가 되는 시스템의 경우, 초반에 식별된 인터페이스는 버스비를 결제할 수 있는 카드의 추상화된 요소로부터 시스템으로 커뮤니케이션하는 내용을 통해 인터페이스를 식별했다면, 설계 단계에서는 이 유스케이스를 구체화시켜서 버스카드, 신용카드 등으로 세분화시켜서 인터페이스를 상세화시켜야 한다. 이 과정에서 초기 식별된 인터페이스를 그대로 사용할 것인지 혹은 각 카드 종류별로 세분화시켜서 인터페이스를 분할할 것인지에 따라서 시스템이 제공하는 서비스의 품질(Granularity of Service)이 달라지게 된다. 즉, 일반화된/공통화된 인터페이스를 설계 단계에서 사용하도록 만들었다면 해당 서비스는 상당히 많은 정보를 (혹은 선택적인 정보를 주고 받을 수 있는 형태로 정보 구조가 복잡해지고 많아질 수 있음) 주고받는 인터페이스가 만들어질 것이며, 이와 의존관계를 맺는 컴포넌트들도 상당히 많아질 수 있다. 이러한 시스템의 경우, 범용적이며 모든 것을 통합할 수 있는 성질을 가지겠지만, 특정 상황에서는 (예를 들어, 학생을 대상으로 하는 스쿨버스의 경우 학생카드만을 인식함) 불필요한 컴포넌트를 포함해야 하는 경우가 발생할 수도 있다. 즉, 얼마만큼의 구체화된 비즈니스 용례를 찾을 것인가가 컴포넌트의 품질을 좌우할 수 있다. 물론, 해당 도메인을 잘 아는 경우에는 기존의 경험으로도 충분히 설계 문서를 만들어낼 수도 있겠지만, 지금의 비즈니스는 하루가 다르게 변화하기 때문에 이러한 변화를 설계에서 역시 고려할 필요가 있다.

컴포넌트의 내부설계의 경우, 정적과 동적으로 구분하여 표현할 수 있으며, 그 안에 포함되는 내용은 컴포넌트의 성격이나 유형에 따라서 다양할 수 있다. 또한, 이 부분의 설계는 위에서 말한 설계와 구현의 round trip의 과정을 거쳐서 완성되어 가는 부분이기 때문에 산출물 형태로 표현되는 시점에서는 이 부분이 미처 완성되지 못한 경우도 있을 것이다. 내부설계를 독립적으로 표현하는 이유는 컴포넌트의 외형과의 분리를 통해서 비즈니스 로직을 캡슐화하는 장점도 있다. 설계 산출물을 제출할 당시의 컴포넌트가 충분히 내부 설계가 작성되지 않았다고 한다면 해당 컴포넌트에 관련된 다양한 문서를 그 안에서 포함시킬 수도 있다.

이와는 별도로 전체 컴포넌트를 하나의 통합된 형태로 보여줄 수 있다면 산출물로써 크게 손색이 없을 것이다. 다만, 산출물로써의 설계는 그 용도가 가장 크게 작용하기 때문에 용도에서 벗어나거나 그 의도에 못미치는 문서를 작업해서는 안된다. 산출물이 청사진으로써의 설계로 사용되는 것이 가장 바람직한 형태이겠지만, 프로젝트의 내부 방식이나 정책에 따라서 이를 보는 관점이 달라질 수 있으며, 후에 운영하는 사람들과의 수준을 고려해서 산출물의 수준을 적절히 조정할 필요는 있다.

소프트웨어 설계의 중요성에 대해서는 누구나가 알고 있고 늘 강조하고는 있지만, 제대로된 설계를 수행했거나 하고 있다라고 자신있게 말할 수 있는 조직은 찾아보기 힘들다. 늘 시스템에 문제가 생기는 경우에는 제대로된 설계가 없기 때문이라는 내용이 관용어구처럼 등장한다. 설계는 가이드나 템플릿을 통해서 만들어지는 것이 아니라, 구현과의 검증과 설계자의 사상이라는 두가지 요소로 완성되기 때문에 시스템이 진화하는 동안 같이 진화되어야 한다. 설계 단계는 시작 시점은 있지만, 종료 시점은 없는 단계라고도 볼 수 있다. 
반응형