우아한테크코스 8기 프리코스[BE] 2주차 회고: 3번째 자동차 경주

최기웅·2025년 10월 28일
2
post-thumbnail

들어가며

이번이 3번째… 풀어보는 자동차 경주 과제입니다.

그럼에도 저는 매년 성장하고 있고, 항상 코드는 달랐습니다.
첫 번째 풀 때는 단순히 돌아가게 만들기에 급급했지만,
두 번째는 “객체지향적으로 짜보자”라는 막연한 시도를 했었고,
이번 세 번째는 “왜 이렇게 설계해야 하는가?”를 스스로 납득하며 구현할 수 있었습니다.

과제 목표

저의 2주차 목표는 이와 같았습니다.

  • 1주차 공통 피드백 신경쓰기
  • 프로그래밍 요구사항 잘 지키기
  • 스스로 고민하고 생각하기
  • 의미있는 코드 작성하기

구현 시 고민한 점

객체에게 묻지 말고 시켜라

이번 과제에서 핵심은 “객체에게 묻지 말고 시켜라” 였습니다.
예전에는 이런 코드들이 많았습니다.

cars.stream()
		.filter(car -> car.getposition() == maxPosition_
		.toList();

겉으로 봤을 때는 문제 없어보이지만, 이건 Cars가 Car의 내부 상태를 꺼내서 직접 판단하는 구조입니다.
Car는 단순한 데이터 덩어리이고, 진짜 판단은 Cars가 대신하고 있었습니다.
이걸 “객체에게 시키는 방식”으로 바꾸면 이렇습니다.

cars.findWinners(); // Cars 내부에서 Car에게 직접 판단하도록 위임

이제 Cars는 “우승자를 찾아라”라고 명령만 내리고,
실제 판단은 Car가 스스로 판단합니다.
이렇게 바꾸자 객체 간의 결합도가 낮아지고, 테스트가 자연스러워졌습니다.

처음에는 단순히 Getter를 지양하자는 의미로 설계를 했지만, 돌아보니 객체가 스스로 일하도록 설계하는 사고방식의 전환이었습니다.

상수에 의미 부여하기

이전에는 단순히 매직 넘버를 없애자는 생각에 상수를 사용했습니다.
예를 들어, 0이라면 ZERO 와 같이 단순하게 사용했습니다.

이번에는 한 단계 나아가, 도메인을 설명하는 언어로 상수를 정의했습니다.

private static final int MAX_NAME_LENGTH = 5;
private static final int FORWARD_THRESHOLD = 4;

이와 같이 단순한 숫자가 아니라 도메인의 구칙을 표현하는 상수가 되었습니다.
코드를 읽는 순간 어떤 규칙인지 바로 드러납니다.

애플리케이션 생명주기와 자원 관리

camp.nextstep.edu.missionutils.Console을 사용할 때, Console.close()를 어디서 호출할지 고민이 많았습니다.

  • InputView 내부에서 닫으면, 이후 입력시 IllegalStateException이 발생하고
  • Contriller에서 닫으면, I/O 계층과 비즈니스 계층의 결합도가 높아집니다.

결국 프로그램의 생명주기를 관리하는 application.main()에서 try-finally 구문으로 Console.close()를 호출하는 방식을 선택했습니다.

마무리

3번째 자동차 경주를 풀면서 느낀 것은, 같은 문제라도 나의 성장 단계마다 다른 문제처럼 느껴진다는 점이었습니다.

처음에는 단순히 동작하게 만드는 코드를 만들었다면, 이제는 왜 이렇게 동작해야 하는지 고민하며 설계하게 되었습니다.

단순히 코드를 짜는 단계를 넘어서 설계하고, 리팩토링하고, 생각하는 과정 자체가 즐거웠습니다.
매년 같은 문제를 풀지만, 그 안에서 성장을 직접 느낄 수 있었습니다.

남은 프리코스도 꾸준히, 열심히 달려보겠습니다!

코드: https://github.com/giwoong01/java-racingcar-8/tree/giwoong01
PR: https://github.com/woowacourse-precourse/java-racingcar-8/pull/406

profile
https://giwoong01.tistory.com/

0개의 댓글