본문 바로가기

회고/성과 회고

[우아한테크코스 7기] 프리코스 3주차 회고록 | 불안감 탈출

 

3주차 미션에서 매일 되새긴 문장은 ‘지난주의 나를 넘어서자’였습니다.

🎯 풀리퀘스트 주소: https://github.com/woowacourse-precourse/javascript-lotto-7/pull/23


1. 메타인지를 적용해 불안함에서 탈출하는 법을 배우다

프리코스를 시작하기 전, 착실하게 설계하고 설계를 바탕으로 구현하며 코드의 이유를 명확히 한다는 목표를 세웠습니다. 매주 화요일마다 미션이 나오면, 목표 달성 여부 확인 목록을 만들어 목표를 달성하고자 노력했습니다. 하지만 스스로가 세운 기준을 바탕으로 앞으로 나아가고 있다는 생각과 달리, 여러 개발자분들과 활발한 코드리뷰를 하며, 다양한 패턴을 적용된 멋들어진 코드들 앞에서 점점 작아지는 자신을 발견했습니다.

 

해당 주차마다 나오는 미션의 복잡도와 학습 목표에 집중하여, 필요한 기능을 동작하도록 작성하면 된다는 생각을 바탕으로 코드를 작성했음에도 불구하고, 더 멋진 구현 결과를 위해 새로운 무언가를 추가해야만 한다는 강박이 들었습니다.

 

2 주차 공통 피드백을 보며, 강박에서 탈출해 나의 속도를 지키며 어제의 나보다 더 성장할 수 있는 목표를 설정하는 것이 중요하다는 사실을 깨닫게 되었습니다. 더 좋은 프로그래머로 성장하는 과정 속에 있다는 말이 불안함에 떨고 있던 저를 위로해 주었습니다.

 

메타인지를 올바르게 적용한다면, 불안을 줄이고 더 좋은 프로그래머로 성장하는 역량을 키우는 것에 집중할 수 있다고 생각했습니다.

코드의 책임을 분리하고 단위 테스트를 통해 안정성 높은 프로그램을 만드는 것을 목표로 설정했습니다.

 

2. 메타인지를 적용해 개선할 목표를 명확히 하다

다른 개발자가 아닌 지난주의 나를 기준으로 설정하고, 잘 한 점과 부족한 점을 면밀히 분석했습니다.

 

잘 한 점은 다음과 같습니다.

  • 기능 목록에서 구현할 기능 리스트와 예외 처리가 필요한 리스트를 분리한 것
  • 구현을 하며 지속적으로 문서를 업데이트하여 코드 구현의 기준이 README가 되도록 한 것
  • 하드 코딩되어 있는 값들을 const를 활용해 뺀 것
  • Jest의 test.each 기능을 활용해 테스트를 진행하며 반복적인 입출력 부분을 하나로 통합한 것

 

반대로 개선이 필요한 부족한 점은 다음과 같습니다.

  • 코드가 유기적으로 연결되어 있어, 단위 테스트가 아닌 통합 테스트만을 진행한 것
  • 로직을 실행하는 App.js의 run()에 모든 로직을 불러와 호출함으로써 책임이 과하게 할당된 것

 

이러한 분석을 바탕으로, 로또 미션에서 함수가 자신의 역할만을 가질 수 있도록 책임을 분할해 단위 테스트에 성공하는 것을 목표로 설정했습니다. 👍

 

3. 코드의 책임을 분리하다

함수가 자신의 역할만 가질 수 있는 방법에 대해 고민한 결과 고유의 역할이 존재하는 부분을 클래스로 구현하고, 클래스 내부에 고유의 역할을 위한 값(필드값), 고유의 역할을 위한 행동(메서드)을 배치하는 방법을 선택했습니다.

 

기능 목록을 입력-기능 수행-출력의 단계로 분리하였습니다. 지난주의 저는 기능 수행의 단계 부분을 자동차 정보를 담은 핵심 클래스를 제외하고 App.js의 run()에게 모든 책임을 부여했기에, 각각의 기능들을 클래스로 구현해 책임을 분할하는 방법을 시도했습니다.

 

root/
│
├── src/
│   ├── domain/
│   │   ├── Lotto.js
│   │   ├── BonusLotto.js
│   │   ├── Money.js
│   │   ├── Rank.js
│   │   ├── RankCounter.js
│   │   └── Profit.js
│   │

 

이를 통해 각각의 단계에 포함되는 정보가 독립적으로 생성되고, 전달되도록 설정하여 정보의 책임을 해당 클래스에게만 부여할 수 있었습니다. 예를 들어, 로또 금액 클래스에는 로또 구입 금액을 인스턴스를 생성할 때 전달받고, 이를 검증하여 public 메서드로 로또 구입 금액만을 출력할 수 있습니다. 다른 클래스에선 로또 구입 금액을 변경하거나 관리할 수 없게 되며, 로또 금액 클래스만 유일하게 로또 금액에 대한 책임을 가지게 됩니다.

 

