[우테코 프리코스] 2주차 회고

·2022년 11월 9일
2
post-thumbnail

0. 프로젝트 가이드라인 확인

이번에는 숫자 야구 게임(우테코 2주차 깃허브 링크)이었다. 주 기능은 컴퓨터에서 3자리 숫자를 랜덤으로 생성한 후, 사용자의 입력값을 받아와 사용자에게 스트라이크/볼/낫싱으로 힌트를 주는 것이다. 추가된 요구 사항은 크게 정리하자면

  1. 함수를 분리해서 indent(들여쓰기)레벨을 2까지 맞추기
  2. jest를 사용하여 테스트 코드를 구현하기
  3. 주어진 라이브러리를 사용하기

가 되겠다. 가이드라인을 확인한 후

  1. 기능 목록 정리하기
  2. jest 사용 방법 익히기
  3. 테스트코드 작성
  4. 기능 구현
  5. prettier/es lint 적용
  6. pull request 보내기

순으로 진행하였다.
이번에 진행한 내 깃허브 레포지토리는 여기이다.

이 글의 마지막에는 피드백과 소감을 적어 보았다.

1. 기능 목록 정리하기

처음에 정리한 이후 수정을 좀 거쳤지만 최종적인 기능 목록은 다음과 같다.

1. 게임 시작 문구 출력
2. 숫자 랜덤 생성
    - 3자리 자연수
    - 1부터 9까지의 숫자로 구성
    - 중복 불가
3. 사용자 입력 유효성 검사
    - e) 3자리 자연수가 아닌 경우
    - e) 0이하의 정수 불가
    - e) 중복된 숫자 불가
4. 사용자 입력 받아오기
5. 스트라이크/볼 카운트 세기
5. 정답 검사 결과 출력
    - 볼, 스트라이크 둘다 존재 : 볼 -> 스트라이크 순서, 숫자 + 볼/스트라이크
    - 하나도 없는 경우 - 낫싱
    - 정답시 종료 문구 출력
    - 오답시 3. 사용자 입력 검사 반복
6. 종료 검사
    - 1 입력시 1. 게임 시작 문구 출력으로 돌아감
    - 2 입력시 종료
    - e) 나머지 숫자 입력시 오류 출력

2. jest 사용 방법 익히기

이번주에는 jest의 사용 방법을 익히고 테스트코드를 작성하는 데서 시간을 많이 썼다. 왜냐하면 나는 남들이 짜준 테스트코드만 사용해봤지 한 번도 테스트코드를 짜본 적이 없었기 때문이다. 처음에는 jest를 깔라는 이야기인줄 알고 깔았었는데 npm install을 하니 jest가 자동으로 설치되었다. 저번 주에 npm을 이미 깔았어서 안 깔아도 되는줄 알았는데 npm이라는 건 node 전체의 패키지가 아니라 프로젝트마다 달라지는 듯 하다. 제일 당황스러웠던 것은 이 jest did not exit one second after the test runs has completed라는 오류였다. 이 오류가 발생하면 터미널에서 다음 값을 입력할 수 없어서 강제종료를 시켜 주어야 했다.
터미널에서는 jest를 시작할 때 --detectOpenHandles라는 옵션을 이용하라고 설명하긴 하지만 근본적인 원인을 해결하고 싶어서 검색을 한참 했다. 알고보니 어떤 비동기적 처리가 jest를 실행하고 나서도 종료되지 않아서 일어나는 오류라고 한다.

추정으로는, 아마도 숫자 야구 게임에서 사용자의 숫자값을 입력 받는데, 그 값을 1초안에 입력하지 않아서 이러한 문구를 띄워주는 듯 하다. (깃허브 디스커션에 자세한 설명이 적혀 있던데, 동기/비동기, async/await 개념에 대해 공부를 하고 와야 이해가 될 것 같다).

그래서 이 오류를 그냥 무시하고 진행하였고, 완성한 뒤에도 이 오류는 여전히 발생했지만 테스트 케이스 자체는 통과할 수 있었다.

3. 테스트 케이스 작성

