[프리코스 길잡이 #1] 기능명세서 그리고 커밋

pengooseDev·2023년 10월 20일
66

함께하는 프리코스 크루들에게

프리코스를 참여하는 친구와 함께 모각코를 하다가, 친구가 물었다.

야 기능명세서는 어떻게 쓰는거냐?

작년의 내 모습이 떠올랐다.
독학으로 협업 경험이 없던 나에게 작년 프리코스는 개발자로서의 전환점이었다.

음... 그때 누가 이런 방식으로 방향성을 제시해줬으면 조금 더 많이 고민할 수 있었을텐데..!


MVC? TDD? DDD? 디자인 패턴..? 그게 뭐에요?

너무 어렵다.
필자도 작년 프리코스에서 이런 키워드들을 처음 접하고, 미션에 열심히 적용하느라 너무 힘들었다.

다만! 너무 어렵다면, 우선 아래의 방식으로 기능 명세서를 분석해보며 첫 걸음을 내딛어보자.

물론, 이때 얻은 키워드들이 1년 동안의 좋은 학습 방향성을 제공해준 것은 명백하다. 또한, 이러한 키워드들을 열심히 학습해서 현재의 미션에 한 번은 적용해보는 것이 나쁜 경험은 아니라고 생각된다.
1주차 미션이 끝나면, 반드시 다른 사람들의 PR을 분석해보고 따로 키워드 적어서 공부하고 적용해보자! :)


기능명세서

필자는 기능명세서를 작성하기 전, 아래의 단계를 거쳐 문제를 분석한다.

  1. 어떤 기능들이 필요한가?
  2. 필요한 객체는 무엇인가?
  3. 이 객체들은 어떻게 상호작용하고 있는가?

예를 들어, 다음과 같은 문제를 생각해보자.

문제 : 금액을 입력받아 붕어빵을 판매하는 게임을 만드시오.

이 문제를 풀기 위한 접근 방법을 조금 더 구체적으로 살펴보자.


1. 어떤 기능들이 있는가?

우선, 구현해야 할 애플리케이션의 기능들을 체계적으로 나열해보자. 이렇게 하면 무엇을 해야 할지 명확히 알 수 있고, 각 기능이 서로 어떻게 연결되어 있는지 이해할 수 있다.

- [ ] 금액을 입력받는다.
- [ ] 붕어빵의 수량을 계산한다.
- [ ] 수량만큼 붕어빵을 생산한다.
- [ ] 수량만큼의 붕어빵을 건네준다.

간단해보이지만, 이렇게 기능을 구체적으로 나누고, 각각의 세부 사항까지 고려하면서 작성하는 것은 프로그램의 전반적인 흐름을 이해하는 데 큰 도움이 된다. 또한, 이 과정을 통해 미처 생각하지 못했던 부분이나 잠재적인 문제점들을 미리 발견할 수 있다.


2. 어떤 객체들로 이루어져있는가?

여기서 객체란 특정한 역할을 담당하는 주체 또는 요소를 말한다.

이 게임에서는 손님붕어빵 장수에게 돈을 지불하고, 붕어빵 장수는 해당 금액에 알맞은 갯수의 붕어빵손님에게 제공한다.
이 과정 속에서 각 객체는 아래와 같은 역할을 수행한다.

손님

속성: 지불하고자 하는 금액
행동: 금액을 지불한다, 붕어빵을 받는다.

붕어빵 장수

속성: 붕어빵 가격
#행동: 금액을 받아 붕어빵의 수량을 계산한다. 붕어빵을 제공한다.

이를 기반으로 기능명세서를 분리해보자.

## 손님
- [ ] 구입 금액을 입력할 수 있다.
- [ ] 붕어빵을 구매한다.

## 붕어빵 장수
- [ ] 손님에게 금액을 받아 그에 맞는 수량을 계산한다.
- [ ] 수량에 맞는 붕어빵을 전달한다.

## 붕어빵
- 맛있다. 얌미

3. 어떻게 상호작용하는가?

우리가 분석한 객체는 서로 상호작용하며 유기적으로 동작한다.
위의 분석에서 각 "객체"들의 상호작용을 생각해보자.

  • 손님 <=> 붕어빵 장수
  • 붕어빵 장수 <=> 붕어빵
  • 붕어빵 <=> 손님