각 클래스가 자신의 정보만을 보유할 수 있게 되자, 시작조차 어려웠던 단위 테스트가 통합 테스트보다 쉬워지는 경험을 하게 되었습니다. 코드의 책임을 분리하는 목표를 달성하자, 단위 테스트의 목표를 자연스레 달성하며 통합 테스트만을 했던 지난주의 저의 모습으로부터 탈출했습니다. 😎

 

4. 단위 테스트와 통합 테스트의 작성에 대해 고찰하다

각 기능의 목록을 클래스로 구현하고, 이를 하나의 컨트롤러에서 테스트하는 방식을 선택했습니다. 컨트롤러를 로또 준비 단계, 로또 실행 단계, 로또 완료 단계로 분리하고, 실행 부분에 각 단계를 불러와 App.js의 run()에는 하나의 실행 부분만이 담기도록 설정하였습니다. 컨트롤러를 설계한 후, 해당 부분의 테스트 방법을 고민하기 시작했습니다.

 

테스트를 만드는 것 자체도 비용이기에, 무작정 테스트를 만들기보다 해당 테스트의 의미를 스스로가 정의하고 검증이 필요한 로직에 대한 테스트를 만들어야 한다고 생각했습니다.

 

컨트롤러엔 생성한 클래스를 불러와 정제된 값을 생성한 후, 다른 클래스로 값을 전달하는 과정만이 존재했습니다. 각각의 클래스가 정제되지 않은 값을 입력받아, 정제된 값을 출력함을 단위 테스트로 이미 확인을 한 상태이며, 입력부터 출력까지의 전체적인 통합 테스트가 이미 구현되어 있었기에, 컨트롤러에 대한 추가적인 테스트를 생성하는 것이 의미가 없다는 판단을 했습니다. 하위 테스트에서 검증을 하고, 상위 테스트에서 하위 테스트를 묶어 재 검증하는 과정은 기존 클래스의 데이터 연결만을 테스트하는 반복적인 검증 부분이기에, 추가적 비용을 소비하여 제작할 필요가 없음을 경험하게 되었습니다.

 

사용자의 입출력에 대한 예외 처리와 올바른 동작에 대한 검증, 입력받은 값들을 정제하는 과정에서 도출되는 오류 발생 여부에 대한 검증을 모두 테스트하며, 각 단계에서 다음 단계로 넘어가는 과정이 모두 올바르게 동작함을 여러 단위 테스트와 하나의 통합 테스트로 확인할 수 있었습니다.

root/
│
├── __test__/
│   ├── ApplicationTest.js // 통합 테스트
│   ├── LottoTest.js       // 단일 테스트
│   ├── MoneyTest.js       // 단일 테스트
│   ├── RankTest.js        // 단일 테스트
│   ├── RankCounterTest.js // 단일 테스트
│   └── ProfitTest.js      // 단일 테스트
│

 

 

5. 성장하다

프리코스에서 제시한 학습 목표, 공통 피드백을 따라가며, 무엇을 배우고 나의 것으로 만들면 더 좋은 개발자로 성장할 수 있는지가 보이는 신기한 경험을 했습니다. 올바른 방향 설계를 따라가며 발견할 수 있는 학습의 요소들을 하나씩 저의 것으로 만들며, 과거의 저에서 앞으로 한 단계 나아가는 성장을 해낼 수 있었습니다.

 

스스로 학습하며, 코드 리뷰를 통해 잘못된 부분이나 개선하면 좋은 점들에 대한 조언을 얻었기에 가능했던 일이었습니다.

코드 리뷰를 해드리며 얻은 좋은 지식과 코드 리뷰를 받으며 얻은 개선점을 모아 리스트로 만들어, 이번 미션에서 적용하고자 노력했습니다.

2 주차 자동차 경주의 코드 리뷰엔 감사하게도 7명의 리뷰어가 참여해 주셨습니다.👍

 

 

 

더불어 지난 주차의 회고에서 변경한 목표인 ‘코드 이유를 명확하게 설명할 수 있으며 해당 기준을 README에 반영하여 문서화한다’를 지키기 위해, 구현에서 고민이 드는 부분을 작성하며 지속적인 업데이트를 진행했습니다. 사용자로부터 값을 입력받는 값을 검증하는 부분을 Validator 클래스로 모두 분리하려는 시도를 하였으나, 책임을 각 클래스에게 부여하는 편이 캡슐화된 객체를 만들 수 있다는 판단을 했습니다. 해당 클래스에만 사용되는 검증 로직은 클래스 내부에 위치하고, 여러 클래스에서 반복적으로 사용되는 검증 로직은 Validator 클래스로 분리하여 사용했습니다. 이를 선택하는 과정을 문서에 반영하며, 스스로가 코드의 흐름을 더 명확히 이해하고 설명할 수 있도록 성장할 수 있었습니다.

 


3주 차 로또 미션에서도 설계, 구현, 테스트, 리팩토링을 진행하며 개발에 온전히 몰입했습니다.

다음 과제에서 얼마나 더 성장할 수 있을지 기대됩니다. 이번주도 목표 달성 성공입니다! 👍⭐