[우아한 테크코스 8기 백엔드]프리코스 2주차 회고 -자동차 경주-

2025. 10. 29. 20:03·우아한 테크코스 프리코스

우아한 테크코스 8기 2주차가 종료됐습니다.

2주차의 미션은 7기의 2주차 미션과 같았습니다.

문제 링크는 아래와 같습니다.

https://github.com/woowacourse-precourse/java-racingcar-8

 

GitHub - woowacourse-precourse/java-racingcar-8

Contribute to woowacourse-precourse/java-racingcar-8 development by creating an account on GitHub.

github.com

 

 

아래는 제출한 PR 주소입니다.

https://github.com/woowacourse-precourse/java-racingcar-8/pull/97

 

[자동차 경주] 이재혁 미션 제출합니다. by LEEJaeHyeok97 · Pull Request #97 · woowacourse-precourse/java-racingca

 

github.com

 

2주차의 과제는 7기와 히어로테크코스를 진행하며 자바로도 코틀린 코드로도 풀어봤기 때문에 큰 부담없이 미션을 진행할 수 있었습니다.

아는 문제였기 때문에 오히려 미션의 테스트 코드 통과는 물론 객체지향적인 설계를 하는 데 많은 시간을 들이며 코드를 계속 수정했습니다.

구체화된 학습 목표와 드러난 미션의 방향성

이번 주의 학습 목표는 정말 간단했던 1주차와 비교하면 훨씬 구체화되고 무엇을 하라는 구체적 지시가 분명해졌습니다.

학습 목표는 다음과 같았습니다.

  • 여러 역할을 수행하는 큰 함수를 단일 역할을 수행하는 작은 함수로 분리한다.
  • 테스트 도구를 사용하는 방법을 배우고 프로그램이 제대로 작동하는지 테스트한다.
  • 디스코드에 올라온 1주 차 공통 피드백을 최대한 반영한다.

이번 8기의 피드백의 특별한 점으로는 특히 ‘도전’ 하는 것을 강조하는 것이 눈에 띈다고 느꼈습니다.

 

 

 

이 피드백에 영향을 받아 1주차 회고에서는 비교적 간단히 썼던 소감문을 2주 차에서는 새로 도전하고 적용해본 것들을 작성하여 3000자 가까이로 늘어났습니다.

3주차 소감문은 조금 더 깊이 있고 많은 도전을 담아보고 싶습니다.

구체적으로 추가된 요구사항

미션 요구사항에 추가된 요구사항은 다음과 같았습니다.

  • 인덴트의 depth 가 2를 초과하지 않도록 한다
  • 함수가 한 가지 일만 하도록 최대한 작게 만들어라
  • JUnit5, AssertJ를 사용한 테스트 코드 작성

공통 피드백에도 여러 가지 요구사항이 추가됐는데 이 부분들은 모두 지키려고 의식 중에 항상 떠올리며 미션을 진행했습니다!

이제부터 2주차 미션을 진행하면서 고민하고 많은 시간을 들인 부분들과 배운점에 대해 이야기 해보겠습니다.

테스트 도구는 어떤 것이 있고 어떤 식으로 써야 할까?

테스트 도구를 공부하기 위해 ‘테코톡’ 영상 중 ‘바다의 JUnit5 사용법’ 이라는 영상을 통해 테스트 도구에 대해 공부를 하고 나름대로 테스트 사용에 대한 방향을 정리할 수 있었습니다.

특히, 여러 예외 케이스들을 한 번에 검증하기 위한 @ValueSource를 배웠습니다. @CsvSource 와 비슷하게 예외 케이스를 “값의 나열”로 표현하는 데 @ValueSource가 간결했고, 테스트 본문도 반복문을 쓰는 것 보다 자연스럽게 “하나의 규칙에 대한 여러 입력” 이라는 의도를 유지할 수 있었습니다.

 

 

 

 

테스트의 이름을 @DisplayName(””)으로 지어줄 수 있다는 것도 배웠는데, 테스트 명을 어떻게 지을지 처음에는 명사형으로 지었으나 테스트 작성법에 대해 공부하던 중, @DisplayName 에는 결과 중심의 명사형 문장 대신 “무엇을 해야 한다/하지 말아야 한다” 같은 행위를 담은 명령형 서술로 바꾸어야 테스트의 의도를 명확히 드러낼 수 있다는 것을 알게되었습니다.

