////
Search
Duplicate
🎶

3. 준비는 철저하게: 선행 조건

공사를 시작하기 전 건축가는 설계도를 검토하고 서류를 작성한다. 당연히 고층 빌딩을 지을 대와 주택을 지을 때, 강아지 집을 지을때 각각 다른 방법으로 준비한다.
프로젝트가 무엇이든 준비 작업은 프로젝트의 구체적인 요구사항에 맞춰 구현을 시작하기 전에 상세하게 진행되어야 한다.
이 장에서는 소프트웨어 구현에 앞서 꼭 수행해야 하는 준비 작업들을 설명한다.

1. 선행 조건의 중요성

좋은 품질의 소프트웨어를 개발하는 개발자들은 프로젝트의 시작과 중간, 끝 단계에서 품질을 중요시 여긴다.
프로젝트의 시작 단계에서 품질을 강조하는 경우, 제품을 계획하고 요구사항을 수집하고 설계한다.
프로젝트의 중간 단계에서 품질을 강조하는 경우, 구현 방법에 역점을 둔다.
프로젝트의 끝 단계에서 품질을 강조하는 경우, 시스템 테스트에 중점을 둔다.
선행 조건이 최신 소프트웨어 프로젝트에도 적용되는가?
물론이다. 준비 작업의 가장 중요한 목표는 위험 축소다. 훌륭한 프로젝트 기획자는 프로젝트가 매끄럽게 진행될 수 있도록 위험요소를 초기에 가능한 제거한다.
불완전한 준비의 원인
불완전한 준비의 일반적인 원인은 선행 조건 작업에 투입되는 개발자가 자신의 작업을 수행할 수 있을 정도의 전문가적인 지식을 갖고 있지 않기 때문이다.
일반적으로 개발자들은 그러한 활동을 어떻게 수행할 것인지에 대한 교육을 받은 적이 없다.
개발자들이 선행 작업을 어떻게 수행하는지도 모르는데 선행 작업을 더 많이 수행하라고 권하는 것은 말이 안 된다.
선행 작업을 수행하는 방법을 어느정도 알고 있지만 코드를 작성하는데 급급해 준비 작업을 하지 않는 개발자도 있다.
커다란 프로그램은 미리 계획을 세워두는 것만으로도 어느정도 미래의 문제들이 해결된다. 코드 작성에 급급해하지 말자.
개발자가 선행 조건을 준비하지 않는 마지막 이유는 관리자들이 구현에 필요한 선행 조건을 수행하기 위한 시간을 못마땅하게 생각하기 때문이다.
가급적이면 상사가 모르게 선행 조건을 계획하자.
아니면 상사를 설득해보는 것도 좋은 전략일 것이다.
구현 전에 선행 조건을 수행하기 위한 필수적인 논의
기술자로서 해야 하는 일 중에는 프로젝트 이해관계자들에게 충분히 개발 프로세스에 대해서 교육하는 것도 포함되어 있다.
여기에는 코드 작성과 테스트, 디버깅을 시작하기 전 요구사항 분석 및 아키텍처 설계에 대해 상사와 논쟁하는 과정이 포함된다.
논리적 설득
큰 프로젝트는 더 많은 계획 수립이 필요하고 작은 프로젝트는 상대적으로 덜 필요하다.
관리 측면에서 계획 수립은 프로젝트에 잘못된 작업으로 인해 자원을 낭비하는 일이 없도록 하는 것이다.
비유적 설득
소프트웨어 시스템을 구축하는 것은 인력과 돈이 필요한 다른 프로젝트와 같다.
집을 지을 때 다양한 절차들이 있듯이 프로젝트를 구현하는데도 다양한 절차가 있음을 비유적으로 표현하면 설득해보라.
데이터에 근거한 설득
지난 25년 간의 연구 결과에서 증명된 사실은 처음부터 작업을 제대로 수행해야 한다는 것이다.
어느정도 프로젝트가 진행된 시점에서 변경사항이 발생하는 것은 생산성을 현저히 저하시키는 행위다.
이것은 가능한 빨리 문제를 찾고 해결하는 것이 좋다는 주장을 뒷받침한다.
그래서 소프트웨어 테스트를 작성하라고 하는건가..?

2. 작업 중인 소프트웨어의 종류 결정