## 손님
- [ ] 구입 금액을 입력할 수 있다.
- [ ] 금액을 입력받아 붕어빵 장수에게 전달한다.
- [ ] 붕어빵 장수가 건네준 붕어빵을 받아서 먹는다.

## 붕어빵 장수
- [ ] 손님이 건네준 돈을 확인한다.
- [ ] 금액에 맞는 붕어빵 개수를 계산한다.
- [ ] 계산한 개수만큼 붕어빵을 만든다.
- [ ] 붕어빵이 든 봉투를 손님에게 건네준다.

## 붕어빵
- 맛있다.

어느정도 문제 분석과 기능명세서 작성이 완료되었다면 기능명세서 단위로 커밋을 진행한다.
너무 기능명세서를 완벽하게 쓰지 않아도 괜찮다. :)
코드를 작성하다보면 새로운 기능이 떠오를 것이고, 그때 천천히 기능명세서를 수정하는 것이 좋다!

살아있는 기능 명세서를 만들어보자.

git commit -m "docs: 기능 명세서 추가(구현 목록 추가)"
커밋 메시지는 자유롭게! :)

자 이제 기능 명세서 작성은 1차적으로 완료되었다.
이제 우리가 작성한 기능명세서를 기반으로 구현과 커밋을 진행해보자 :)


커밋하기

이제 우리가 작성한 기능명세서를 기반으로 코드를 구현 => 커밋 => 기능명세서 수정을 진행해보자.

붕어빵 장수의 기능 중 하나를 구현해보자.

1. 코드 구현

  • 붕어빵 장수는 금액에 맞는 붕어빵 개수를 계산한다.
// JS :)

class 붕어빵_장수 {
  private 붕어빵_가격 = 1_000;

  붕어빵_수_계산(금액){
    return parseInt(금액 / this.붕어빵_가격, 10);
  }
}

2. 기능명세서 수정

## 손님
- [ ] 구입 금액을 입력할 수 있다.
- [ ] 금액을 입력받아 붕어빵 장수에게 전달한다.
- [ ] 붕어빵 장수가 건네준 붕어빵을 받아서 먹는다.

## 붕어빵 장수
- [ ] 손님이 건네준 돈을 확인한다.
- [x] 금액에 맞는 붕어빵 개수를 계산한다.
- [ ] 계산한 개수만큼 붕어빵을 만든다.
- [ ] 붕어빵이 든 봉투를 손님에게 건네준다.

## 붕어빵
- 맛있다.

3. 커밋! 🥳

필자는 기능명세서의 내용을 그대로 쓰는편이다.

> git add .
> git commit -m "feat: 금액에 맞는 붕어빵 개수를 계산한다"

4. 앗! 아이디어가 떠올랐다!

코드를 작성하다보면 추가적인 구현 사항이 떠오르거나, 설계가 변경되기 마련이다.
기능명세서를 수정하는 것에 두려워하지 말자!

## 손님
- [ ] 구입 금액을 입력할 수 있다.
- [ ] 금액을 입력받아 붕어빵 장수에게 전달한다.
- [ ] 붕어빵 장수가 건네준 붕어빵을 받아서 먹는다.

## 붕어빵 장수
- [ ] 손님이 건네준 돈을 확인한다.
- [x] 금액에 맞는 붕어빵 개수를 계산한다.
- [ ] 전달받은 금액이 유효한 금액인지 확인한다. << 추가된 부분!
- [ ] 계산한 개수만큼 붕어빵을 만든다.
- [ ] 붕어빵이 든 봉투를 손님에게 건네준다.

## 붕어빵
- 맛있다.

커밋에 올리자!

git add .
git commit -m "docs: 기능 명세서 수정(구현목록 추가)"

역시나 커밋 메시지는 자유롭게! :)


열심히 구현하기

대략적으로 붕어빵 장수를 추상화해보자.
추상화의 정도는 본인이 스스로 결정한다.

class 붕어빵_장수 {
  private 오늘_번_돈 = 0;
  private 붕어빵_가격 = 1_000;
  private 붕어빵_생성기;

  constructor(팥_붕어빵_생성기) {
    this.붕어빵_생성기 = 팥_붕어빵_생성기;
  }

  private 붕어빵_수_계산(금액){
    return parseInt(금액 / this.붕어빵_가격, 10);
  }
  
  private 팥_붕어빵_만들기(개수) {
    return this.팥_붕어빵_생성기(개수);
  }