실제로 테스트 코드명을 지을 때 “중복 이름 예외 테스트” 같이 명사형 서술 방식을 “중복된 이름이 입력되면 예외를 발생시킨다.” 같이 명령형 서술로 변경했을 때 테스트의 목적과 전제, 결과가 더 또렷하게 느껴졌습니다.

이 부분은 리뷰어와 미래에 코드를 다시 볼 나를 위한 작은 배려같다고 생각됐습니다.

테스트하기 어려운 부분은 어떻게 해야할까?

테스트를 작성하면서 테스트를 하기 어려운 부분이 있다는 것을 느끼게 됐습니다.

이 부분은 랜덤한 숫자를 입력받고 랜덤 숫자가 4이상일 때 자동차를 전진하는 메소드를 테스트해야 할 때가 문제가 됐습니다.

저는 숫자 생성기라는 인터페이스를 만들고 이를 실제 코드에서는 랜덤 숫자를 뽑아 주는 메소드를 오버라이딩 해서 사용했고, 테스트 코드 쪽에서는 Stub을 위한 고정된 숫자를 반환해줄 수 있는 클래스를 테스트 쪽에 만들어주고 테스트 가능한 구조로 만들었습니다.

 

숫자 생성기라는 인터페이스입니다.

 

 

랜덤한 숫자를 뽑는 API를 오버라이드한 RandomNumberGenerator 입니다.

 

도메인인 Race에서는 이러한 전략을 입력받아 매 라운드 숫자를 입력받을 수 있도록 설계했습니다.

 

 

고정된 숫자 반환을 위한 테스트를 위한 Stub 코드입니다.

 

매 경기 진행을 담당하는 Racing 도메인이 인터페이스를 의존하게 함으로써 테스트가 가능한 구조를 유지할 수 있었습니다.

단일 역할을 수행하는 메소드는 어떤 식으로 작성할 수 있을까?

저의 컨트롤러 run() 메소드의 단일 책임 원칙을 지키려고 기능 단위로 메소드화를 진행한 부분이 많은 도움이 됐습니다.

제가 정의하는 객체지향 프로그래밍이란 개발자가 읽을 때 읽기가 좋아 하나의 흐름으로 쭉 읽어 내려가기 좋은 코드입니다.

이 부분을 많이 고민하여 디미터의 법칙을 지키려고 했고 메소드의 인자는 가능하면 의도를 드러낼 수 있게 .이 들어가야 한다면 메소드화를 고려하는 방식으로 긴 메소드를 기능별로 각각의 메소드로 분리하며 단일 역할을 수행하는 메소드를 작성하는 방식으로 구현을 진행했습니다.

 

 

 

도메인 설계는 어떻게 했어?

 

 

1주차를 진행하며 배우게된 VO 개념을 적극적으로 사용하려고 했습니다.

각 도메인이 갖는 원시값은 가능한 포장하여 값 객체를 만들어 입력을 검증하고 메시지를 처리할 수 있는 메소드를 두었습니다. 상위의 Car나 Cars, Racing 도메인들은 서로에게 필요한 요청이 있다면 꺼내 쓰는게 아니라 해당 역할의 전문가에게 ‘메시지’를 보내서 직접 처리하게 하는 구조를 고민했습니다.

이른바 Tell, Don’t Ask. 바깥 객체는 “움직여라”, “우승자를 알려줘!” 같이 요청만 하고 계산, 판단은 도메인 맡게 했습니다. getter로 메소드 체이닝으로 낯선 객체에 접근해 값을 꺼내 계산을 하는 것 보다 메시지를 보내 값을 관련된 객체가 스스로 처리하게 하는 것이 코드의 가독성을 지키고 보다 질서 있는 설계로 느껴졌습니다. 즉, 도메인 바깥에서는 조회용 getter는 필요한 최소한으로 허용하되, 판단과 로직은 도메인 내부로 밀어넣었습니다. 이 원칙을 지키자, 책임의 위치가 선명해지고, 객체가 메시지로 협력하는 방향으로 코드가 정리됐습니다.

