인터페이스 설계에서 오퍼레이션은 그 나름대로 책임을 가지게 된다. 즉, 해당 오퍼레이션을 호출하기 위해 입력받는 정보에 대해서는 호출하는 측(이하 클라이언트)에서 그 데이터가 올바로 들어갔는지를 점검할 책임이 있으며, 입력된 정보를 가지고 출력 정보를 형성하는 측(이하 서버)에서는 반환 정보에 대해서 올바른 값이 들어갔는지를 점검할 책임이 있다. 다시 말해서, 오퍼레이션은 사전 조건(precondition)과 사후 조건(postcondition)에 만족한 상태가 되어야 클라이언트와 서버가 원활하게 정보를 주고 받을 수 있다.


이와 같은 책임성에 기반해서 설계하는 방식을 '계약에 의한 설계(design by contract)'라고도 한다. 메시지를 주고 받는 양측은 서로 조건에 만족시킬 책임(responsibility)과 의무(obligation)를 양측에게 가지며, 이는 계약과 같은 형태로 존재하기 때문에 어느 한쪽이 이를 무시하거나 지키지 않는다면, 응당 그에 대항하는 책임이나 의무를 지을 필요가 없게 된다. 예를 들어, 숫자 1을 입력받고 한글 '하나'를 반환하는 오퍼레이션의 경우, 숫자 1이외의 값이 넘어오는 경우에 당연히 한글 숫자 '하나'를 반환할 의무가 없으며, 그외의 기타 예외나 null과 같은 형태로 계약이 파기되었음을 알릴 필요가 있다. 클라이언트에서는 오퍼레이션을 호출할 때 입력값을 올바르게 넣을 책임이 있으며, 이러한 책임은 서버에서 그에 합당한 올바른 값을 반환할 의무가 발생하는 것이다. 마찬가지로, 서버가 올바른 값을 반환할 것이라고 생각한 클라이언트가 올바른 값을 받지 못할 때에(서버가 올바른 값을 넘겨줄 책임을 다하지 못하는 경우), 클라이언트는 반환된 값에 대해 마찬가지로 계약 파기와 같은 행위(예외 처리와 같은)를 할 수 있다.



Apple Temptation
Apple Temptation by Lawrence OP 저작자 표시비영리



인터페이스 명세는 이러한 'Design by Contract (DbC)'라는 원칙을 준수할 수 있도록 기술(description)되어야 하며, 이는 문서를 만드는 경우에도 마찬가지로 포함되어야 한다. 하지만, 현실 세계에서는 이러한 원칙으로 인터페이스 명세를 작성하는 예를 찾아보기란 힘든게 사실이다.


여기에 한가지 현실적인 팁을 제공하자면, 이러한 DbC에 대한 명세를 제공하지 못한다면, (비)대칭적인 오퍼레이션을 제공하는 것도 방법이 될 수 있다. 즉, 대칭적인 오퍼레이션이란 정보를 저장하는 행위와 조회하는 행위를 일치시키는 방식으로 저장하는 구조 그대로 조회하는 오퍼레이션을 제공하는 것이다. 비대칭은 저장하는 정보의 구조와 조회하는 정보의 구조가 달라지는 형태라고 보면 된다.


이 경우, 정보를 검증하는 책임의 위치가 다소 달라질 수 있을 것이다. 예를 들어, 은행에 돈을 맡기는 경우, 고객이 1만원권 5장을 저금하고, 나중에 이 돈을 출금하는 경우, 은행 입장에서 1만원권 5장을 제공하는 경우와 5만원권 1장을 제공하는 경우로 나누어 볼 수 있다. 1만원권 5장의 경우에는 고객이 이미 1만원권을 알고 있고, 응당 저금시의 형태와 출금시의 형태가 같기 때문에 이는 자신이 받아야 하는 금액으로 인식을 할 것이다. 하지만, 은행이 5만원권을 내어주는 경우에는 고객이 만일 5만원권에 대한 인지를 하지 못한다면, 은행은 고객에게 5만원권 1장이 1만원권 5장과 같음을 증명해야 할 것이다.