  // 외부에서 접근해야하기 때문에 private을 추가하지 않는다.
  붕어빵_판매(금액) {
    this.진짜_돈인지_확인(금액);
    this.오늘_번_돈 += 금액;
    
    const 개수 = this.붕어빵_수_계산(금액);
    const 따끈따끈_붕어빵들 = this.팥_붕어빵_만들기(개수);    
    
    return 따끈따끈_붕어빵들;
  }

 // ..codes
}

어떨때는 오버엔지니어링이 될 수도, 언더엔지니어링이 될 수도 있다.
하지만 너무 슬퍼하지 말자. 성장의 과정일 뿐이다.

프리코스 크루들의 PR을 열심히 염탐하고, 함께 리뷰하고 토론을 하며 매주 발전하는 코드를 작성한다면 그게 가장 큰 성과이지 않을까 생각한다. 🥳


입구에서 펭구스를 찾아주세요

충분한 고민이 들어가있고, 의사결정 근거가 들어있는 코드에 대한 토론 및 리뷰가 필요하다면 언제든 프리코스의 [FE]펭구스를 링크해주시면 감사하겠다. 🥳

FE / BE / AOS 구분 없이, 동일한 미션에 대해 함께 고민한 것을 나누는 것이 가장 빠른 성장의 길이었다! :)

23개의 댓글

comment-user-thumbnail
2023년 10월 20일

기능 명세에 좋은 가이드인것같네요!
붕어빵 얌미 ㅋㅋㅋㅋㅋ귀엽네요
입구에서 기다리겠습니다 펭구스님!🙇🏻

1개의 답글
comment-user-thumbnail
2023년 10월 20일

저도 어제 기능 명세 작성하느라 시간이 엄청 오래 걸렸는데 잘 작성했는지 긴가민가 했거든요.
그런데 펭구스님의 글과 겹치는 내용이 많아서 올바른 방향으로 고민했다는 생각이 드네요 ㅎㅎ
앞으로도 종종 찾도록 하겠습니다 🐧🐧

1개의 답글
comment-user-thumbnail
2023년 10월 20일

"1. 어떤 기능이 있는가?"에 있는 형태로만 작성했는데, 덕분에 더 발전시킬 수 있었어요!!!!☺️👍🏿👍🏿👍🏿
펭구스,,,귀한 자료 감사합니다!!🙏

1개의 답글
comment-user-thumbnail
2023년 10월 21일

단순 기능 명세한 다음에 구현하면서 객체에게 기능을 할당할 것인가, 아니면 객체가 어떤 역할을 할 지까지도 미리 명세해둘까 라는 고민이 있었는데 덕분에 갈피가 잡히네요. 펭구스 감사합니다 :D

1개의 답글
comment-user-thumbnail
2023년 10월 23일

ㅋㅋㅋㅋㅋㅋ 왠지 객체의 소리를 들을 때가 새록새록 떠오르네요.. 프리코스에서도 펭구스님을 만나게 되어 반갑네여 프리코스 화이팅입니다! 🙇‍♀️ 글 잘 보고 가요 ㅎㅎ

1개의 답글
comment-user-thumbnail
2023년 10월 23일

우연히 들어왔는데 이 글을 보면서 제 1주차 미션 코드를 많이 반성하게 됐네요...🥲
펭구스님 덕분에 많은 것 배워갈 것 같습니다!
2주차도 화이팅 하세요!

1개의 답글
comment-user-thumbnail
2023년 10월 24일

정말 좋은 글이네요. 갓펭구

1개의 답글
comment-user-thumbnail
2023년 10월 25일

펭츕님 폼 미춋다이

1개의 답글
comment-user-thumbnail
2023년 10월 25일

프리코스 커뮤니티에서 몇번 뵀었는데 여기서 뵈니까 신기하네요 ㅋㅋㅋ
글 잘 읽었습니다 같이 프리코스 화이팅입니다!

1개의 답글
comment-user-thumbnail
2023년 10월 26일

안녕하세요!! 저도 이번 프리코스 하는데 큰 도움이 되었어요! 블로그에 인용해도 될까요??

1개의 답글
comment-user-thumbnail
2023년 11월 1일

ㅋㅋㅋㅋㅋ 좋은 내용인거 같아요! 붕어빵 얌미가 너무 귀엽네욬ㅋㅋㅋ

1개의 답글