블로그 이미지
소프트웨어 개발 경험을 공유하고 싶은 재밌게 사는 소프트웨어 엔지니어입니다^^

카테고리

Chungha Story (46)
Agile Experience (22)
My Family (4)
Life Style (8)
Programming (8)
Android (3)
Total120,782
Today108
Yesterday128
프로젝트 초반, 그리고 설계

상위설계(High Level Design)는 일반적으로 프로젝트 초반에 작성됩니다. 상위설계는 해당 프로젝트의 결과물의 근간이 되기 때문에 매우 중요하며 크게 변하는 경우는 드뭅니다. 어디까지나 상위설계이기 때문이죠. 뜬구름 잡는 얘기일 수도 있기 때문에 기술적으로 아주 세세하게 알지 못해도 작성할수 있는 경우가 있습니다. 하지만 상세설계(Low Level Design)에 접어들게 되면 구체적으로 많은 선택을 해야합니다. 골치 아프죠.
많은 경우에 어느 수준까지 작성해야 할지 갈피를 못잡고 방황하다가 적당히 보고 수준의 문서를 작성하고 구현에 들어갑니다. 결국 구현 따로 상세설계 따로인 결과물이 탄생하게 됩니다.

유지보수와 스파게티 코드 양산

유지보수중 스파게티 코드를 양산하게 되는 경우중 하나는 소스코드만 가지고 문제 해결을 할수 밖에 없는 경우 입니다. 아마 대부분의 경우가 이러할꺼라 생각됩니다. 근본적으로 문제를 해결하고 싶지만 근본적인 원인을 찾는데 도움이 될수 있는 큰 그림을 볼 수 있는 단서가 유지보수 단계에까지 남아있는 경우가 드물죠. 결국 기존 소스를 분석하다 지쳐서 땜빵코드를 삽입할수 밖에 없는 경지에 이릅니다. 제가 아는 대부분의 개발자는 땜빵코드를 삽입하는 것에 대해 부정적이지만 어쩔수 없이 하는 경우가 많습니다. 물론 저를 포함해서..


파일럿 프로젝트로 시작하는 '동작하는' 프로젝트

앞에서도 말씀드렸지만 상세설계를 어느 수준까지 작성해야할지 고민되는 경우가 많습니다. 저는 이를 해결하기 위해 프로젝트 초반에 파일럿 프로젝트를 진행합니다. 어떤 레퍼런스를 쓰던 일단 원하는 결과물을 얻기 위해 이것 저것 시도해보며 최종적으로 해당 기능들을 간신히 수행하는(하지만 있을건 다있는) '동작하는' 소스코드를 만들어 냅니다. 그리고 이것을 통해 프로젝트를 본격적으로 시작할때부터 '동작하는' 소스코드를 가지고 시작할 수 있게 합니다. 그리고 현재 수준에서 껍데기(Front-End) 바로 아래부분(Top)부터 추상화(Abstraction)을 통한 인터페이스 추출(Interface Extraction) 작업을 시작합니다. 추출된 인터페이스를 정리하면 매우 간단한(Class가 몇개 안되는) Class Diagram과 Sequence Diagram을 그릴수 있습니다. 이것이 상세설계서의 0.01 버전이 될수 있겠습니다. 이를 바탕으로 리팩토링을 하게 되면 인터페이스 추출이 완료된 상위 클래스를 제외하고는 나머지는 뚱땡이 클래스가 되어있겠죠. 이제 시작입니다.

Top-Down으로 진행되는 리팩토링, 그리고 지속적인 설계

리팩토링을 Top-Down으로 하게 되면 소스코드의 리팩토링 단위가 커지게 되므로 보통은 추천하지 않습니다. 하지만 설계는 Top-Down으로 할수록 깔끔해집니다.(제 의견입니다.) 가장 상위(Top)부터 시작하여 단계적으로 하위(Bottom)까지 진행되는 인터페이스 추출은 리팩토링을 지속적으로 하도록 유도합니다. 그리고 리팩토링된 소스코드는 항상 '동작하는' 상태여야 합니다. 그리고 결과물인 소스코드와 UML 문서는 최소 1명의 팀원과 리뷰를 합니다. 반복하다보면 뚱땡이 클래스들이 점점 분리되여 계층적인 클래스 구조를 만들게 될겁니다. 고럼 다음과 같은 프로세스가 만들어 집니다.