결론적으로, 대칭적인 오퍼레이션을 제공하는 경우, 클라이언트 측에서는 저장에 상응하는 조회 오퍼레이션을 서버측이 제공함으로써 자신이 입력한 정보가 저장이 되었는지를 점검할 수 있으나, 비대칭적인 오퍼레이션을 제공하는 경우, 서버측에서 저장된 정보가 조회시 올바로 조회되는지에 대한 책임을 져야 한다.


이러한 (비)대칭 오퍼레이션[기능]에 대한 부분은 테스트를 통해서 충분히 검증이 가능하다. 예를 들어, 돈을 이체하는 기능의 경우, 이체를 요청하는 측(클라이언트)은 입금액을 파라미터로 넘기고, 잔액을 리턴으로 받아서 이체에 대한 검증을 이체를 수행하는 주체(서버)에서 이를 수행하게끔 할 수도 있다.(비대칭 signature) 혹은 이체를 수행하고 나서 그 결과값만을 보내고, 이체를 요청하는 측(클라이언트)에서 잔액을 다시 조회함으로써 이체에 대한 결과를 검증해볼 수 있다.(대칭 signature)


통상 설계나 구현을 할 때에 이러한 검증에 대한 고려를 하지 않는다면, 어느 한쪽에 치우친 기능만이 도출될 우려가 있다. 즉, 검증을 고려하여 기능의 책임을 양측(기능을 호출하는 측과 이를 제공하는 측)에 대한 균형을 유지하는게 좋은 설계라고 볼 수 있다.




기능이 비대칭적으로 혹은 대칭적으로 설계/구현이 되었든 간에 기능 검증의 책임은 서버와 클라이언트 측 어느 한곳에 반드시 있어야 하며, 이를 검증할 수 있는 메커니즘은 반드시 필요하다. 비대칭의 경우, 서버의 상태를 투명하게 보이게 하거나 혹은 외부에서 진입될 수 있는 지점을 열어놓음으로써 이러한 검증을 수행할 수 있고, 대칭의 경우, 클라이언트 측에서 서버가 제공하는 기능을 사용해서 검증할 수 있어야 한다. 전자는 식별된 기능을 중심으로 식별된 내용을 그대로 유지한 채 시스템을 설계하는 방식이 될 것이며, 후자의 경우에는 식별된 기능 이외에 안보이는 기능을 추가로 식별하는 과정으로 볼 수 있을 것이다. 후자는 최초 기능 식별에서 나타나지 않는 기능이라 하더라도 점차 기능 식별이 더 활발하게 진행되고 SW가 완성되어 가는 과정에서 이러한 기능은 재사용될 가능성이 더 높다.


계좌이체 예제에서 잔액을 확인하는 기능은 비대칭으로 구현시 계좌이체 프로세스 내에 섞여있는 형태로 나타나지만, 대칭 형태로 구현시에는 잔액 확인은 다른 기능에서 재사용될 가능성이 높아지고, 결국 현재 식별/구현되는 기능 이외에서 필요한 기능이 될 가능성이 높다.


대칭과 비대칭 signature는 시스템을 설계/구현하는 입장에서 어떤 것이 사용하기에 더 적합한지를 고려하여 선택하게 된다. 하지만, 이 두가지 형태는 모두 책임과 의무를 어느 측에 둘 것인가를 고려하면서 양측에게 이러한 책임과 의무가 균형을 이루도록 설계하는 DbC 원칙을 유지하게끔 하는 방식이라고 보면 된다.

저작자 표시 비영리 동일 조건 변경 허락
신고
작업을 수행하는 사람들은 늘 흔적을 남기기 마련이며, 이를 SW에서는 산출물이라고 말한다. 즉, 어떠한 활동을 하든지 간에 그 흔적이 어떠한 형태로든 존재하기 마련인 것이다. SW 개발하는 입장에서 설계와 구현의 정확한 구분을 한다는 것은 사실 거의 불가능한 영역이기도 하다. 설계를 개발 단계 중에 정해진 기간으로 놓고 그 단계 내에서 산출물을 강요하는 식의 방식은 설계의 본연의 목적을 잃을 가능성이 너무나도 높다.