테스트 케이스 작성도 애를 많이 먹은 부분이다. jest를 사용해본 적이 아예 없으니 jest의 명령어에 대해 잘 몰랐기 때문이다.

간단하게 말하면 함수를 만든 다음 그 함수가 통과되면 테스트케이스가 통과되는 것이다. 제일 간단한 형식으로 쓰면 이런 식으로 쓸 수 있다. test뒤에 괄호를 열어준 다음, 첫 번째 인수로 테스트할 내용, 두번째 인수로 통과할 함수를 넣어준다. 그리고 expect안에 테스트할 값을 넣어 주고 뒷 부분은 그 테스트값이 어떨지 적절한 메소드를 넣어 주면 된다. 이 경우에는 .toContain이라는 메소드를 사용하면 테스트할 값이 괄호 안의 값을 포함하는지 알려 주는 것이다.

test('split 메서드로 구분자가 포함되지 않은 경우 값을 그대로 반환', () => {
    const input = '1';
    const result = input.split(',');

    expect(result).toContain('1');
  });

그리고 알아야 할 중요한 개념은 jest.fn()이라는 개념이다.

const mockRandoms = (numbers) => {
  MissionUtils.Random.pickNumberInRange = jest.fn();
  numbers.reduce((acc, number) => {
    return acc.mockReturnValueOnce(number);
  }, MissionUtils.Random.pickNumberInRange);
};

const randoms = [1, 3, 5];
mockRandoms(randoms);

여기서 이 부분은

MissionUtils.Random.pickNumberInRange = jest.fn();

라이브러리의 랜덤값을 추출해주는 메소드를 가짜 함수로 대체하겠다는 것이다. 가짜 함수로 만들어주었으니 대체할 값을 직접 만들어서 넣어 주어야 한다. 이 경우에는 하단에서 mockRandoms(randoms)라고 호출해 줌으로써 numbers라는 부분에 [1,3,5]를 넣어준다.
이번 것은 얼추 이해는 했는데 아무래도 활용하려면 아직 시간이 좀 필요할 듯 하다. Jest 공식 API 설명 사이트에서 필요한 기능을 찾아서 활용해 봐야겠다.

각 함수에 대한 테스트는 해봤는데 함수를 연결했을 때 제대로 작동하는지는 테스트 케이스를 짤 엄두가 안 나서 그냥 테스트 케이스를 짜지 않았다. 하지만 나중에 그 부분에서 에러가 나서 어떻게든 이해해서 테스트 케이스를 짤 걸 하는 생각이 들었다.

4. 기능 구현

기능 구현에서 어려웠던 점은 함수를 분리시키는 일이었다. 함수 분리 자체는 어렵지 않았지만 분리된 함수에서 얻은 값을 어떻게 다시 끌어오냐가 고민이 많이 되었다. 지역변수로 선언했기 때문에 그 함수를 나오면 값 자체가 유실되었기 때문이다.

이번에는 한 함수를 호출하고 그 함수 내에서 다른 함수를 호출하는 식으로 진행을 했다. 다른 방법을 찾을 시간이 모자랐기 때문이다. 다음에 진행할 때는 함수에서 값을 받아와서 그 값을 다른 함수 내에서 끌어올 수 있는 방법을 고민해 볼 생각이다. 아마 class 개념이 덜 잡혀서 그런 것 같다.

5. prettier/es lint 적용

저번주 피드백을 반영해서, 이번에는 prettier과 eslint를 사용했다. 보통 처음에 프로젝트를 시작하는데 설치하라고 권장되는데, 나는 마지막에 사용했다. 왜냐하면 eslint를 사용하면 package.json파일이 변경되는데 이 파일을 변경하지 말라는 요구가 있었기 때문이다. 그래서 나중에 모두 작성한 뒤 es lint를 돌리고 package.json파일을 올리지 않는 방법으로 진행했다.

코딩스타일 가이드는 airbnb 코딩 스타일을 따르는 게 권장되어 airbnb 스타일로 prettier을 설정해 주었다.

arrowParens: 'always'
bracketSpacing: true
jsxBracketSameLine: false
jsxSingleQuote: false
printWidth: 80
proseWrap: 'always'
quoteProps: 'as-needed'
semi: true
singleQuote: true
tabWidth: 2
trailingComma: 'es5'
useTabs: false