다음은 일반적인 세 가지 종류의 프로젝트와 각 프로젝트에 적합한 방법을 표로 정리해둔 것이다.
다음 표를 참고해서 본인의 프로젝트를 규정하고 그에 맞는 준비 사항들을 알아보자.
비즈니스 시스템
특수임무용 시스템
임베디드 안전 필수 시스템
일반적인 응용 프로그램
인터넷 사이트 인트라넷 사이트 재고 관리 게임 정보 관리 시스템 급여 지급 시스템
임베디드 소프트웨어 게임 인터넷 사이트 패키지 소프트웨어 소프트웨어 도구 웹 서비스
항공전자 소프트웨어 임베디드 소프트웨어 의료기기 운영체제 패키지 소프트웨어
수명 주기 모델
애자일 개발 진화적 프로토타이핑
단계적 출시 진화적 출시 나선형 개발
단계별 출시 나선형 개발 진화적 출시
계획 및 관리
점증적 프로젝트 계획 필요에 따라 테스트 및 QA 계획 수립 비형식적인 변경 관리
기초적인 선행 계획 수립 기초적인 테스트 계획 수립 필요에 따라 QA 계획 수립 형식적인 변경 관리
광범위한 선행 계획 수립 광범위한 테스트 계획 수립 광범위한 QA 계획 수립 엄격한 변경 관리
요구 사항
비형식적인 요구사항 명세
중간 수준의 정형화된 요구사항과 명세 필요에 따라 요구사항 검토
형식적인 요구사항 명세 형식적인 요구사항 정밀 검사
설계
설계 및 코드 작성의 병행
아키텍처 설계 비형식적인 상세 설계 필요에 따라 설계 검토
아키텍처 설계 형식적인 아키텍처 정밀 검사 형식적인 상세 설계 형식적인 상세 설계 정밀 검사
구현
페어 프로그래밍이나 개별적인 코드 작성 비형식적인 체크인 절차 또는 체크인 절차 없음
페어 프로그래밍이나 개별적인 코드 작성 비형식적인 체크인 절차 필요에 따라 코드 검토
페어 프로그래밍이나 개별적인 코드 작성 형식적인 체크인 절차 형식적인 코드 정밀 검사
테스트 및 QA
개발자가 자신이 작성한 코드를 테스트 TDD 별도의 테스트 그룹에 의한 테스트 부재
개발자가 자신이 작성한 코드를 테스트 TDD 별도의 테스트 그룹
개발자가 자신이 작성한 코드를 테스트 TDD 별도의 테스트 그룹 별도의 QA 그룹
배포
비형식적인 배포 절차
형식적인 배포 절차
형식적인 배포 절차
선행 조건에서 반복적인 접근 방법이 갖는 효과
반복적인 방법은 프로젝트가 진행되는 과정에서 조금씩 재작업하기 때문에 전체적으로 드는 비용이 더 적어지게 된다.
선행 조건을 줄이거나 없앤 반복적인 프로젝트는 동일한 조건의 순차적 프로젝트와 두 가지 측면에서 다르다.
첫째, 결합 발생 후 상대적으로 빠르게 발견되므로 평균 결함 수정 비용이 더 적게 든다.
결함이 각 단계의 마지막에 발견될 것이므로 결함을 수정하는 과정에서 소프트웨어의 일부분을 재설계하고 코드를 재작성하며 테스드도 다시해야 한다. 이는 결함 수정 비용을 증가시킨다.
둘째, 반복적인 접근 방법에서의 비용은 마지막에 한꺼번에 들지 않고 전체 프로젝트 과정에 조금씩 흡수된다.
저자가 추천하는 방법은 요구사항 중 80% 정도를 미리 명시하고 추가적으로 기술할 시간을 할당해둔 다음 프로젝트를 진행하면서 중요한 요구사항들만을 새로 수용할 수 있도록 설계하는 것이다.
반복적인 방법과 순차적인 방법의 선택
다음의 경우, 순차적인 접근 방법을 선택하는 것이 낫다.
요구사항이 안정적일 때
설계가 직관적이며 이해하기 쉬울 때
개발 팀이 해당 응용 분야에 익숙할 때
프로젝트의 위험 부담이 적을 때
장기적인 계획이 중요할 때
요구사항, 설계, 코드 변경 비용이 높을 것 같을 때
다음 경우에는 반복적인 접근 방법이 낫다.
요구사항을 제대로 이해하기 힘들거나 다른 여러 이유로 변경될 가능성이 높을 때
설계가 복잡하거나 어려울 때
개발 팀이 해당 응용 분야에 대해 잘 모를때
프로젝트의 위험 부담이 높을 때
장기적인 계획이 중요하지 않을 때
요구사항, 설계, 코드 변경 비용이 높지 않을 것 같을 때
즉 변동 가능성이 높다면 반복적인 방법을 낮다면 순차적인 방법을 선택하는 것이 좋다.
소프트웨어의 특성상 일반적으로 반복적인 방법이 순차적인 방법보다 훨씬 유용한 경우가 많다.