Anonymity; and the Internet.
Anonymity; and the Internet. by Stian Eikeland 저작자 표시비영리동일조건 변경허락



우리는 어떤 일을 하게 될때 머리속으로 먼저 무엇을 어떻게 수행할지를 가늠해본다. 좀더 깊이 생각하는 사람은 다양한 대안들을 생각해보고 각각의 장단점을 비교하여 사전 시뮬레이션까지도 고려하여 최적의 해결책이라고 여기는 방식을 선택하기도 한다. SW 개발에서 설계는 바로 이러한 활동들과 마찬가지이다. 설계는 비즈니스의 요구사항을 이해하고, 이를 시스템 관점에서 어떻게 구현할 것인지를 사전에 고민해보는 시간이다. 물론, 그러한 고민에는 다양한 제약사항들이 포함되어서 고려되는 것이 좋다. 하지만, 지금의 시스템이 단순하지도 않으며, 상당히 복잡한 비즈니스 로직이 이미 가지고 있는 상태이며, 서로 다른 시스템들의 관계까지 포함되어 있기 때문에 모든 사항을 고려해서 설계한다는 것은 거의 불가능한 일이다. 물론, 이는 경험으로 축적된 지식을 가진 사람이라면 다양한 조건들을 고려해서 설계를 할 수도 있다. 그렇다 하더라도, 설계 단계에서 고려는 그 이후 구현 시점에서 많은 부분이 바뀐다고 봐야 한다.

하지만, 아무리 경험을 많이 한 사람이라고 하더라도 설계때 만든 것을 가지고 SW를 이미 절반을 만들었다고 볼 수는 없다. SW에서도 재고라는 개념을 도입해보면, 만들어진 설계 산출물은 SW 구현을 위한 재고라고도 볼 수 있다. 현실세계에서의 재고와 SW에서의 재고의 차이는 눈에 보이는 물품의 재고는 바로 팔아서 현금화가 가능하다는 것이다. 실제 투입된 비용보다도 더 싸게 팔 수도 있겠지만, 어찌되었든 이는 명확하게 자산에 해당한다. 그렇지만, 구현되지 못한 SW의 설계는 아무리 많이 가지고 있다고 하더라도 현금화가 되지 못한다. 실제로 금융업계에서도 설계문서를 만들어서 파는 곳도 있지만, 이를 가지고 무엇을 할 수 있다는 것인가. 종이 인쇄비 만큼만 값어치가 있을 것이다. 만일 설계 문서만으로 가격을 책정한다면 많은 내용을 포함하는 설계와 단순한 몇가지 그림을 포함하는 설계, 이 두가지 중에서 어떤 것이 가격을 더 높게 쳐줄 것인가.

이를 다른 시각에서 보도록 하자. 금융 시스템은 상당히 복잡한 시스템들이 많이 있으며, 비즈니스 로직 또한 상당하다. 소스 코드 양도 천만 라인이 넘는 경우도 허다하며, 많은 인력과 오랜 경험의 축적으로 쌓여 있다. 금융 시스템의 설계의 양은 페이스북이나 트위터의 설계의 양보다도 훨씬 많을 것이다. 그럼 금융 시스템의 설계 문서와 페이스북의 설계 문서의 가치는 어떻게 책정할 것인가. (아직 해당 시스템이 구현되지 않았다고 가정한다) 결론적으로 그 가치는 아무도 모른다. 설계의 양이 많고 복잡하다고 해서 구현된 SW가 가치가 더 있다고 말할 수도 없으며, 아주 단순한 몇장의 그림만을 가진 설계로부터 구현된 SW가 가치가 훨씬 떨어진다고 말할 수 없다.

설계는 가치가 0인 산물을 만들어낸다. 그러한 가치를 매겨주는 것이 바로 우리나라의 SW 프로젝트의 특징이다. 설계가 가치를 가지는 것은 바로 사용자의 PC(디바이스) 앞에서 동작하는 SW가 있고, 그 사용자에게 가치를 줄 때 바로 의미가 있다.

