Eternity's Chit-Chat

aeternum.egloos.com



분석/설계 미신 Software Design

우리는 분석 모델, 설계 모델, 구현 모델이 서로 달라야 한다는 오랜 미신 속에 살아 왔다. 이론적으로 분석 모델은 해결 방법에 대한 언급 없이 문제 도메인을 설명하는 모델이다. 분석 모델은 순수하게 문제 도메인에 초점을 맞추어야 하며 기술적인 해결 방법을 언급해서는 안된다. 분석 모델이 완성되면 이를 바탕으로 기술적인 관점에서 솔루션을 서술하는 설계 모델이 만들어 진다. 프로그래머는 이렇게 만들어진 청사진을 프로그래밍 언어를 사용하여 컴퓨터가 이해할 수 있는 명령어로 변환한다. 그러나 분석 모델, 설계 모델, 구현 모델을 명확하게 구분하는 것은 가능하지도 않을 뿐만 아니라 오히려 소프트웨어의 품질에 악영향을 미친다. 진실로 우리가 원하는 것은 소프트웨어의 영혼에 영광을 안겨줄 분석과 설계와 구현의 삼위일체론이다.

필자의 개인적인 견해로는 분석 모델이 사용할 구현 기술을 지향하는 것은 매우 합리적이며 그 결과 모델은 작업해야할 문제를 이해하는데 더 유용해 진다는 것이다. 분석과 설계의 근본적인 차이는 분석이란 도메인을 이해하는 것인 반면, 설계는 도메인을 지원하는 소프트웨어를 이해하는 것이라는 점이다. 명확하게 이 두 가지는 밀접하게 연결되어 있으며 둘 사이의 경계가 매우 모호해질 때가 많다. 그러나 경계가 뚜렷할 필요는 없다. 유용성보다 순수성을 강조해서는 안 된다. 이론적으로는 분석인 동시에 설계의 특성을 가지는 하이브리드 모델이 절대로 좋은 것이 아니지만 이런 하이브리드한 특징이 가장 좋은 모델을 만든다고 믿는다.

분석 모델과 설계 모델의 하이브리드한 특징이 가장 좋은 모델을 낳는 토양이라면 프로그래밍 언어를 사용하여 구현한 코드가 이 모델을 최대한 반영하는 것이 가장 이상적일 것이다. 만약 설계 모델의 일부가 적용 기술 내에서 구현 불가능하다면 설계 모델을 변경해야 한다. 프로그래밍 과정동안 설계의 실현 가능성과 정확성이 검증되고 테스트되며 그 결과 잘못된 설계가 수정되거나 새로운 설계로 대체된다. 따라서 프로그래밍은 설계의 한 과정이며 설계는 프로그래밍을 통해 개선된다.

많은 방법론에서 분석, 설계, 구현 단계를 세분화하는 이유는 대부분의 사람들이 그것을 프로그래밍 세계의 이데아라고 생각하기 때문이다. 그러나 실제 소프트웨어 설계 과정은 아름답지도, 깔끔하지도, 올곧지도 않다. 소프트웨어 설계는 지저분하고 변덕스러우며 지우고 새로 그리는 과정을 무한히 반복해야 하는 ‘스케치’ 작업이다. 프로그래밍은 설계를 명령어로 옮기는 작업이 아니라 설계 그 자체를 만들기 위한 과정이다.

초등학교 시절에 선생님이 가르쳐준 대로 연필을 쥐지 못해서 괴로워했던 것처럼, 나는 오랫동안 이런 프로그래밍 방식에 대해서 남몰래 부끄러워 했다. 하지만 내가 그 당시에 화가나 건축가 같은 다른 창조자들이 일하는 방식을 알았더라면, 내가 프로그래밍하는 방식을 지칭하는 특별한 이름이 있다는 것을 알 수 있었을 것이다. 그 이름은 바로 ‘스케치’다. 적어도 내가 보기에 대학 시절에 배운 프로그래밍 방식은 전부 잘못 되었다. 소설가, 화가, 그리고 건축가의 작업이 그런 것처럼 프로그램이란 전체 모습을 미리 알 수 있는 것이 아니라 작성해 나가면서 이해하게 되는 존재다.

이런 깨달음은 소프트웨어 디자인에 대한 실질적인 의미를 갖는다. 그것은 프로그래밍이라는 것이 부드럽고 말랑말랑한 존재라는 엄염한 사실에 대한 재확인이다. 프로그래밍 언어는 당신이 이미 머릿속으로 생각한 프로그램을 표현하는 도구가 아니라, 아직 존재하지 않는 프로그램을 생각해 내기 위한 도구다.

- Paul Graham, 해커와 화가