6. pull request 보내기

한 번 해봐서 그런지 pull request는 쉽게 보냈다.


피드백 정리(공통 피드백 + 코수타 + 추가 학습 자료)

공통 피드백

  • README.md를 상세히 작성한다

    • 프로젝트에 대한 설명은 기존 README.md에 잘 작성되어 있다고 생각해서 기능 목록을 작성하는 부분에서 적진 않았는데, 기능 목록 부분에서도 다시 설명을 해야 하는지 고민이 된다. 적는다면 이해하기 쉽겠지만, 반복적인 부분이 되기 때문이다.
  • 기능 목록을 재검토한다

    • 이 부분은 현재 잘 작성하고 있다고 생각한다.
  • 기능 목록을 업데이트한다

    • 기능목록을 처음부터 완벽하게 짜려고 해도 완벽하게 완성되지 않았다. 기능을 짜다 보면 여러 개의 기능인데 한 기능으로 너무 뭉쳐서 작성한 경우도 있었다. 그래서 큰 틀만 짠다는 생각으로 짠 다음 차차 업데이트할 생각이다.
  • 값을 하드 코딩하지 않는다

    • 사실 문자열 같은 경우는 굳이 상수로 빼서 코드를 늘릴 필요가 있나? 싶은 생각이 들었다. 의도를 나타내기 위해서 이름을 만들라고 하니 납득이 된다. 다음에는 상수를 만들어 값을 부여해야겠다.
  • 구현 순서도 코딩 컨벤션이다

    • 필드와 생성자가 뭔지 모르겠어서 알아보니 필드는 클래스 내에서 =으로 값을 할당하는 것, 생성자는 constructor, 즉 객체를 찍어내는 틀을 의미했다. 무의식적으로 사용은 하고 있으나 용어를 잘 몰라서 가끔 이해하기 어려운 부분이 있다. 용어를 모르면 의사소통하기 어려우니 용어 공부도 조금씩 해야겠다는 생각이 들었다.
  • 한 함수가 한 가지 기능만 담당하게 한다

    • 이번에 한 가지 일만 하도록 함수를 짜려고 노력했지만 마지막 부분에 다른 함수를 호출했으므로 한 가지 기능만 들어가진 않은 것 같다. 고민이 필요한 지점이다.
  • 함수가 한 가지 기능을 하는지 확인하는 기준을 세운다

    • 함수를 일단 15줄 이내로 짰는지 확인하고 마지막에 어떤 기능을 하는지 적음으로써 한 가지 기능을 하는지 확인해야 할 듯 하다.
  • JavaScript에서 객체를 만드는 다양한 방법을 이해하고 사용한다

    • 자바스크립트의 메소드 이용만 해 봤지 객체에 대한 개념이 부족한 것 같다. 객체에 대한 개념이 부족해서 함수 분리에도 어려움을 겪은 것 같다. 이번 주에는 객체에 대해 자세히 공부해볼 예정이다.
  • 테스트를 작성하는 이유에 대해 본인의 경험을 토대로 정리해본다

    • 이번에 시간 내에 완성을 못할까봐 마음이 급해서 테스트를 대충 짜고 다음으로 넘어갔는데, 결국 뒤쪽에서 문제가 생기고 어디서 문제가 발생했는지 한참 찾아봐야 했다. 미리 사용자 입력값에 대한 테스트를 진행했더라면 발생하지 않았을 문제라는 생각이 들었다. 그리고 이번 과제는 짧은 코드라 다행이지 긴 코드였다면 테스트 짜는 것 보다 문제 찾는 데 시간을 많이 허비했을 것 같다. 이번 주에는 필요한 테스트를 꼼꼼하게 작성하고 다음 단계로 넘어가고 싶다.
  • 처음부터 큰 단위의 테스트를 만들지 않는다

    • 테스트는 순차적으로 진행했는데, 피드백에서는 중요한 기능부터 테스트를 해 보라고 나와 있다. 기능 목록을 만들고 중요도를 매겨보는 일도 필요할 듯 하다.