예를 들어, 자동차가 move() 특정 조건에 움직여야 하는 메소드가 있었는데 이 움직이는 것은 Position 객체가 1만큼 전진하는 것을 의미하므로 Car 도메인은 값 객체인 Position에게 메시지를 보내어 한 칸 전진할 수 있게 ‘요청’하는 방식으로 객체간의 협력 구조를 만들고자 했습니다.

 

 

 

 

무분별한 getter를 지양함으로써 배우게된 메시지를 통한 객체 간 협력

라운드 결과를 출력하기 위한 출력 뷰에서 getCars()로 리스트를 꺼내 순회하던 부분을, Cars가 Iterable<Car> 를 구현하도록 수정했습니다. 이후 출력부는 for ( Car car : cars ) 처럼 컬렉션을 getter 요청 없이 순회할 수 있도록 변경돼었습니다. 내부 리스트를 통째로 노출하지 않으니 캡슐화가 지켜지고, Cars가 향후 자료구조를 바꿔도 외부 코드는 영향이 없는 구조가 되었습니다.

 

 

 

 

Racing 도메인을 View에서 의존하며 getter을 제거하여 getter 사용을 지양하고 더 가독성 좋은 코드를 유지할 수 있었습니다.

느낀점

 

 

1주차에서 아쉬웠던 점을 2주차에 적극 반영하며 조금 더 성장했다고 느꼈지만, 2주차 코드를 리뷰하면서 다른 사람들의 코드를 보고 제 코드의 아쉬운 점들이 뒤늦게 보였습니다. 혼자 코드를 작성하고 스스로 부족한 점을 찾는 것이 쉽지 않은 일이었습니다. 다른 사람과 코드로 교류하고 다른 사람의 코드를 보고 배우는 것이 많았습니다. 성장과 앞으로의 도전의 방향을 결정하는데 중요하다고 느껴 결국, 다른 사람들이 읽기 쉬운 가독성 측면에서 많은 노력을 들여야 한다는 생각을 했습니다. 요구사항을 만족하며 가독성 좋은 코드를 만드는 일 두마리 토끼를 잡는 것이 문제가 굉장히 어려워진다면 가독성까지는 고려하지 못했을 것 같다는 생각을 했습니다.

5주 간의 프리코스 중 이제 2주차가 끝나고 3주차가 진행중입니다.

3주차에는 객체 간의 협력에 더 깊이 고민하고 더 가독성 높은 코드를 만드는 것에 도전하고 싶습니다.

좋은 설계에서 문제 해결의 실마리가 나온다고 믿기 때문에 조금 객체 스스로 책임을 지고 메시지로 협력하는 관계를 구현하는데 많은 시간을 쓰며 3주차도 잘 진행하고 싶습니다! 감사합니다!

'우아한 테크코스 프리코스' 카테고리의 다른 글

[우아한 테크코스 8기 백엔드]프리코스 4~6주차 회고 -오픈 미션-  (1) 2025.11.25
[우아한 테크코스 8기 백엔드]프리코스 3주차 회고 -로또-  (0) 2025.11.04
[우아한 테크코스 8기 백엔드]프리코스 1주차 회고 -문자열 덧셈 계산기-  (0) 2025.10.21
'우아한 테크코스 프리코스' 카테고리의 다른 글
  • [우아한 테크코스 8기 백엔드]프리코스 4~6주차 회고 -오픈 미션-
  • [우아한 테크코스 8기 백엔드]프리코스 3주차 회고 -로또-
  • [우아한 테크코스 8기 백엔드]프리코스 1주차 회고 -문자열 덧셈 계산기-
dev_noonoo
dev_noonoo
인생의 스노우볼을 굴리는 개발자 누누(이재혁)의 블로그입니다.
  • dev_noonoo
    개발자 누누님의 블로그
    dev_noonoo
  • 전체
    오늘
    어제
    • 분류 전체보기 (34)
      • 운영체제 (0)
      • 네트워크 (5)
      • DB (5)
      • 코딩테스트 (0)
      • 아키텍처 (7)
      • 회고 (1)
      • 언어(java, kotlin, python ..... (5)
      • 우아한 테크코스 프리코스 (4)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • 깃허브
  • 공지사항

  • 인기 글

  • 태그

    좋아요api
    MySQL
    정렬방식
    filesort
    redis
    분산락
    Using temporary
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
dev_noonoo
[우아한 테크코스 8기 백엔드]프리코스 2주차 회고 -자동차 경주-
상단으로

티스토리툴바