그렇다면, (현물적인) 가치를 전혀 갖지 못하는 설계를 만드는 이유는 무엇일까. 우선은 커뮤니케이션과 가시화를 말한다. SW 시스템은 생명주기를 가진다. 즉, 개발 단계라는 탄생에서부터 운영을 거쳐 파기까지 길거나 짧은 시간을 거쳐서 사용자와 상호작용을 하게 된다. 그 기간 동안에 다양하고 많은 사람들이 관여를 할 수 밖에 없다. 소스 코드를 일일히 뒤져서 무슨 문제가 있고, 어떠한 상태인지를 파악하기란 지금의 시스템에서는 힘들기 때문에 이를 가시화시켜서 문서화해서 커뮤니케이션을 한다. 프로젝트의 산출물로의 가치는 바로 이러한 이유로 출발하게 된다. 그리고 그렇게 만들어진 문서는 점점 다양한 내용을 넣으려고 하고 종류나 내용이 많아지게 된다. 개발하는 입장에서는 바로 봐야할 문서가 많아지고 도통 서로간의 연관관계조차도 파악하기 힘든 경우도 많다. 이러한 설계문서는 운영이나 유지보수에 필요한 내용이 갱신되리라고 보장할 수도 없다.

설계 활동에 대한 가치를 떨어뜨리는 행위들은 매번 SW 개발 프로젝트를 수행할 때마다 반복해서 발생되며, 여기에 설계가 가지는 단어에 대한 반감을 가지게 만든다. 실제로 하나의 개념에 대해서 10가지가 넘는 문서들을 만들고 이를 보고 개발자에게 개발하라고 말하지만, 개발자는 어떠한 문서도 보지 않고 바로 해당 설계를 만든 사람에게 입과 귀로 그 내용을 듣는 경우가 허다하다. 이러한 식의 설계 활동은 전혀 개발에 도움을 주지 않으며, 오히려 개발자에게 부담만을 안겨준다.

현실적으로 제대로 된 설계를 만나보기가 힘들다. 개발자들에게 설계를 보고 만들라고 입버릇처럼 말하지만, 이를 곧이 곧대로 듣고 개발하는 사람들은 큰 낭패를 보거나 실력없는 개발자로 낙인찍히기 딱 알맞다. 설계와 구현은 사실 그 경계가 모호하고 거의 없다고 봐야 한다. 실행력이 없는 기획이나 설계는 가치가 전혀 없는 것과 마찬가지로 생각하고 사고한 것을 소스 코드로 구현할 수 있는 능력이야 말로 SW를 구현하는데 있어서 필요한 능력이라고 볼 수 있다. 정말 설계한대로 소스코드를 만들어낸다면 대단한 SW를 만들 수 있다고 생각한다면, 이는 아주 큰 오해 중에 하나이다. 설계는 세밀한 구현체와는 달리 동작하는 SW의 윤곽을 보여준다. 그 윤곽은 다양한 관점에서 바라볼 수 있는 시각을 제시하며 SW가 가지는 여러가지 제약들을 고려할 수 있는 단초를 제공한다. UML이 그러한 부분을 제시해줄 수도 있겠지만, 클래스 다이어그램 한가지만으로도 한가지 기능의 다양한 측면들을 그려낼 수 있다. 이를 그려낼 수 있는 능력이 설계자가 가지는 능력이지만, 이는 결국 구현체를 미리 머리 속에서 그려낼 수 있는 능력이기도 하다. 역으로 설계의 능력을 가진 자가 설계 문서를 만들지 않고 코드를 바로 작성하면서 머리 속에서 설계를 생각하는 것 역시 설계의 능력을 가졌다고 볼 수 있다. 즉, 설계를 통해 구현체의 투상을 볼 수 있어야 하며, 구현체를 통해서 설계를 가늠해볼 수 있어야 한다.

