모든 소프트웨어 개발 방법론에는 공통적으로 Specification - Design and Implementation - Testing - Maintenance 의 5단계가 들어간다.
Waterfall 은 각 단계가 1번씩만 등장하며, 하나의 단계가 끝나야만 다음 단계로 넘어갈 수 있었고,
Incremental Development 는 이 단게가 반복되었다.
이제 각각의 자세한 단계를 정리해보자.
Software Specification
흔히 '스펙' 이라고 부르는 specification 은 이름 그대로 소프트웨어 개발에 있어 필요한 사항을 명시하는 과정이다.
그리고 소프트웨어 개발에 있어 필요한 사항에는 소프트웨어에서 필요로 하는 기능과 시스템 기능과 개발 단계에서 나타나는 제약 조건이 있다.
이때 제약 조건에는 소프트웨어가 동작할 컴퓨터의 성능 (CPU, 메모리, 스토리지 등), 개발 기간, 투입 가능한 인원 등이 있다.
간단하게 정리하면 specification 단계는 개발할 기능과 여러가지 제약 조건을 모두 찾아 명시하는 과정이다.
소프트웨어에서 필요로 하는 기능을 명시한다는 것은 곧 사용자의 요구사항(requirement)를 파악하는 것과 같다.
specification 단계에서는 위와 같은 단계의 액션이 진행된다.
위 그림에서 둥근 네모는 action 을 말하고, 각진 네모는 그 결과로 만들어지는 document를 말한다.
1. requirements elicitation and analysis
먼저 첫 번째로 요구사항을 추출하고 분석한다.
예를 들어 클래스넷이 마음에 안들어서 개편한다고 해보자.
requirement elicitation 단계는 정말 필요한 요구사항을을 추출하는 과정이다.
사용자들에게 설문조사를 돌려서 어떤 점들이 불편하고, 어떤 기능이 필요한지 물어볼 수도 있고, 기존 시스템을 분석하기도 한다.
아니면 학생, 교수, 직원들을 만나서 직접 인터뷰를 할 수도 있다.
이 과정이 전체 개발 기간의 20%를 차지한다. (이전 글에서 정리했던 막대 그래프를 떠올리자)
정리하면
1. 기존 시스템과 유사 시스템들을 분석하면서 꼭 포함되어야 하는 기능들이 무엇인지 파악하고
2. 사용자에게 가서 설문조사, 인터뷰 등의 방법으로 사용자들이 원하는 요구사항을 파악해야 한다.
이 단계가 제대로 수행되지 않으면 아무리 설계를 잘하고 잘 개발했더라도 사용자들이 만족하는 소프트웨어가 나오기 힘들다.
교수님이 말씀해주신 사례로, 어떤 가수가 병역 대체로 소프트웨어 회사에서 일을 했다고 한다.
그 가수는 회사에서 소프트웨어 기획 일을 했다고 한다.
그러자 사람들이 '개발을 할 줄 모르는 사람이 어떻게 소프트웨어 기획을 하냐' 라고 따졌다고 한다.
그 사람이 진짜로 '소프트웨어 기획' 을 했는지는 다른 문제겠지만, '소프트웨어 기획' 은 분명 전체 개발 프로세스에서 매우 중요한 단계이고, 이 단계도 '소프트웨어 개발' 에 포함되는 일이다.
결론적으로 requirement specification 도 아무리 코드 작성과 직접적인 관련이 없더라도 매우 중요한 일이다.
2. requirements specification
기존 시스템, 유사 시스템을 분석하고 사용자들의 요구사항을 잘 받았다면 그 내용을 정리하여 requirement specification 으로 만들어야 한다.
3. requirement validation
마지막으로는 이렇게 파악한 요구사항이 정말 유효한지 검증해야 한다.
검증은 크게 3가지를 검증한다.
- feasible(실현가능한지)
현재 하드웨어, 소프트웨어, 시간 및 인력 제약 조건 상에서 이 요구사항이 구현가능한 요구사항인지 검토해야 한다.
사용자가 머릿속에 상상한 것을 그대로 그려내주는 UI 를 원한다고 그걸 현재 기술로는 구현할 수는 없다.
- consistency (일관성 있는지)
요구사항들이 서로 앞 뒤가 맞아야 한다.
예를 들어 구현하는 기능 중에 회원들의 나이를 기반으로 상품을 추천하는 기능이 있는데, 회원가입할 때 나이를 입력받지 않는다고 해보자.
그러면 당연히 나이를 기반으로 상품을 추천하는 기능은 구현할 수 없다.
- completeness (완전한지)
유저가 원하는 기능을 하나도 빠짐없이 모두 반영했는지 검토해야 한다.
이 과정까지 모두 거치고 나면 최종적으로 확정된 요구사항인 requirement document 가 나온다.
Software design and implementation
requirement document 를 실제로 실행 가능한 시스템(binary code)으로 변환하는 단계이다.
즉, 자연어로 정의된 requirement document 가 없다면 design 도 implementation 도 할 수 없다.
따라서 requirement document 는 매우 중요하다. 코드 타이핑부터 시작하면 안된다. (여러 번 강조하셨다..)
소프트웨어를 설계한다는 것은 requirement를 만족하는 소프트웨어의 구조(structure)를 설계한다는 것이다.
구조를 설계한다는 것은 구체적으로 필요한 클래스와 public function 들을 설계하는 것과 같다.
이때까지는 단 한 줄의 코드도 작성하지 않는다.
그리고 소프트웨어를 구현한다는 것은 이 structure를 실행가능한 프로그램으로 변환하는 것과 같다.
앞서 정의한 public function 들을 채우는 단계이며, 설계할 때는 public function 들만 설계했기 때문에 구현 과정에서 필요한 경우에는 private function 들을 추가로 구현한다. (참고로 클래스의 data member 는 모두 private 으로 선언해야 한다.)
소프트웨어 설계와 구현은 딱 나눠지지 않고 서로 깊게 연관되어 있기 때문에 수시로 설계하고 구현하는 과정이 반복될 수 있다.
Software Design
소프트웨어를 설계하는 일반적인 과정은 위와 같다.
먼저 이전 단계에서 작성한 requirement specification 을 design input 으로 넣는다.
설계할 때는 프로그램이 돌아갈 플랫폼에 대한 정보와 데이터베이스를 설계할 때 필요한 data description 도 input 에 포함된다.
이 input 을 기반으로 아키텍처 설계, 인터페이스 설계, 컴포넌트 설계를 하고, 데이터베이스 설계까지 하고 나면 design output 으로 시스템 아키텍처, DB 명세, 인터페이스 명세, 컴포넌트 명세가 나온다.
각각의 설계들에 대해서 자세히 정리해보자.
- Architectural design
시스템 아키텍처를 설계한다는 것은 소프트웨어의 가장 큰 그림을 설계하는 것과 같다.
이 과정에서 주요 모듈(컴포넌트 혹은 서브 시스템)과 이들의 관계를 설계한다.
위 그림은 안드로이드의 큰 시스템 아키텍처를 보여준다.
리눅스 커널 - 라이브러리 - 어플리케이션 프레임워크 - 어플리케이션 이라는 계층으로 나누어져 있고, 각 계층을 구성하는 모듈들에 어떤 것들이 있는지 기술되어 있다.
이렇게 시스템 아키텍처를 설계할 때는 전체 시스템을 구성하는 모듈, 서브시스템들을 설계하고 각 시스템간 관계를 설계해야 한다.
- Database design
데이터베이스는 시스템과 독립적으로 떨어져있기 때문에 설계도 독립적으로 할 수 있다.
design input 으로 들어온 data description 을 기반으로 ERD를 그리고 스키마를 설계할 수 있다.
- Interface design
아키텍처 디자인을 통해 설계한 각각의 시스템 컴포넌트가 다른 컴포넌트와 커뮤니케이션할 때 필요한 인터페이스를 설계한다.
(객체지향 관점에서는 위에서 말한 클래스의 public function 을 설계하는 과정이다.)
- component selection and design
아키텍처 디자인을 통해 설계한 서브시스템을 다시 컴포넌트 단위로 나눈다.
이 컴포넌트 내에서도 다른 컴포넌트와 커뮤니케이션할 인터페이스를 설계하는 과정이 필요하다.
또 필요한 컴포넌트 중에서 다른 컴포넌트를 재사용하여 해결할 수 있는 컴포넌트가 있는지도 찾아본다.
System Implementation
설계가 끝났다면 이제 설계한 틀에 맞추어 구현을 해야 한다.
책에서는 구현 과정은 역할을 나눠서 개개인이 각자 알아서 하면 되고, 이 과정에는 표준이 존재하지 않는다고 하지만, 그래도 구현을 더 체계적으로 잘 하기 위한 방법은 있다.
교수님 말씀으로는 구현을 잘하기 위해서는 다음 3가지를 하면 된다고 말씀하셨다.
1. 많이 반복해봐야 한다.
2. 코딩 컨벤션을 따라서 코딩해야 한다.
3. 다른 사람들이 작성한 좋은 코드를 많이 봐야 한다.
실제로 나도 프로젝트 하면서 3가지 모두 중요하다고 느꼈다보니 많이 공감했다.
반복과 컨벤션은 당연히 중요한 말이고, 프로젝트를 할 때도 개발 잘하는 사람들이 진행한 프로젝트나 오픈소스를 읽어보면 이렇게 구현할 수도 있구나 라는 것을 많이 배울 수 있었다.
구현을 하다보면 에러를 수시로 만난다.
그러면 에러를 고치기 위해 디버깅을 하게 될 텐데, 보통 디버깅하는 과정은 위와 같다.
먼저 에러가 발생한 위치를 찾고, 에러를 고칠 방법을 설계한 뒤, 에러를 고치고, 다시 프로그램을 테스트한다.
(너무 당연한 말 아닌가 싶기도 하다)
이때 이 단계에서 제일 어려운 부분은 '에러가 발생한 위치를 찾는 것' 이다.
단순히 IDE 가 알려줘서 에러 위치를 찾는 것 뿐만 아니라, IDE가 알려주지 못하는 런타임에러와 같은 경우에는 그 원인을 파악하기가 매우 힘든 경우가 많다. 특히 그 에러를 재현할 수 있으면 고치기 쉬운 에러지만, 에러가 발생했는데 재현도 안되면 원인을 파악하기가 매우 힘들다. (그런 경우엔 테스트를 엄청 하는 수밖에 없다..)
그리고 그 다음으로 중요한 부분은 Re-test 하는 단계이다.
코드를 수정한 다음에는 에러가 난 부분만 하는 게 아니라 모든 단게를 전체적으로 다시 테스트를 해봐야 한다.
Validation (Testing)
소프트웨어 validation은 크게 Verification 과 Validation 으로 나눠진다.
verification 은 소프트웨어가 specification 을 만족하는지 확인하는 것이고
validation 은 시스템이 requirements 를 만족하는지 확인하는 것이다.
예를 들어 소프트웨어가 스펙에 맞게 버그없이 잘 돌아가는데, 유저가 원하는 방향과는 조금 다르게 돌아간다고 해보자.
이 경우에는 verification 은 만족했지만, validation 은 만족하지 못한 상황이다.
validation 은 체크리스트에 들어있는 것들이 잘 돌아가는지 체크하는 과정(checking), 실제 데이터를 넣고 돌리기 전에 사전에 눈으로 코드를 읽으면서 검사하는 과정 (review), 프로그램을 실행시키고 실제로 데이터를 넣어보고 원하는 결과가 나오는지 확인하는 과정(system testing)을 모두 포함하고 있다.
그리고 testing 은 주로 위에서 정리한 V & V activity 를 사용한다.
테스팅을 하는 단계는 크게 3가지 단계가 있다.
먼저 component testing 은 다른 말로 unit testing 이라고도 하며, 개발자가 자신이 구현한 코드 단위를 테스트하는 것을 말한다.
다음으로 system testing 은 사내 QA 팀에서 진행하는 테스트로 각 컴포넌트를 조립한 전체 시스템에 대한 테스트를 진행한다.
이때 QA 팀에서는 전체 시스템의 아키텍처와 인터페이스를 잘 아는 사람이 테스트를 진행하며, 모듈과 모듈 사이의 상호작용을 위주로 테스트한다.
마지막으로 Acceptance testing 은 고객의 데이터를 가지고 사용자의 요구사항을 만족하는지 검증하는 테스트이다.
회사에서 마치 사용자가 사용하는 것처럼 테스트하며, 이를 '알파 테스트' 라고 부르기도 한다.
이제 기존의 process activity 와 함께 곁들여서 testing phase 를 살펴보자.
먼저 사용자의 요구사항을 분석하여 system specification 을 확정하는 과정에서 acceptance test plan 이 나온다.
specification 은 사용자 입장에서 요구사항을 분석하는 단계이므로 사용자 입장에서 테스트하는 acceptance test 계획을 세울 수 있다.
그 다음 단계로 system specification 을 기반으로 system design 을 하는 단계에서는 system integration test plan 을 세울 수 있고, system design 을 기반으로 detailed design 을 하는 과정에서는 sub system integration test 계획을 세울 수 있다.
설계가 끝나고 각 모듈을 구현하는 단계에서는 개발자가 구현한 뒤 자체적으로 unit test 를 진행한다.
그 다음으로 sub system integration test plan 을 기반으로 서브 시스템 통합 테스트를 진행하고,
system integration test plan 을 기반으로 시스템 통합 테스트를, 마지막으로 acceptance test plan 을 기반으로 acceptance test 를 수행한 뒤, 어플리케이션을 배포하여 실제 사용자들을 대상으로 '베타 테스트'를 진행한다.
베타 테스트까지 끝나면 정식 서비스가 출시된다.
Software evolution (Maintenance)
지금까지의 단계를 거치면 하나의 소프트웨어 버전이 완성된다.
maintenance 단계는 유저의 요구사항이 바뀌거나 버그가 발생하는 등 기존 소프트웨어를 수정할 필요가 생겼을 때 진행하는 단계이다.
소프트웨어는 태생적으로 flexible 하고 계속 변화한다.
비즈니스 환경이 계속 변화하므로, 비즈니스를 지원하는 소프트웨어에 대한 사용자의 요구사항도 계속 변할 수 밖에 없는 것이다.
또한 새로운 기술의 등장에 의해서도 소프트웨어는 변화하기도 한다.
예를 들어 과거 컴퓨터에서는 오직 문자 데이터만 다루었기 때문에 저장 공간이 MB 단위만 되어도 충분했지만, 이미지와 비디오 등 여러 데이터 타입이 등장한 지금은 더 큰 용량이 필요해졌다.
네트워크 통신의 발전으로 더 많은 데이터를 빠르게 주고받을 수 있게 된 것도 영향이 크다.
마지막으로 스마트폰의 출시, OS 버전 업그레이드와 같이 플랫폼의 변화에 의해서도 소프트웨어를 수정해야 하기도 한다.
소프트웨어의 요구사항이 바뀌면 소프트웨어 유지보수를 위해서 다시 처음부터 process 를 반복해야 한다.
그리고 이렇게 과정을 반복하는 것 자체도 커다란 시스템에서 보면 하나의 process part 로 볼 수 있다.
이때 전체 프로세스를 반복하는 것과 관련하여 소프트웨어를 개발하는 방법 중에 Incremental delivery 라는 접근 방법이 있다.
Incremental Delivery
Incremental Development 가 increment 단위로 쪼개서 개발하는 것을 말했다면, incremental delivery 는 크게 하나의 완성된 시스템을 delivery 하지 않고, increment 단위로 delivery 하는 것을 말한다.
이를 위해서 사용자의 요구사항을 쪼갤 때 우선순위를 부여하고, 우선순위가 높은 요구사항을 초기 increment 에 포함해서 배포한다.
보통 가장 중요한 기능이나, 공통 기능의 우선순위가 높다.
그리고 이 방식은 계속해서 후속 increment 를 통해 개발하고 발전시킬 수 있기 때문에 현재 개발중인 increment 에 대해서는 요구사항 변화를 수용하지 않는다.
만약 수정사항이 생기면 뒷 increment 에서 반영한다.
incremental delivery 의 과정을 보면 위와 같다.
incremental development 와 비슷하게 처음에는 간단히 작성된 outline requirement 를 정의하고, 각각의 requirement 에 우선순위를 매겨 increment 에 할당한다.
다음으로 system 아키텍처를 설계하고, 세부적인 system increment 를 개발한다.
개발한 system increment 는 검증하고나서 시스템에 통합시키고, 새로운 increment 가 통합된 시스템을 테스트 한 뒤에 해당 increment 를 배포한다.
만약 전체 개발이 끝났다면 개발을 종료하고, 아직 개발할 increment 가 남아있다면 다시 system increment 를 개발한다.
- 장점
incremental delivery 방식은 각각의 기능이 increment 단위로 나뉘어 들어간 뒤 increment 단위로 배포되므로 고객이 원하는 기능 (customer value) 을 빠르게 배포할 수 있다.
또한 increment 단위로 개발하고 테스트를 반복하므로 초기에 개발된 increment 는 여러번 테스트를 반복해서 하게 되어 전체 시스템의 안정성이 올라간다. 특히 초기 increment 에 포함된 기능은 우선순위가 높은 기능이었던 만큼 우선순위가 높은 기능의 안정성을 높일 수 있다.
게다가 초기 increment 에 포함한 기능들은 일종의 프로토타입 역할을 하여 뒷 increment 를 개발할 때 필요한 요구사항을 추출하는데 도움을 주기도 한다.
예를 들어 초기에는 간단한 전화 기능만 개발했는데, 사용자들이 수신 차단이나 해외 번호 차단과 같은 기능을 원하는 것을 추가로 알게되어 뒷 increment 에 해당 기능을 넣어 개발할 수 있다.
- 문제점
이 방식은 단점은 없지만 문제점이라고 하면 모든 increment 에서 공통적으로 요구하는, 초기에 개발할 common service 를 파악하는 것이 어렵다는 문제점이 있다.
지금까지 Software Process 의 각 세부 단계인 specification, design and implementation, validating, maintenance 의 세부적인 내용들을 정리하였다.
다음 글에서는 RUP 라는 새로운 소프트웨어 프로세스 모델을 정리하는 것으로 개발 방법론의 큰 개요에 대한 정리를 마무리 한다.
'CS > 소프트웨어공학' 카테고리의 다른 글
[소프트웨어공학] 3. Software Process (0) | 2025.04.15 |
---|---|
[소프트웨어공학] 2. 소프트웨어 공학의 의미 (1) | 2025.04.13 |
[소프트웨어공학] 1. 소프트웨어 공학의 목적 (3) | 2025.04.12 |