3. 문제-정의 선행 조건

구현에 앞서 첫 번째 선행 조건은 시스템이 해결해야 하는 문제를 명확하게 기술하는 것이다.
이를 제품 정의, 문제 정의라고도 한다.
문제 정의는 반드시 도메인 상세 언어로 작성해야 하며 문제는 사용자 관점에서 기술해야 한다.
문제 정의를 제대로 하지 않으면 잘못된 문제를 해결하는 데 시간을 낭비할 수도 있으므로 신중히 많은 시간을 들여서 정의하는 것이 좋다.

4. 요구사항 선행 조건

요구사항은 소프트웨어 시스템이 무엇을 수행해야 하는지에 대해 상세하게 기술하고 해결책을 구현하기 위한 첫 번째 과정이다.
요구사항을 수집하는 작업을 요구사항 개발, 요구사항 분석, 요구사항 정의, 기능 명세, 명세라고 한다.
왜 명시적인 요구사항이 필요한가?
명시적인 요구사항은 개발자 대신 사용자가 시스템의 기능을 주도하게 하는 데 도움이 된다.
요구사항이 명시적이면 사용자가 요구사항을 보고 동의할 수 있다. 그렇지 않으면 개발자의 관점에서 요구사항을 결정해 버리는 경우가 많다.
요구사항을 명시적으로 정의함으로써 사용자가 원하는 것이 무엇인지를 이해할 수 있다.
명시적인 요구사항은 논쟁을 피하게 해준다. 프로그래밍을 시작하기 전에 시스템 기능을 결정하므로 프로그램의 기능에 대해서 다른 개발자가 동의하지 않는다면 요구사항을 살펴보면서 문제를 해결할 수 있다.
요구사항에 집중하면 개발을 시작하고 난 후 변경 사항을 최소화하는 데 도움을 준다.
요구사항이 변경되면 기존의 코드를 재설계해야 하고 새로 설계하는 것보다 시간이 더 오래 걸리게 될 것이다.
요구사항을 제대로 명시하는 것은 프로젝트 성공에 있어 효과적인 구현 기술보다 더 중요하다.
견고한 요구사항에 대한 미신
견고한 요구사항은 소프트웨어 개발의 성배와 같다. 요구사항이 견고하면 아키텍처부터 설계, 코드 작성, 테스트까지 프로젝트를 차분하게 잘 진행할 수 있다.
일반적으로 사용자는 코드가 작성되기 전까지 자기에게 필요한 사항을 확실하게 설명하지 못한다.
사용자에게 문제가 있는것이 아니다. 프로젝트를 진행할수록 프로젝트에 더 많이 알듯이 사용자도 마찬가지기 때문이다.
개발 과정에서 사용자는 자연스럽게 자신에게 필요한 요구사항을 더 잘 이해하게 되며 이러한 과정이 요구사항 변경의 주요한 원인이다.
구현 중에 요구사항 변경 다루기
다음은 요구사항의 변경을 잘 다루기 위한 몇 가지 방법이다.
1.
요구사항의 품질을 평가한다.
요구사항이 충분치 않다면 작업을 멈추고 저장해둔 다음 요구사항을 제대로 수정한 후 일을 진행한다.
이는 불필요한 과정이 아니다. 빠르게, 느리게가 중요한게 아니다. 올바르게 가고 있는가가 중요하다.
2.
모든 사람이 요구사항 변경 비용에 대해서 알게 한다.
자원의 소모는 사람의 정신을 맑게 해준다.
3.
요구사항 변경 절차를 구축한다.
4.
변경 사항들을 수용하는 개발 접근 방법을 사용한다.
진화적 프로토타이핑 접근 방법을 사용하면 요구사항에 능동적으로 대응할 수 있다.
작게 구축하여 피드백을 받고 설계를 약간만 수정한 다음 피드백을 받는다. 핵심은 사용자에게 빠르게 피드백을 받을 수 있도록 개발 주기를 짧게 가져가는 것이다.
5.
프로젝트를 취소한다.
요구사항이 형편없거나 변경 가능성이 높다면 그 프로젝트는 취소해야 한다.
6.
프로젝트의 사업성을 주시한다.
요구사항 문제의 상당수는 프로젝트를 수행하는 사업상 목적을 고려하게 된다면 무의미해진다.
정말로 필요한가에 대한 고민을 시켜보자.

5. 아키텍처 선행 조건

