[우테코 프리코스] 1주차 - 요구사항 분석
1주차 미션의 요구사항을 분석하며
들어가며
우테코 8기 프리코스 1주차 미션이 공개되어 요구사항을 분석하고 설계하는 과정을 기록해보려 한다.
프리코스의 진행 방식
미션은 다음 세 가지로 구성되어 있다.
- 과제 진행 요구 사항
- 기능 요구 사항
- 프로그래밍 요구 사항
프리코스를 진행하며 세 개의 요구사항을 만족하기 위해 노력해야 하며, 기능을 구현하기 전에 구현할 기능 목록을 만들고 기능 단위의 커밋을 해야 한다.
특히 진행 방식에서 아래 항목이 가장 인상적이었다.
기능 요구 사항에 기재되지 않은 내용은 스스로 판단하여 구현한다.
즉, 미션에 명시되지 않은 요구사항을 직접 정리하고 정의하여 끊임없이 작성하고 고치는 과정을 거쳐야 한다.
과제 진행 요구사항
먼저 기능을 구현하기 전에 README.md에 구현할 기능 목록을 정리하고, Git의 커밋 단위는 정의한 기능 목록 단위로 추가해야 한다. Git 컨벤션은 AngularJS Git Commit Message Conventions을 참고해서 작성해야 한다.
기능 단위의 커밋이 중요하다는 건 알고 있었지만, 정확히 어느 수준까지를 한 기능으로 봐야 하는지 기준이 모호하게 느껴졌다. 개인 프로젝트나 팀 프로젝트에서는 어느 정도 자유도가 있더라도, 우테코 프리코스는 선발 과정인 만큼 실수 없이 작성해야 할 것 같았다.
코드를 바로 작성하기보다는 설계 과정을 충분히 거쳐서 코드를 작성해야겠다. 먼저 명시된 요구사항에서 최대한 개인적으로 해석해야 하는 부분들을 해석해보았다.
프로그래밍 요구사항
기능 요구 사항에 앞서 프로그래밍 요구 사항을 살펴보겠다. 주요 내용을 정리하면 다음과 같다:
JDK 21버전 사용- 진입점은
main()메서드 - 우테코 제공 라이브러리 외 외부 라이브러리 사용 불가
- Java Style Guide 준수
System.exit()사용 금지
여기서 도출할 수 있는 핵심은 우테코답게 Java를 잘 사용해야 한다는 점이다.
Java를 잘 사용한다는 것은 필연적으로 객체 지향적인 설계와 코드 작성을 의미한다. 따라서 단일 책임 원칙에 따라 코드를 작성해야 한다고 생각한다.
기능 요구 사항
이번 1주차에서는 문자열 덧셈 계산기를 구현해야 한다. 단순히 문제만 봤을 때는 간단해 보였지만, 막상 명시된 요구사항에서 기능을 도출하고 클래스를 도출해가는 과정이 쉽지 않았다.
- 쉼표(,) 또는 콜론(:)을 구분자로 가지는 문자열을 전달하는 경우 구분자를 기준으로 분리한 각 숫자의 합을 반환한다.
- 앞의 기본 구분자(쉼표, 콜론) 외에 커스텀 구분자를 지정할 수 있다. 커스텀 구분자는 문자열 앞부분의 “//”와 “\n” 사이에 위치하는 문자를 커스텀 구분자로 사용한다.
- 사용자가 잘못된 값을 입력할 경우
IllegalArgumentException을 발생시킨 후 애플리케이션은 종료되어야 한다.
기능 요구 사항은 딱 세 가지다. 기본적인 덧셈 연산에서 연산자 대신 ,와 :를 기본 구분자로 가지고, 커스텀 구분자를 추가하여 연산하는 기능이다. 또한 사용자의 잘못된 값은 IllegalArgumentException으로 통일시켜 에러를 발생시키고 애플리케이션을 종료시켜야 한다.
근거 있는 설계에 도전해보자
설계한 모든 내용에는 명확한 근거가 있어야 한다고 생각한다. 따라서 주어진 요구사항을 하나씩 정리하면서 나만의 요구사항으로 재정의하고 개발에 들어가야겠다.
먼저 요구사항을 읽으면서 유의미한 명사와 동사를 강조해서 객체의 후보군이 되는 것들을 정리해보면
- 문자열에서 숫자를 추출하여 더하는 계산기
- 구분자를 기준으로 분리
- 커스텀 구분자를 지정
- 잘못된 값 입력 시 예외 발생
객체 후보군(명사)을 요약하면 아래와 같다.
- 계산기
- 구분자
- 숫자
- 문자열
- 예외
책임 후보군(동사)을 요약하면 아래와 같다.
- 추출
- 덧셈
- 분리
- 검증
객체 후보군과 책임 후보군을 정리했지만, 바로 클래스로 정리하기에는 머릿속에서 정리가 잘 되지 않아 각 책임을 어떤 객체가 가져야 하는가에 대해 생각해봤다.
책임 중심
요구사항에서 추출한 동사들을 구체화시켜보면 아래와 같이 정리할 수 있다.
- 추출: 문자열에서 구분자와 숫자를 뽑아내기
- 분리: 구분자로 문자열 나누기
- 검증: 올바른 숫자인지 확인하기
- 계산: 숫자들을 더하기
이 네 가지 책임이 각각 독립적으로 동작할 수 있다고 생각한다.
객체에 책임을 배분
구체화한 책임을 위의 객체 후보군과 함께 아래와 같이 정리할 수 있다.
1. Parser - 입력 파싱 책임
"//;\n1;2;3" 같은 특수 형식을 처리해야 한다.
- 커스텀 구분자가 있는지 확인
- 구분자 부분 추출
- 숫자 부분 추출
문자열에서 구분자(커스텀 포함)와 숫자를 추출하는 것이 Parser의 역할이다.
2. Delimiter - 구분자 처리 책임
- 기본 구분자(
,,:)를 알고 있어야 한다 - 커스텀 구분자를 추가할 수 있어야 한다
- 구분자들로 문자열을 분리해야 한다
3. NumberValidator - 숫자 검증 책임
- 문자열이 숫자인지, 음수는 아닌지 확인한다
- 잘못된 값이면 예외를 발생시킨다
4. Calculator - 전체 조율 책임
- 세부 구현을 각 객체에 위임하고 Calculator는 흐름만 관리한다
각 클래스에 들어갈 기본적인 기능들을 정리하면 아래와 같다. 
마치며
기능 단위 개발을 위해 클래스 구조를 설계해보았다. 이 설계를 완벽하게 지킬 수는 없겠지만, 설계에 많은 시간을 들인 만큼 변경사항을 최소화하며 개발을 진행해야겠다. 설령 접근 방식이 틀렸더라도, 이 과정에서 배운 점들을 다음 미션에 적용할 수 있을 것이다.