분석, 설계, 구현 단계 모두가 설계를 위한 과정이라고 본다면 테스트를 먼저 작성하고 리팩토링에 의해 설계를 개선시키는 TDD의 장점이 명확해 진다.

그냥 짚고 넘어가는 것으로, 모든 프로그래머는 코드 작성 이전이 아니라 이후에 소프트웨어 설계 문서를 작성하는 것이 훨씬 정확한 문서를 만들어낸다는 것을 알고 있다. 이제 그 이유는 명백하다. 코드에 반영된 최종 설계는 빌드/테스트 주기에서 다듬어진 단 하나의 설계이다. 처음 설계가 이 주기 동안 바뀌지 않았을 확률은 모듈의 개수와 그 프로젝트의 프로그래머 수에 반비례한다. 이 확률은 빠른 속도로 0과 구분할 수 없게 되어 버릴 것이다. …… 궁극적으로, 소프트웨어 설계는 어떤 언어로 표현되어야 하고, 빌드/테스트 주기를 통해 검증되고 다듬어져야 한다.
- Jack W. Reeves, What Is Software Design?

모델과 코드의 결합은 Eric Evans의 저서인 Domain-Drvien Design의 핵심적인 개념이다. 즉, 모델은 도메인을 반영하고 코드는 도메인을 반영한 모델을 반영해야 한다는 것이다. 이를 MODEL-DRIVEN DESIGN이라고 한다.

도메인 모델과 소프트웨어 시스템 간의 맵핑이 명확해지도록 도메인 모델을 충실하게 반영하는 소프트웨어 시스템을 설계하라. 도메인에 대한 더 깊은 식견을 반영할 방법을 찾는 순간 소프트웨어 내에서 모델을 더 자연스럽게 구현할 수 있도록 모델을 재검토하고 수정하라.  견고한 유비쿼터스 언어(UBIQUITOUS LANGUAGE)를 지원함과 동시에 두 가지 목적 모두에 잘 부합하는 하나의 모델을 추구하라.

설계에서 사용되는 용어와 기본 책임 할당을 사용해서 모델을 작성하라. 코드는 모델의 표현이 되고 코드에 대한 수정은 모델에 대한 수정이 된다. 효과는 나머지 프로젝트 활동 내내 적절히 파급되어야 한다.

- Eric Evans, Domain-Driven Design

따라서 분석과 설계와 구현 간의 구분이 방법론과 프로젝트 관리를 위해 필요한 중요 요소라고 하더라도 모델과 코드 간의 관계에 이를 강요해서는 안된다. 모델링 툴에 저장된 다이어그램이 코드와 무관하다면 당장 다이어그램을 파기하고 모델링 툴을 쓰레기 통에 집어 던진 후 프로젝트 관리자에게 라이센스 비용이 더 이상 필요하지 않다는 희소식을 전하자. 프로젝트 내에서 분석 모델을 설계 모델로 변환하는 작업에 많은 시간을 소비하고 있다면 설계 모델을 도메인을 반영하도록 수정하고 분석 모델을 폐기처분 하자. 이런 프로젝트는 소프트웨어 자체가 아니라 프로세스를 위한 맹목적인 작업에 개발자들의 소중한 시간과 체력을 낭비하고 있을 뿐이다.

코드와 모델의 차이를 줄이기 위해서는 도메인과 코드 간의 차이가 적어야 한다. 현재 프로그래밍 패러다임을 주도하고 있는 객체 지향의 가장 큰 힘은 도메인을 표현하는 방법과 프로그램 코드를 표현하는 방법이 동일하다는 것이다. 만약 객체 지향 언어를 사용하고 있다면 프로그램 코드를 설계 문서로 간주할 수 있는 기반은 갖추어진 셈이다.

만약 프로그래밍이 곧 설계라면 최대한 빨리 코드를 작성하는 것이 최선의 방법이다. 반복적이고 점진적인 프로세스가 우리를 구원한다. 코드와 모델 간의 유사성을 유지하기 위해서는 프로그래밍 과정에서 발견된 설계 결함을 즉각 수정할 수 있는 방법이 필요하다. 리팩토링이 우리를 인도한다. 즉각적인 코드 리팩토링을 위해서는 리팩토링에 따라 코드가 잘 못 되지는 않았는지를 판단할 안정망이 필요하다. TDD가 우리를 보호한다.

무엇보다 Jack W. Reeves의 다음 견해는 이런 측면에서 최근의 모든 애자일 방법론을 이끄는 핵심 사상을 잘 설명하고 있다.