주기는 짧을 수록 좋다

저는 위의 주기를 하루에 최소 한번 할수 있도록 개발 계획을 수립합니다. (작은 마일스톤으로 쪼개는 방법은 다음에 써보도록 하겠습니다.) 그나마 주기가 짧아야 리팩토링 단위와 정리해야할 UML 문서의 단위가 작아집니다.

결과적으로 얻을 수 있는건..
  1. 항상 '동작하는' 소스코드
  2. 항상 정확하게 현재 소스코드를 큰 그림으로 파악(Static and Dynamic!)할 수 있는 딸랑 2종류의 UML Diagram
  3. 새로운 기능 넣기 전에 UML Diagram 으로 검토하는 습관...
  4. 바쁜 이슈처리 상황에서 근본적으로 문제해결을 할 수 있는 여유..
  5. 객체지향적 설계 능력?ㅡㅡ;;
그런데 결국은 뭐라도 해봐야..뭐가 다른지 압니다.

저작자 표시 비영리 동일 조건 변경 허락
신고
Posted by 윤청하

댓글을 달아 주세요

  1. 2011.02.16 10:49 신고 k16wire  댓글주소  수정/삭제  댓글쓰기

    지속적인 설계라는 표현 맘에 드네요. ^^

  2. 2013.04.08 03:57 신고 longchamp  댓글주소  수정/삭제  댓글쓰기

    http://mih.freerunso.com/

   켄트백의 "익스트림 프로그래밍 2/E"에 다음과 같은 글이 있다.

매일 나아지고 있는 똘망이

  •   상황이 어떻건 간에 당신은 언제나 더 나아질 수 있습니다.
       No matter the circumstance you can always improve.
  •   당신은 언제나 자기 자신부터 개선을 시작할 수 있습니다.
      You can always start improving with yourself.
  •   당신은 언제나 오늘부터 개선을 시작할 수 있습니다.
      You can always start improving today.

나는 오늘부터 개발자로써의 나 자신을 개선하기 시작한다. 
(먼저 저에게 확신, 용기 그리고 영감을 주신 변신철님, 박피디님, 이희찬님, 박형근님, 김창준님께 감사드립니다.^----^)

회고 - 왜 실패했을까?