설계의 가치를 인정하지 않는 것은 아니다. 설계는 분명 그 자체로 가치가 충분하며 설계자의 의도가 명확할 때에만 그리고 남을 이해시킬 수 있는 관점을 정확하게 제시할 때 그 가치가 제대로 발휘된다. 물론 구현체로써도 설계 문서를 가지고 설명이 된다면 더할 나위 없을 것이다. 설계는 그 누구를 위한 것보다도 개발자 자신을 위한 산출물을 만들어낼 때에 그 가치가 있다. 아무리 단순한 기능이라고 하더라도 하나 둘 제약사항이 들어가기 시작하면 처음에 단순한 모델이 복잡한 구현체로 변모했음을 알 수 있을 것이다. 시스템을 단순히 CRUD를 가지는 기능 덩어리로 바라보는 관점은 이제는 바뀌어야 한다. 과거의 시스템은 하나의 기능을 수행하기 위해서 사용하는 시스템의 자원을 지금의 시스템에서 제공하는 기능이 사용하는 시스템의 자원과 비교를 한다면 엄청나고 복잡할 것이다. 때로는 이러한 기능을 한 사람이 아닌 여러 사람이 공동으로 개발하는 경우도 많다. 이를 소스 코드만으로 분석하려고 한다면 그리고 이를 말로만 설명하려 한다면 엄청난 오해와 곡해로 인해서 전혀 예상했던 기능과는 다른 기능이 만들어질 것이다. 이미 그 때에는 되돌리기에는 너무나 많은 노력을 투여했기 때문에 그 복잡성에 더해 새로운 복잡성을 만들어내기도 한다.

구현시 수없시 많은 재반복 작업을 경험해본 적이 있는가. 그렇다면 우선은 설계를 만들어서 전체적인 윤곽을 그려보라. 거기에서 장단점을 볼 수 있는가. 단점을 극복할 수 있는 방법을 추가해보라. 설계를 먼저 그러한 용도를 사용해본다면 반복되는 구현 작업을 최소화시킬 수 있을 것이다. 설계는 구현을 하는 방법을 최적으로 하기 위한 전략을 구상하고 예측할 수 있게 만드는 장치로 활용한다는 사고를 가진다면 설계 작업이 더 없이 필요함을 느낄 것이다. 코딩은 단순한 작업이 아니다. 결코 단순해질 수 없는 작업이며, 앞으로도 더 복잡해졌으면 복잡해졌지 단순해질 수 없는 작업이다.
저작자 표시 비영리 동일 조건 변경 허락
신고
  1. BlogIcon 김민재 2012.01.16 10:31 신고

    설계와 구현을 통상 구분하지만, 구현을 포함한 설계 개념으로 바라보면 어떨까 싶네요.
    DDD에서는 모델과 설계로 구분하고 있다고 생각합니다.
    구현을 포함한 설계면.. 설계는 무조건 존재해야 하는 것이 됩니다.

  2. Favicon of http://homo-ware.tistory.com BlogIcon javauser 2012.01.16 10:35 신고

    궁극적으로는 구현을 포함한 설계로 구현 기술이 발전해야 한다고 봅니다. 그러한 영역이 DSM이나 DSL 영역이죠.
    하지만, 구현에서의 상세한 내용이 어떻게 간편화(모델화)가 될 수 있을 것인가에 따라서 설계 모델로의 통합화의 정도가 달라질 것 같습니다.

    지금 새롭게 나타나고 있는 언어들이 구현의 상세함을 감추고 단순한 선언만으로 상당히 많은 양의 비즈니스 로직을 담당하도록 만들어지고 있는데요, 이러한 부분들이 앞으로의 설계 방향에도 영향을 줄 듯 싶습니다.

시스템 구축시 설계(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의 과정을 거쳐서 완성되어 가는 부분이기 때문에 산출물 형태로 표현되는 시점에서는 이 부분이 미처 완성되지 못한 경우도 있을 것이다. 내부설계를 독립적으로 표현하는 이유는 컴포넌트의 외형과의 분리를 통해서 비즈니스 로직을 캡슐화하는 장점도 있다. 설계 산출물을 제출할 당시의 컴포넌트가 충분히 내부 설계가 작성되지 않았다고 한다면 해당 컴포넌트에 관련된 다양한 문서를 그 안에서 포함시킬 수도 있다.

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

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

+ Recent posts