소프트웨어 아키텍처는 소프트웨어 설계의 상위 부분에 속하며 설계 중에서 더 상세한 부분을 담은 틀이다.
아키텍처는 시스템 아키텍처, 상위 수준 설계, 최상위 설계라고도 불린다.
아키텍처가 왜 선행 조건에 포함될까? 그것은 아키텍처의 품질이 시스템의 개념적인 무결성을 결정하기 때문이다. 이는 곧 시스템의 궁극적인 품질을 결정짓는다.
좋은 아키텍처는 구현을 쉽게 만든다. 나쁜 아키텍처는 구현을 거의 불가능하게 만든다.
전형적인 아키텍처의 구성 요소
좋은 시스템 아키텍처에는 공통 요소가 많다. 다른 사람과 협업을 하게 되므로 반복되는 코드나 함수를 유틸로 뺀다던지, 데이터 소스 접근 방법을 일관화한다든지 말이다.
비즈니스 로직 외의 요소들은 가급적이면 공통 요소들이 처리하게 두는 것이 낫다.
프로그램 구조, 주요 클래스, 데이터 설계, 비즈니스 규칙, 사용자 인터페이스 설계, 자원 관리, 보안, 성능, 확장성, 상호운용성, 국제화와 지역화, 입력/출력, 오류 처리, 장애 허용, 구조적인 실행 가능성, 과도한 엔지니어링, 구입과 구현 결정, 재사용 결정, 변경 전략, 일반적인 아키텍처 품질

6. 선행 조건에 소요되는 시간

문제 정의와 요구사항, 소프트웨어 아키텍처 작업에 소요하는 시간은 프로젝트의 필요에 따라 달라진다.
일반적으로 제대로 진행되는 프로젝트는 요구사항과 아키텍처, 사전 계획 수립을 위해서 전체 노력의 10%~20% 정도와 전체 시간의 20~30%의 시간을 투자한다.
상세 설계는 제외된 시간이다. 상세 설계는 구현의 일종이다.
요구사항이 불안정하고 작업 중인 프로젝트의 규모가 크다면 구현 초기에 발생하는 요구사항 이슈를 해결하기 위해 요구사항 분석가와 작업해야할 수도 있다.
요구사항이 불안정하고 작업 중인 프로젝트의 규모가 작다면 직접 요구사항 이슈를 해결해야할 것이다. 요구사항을 정의하는 데 충분한 시간을 투입하여 요구사항의 변경이 구현에 미치는 영향을 최소화하라.
소프트웨어 아키텍처에 시간을 할당할 때도 요구사항 개발과 유사한 방법을 사용한다.
지금까지 한 번도 다루지 않은 소프트웨어라면 새로운 분야에서의 불확실한 설계에 대비하여 더 많은 시간을 할애하라.
좋은 아키텍처를 위해 소비하는 시간 때문에 다른 작업 영역에 지장을 주지 않도록 하라. 필요하다면 아키텍처 작업 역시 요구사항 작업과 같이 별도의 프로젝트로 진행한다.

요점 정리

구현을 준비할 때 가장 중요한 목표는 위험을 줄이는 것이다. 준비 작업이 위험을 증가시키는 게 아니라 감소시키도록 하라.
품질이 뛰어난 소프트웨어를 개발하고 싶다면 처음부터 끝가지 소프트웨어 개발 과정 내내 품질에 관심을 두라.
품질에 대한 관심을 처음에 갖는 것이 나중에 갖는 것보다 제품의 품질에 훨씬 큰 영향을 끼친다.
프로그래밍을 시작하기 전 적절한 준비의 중요성을 포함한 소프트웨어 개발 과정에 대해 상사와 동료를 설득하는 일도 개발자의 몫이다.
프로젝트의 종류가 구현 선행 조건에 중대한 영향을 미친다. 반복적으로 진행해야 하는 프로젝트도 많지만 순차적으로 진행해야 하는 프로젝트도 있다.
문제 정의가 명시되어 있지 않다면 구현 시에 잘못된 문제를 풀게 될 것이다.
요구사항 개발이 제대로 이루어지지 않았다면 문제의 중요한 사항을 놓칠 수가 있다. 구현 다음 단계부터는 요구사항을 변경할 때 처음부터 20배에서 100배 정도의 비용이 더 들기 때문에 프로그래밍을 시작하기 전에 요구사항어 정확한지 확인해야 한다.
아키텍처 설계가 제대로 이루어지지 않았다면 구현 시에 올바른 문제를 잘못된 방법으로 해결할 수 있다.
잘못된 아키텍처로 작성된 코드가 증가할수록 구조적인 변경 비용이 발생하므로 아키텍처가 적합한지 확인하라.
프로젝트에서 구현 선행 조건에 어떤 접근 방법을 적용했는지 알고 그에 따라 적절한 구현 방법을 선택하라.