나는 지난 수개월간 TDD를 스스로에게 적응시키기 위해 부단히 노력하였다. (켄트백의 책은 이해가 잘안되서 3번이나 읽었다.ㅠㅠ) 팀내 동기인 이희찬(http://heestory.kr)씨와 함께하였으며, TDD에 적극적으로 동참하고자 하였다. (불행히도 둘다 팀에서 말단급이다ㅠㅠ. 하지만 나는 팀의 말단에서부터도 변화할 수 있다고 생각한다^^)
하지만, 난 아직도 TDD에 적응하지 못하였다. 이유가 무엇일까? 스스로에게 물어보았다.
  • 의도적 수련 시간의 부족 
    안데쉬 에릭손이 주장한 1만 법칙에 따르면 1만 시간 동안 의도적 수련(deliberate practice, 자신의 기량을 향상시킬 목적으로 반복적으로 하는 수련)을 해야 그 분야의 전문가가 될수 있다고 한다. 또한 TDD의 성공사례를 찾아보면 수개월만에 몸에 익숙해졌다는 사례는 찾기힘들다.
    TDD는 기존 개발 방식을 완전히 뒤바꾸어 놓은 개발 방식이다. 즉, 이미 수년간 몸에 익은 습관을 버리기 매우 힘들다. 변화할만 할때 변화한다. 난 아직 의도적 수련을 더 많이 해야 한다!
  • 테스트 케이스 작성의 어려움
    나는 팀에서 독립적으로 개발 가능한 라이브러리(영상 코덱)을 개발할때 TDD를 적용하려고 했다. 
    하지만, 쉽지않았다. 영상 코덱은 결과물이 영상이기 때문에 자동적으로 옳고 그름을 판단하기 어려웠다.
    어떤 알고리즘은 특성상 최적해(optimal value)를 찾기 보다는 제일 괜찮은 해(best effort)를 찾는 경우도 있는데 정답을 판단하기 어려웠으며, 수학 공식이 있는 부분은 손으로 계산하기 귀찮았다.ㅠㅠ

그럼에도 불구하고 왜 꼭 TDD를 해야 하는가?

  • 선배들의 아픔을 똑같이 경험하고 싶지 않다. 
    기 개발된 다른 코덱들은 테스트 케이스가 전혀 없었으며, 지금도 가끔 상용싸이트에서 장애를 일으키고 있다. 장애가 나면 담당 개발자는 무지하게 골치아파진다.
  • 기존(legacy) 코드는 테스트하기 어렵다.
    내가 작성중인 코드도 어렵다.ㅠㅠ
  • 지속적인 검증이 필요하다.
    영상 코덱은 리눅스 버전으로 기능 개발이 완료된 후 리눅스에서의 최적화 작업(알고리즘 및 어셈블리 최적화)과 DSP 보드 상에서의 최적화 작업(메모리 및 어셈블리 최적화)을 하게 된다. 따라서 자동화된 유닛 테스트가 있다면 해당 작업들이 매우(x백만개) 수월하게 작업할 수 있게 된다.
원래 목표는 자동화된 단위테스트(unit test) 케이스를 누적시키는 것이다. 회사내 수석 개발자 분에게 TDD를 언급하면 항상 이점을 지적하시면서 화이트 박스 테스팅을 하라고 강조(TDD는 말고)하신다.
하지만 TDD의 이점은 자동화된 테스트 케이스의 누적에만 있지 않다. 기존(legacy) 코드를 위해 테스트 케이스를 만들어보려고 시도해본 이는 알것이다. 테스트에 적합하게 작성되어 있지 않은 코드는 당연히 테스트 하기 어렵다. 불행히도 거의 대부분의 기존 코드는 테스트에 적합하게 작성되어 있지 않다. 재미있는 사실은 테스트에 적합하게 작성된 코드는 매우 명확하고 깔끔해 진다는 것이다.
또한 TDD는 점진적인 리팩토링을 하도록 유도한다. 즉, 기존 코드도 점진적인 리팩토링을 통해 거듭날 수 있다. (이는 TDD와 무관할 수도 있다.)

그럼 바로 지금부터 무엇을 할 것인가?

  • 기존 코드는 큰 기능 단위부터 자동화된 테스트를 만들어 본다.
    결과물이 영상이기 때문에 완전히 일치하는지 검사하는 것 보다는 유사성 테스트를 통해 자동적으로 판별하고 유사성이 크게 떨어질 경우 눈으로 확인하는 절치를 스크립트로 작성한다.
  • 신규 개발 코드는 어떤 일이 있어도 TDD로 작성한다.
  • 추가 개발 코드는 테스트 케이스 추가 및 테스트 가능한 인터페이스로의 리팩토링, 이 두가지 작업을 적절하게 조합하여 테스트 케이스를 어느정도 만든뒤 작업한다.
이렇게 꾸준히 작업하면 테스트 커버리지는 자연적으로 상승할 것이다.
나는 XP 정신으로 바로 오늘부터 시작하였다!^^ 뽐뿌 백만개 받았다~ (금요일이라 그런가ㅡㅡ^)
오늘 신규 개발된 코드는 모두 TDD로 작성되었으며, 빠른 테스트를 위해 스크립트도 작성하였다.


앞으로 TDD를 잘하기 위해 필요한 자료들을 정리해서 올려보도록 하겠습니다~ 감사합니다.

저작자 표시 비영리 동일 조건 변경 허락
신고
Posted by 윤청하

댓글을 달아 주세요

  1. 2009.10.31 10:03 신고 박형근  댓글주소  수정/삭제  댓글쓰기

    화이팅입니다.!!!

  2. 2009.10.31 10:57 신고 heestory.me  댓글주소  수정/삭제  댓글쓰기

    ㅋㅋ청하씨 화이팅!!ㅋㅋ충전 만땅되셨네-ㅎㅎ
    저는 베터리 방전될거 같아유...ㅠ


어느날 아침에 한 영업실의 실장님과 간단한 대화를 나누었다. 그때 실장님은 귀에 거슬리는 말씀을 하셨다.
맨날 구조 바꾸고 갈아 엎는다고만 하지 말고 생각 좀 해서 개발해봐! 버그만 심지 말고..
이전에(애자일 마인드를 갖기 전) 이 말씀을 들었다면 매우 부정적으로 "니가 개발을 알아?" 라고 마음속으로 콧방귀를 꼈을 것이다. 하지만 오늘 나는 개발자로써 반성문을 써보고 무엇이 문제인지 밝혀보고자 한다.

영업부서와 개발부서와의 미팅에서 개발자들이 시간적으로나 기능적으로 불합리한 요구사항에 대처하는 핑계중에 하나는 아마 다음과 같을 것이다.
현재 우리 구조에는 적용하기 어렵습니다. 적용하더라도 시간이 걸릴것 같으며, 추후에는 전체적으로 뒤집어 엎어야 합니다.
실제로 내가 다니고 있는 회사의 모습만 봐도 구조 및 설계 개선 등의 이유로 전체 시스템 소스코드를 뒤집어 엎는 경우(전역 리팩토링)가 매우 많다. 우리팀도 작년부터 이전 플래폼을 개선한다는 이유로 2.0이라는 이름을 달고 1년이 넘게 팀의 리소스 중 많은 부분을 플래폼 구조 개선 작업에 투입하였다.

문제는 이러한 작업의 결과가 비지니스적인 가치로 창출되는 경우는 매우 드물다는 것이다. 오히려 새로운 소스코드에 대한 검증 및 안정화 작업으로 인한 업무 오버헤드가 더 증가할 수 있다. 물론 추후 생길수 있는 요구사항을 손쉽게 적용할 수 있을 수도 있다. 그러나 이것은 XP를 인용해보자면 쓸데없는 짓이다. "사용자 스토리"라는 책을 보면 스토리(요구사항)는 투자되는 리소스 대비 비지니스적인 가치가 높은 것의 우선순위를 높게 책정하도록 권장하고 있다. 지금 현재 다른 업무가 거의 없지 않은 이상 전체를 뒤집어 엎는 스토리의 우선순위는 높아질 수 없는것이 자명하다.

그렇다면, 무엇이 문제일까? 개발을 잘 못한 개발자들만의 잘못일까? 이와 같은 일이 벌어지는 이유를 내 경험을 통해 정리해 보겠다. (현재 재직중인 회사만의 현상일 수 있으나, 한국의 개발회사는 크게 차이 없을 것으로 생각된다.)
  1. 개발자마다 "개발완료"의 의미가 다르다.
    어떤 개발자는 코딩 및 컴파일 완료를 개발 완료라고 생각한다.
    어떤 개발자는 기능 테스트(화이트 박스 테스트) 완료를 개발 완료라고 생각한다.
    어떤 개발자는 리팩토링까지 완료해야 개발 완료라고 생각한다.
    불행히도 많은 경우에 두번째의 경우를 개발 완료라고 생각한다.
  2. 개발 기간이 너무 촉박하다.
    영업부서에서 전달하는 요구사항 대비 주어지는 개발 기간이 매우 적은 경우가 많다.
    이럴 경우 핵심적인 기능(비지니스적인 가치가 높은)을 선별적으로 개발해야 하나, 대부분의 협의는 모든 기능 구현으로 종결된다.
    즉, 개발자는 기능 구현에만 집착하게 되며, 리팩토링은 신경쓸 수 없게 된다.
  3. 과도한 업무로 보상 심리가 강해진다.
    개발양은 많고 개발 기간이 촉박해지면, 잦은 야근, 밤샘 작업 및 주말 작업은 일상생활이 된다.
    이로 인해, 프로젝트가 일단락 되어 여유 시간이 생기더라도 보상 심리로 인해 리팩토링 작업은 미뤄지게 된다.
  4. 리팩토링에 대한 교육이 없다.
    리팩토링 뿐만이 아니겠지만, 리팩토링을 강조하고 무엇을, 어떻게 해야하지는 알려주지 않는다.
  5. 깨진 자동차 유리 
    "실용주의 프로그래머"라는 책에 소개된 깨진 자동차 유리 실험처럼, 지속적인 리팩토링이 이루어지지 않은 코드의 중복성은 기하 급수적으로 증가하게 된다.

이유를 적다보니 개발자의 책임이 큰것을 알 수 있었다ㅠㅠ. 
물론 영업부서의 유연하지 못한 요구사항도 큰 문제이다.

나의 결론은 간단하다. 목표는 전체적으로 뒤집어 엎어야 하는 경우를 줄이는 것이다. 
다음과 같은 원칙을 가지고 개발한다면 어느정도 도움이 될 것이다.
  • 항상 중복을 제거한다. [리팩토링]
  • 코딩 전에 테스트를 작성한다. [TDD , 어렵다면 어떻게 테스트를 할지 미리 결정해야 한다.]
  • 설계와 구현은 동시에 진행한다. [XP, 점진적인 설계]
  • 코드 공유 및 리뷰를 수행한다. [XP, Pair Programming]

하지만, 시간이 촉박한 프로젝트의 경우에 해답을 찾기란 쉽지 않다.
결국은 영업 부서와 개발 부서가 한팀이 되어 긴밀한 협업을 하는 것이 중요한 관건이다.
협업이 원활이 이루어 진다면 영업 부서는 비지니스 적인 가치를 극대화 할수 있으며, 개발팀은 핵심 기능에 집중하여 더욱 신뢰성 높일 수 있을 것이다. 고객과의 협업까지 이루어 진다면 금상첨화가 아닐수 없다.
영업 부서와의 협업 방법으로 사용자 스토리스크럼을 추천한다.^^

사용자 스토리와 스크럼에 대한 내용은 다음 책을 참고하면 좋다.
사용자 스토리
고객 중심의 요구사항 기법
마이크 콘, 심우곤 역
인사이트
스크럼과 XP
애자일 최전선에서 일군 성공 무용담
헨릭 크닉버그
인사이트
신고
Posted by 윤청하

댓글을 달아 주세요

  1. 2009.11.05 14:09 신고 윤청하  댓글주소  수정/삭제  댓글쓰기

    스스로 피드백~ (아무도 안줘서..ㅋㅋ)
    거의 동일한 기능을 가지는 새로운 제품을 만들때(설계/구조 개선등의 목적) 생기는 또하나의 단점은
    만약 새로운 제품이 기 제품이 납품된 싸이트에 적용(migration) 될 수 없다면 개발팀으로써는 거의 동일한 두가지 제품을 follow-up 및 유지보수 해야 하는 것이다. 이는 혹떼러 갔다가 혹 더붙이는 꼴이 될 수 있다.
    (특히 상용에서 정상적으로 서비스 중인 제품을 검증되지 않은 새 제품으로 migration 하는 작업을 달가워할 고객은 별로 없을 것이다. - 설득의 문제)

  2. 2009.11.05 14:11 신고 윤청하  댓글주소  수정/삭제  댓글쓰기

    최근 옆팀에서 기존 제품에서 설계/구조 개선을 목적으로 새로 제품을 개발하는 작업을 시작하였다.
    이 팀의 경우 신규 팀원들의 능력 및 업무 만족도 향상이 이 작업의 목적중 하나라고 하였다.
    새로 만드는 것만이 교육적으로 의미가 있고 업무 만족도를 향상 시킬수 있다는 것은 생각해 볼 문제이다.^^

  3. 2009.11.12 18:01 신고 neokido  댓글주소  수정/삭제  댓글쓰기

    좋은 내용 참 잘 읽었습니다. ^^

    제가 TDD와 리팩토링 관련 컨퍼런스에 갔었는데. 그때는 초창기라 TDD와 리팩토링에 대한 관심이 대단했던것 같습니다. 그런데 거기 발표자의 발표 내용에서 제가 느낀것은 그 발표자가 말하는 TDD와 리팩토링의 목표가 정확히 무엇인지 알수 없는 말들을 늘어놓았다는 것입니다. (그분은 그냥 TDD를 이용하고, 이렇게 리팩토링을 하면 소스가 이렇게 짧아지고, .. 틈만나면 리팩토링을 해서 좀더 멋지게 잘 돌아가는 코드를 만든다.. 어쩌고.. 저쩌고..)

    과연 TDD와 리팩토링의 목적은 무엇인가? 에 대한 나름대로의 답을 가지고 있을거라 생각합니다.
    하지만 그 나름대로의 생각이, 회사의 이익으로 나타나지 않는다면 그것은 의미가 없을것입니다.

    단지 개발자 자신이 좋아서 하는 리팩토링,
    내가 만든 코드가 상당히 간결하니 내것을 쓰는게 좋을꺼야.. 자 ~ 써.~..
    남들이 TDD랑 리팩토링은 좋은 것이고, 꼭 해야한다고 생각해서
    기타 등등..

    이런 생각의 개발은 프로젝트중에서 또하나의 구멍을 뚫어서 자원을 낭비하는 거나 다름 없는 것이라 생각합니다.
    이제는 개발자가, 사용자와 니즈에 대한 적극적인 자세와 마인드로 개발을 해야할 시대인듯 합니다.
    좀더 Business적인 관점의 개발 마인드를 가지고, 그러한 Business needs 를 구현하기 위해서, TDD나 리팩토링은 좀더 Agile하게 개발을 쉽고, 명확하게 할수 있는 아주 좋은 툴이 될것같네요.

    님의 항상 연구하고, 적용하고자 하는 모습에 저도 다시한번 자극을 받게 되네요 ^^

    자주와서 좋은정보 공유하고 싶습니다. ^^

    • 2009.11.13 10:40 신고 윤청하  댓글주소  수정/삭제

      크나큰 관심과 엄청난 피드백 감사드립니다.^----^
      저는 고객의 비즈니스 가치는 개발자에게 매우 큰 동기 부여라고 생각합니다. 개발자는 자신이 개발하는 기능이 고객의 어떤 환경에서 어떻게 동작하고 어떤 이로움을 주는지 명확하게 알아야 한다고 생각합니다.
      그래서 저는 개발자의 시야가 좀더 넓어질수 있는 '기능개발팀' 혹은 '교차기능팀'을 구성하는 것을 회사에 제안하고 싶지만..
      아쉽게도 아직은 어렵네요.. 기술적 배경으로 성장한 회사라 그런지 기술적 성장에 더 관심이 많은것 같습니다.^^

      TDD는 고객에게 꼭 필요한 기능들을 명확하게 개발하고 품질을 보장할 수 있는 좋은 방법중에 하나라고 생각합니다.~

      다시한번 좋은 말씀 감사드리구요~ 피드백은 언제나 환영입니다.^^

  4. 2010.04.21 11:01 신고 ryoo  댓글주소  수정/삭제  댓글쓰기

    좋은 글 감사합니다..
    영업부와 항상 피해의식만 생겼었는데 이 글을 보니 개발자도 달라져야겠다는 생각이 드네요.
    개발자의 책임이 큰만큼 먼저 반성하고 주도적으로 이끌수 있는 프로젝트를 역량을 갖춰야겠습니다.

티스토리 툴바