소프트웨어 개발 과정이 어떻게 바뀌고 있는지도 살펴보자. 옛날 옛적에, 우리는 폭포수형 프로세스(waterfall process)를 썼다. 이제 우리는 나선형 개발(spiral development)과 신속 시제품 작성(rapid prototyping)을 논하고 있다. 이런 기법이 ‘위험 완화’나 ‘단축된 제품 출하 시간’과 같은 말로 정당화되고 있지만, 사실 이런 것은 생명 주기에서 코딩을 일찍 시작하는 것에 대한 변명일 뿐이다. 좋다. 이는 설계를 검증하고 다듬기 위한 빌드/테스트 주기를 더 일찍 시작할 수 있게 해준다. 이는 또한 높은 단계의 설계를 개발하는 소프트웨어 설계자가 구체적인 설계 주위를 맴돌 가능성이 더 있음을 의미한다.
- Jack W. Reeves, What Is Software Design?


덧글

  • Kevin 2009/06/20 15:25 # 삭제

    이글 정말 맘에 드네요. :)
    DDD 관련 글도 물론 잘 쓰셨지만, 이글은 무엇보다도 맘에 드는 글입니다.
    '분석과 설계와 구현의 삼위일체론' 이란 말은 원래 쓰이던 말인가요?
    아니면 이터너티님께서 만드신 말인가요?
    나중에 제글에 인용을 하고 싶은데, 출처를 알아야...^^;;;
    그냥 제가 만든 말처럼 쓸수는 없으니까요... :)

    그동안 이론과 실제 경험에서 얻은 지식의 충돌로 고민을 했었는데
    의문점들이 좀더 명확해지고 막혔던 하수구가 뻥 뚫리듯 시원하고
    깔끔해지는 느낌이 드는군요. 좋은글 고맙습니다. ^^
  • 이터너티 2009/06/21 23:11 #

    글이 마음에 드셨다니 다행이네요. ^^

    '분석과 설계와 구현의 삼위일체론'이라는 용어는 MODEL-DRIVEN DESIGN의 개념을 은유적으로 표현하기 위해 제가 만든 용어입니다.

    저 역시 방법론을 처음 접하던 시기에는 분석/설계/구현의 경계를 명확하게 구분하고 적용해야 한다고 생각했었지만, 경험이 쌓이고 다양한 서적들을 보면서 그것이 불가능하거나 현실성이 없다는 것을 알게 되더군요.

    산출물을 위한 설계가 아니라 구현을 하는 개발자와 소프트웨어를 사용하는 사용자를 위한 설계가 되기 위해서는 과도한 형식화라는 강박관념에서 벗어나는게 우선이라고 생각합니다.
  • Kevin 2009/06/22 00:29 # 삭제

    아... 역시 만드신 용어군요. ^^
    대충 검색해 보고 그런말이 안 뜨길래
    어느정도 예상은 했습니다만...

    그럼 인용할때 이터너티님을 언급해야 하는데 문제가 좀 생기는군요. :)
    정보 분류 (Information Classification) 에서
    정보 평가 (Information Evaluation) 의
    항목인 출처/권위 (Authority) 와 정확성 (Accuracy) 부분 때문에 그런데요.
    (맞게 번역한건가 모르겠습니다...ㅡ_ㅡ;;;;; )
    이터너티님 넷상의 닉인 '이터너티'를 사용할수가 없잖아요...^^;

    익명성이 보장되는 인터넷에서 이런 부탁드리기 좀 그렇습니다만,
    혹시 이터너티님에 대해 조금더 자세히 알려주실수 있을까요?
    실명과 경력 등등 말이죠.
    자세하면 더 좋구요. 예를 들어 학력이라던가 수상경력 기타 등등...^^;;;

    '분석과 설계와 구현의 삼위일체론' 이란 용어를 처음 사용한 분으로
    언급해야 하는데, 닉네임 하나 달랑 쓸수는...^^;

    당장은 바빠서 금방 쓸수는 없지만, 나중에 제 블로그에 관련글을 쓸때
    꼭 언급하고 싶습니다. 혹시 괜찮으시다면, 부탁 좀 드리겠습니다.
    저에게만 알려주셔도 됩니다만...
    블로그에 이터너티님에 대한 소개 페이지를 만들어 주시면 더 좋구요...^^;;;
    이거 만드시면 이터너티님의 글을 인용하고 싶어 하는
    다른 사람들에게도 도움이 되지 않을까요?

    바쁘실텐데 어려운 부탁드려서 죄송합니다.
    거절하셔도 괜찮으니 절대 부담가지지 마시구요.
    부담가지실까봐 제가 부담이 됩니다...ㅡ_ㅡ;;;
  • 이터너티 2009/06/23 10:29 #

    그렇게 대단한 경력이 있는게 아니라서.. ^^;;

    여기에 비공개 덧글로 이메일 적어 주시면 제가 정리해서 메일 보내도록 하겠습니다.

    감사합니다. ^^
  • 2009/06/23 18:53 # 삭제 비공개

    비공개 덧글입니다.
※ 로그인 사용자만 덧글을 남길 수 있습니다.