코수타

  • 남들과 비교하기보다는 자신이 모르는 것에 집중하기

    • 단위 테스트를 잘 모른다면 TDD는 신경쓰지 말고 단위 테스트를 하는 것부터 집중하라고 하셨는데, 사실 단위 테스트 신경쓴다고 TDD는 머리 저편으로 사라졌었다.... 멘탈은 걱정 없을 것 같다...머쓱하네..

추가 학습 자료

  • 커밋 메시지를 쓸 때 괄호 안에 범위(scope)를 넣어 주기

    • 커밋 컨벤션을 읽었음에도 정신이 없다 보니 범위 부분을 잊어버렸다. 다음 주차에는 이 부분을 신경 써서 커밋 메시지를 써야겠다.
  • 처음 기능 목록을 작성할 때 이 기능을 어떤 함수에 넣어 줄지 적어주기

    • 보면서 내가 기능 목록을 시켜서 기계적으로 만들고 있다는 생각이 들었다. 나 혼자만 보는 게 아니라 다른 사람도 보는 부분이니, 어떤 함수에 어떤 기능이 들어갔다고 설명을 써 주면 더욱 이해하기 쉬울 듯 하다.
  • 기능 목록 구현 앞부분에 체크박스를 만들어 주기.

    • 위와 똑같은 맥락으로, 체크박스를 하나씩 채워주면 다른 사람이 읽었을 때 어떤 기능을 구현한지 쉽게 알 수 있다. 특히나 기능을 순서대로 만들지 않을 때 필요해 보인다.
  • 함수를 기능에 따라 그룹화해서 다른 파일로 분리시켜주기

    • 이런 식으로 작성하면 파일명만 보고도 크게 어떤 기능이 있는지 확인할 수 있다. 유지보수 관점에서도 유용할 것 같다.
  • 기능을 함수로 캡슐화 시켜준 다음, 마지막에 조합할 것

    • 사실 이번에는 함수를 만드는 것과 조합을 동시에 했었다. 그런데 이런 식으로 작성하니 함수 자체는 제대로 동작하나 조합이 잘못되어 추후에 에러가 발생하는 경우가 생겼다. 그래서 커밋 메시지를 구구절절 쓰긴 했는데, 따로 분리해 줘야 나중에 커밋 메시지만 보고도 어떤 일이 일어났는지 간략하기 이해하기 쉬울 것 같다. 다음에는 기능 구현만 커밋하지 말고 조합도 커밋 한 개로 분리해야겠다.
  • 기능 구현과 테스트 실행도 다른 커밋으로 분리

    • 이번에는 테스트가 제대로 짜졌는지 잘 모르겠어서 기능 구현과 관련 테스트 코드를 함께 커밋했는데, 다음에는 따로 커밋해 줘야겠다.

소감

jest를 활용하여 테스트 케이스를 짜는 연습이 많이 필요하다고 생각이 들었다. 테스트 케이스 짜는게 서툴러서 적당히 짰더니, 나중에 생각지도 못한 문제가 발생했다. 테스트를 제대로 짰으면 이런 문제가 생기지 않았을 것 같다는 생각이 들었다. 함수 자체 테스트 뿐만 아니라 기능이 연결되는지에 대한 테스트도 필요할 듯 하다.

jest의 오류에 대해서 이해하지 못한 건 아쉬움이 크다. 현재로써 이해하기엔 너무 추가 학습이 많이 필요할 것 같아서 건너 뛰었지만 고생을 많이 한 부분이라서 언젠가 이해하고 싶다.

공부할 건 많고 시간은 부족해서 일단 중요해보이는 것 위주로 학습하고 크게 중요하지 않은 건 일단 패스했는데, 모르는 건 회고 글에 잔뜩 적어놨으니 시간이 될 때나 그 기능이 중요해질 때 차근차근 머리에 넣어 봐야겠다.

이번에는 첨부해준 영상이 많은 도움이 되었다. 물론 자바 강의라서 메소드가 다 다르긴 하지만 일단 객체지향 언어라서 유사한 점이 많아서 배울 점이 많았다.

profile
전 이것도 몰라요

0개의 댓글