From 8825da2c008291da32f4c44b28a76472228340cf Mon Sep 17 00:00:00 2001
From: kjy2844 <kjy2844@kaist.ac.kr>
Date: Thu, 20 Mar 2025 13:20:23 +0900
Subject: [PATCH 1/9] =?UTF-8?q?docs=20:=204=EB=8B=A8=EA=B3=84=20TODO=20?=
 =?UTF-8?q?=EC=A0=95=EB=A6=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 README.md | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 79 insertions(+), 1 deletion(-)

diff --git a/README.md b/README.md
index ba24573e89a..90a3dc54999 100644
--- a/README.md
+++ b/README.md
@@ -37,5 +37,83 @@
 ### 개발 구조
 Game : 게임의 시작과 종료를 담당
 Race : 전체 라운드의 진행을 담당
+GameSettings : 자동차 경주 게임의 설정값
+Car : 자동차 객체
 InputView : 사용자의 입력을 받음
-ResultView : 결과를 출력
\ No newline at end of file
+ResultView : 결과를 출력
+
+## 🚀 4단계 - 자동차 경주(우승자)
+
+### 기능 요구사항
+
+- 각 자동차에 이름을 부여할 수 있다. 자동차 이름은 5자를 초과할 수 없다.
+- 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다.
+- 자동차 이름은 쉼표(,)를 기준으로 구분한다.
+- 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. 우승자는 한명 이상일 수 있다.
+
+### 구현 TODO 목록
+
+1. **자동차 이름 기능**
+
+   - [ ] `Car` 클래스에 이름 필드 추가
+   - [ ] 이름 유효성 검사 (5자 초과 불가)
+   - [ ] `Car` 생성자에 이름 파라미터 추가
+   - [ ] `CarTest`에 이름 관련 테스트 추가
+     - [ ] 이름이 5자를 초과하면 예외 발생
+     - [ ] 유효한 이름으로 생성 가능
+
+2. **자동차 이름 출력**
+
+   - [ ] `ResultView` 수정
+     - [ ] 자동차 이름과 위치를 함께 출력하는 형식 변경
+     - [ ] `presentCars` 메소드 파라미터 수정 (이름 정보 추가)
+   - [ ] `Race` 클래스 수정
+     - [ ] `getCarPositions` 메소드를 `getCarStatus`로 변경
+     - [ ] 자동차 이름과 위치를 함께 반환하도록 수정
+
+3. **자동차 이름 입력**
+
+   - [ ] `InputView` 수정
+     - [ ] 자동차 이름 입력 메소드 추가
+     - [ ] 쉼표로 구분된 이름 문자열 파싱 로직 추가
+   - [ ] `GameSettings` 수정
+     - [ ] 자동차 이름 목록 필드 추가
+     - [ ] 생성자 수정
+
+4. **우승자 판정**
+
+   - [ ] `Race` 클래스에 우승자 판정 로직 추가
+     - [ ] `getWinners` 메소드 추가
+     - [ ] 가장 멀리 간 자동차들 찾기
+   - [ ] `ResultView`에 우승자 출력 메소드 추가
+   - [ ] `Game` 클래스 수정
+     - [ ] 경주 종료 후 우승자 출력 로직 추가
+
+5. **테스트 추가**
+
+   - [ ] `RaceTest`에 우승자 판정 테스트 추가
+     - [ ] 단일 우승자 케이스
+     - [ ] 다중 우승자 케이스
+   - [ ] `InputViewTest` 추가
+     - [ ] 자동차 이름 입력 테스트
+     - [ ] 잘못된 입력 처리 테스트
+
+6. **리팩토링 고려사항**
+   - [ ] `Car` 클래스에 `Position` 값 객체 도입 검토
+   - [ ] `CarName` 값 객체 도입 검토
+   - [ ] `CarStatus` DTO 도입 검토 (이름과 위치를 함께 전달하기 위해)
+
+### 프로그래밍 요구사항
+* indent(인덴트, 들여쓰기) depth를 2를 넘지 않도록 구현한다. 1까지만 허용한다.
+  * 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다.
+  * 힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메소드)를 분리하면 된다.
+* 함수(또는 메소드)의 길이가 15라인을 넘어가지 않도록 구현한다.
+  * 함수(또는 메소드)가 한 가지 일만 잘 하도록 구현한다.
+* 모든 로직에 단위 테스트를 구현한다. 단, UI(System.out, System.in) 로직은 제외
+  * 핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 구분한다.
+  * UI 로직을 InputView, ResultView와 같은 클래스를 추가해 분리한다.
+* 자바 코드 컨벤션을 지키면서 프로그래밍한다.
+  * 참고문서: https://google.github.io/styleguide/javaguide.html 또는 https://myeonguni.tistory.com/1596
+* else 예약어를 쓰지 않는다.
+  * 힌트: if 조건절에서 값을 return하는 방식으로 구현하면 else를 사용하지 않아도 된다.
+  * else를 쓰지 말라고 하니 switch/case로 구현하는 경우가 있는데 switch/case도 허용하지 않는다.

From c4325fc609f502f0202aec0c413926a1864ebb0f Mon Sep 17 00:00:00 2001
From: kjy2844 <kjy2844@kaist.ac.kr>
Date: Thu, 20 Mar 2025 14:04:41 +0900
Subject: [PATCH 2/9] =?UTF-8?q?feat=20:=20=EC=9E=90=EB=8F=99=EC=B0=A8=20?=
 =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EA=B8=B0=EB=8A=A5=20=20=20=20-=20[x]=20`C?=
 =?UTF-8?q?ar`=20=ED=81=B4=EB=9E=98=EC=8A=A4=EC=97=90=20=EC=9D=B4=EB=A6=84?=
 =?UTF-8?q?=20=ED=95=84=EB=93=9C=20=EC=B6=94=EA=B0=80=20=20=20=20-=20[x]?=
 =?UTF-8?q?=20=EC=9D=B4=EB=A6=84=20=EC=9C=A0=ED=9A=A8=EC=84=B1=20=EA=B2=80?=
 =?UTF-8?q?=EC=82=AC=20(5=EC=9E=90=20=EC=B4=88=EA=B3=BC=20=EB=B6=88?=
 =?UTF-8?q?=EA=B0=80)=20=20=20=20-=20[x]=20`Car`=20=EC=83=9D=EC=84=B1?=
 =?UTF-8?q?=EC=9E=90=EC=97=90=20=EC=9D=B4=EB=A6=84=20=ED=8C=8C=EB=9D=BC?=
 =?UTF-8?q?=EB=AF=B8=ED=84=B0=20=EC=B6=94=EA=B0=80=20=20=20=20-=20[x]=20`C?=
 =?UTF-8?q?arTest`=EC=97=90=20=EC=9D=B4=EB=A6=84=20=EA=B4=80=EB=A0=A8=20?=
 =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80=20=20=20=20=20?=
 =?UTF-8?q?=20-=20[x]=20=EC=9D=B4=EB=A6=84=EC=9D=B4=205=EC=9E=90=EB=A5=BC?=
 =?UTF-8?q?=20=EC=B4=88=EA=B3=BC=ED=95=98=EB=A9=B4=20=EC=98=88=EC=99=B8=20?=
 =?UTF-8?q?=EB=B0=9C=EC=83=9D=20=20=20=20=20=20-=20[x]=20=EC=9C=A0?=
 =?UTF-8?q?=ED=9A=A8=ED=95=9C=20=EC=9D=B4=EB=A6=84=EC=9C=BC=EB=A1=9C=20?=
 =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EA=B0=80=EB=8A=A5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 README.md                  | 12 ++++----
 src/main/java/Car.java     | 26 ++++++++++++++++
 src/test/java/CarTest.java | 61 +++++++++++++++++++++++++++-----------
 3 files changed, 75 insertions(+), 24 deletions(-)

diff --git a/README.md b/README.md
index 90a3dc54999..b3a3913d5ac 100644
--- a/README.md
+++ b/README.md
@@ -55,12 +55,12 @@ ResultView : 결과를 출력
 
 1. **자동차 이름 기능**
 
-   - [ ] `Car` 클래스에 이름 필드 추가
-   - [ ] 이름 유효성 검사 (5자 초과 불가)
-   - [ ] `Car` 생성자에 이름 파라미터 추가
-   - [ ] `CarTest`에 이름 관련 테스트 추가
-     - [ ] 이름이 5자를 초과하면 예외 발생
-     - [ ] 유효한 이름으로 생성 가능
+   - [x] `Car` 클래스에 이름 필드 추가
+   - [x] 이름 유효성 검사 (5자 초과 불가)
+   - [x] `Car` 생성자에 이름 파라미터 추가
+   - [x] `CarTest`에 이름 관련 테스트 추가
+     - [x] 이름이 5자를 초과하면 예외 발생
+     - [x] 유효한 이름으로 생성 가능
 
 2. **자동차 이름 출력**
 
diff --git a/src/main/java/Car.java b/src/main/java/Car.java
index 5175e2535fe..0636bc5354b 100644
--- a/src/main/java/Car.java
+++ b/src/main/java/Car.java
@@ -1,8 +1,30 @@
 public class Car {
 
+    @Deprecated
+    public static final String TEMP_CAR_NAME = "temp";
     private static final int MOVEMENT_THRESHOLD = 4;
+    private final String name;
     private int position = 0;
 
+    @Deprecated
+    public Car() {
+        this.name = TEMP_CAR_NAME;
+    }
+
+    public Car(String name) {
+        validateName(name);
+        this.name = name;
+    }
+
+    private void validateName(String name) {
+        if (name == null || name.isBlank()) {
+            throw new IllegalArgumentException("Name cannot be blank");
+        }
+        if (name.length() > 5) {
+            throw new IllegalArgumentException("Name cannot be longer than 5 characters");
+        }
+    }
+
     public void move(int seed) {
         if (seed < 0 || seed > 9) {
             throw new IllegalArgumentException("Invalid seed: " + seed);
@@ -13,6 +35,10 @@ public void move(int seed) {
         }
     }
 
+    public String getName() {
+        return name;
+    }
+
     public int getPosition() {
         return position;
     }
diff --git a/src/test/java/CarTest.java b/src/test/java/CarTest.java
index 17f6e41b84c..fd02795c76d 100644
--- a/src/test/java/CarTest.java
+++ b/src/test/java/CarTest.java
@@ -1,31 +1,56 @@
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+import org.junit.jupiter.params.provider.ValueSource;
 
 class CarTest {
 
     @Test
-    @DisplayName("랜덤 변수가 4이상이면 차가 한 칸 움직인다.")
-    void carMovesOneStepIfRandomNumberIsGreaterThanEqual4() {
-        for (int i = 0; i < 4; i++) {
-            Car car = new Car();
-            car.move(i);
-            assertThat(car.getPosition()).isEqualTo(0);
-        }
-        for (int i = 4; i < 10; i++) {
-            Car car = new Car();
-            car.move(i);
-            assertThat(car.getPosition()).isEqualTo(1);
-        }
+    @DisplayName("자동차는 이름을 가질 수 있다.")
+    void carHasName() {
+        Car car = new Car();
+        assertThat(car.getName()).isEqualTo(Car.TEMP_CAR_NAME);
+
+        car = new Car("MyCar");
+        assertThat(car.getName()).isEqualTo("MyCar");
     }
 
     @Test
-    @DisplayName("자동차를 움직이는 변수는 0에서 9사이의 값이다.")
-    void carMoveVariableIsBetween0And9() {
-        Car car = new Car();
-        assertThrows(IllegalArgumentException.class, () -> car.move(-1));
-        assertThrows(IllegalArgumentException.class, () -> car.move(10));
+    @DisplayName("자동차 이름은 빈 문자열이 될 수 없다")
+    void carNameCannotBeEmpty() {
+        assertThatThrownBy(() -> new Car("")).isInstanceOf(IllegalArgumentException.class).hasMessage("Name cannot be blank");
+    }
+
+    @Test
+    @DisplayName("자동차 이름은 공백만으로 구성될 수 없다")
+    void carNameCannotBeBlank() {
+        assertThatThrownBy(() -> new Car("   ")).isInstanceOf(IllegalArgumentException.class).hasMessage("Name cannot be blank");
+    }
+
+    @Test
+    @DisplayName("자동차 이름은 5자를 초과할 수 없다")
+    void carNameCannotExceed5Characters() {
+        assertThatThrownBy(() -> new Car("123456")).isInstanceOf(IllegalArgumentException.class).hasMessage("Name cannot be longer than 5 characters");
+    }
+
+    @ParameterizedTest
+    @DisplayName("random값이 4 이상일 경우에 자동차의 위치는 1 추가되고, 4 미만일 경우 위치가 변하지 않는다")
+    @CsvSource({"0, 0", "1, 0", "2, 0", "3, 0", "4, 1", "5, 1", "6, 1", "7, 1", "8, 1", "9, 1"})
+    void carMovesAccordingToRandomValue(int seed, int expectedPosition) {
+        Car car = new Car("MyCar");
+        car.move(seed);
+        assertThat(car.getPosition()).isEqualTo(expectedPosition);
+    }
+
+    @ParameterizedTest
+    @DisplayName("이동을 위한 숫자는 0에서 9 사이여야 한다")
+    @ValueSource(ints = {-1, 10})
+    void carMoveVariableIsBetween0And9(int invalidSeed) {
+        Car car = new Car("MyCar");
+        assertThatThrownBy(() -> car.move(invalidSeed)).isInstanceOf(IllegalArgumentException.class).hasMessage("Invalid seed: " + invalidSeed);
     }
 }

From be368144a68686fe5b80f53a352d60b00d40f515 Mon Sep 17 00:00:00 2001
From: kjy2844 <kjy2844@kaist.ac.kr>
Date: Thu, 20 Mar 2025 14:31:26 +0900
Subject: [PATCH 3/9] =?UTF-8?q?feat=20:=20=EC=9E=90=EB=8F=99=EC=B0=A8=20?=
 =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EC=B6=9C=EB=A0=A5=20=20=20=20-=20[x]=20`R?=
 =?UTF-8?q?esultView`=20=EC=88=98=EC=A0=95=20=20=20=20=20=20-=20[x]=20?=
 =?UTF-8?q?=EC=9E=90=EB=8F=99=EC=B0=A8=20=EC=9D=B4=EB=A6=84=EA=B3=BC=20?=
 =?UTF-8?q?=EC=9C=84=EC=B9=98=EB=A5=BC=20=ED=95=A8=EA=BB=98=20=EC=B6=9C?=
 =?UTF-8?q?=EB=A0=A5=ED=95=98=EB=8A=94=20=ED=98=95=EC=8B=9D=20=EB=B3=80?=
 =?UTF-8?q?=EA=B2=BD=20=20=20=20=20=20-=20[x]=20`presentCars`=20=EB=A9=94?=
 =?UTF-8?q?=EC=86=8C=EB=93=9C=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20?=
 =?UTF-8?q?=EC=88=98=EC=A0=95=20(=EC=9D=B4=EB=A6=84=20=EC=A0=95=EB=B3=B4?=
 =?UTF-8?q?=20=EC=B6=94=EA=B0=80)=20=20=20=20-=20[x]=20`Race`=20=ED=81=B4?=
 =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EC=88=98=EC=A0=95=20=20=20=20=20=20-=20[x?=
 =?UTF-8?q?]=20`getCarPositions`=20=EB=A9=94=EC=86=8C=EB=93=9C=EB=A5=BC=20?=
 =?UTF-8?q?`getCarStatus`=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20=20=20=20=20=20-?=
 =?UTF-8?q?=20[x]=20=EC=9E=90=EB=8F=99=EC=B0=A8=20=EC=9D=B4=EB=A6=84?=
 =?UTF-8?q?=EA=B3=BC=20=EC=9C=84=EC=B9=98=EB=A5=BC=20=ED=95=A8=EA=BB=98=20?=
 =?UTF-8?q?=EB=B0=98=ED=99=98=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98?=
 =?UTF-8?q?=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 README.md                     | 95 +++++++++++++++++++----------------
 src/main/java/CarStatus.java  | 17 +++++++
 src/main/java/Game.java       |  3 +-
 src/main/java/Race.java       |  8 +--
 src/main/java/ResultView.java |  8 +--
 src/test/java/RaceTest.java   | 15 +++---
 6 files changed, 86 insertions(+), 60 deletions(-)
 create mode 100644 src/main/java/CarStatus.java

diff --git a/README.md b/README.md
index b3a3913d5ac..bf358def396 100644
--- a/README.md
+++ b/README.md
@@ -1,40 +1,46 @@
 # 자동차 경주 게임
+
 ## 진행 방법
-* 자동차 경주 게임 요구사항을 파악한다.
-* 요구사항에 대한 구현을 완료한 후 자신의 github 아이디에 해당하는 브랜치에 Pull Request(이하 PR)를 통해 코드 리뷰 요청을 한다.
-* 코드 리뷰 피드백에 대한 개선 작업을 하고 다시 PUSH한다.
-* 모든 피드백을 완료하면 다음 단계를 도전하고 앞의 과정을 반복한다.
+
+- 자동차 경주 게임 요구사항을 파악한다.
+- 요구사항에 대한 구현을 완료한 후 자신의 github 아이디에 해당하는 브랜치에 Pull Request(이하 PR)를 통해 코드 리뷰 요청을 한다.
+- 코드 리뷰 피드백에 대한 개선 작업을 하고 다시 PUSH한다.
+- 모든 피드백을 완료하면 다음 단계를 도전하고 앞의 과정을 반복한다.
 
 ## 온라인 코드 리뷰 과정
-* [텍스트와 이미지로 살펴보는 온라인 코드 리뷰 과정](https://github.com/next-step/nextstep-docs/tree/master/codereview)
+
+- [텍스트와 이미지로 살펴보는 온라인 코드 리뷰 과정](https://github.com/next-step/nextstep-docs/tree/master/codereview)
 
 ## 🚀 3단계 - 자동차 경주
 
 ### 기능 요구사항
-* 초간단 자동차 경주 게임을 구현한다.
-* 주어진 횟수 동안 n대의 자동차는 전진 또는 멈출 수 있다.
-* 사용자는 몇 대의 자동차로 몇 번의 이동을 할 것인지를 입력할 수 있어야 한다.
-* 전진하는 조건은 0에서 9 사이에서 random 값을 구한 후 random 값이 4이상일 경우이다.
-* 자동차의 상태를 화면에 출력한다. 어느 시점에 출력할 것인지에 대한 제약은 없다.
-
-- [x] 자동차의 처음 위치는 0이다.
-- [x] 사용자가 입력한 개수만큼의 자동차가 존재한다.
-- [x] 사용자가 0 또는 음수의 자동차 개수를 입력하면 에러를 반환한다.
-- [x] random값이 4 이상일 경우에 자동차의 위치는 1 추가된다.
-- [x] m 라운드가 끝나면 자동차 경주는 종료된다.
+
+- 초간단 자동차 경주 게임을 구현한다.
+- 주어진 횟수 동안 n대의 자동차는 전진 또는 멈출 수 있다.
+- 사용자는 몇 대의 자동차로 몇 번의 이동을 할 것인지를 입력할 수 있어야 한다.
+- 전진하는 조건은 0에서 9 사이에서 random 값을 구한 후 random 값이 4이상일 경우이다.
+- 자동차의 상태를 화면에 출력한다. 어느 시점에 출력할 것인지에 대한 제약은 없다.
+
+* [x] 자동차의 처음 위치는 0이다.
+* [x] 사용자가 입력한 개수만큼의 자동차가 존재한다.
+* [x] 사용자가 0 또는 음수의 자동차 개수를 입력하면 에러를 반환한다.
+* [x] random값이 4 이상일 경우에 자동차의 위치는 1 추가된다.
+* [x] m 라운드가 끝나면 자동차 경주는 종료된다.
 
 ### 프로그래밍 요구사항
-* 모든 로직에 단위 테스트를 구현한다. 단, UI(System.out, System.in) 로직은 제외
-  * 핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 구분한다.
-  * UI 로직을 InputView, ResultView와 같은 클래스를 추가해 분리한다.
-* 자바 코드 컨벤션을 지키면서 프로그래밍한다.
-  * 이 과정의 Code Style은 intellij idea Code Style. Java을 따른다.
-  * intellij idea Code Style. Java을 따르려면 code formatting 단축키(Windows : Ctrl + Alt + L. Mac : ⌥ (Option) + ⌘ (Command) + L.)를 사용한다.
-* else 예약어를 쓰지 않는다.
-  * 힌트: if 조건절에서 값을 return하는 방식으로 구현하면 else를 사용하지 않아도 된다.
-  * else를 쓰지 말라고 하니 switch/case로 구현하는 경우가 있는데 switch/case도 허용하지 않는다.
+
+- 모든 로직에 단위 테스트를 구현한다. 단, UI(System.out, System.in) 로직은 제외
+  - 핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 구분한다.
+  - UI 로직을 InputView, ResultView와 같은 클래스를 추가해 분리한다.
+- 자바 코드 컨벤션을 지키면서 프로그래밍한다.
+  - 이 과정의 Code Style은 intellij idea Code Style. Java을 따른다.
+  - intellij idea Code Style. Java을 따르려면 code formatting 단축키(Windows : Ctrl + Alt + L. Mac : ⌥ (Option) + ⌘ (Command) + L.)를 사용한다.
+- else 예약어를 쓰지 않는다.
+  - 힌트: if 조건절에서 값을 return하는 방식으로 구현하면 else를 사용하지 않아도 된다.
+  - else를 쓰지 말라고 하니 switch/case로 구현하는 경우가 있는데 switch/case도 허용하지 않는다.
 
 ### 개발 구조
+
 Game : 게임의 시작과 종료를 담당
 Race : 전체 라운드의 진행을 담당
 GameSettings : 자동차 경주 게임의 설정값
@@ -64,12 +70,12 @@ ResultView : 결과를 출력
 
 2. **자동차 이름 출력**
 
-   - [ ] `ResultView` 수정
-     - [ ] 자동차 이름과 위치를 함께 출력하는 형식 변경
-     - [ ] `presentCars` 메소드 파라미터 수정 (이름 정보 추가)
-   - [ ] `Race` 클래스 수정
-     - [ ] `getCarPositions` 메소드를 `getCarStatus`로 변경
-     - [ ] 자동차 이름과 위치를 함께 반환하도록 수정
+   - [x] `ResultView` 수정
+     - [x] 자동차 이름과 위치를 함께 출력하는 형식 변경
+     - [x] `presentCars` 메소드 파라미터 수정 (이름 정보 추가)
+   - [x] `Race` 클래스 수정
+     - [x] `getCarPositions` 메소드를 `getCarStatus`로 변경
+     - [x] 자동차 이름과 위치를 함께 반환하도록 수정
 
 3. **자동차 이름 입력**
 
@@ -104,16 +110,17 @@ ResultView : 결과를 출력
    - [ ] `CarStatus` DTO 도입 검토 (이름과 위치를 함께 전달하기 위해)
 
 ### 프로그래밍 요구사항
-* indent(인덴트, 들여쓰기) depth를 2를 넘지 않도록 구현한다. 1까지만 허용한다.
-  * 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다.
-  * 힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메소드)를 분리하면 된다.
-* 함수(또는 메소드)의 길이가 15라인을 넘어가지 않도록 구현한다.
-  * 함수(또는 메소드)가 한 가지 일만 잘 하도록 구현한다.
-* 모든 로직에 단위 테스트를 구현한다. 단, UI(System.out, System.in) 로직은 제외
-  * 핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 구분한다.
-  * UI 로직을 InputView, ResultView와 같은 클래스를 추가해 분리한다.
-* 자바 코드 컨벤션을 지키면서 프로그래밍한다.
-  * 참고문서: https://google.github.io/styleguide/javaguide.html 또는 https://myeonguni.tistory.com/1596
-* else 예약어를 쓰지 않는다.
-  * 힌트: if 조건절에서 값을 return하는 방식으로 구현하면 else를 사용하지 않아도 된다.
-  * else를 쓰지 말라고 하니 switch/case로 구현하는 경우가 있는데 switch/case도 허용하지 않는다.
+
+- indent(인덴트, 들여쓰기) depth를 2를 넘지 않도록 구현한다. 1까지만 허용한다.
+  - 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다.
+  - 힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메소드)를 분리하면 된다.
+- 함수(또는 메소드)의 길이가 15라인을 넘어가지 않도록 구현한다.
+  - 함수(또는 메소드)가 한 가지 일만 잘 하도록 구현한다.
+- 모든 로직에 단위 테스트를 구현한다. 단, UI(System.out, System.in) 로직은 제외
+  - 핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 구분한다.
+  - UI 로직을 InputView, ResultView와 같은 클래스를 추가해 분리한다.
+- 자바 코드 컨벤션을 지키면서 프로그래밍한다.
+  - 참고문서: https://google.github.io/styleguide/javaguide.html 또는 https://myeonguni.tistory.com/1596
+- else 예약어를 쓰지 않는다.
+  - 힌트: if 조건절에서 값을 return하는 방식으로 구현하면 else를 사용하지 않아도 된다.
+  - else를 쓰지 말라고 하니 switch/case로 구현하는 경우가 있는데 switch/case도 허용하지 않는다.
diff --git a/src/main/java/CarStatus.java b/src/main/java/CarStatus.java
new file mode 100644
index 00000000000..1ba73da4c8f
--- /dev/null
+++ b/src/main/java/CarStatus.java
@@ -0,0 +1,17 @@
+public class CarStatus {
+    private final String name;
+    private final int position;
+
+    public CarStatus(Car car) {
+        this.name = car.getName();
+        this.position = car.getPosition();
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getPosition() {
+        return position;
+    }
+} 
\ No newline at end of file
diff --git a/src/main/java/Game.java b/src/main/java/Game.java
index a12021dad10..642d47e3ea3 100644
--- a/src/main/java/Game.java
+++ b/src/main/java/Game.java
@@ -13,9 +13,10 @@ public void start() {
 
         Race race = new Race(settings);
         while (race.isRaceInProgress()) {
+            resultView.presentCars(race.getCarStatuses());
             race.runRound();
-            resultView.presentCars(race.getCarPositions());
         }
+        resultView.presentCars(race.getCarStatuses());
     }
 
     public static void main(String[] args) {
diff --git a/src/main/java/Race.java b/src/main/java/Race.java
index 652af54f1ff..ed061d05894 100644
--- a/src/main/java/Race.java
+++ b/src/main/java/Race.java
@@ -21,12 +21,12 @@ public Race(GameSettings settings) {
         }
     }
 
-    public List<Integer> getCarPositions() {
-        List<Integer> positions = new ArrayList<>();
+    public List<CarStatus> getCarStatuses() {
+        List<CarStatus> statuses = new ArrayList<>();
         for (Car car : cars) {
-            positions.add(car.getPosition());
+            statuses.add(new CarStatus(car));
         }
-        return positions;
+        return statuses;
     }
 
     public void runRound() {
diff --git a/src/main/java/ResultView.java b/src/main/java/ResultView.java
index 9c175aedb95..f1a27b1658e 100644
--- a/src/main/java/ResultView.java
+++ b/src/main/java/ResultView.java
@@ -6,9 +6,11 @@ public void presentStartMessage() {
         System.out.println("실행 결과");
     }
 
-    public void presentCars(List<Integer> carPositions) {
-        for (int carPosition : carPositions) {
-            System.out.println("-".repeat(carPosition + 1));
+    public void presentCars(List<CarStatus> cars) {
+        for (CarStatus car : cars) {
+            String positionIndicator = "-".repeat(car.getPosition() + 1);
+            String output = String.format("%s : %s", car.getName(), positionIndicator);
+            System.out.println(output);
         }
         System.out.println();
     }
diff --git a/src/test/java/RaceTest.java b/src/test/java/RaceTest.java
index 7f7bdfd8251..d6b6e02c082 100644
--- a/src/test/java/RaceTest.java
+++ b/src/test/java/RaceTest.java
@@ -19,7 +19,7 @@ void negativeOrZeroCarCountInputReturnsError() {
         });
 
         Race race = new Race(new GameSettings(1, 3));
-        assertThat(race.getCarPositions()).hasSize(1);
+        assertThat(race.getCarStatuses()).hasSize(1);
     }
 
     @Test
@@ -41,8 +41,8 @@ void negativeOrZeroRaceCountInputReturnsError() {
     @DisplayName("경기 시작시 자동차의 위치는 0이다.")
     void carPositionsAtStartAreZero() {
         Race race = new Race(new GameSettings(5, 3));
-        for (Integer carPositions : race.getCarPositions()) {
-            assertThat(carPositions).isZero();
+        for (CarStatus carStatus : race.getCarStatuses()) {
+            assertThat(carStatus.getPosition()).isZero();
         }
     }
 
@@ -50,14 +50,13 @@ void carPositionsAtStartAreZero() {
     @DisplayName("한 라운드가 진행되면 자동차의 위치는 기존 위치이거나, 기존 위치 + 1이다.")
     void carPositionsAfterOneRoundAreEitherSameOrIncremented() {
         Race race = new Race(new GameSettings(5, 3));
-        race.runRound();
-        List<Integer> initialPositions = race.getCarPositions();
+        List<CarStatus> initialStatuses = race.getCarStatuses();
 
         race.runRound();
-        List<Integer> finalPositions = race.getCarPositions();
+        List<CarStatus> finalStatuses = race.getCarStatuses();
 
-        for (int i = 0; i < initialPositions.size(); i++) {
-            assertThat(finalPositions.get(i)).isIn(initialPositions.get(i), initialPositions.get(i) + 1);
+        for (int i = 0; i < initialStatuses.size(); i++) {
+            assertThat(finalStatuses.get(i).getPosition()).isIn(initialStatuses.get(i).getPosition(), initialStatuses.get(i).getPosition() + 1);
         }
     }
 

From 040e2789426b816392bcc84cb1ddec67c6816a35 Mon Sep 17 00:00:00 2001
From: kjy2844 <kjy2844@kaist.ac.kr>
Date: Thu, 20 Mar 2025 14:57:52 +0900
Subject: [PATCH 4/9] =?UTF-8?q?feat=20:=20=EC=9E=90=EB=8F=99=EC=B0=A8=20?=
 =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EC=9E=85=EB=A0=A5=20=20=20=20-=20[x]=20`I?=
 =?UTF-8?q?nputView`=20=EC=88=98=EC=A0=95=20=20=20=20=20=20-=20[x]=20?=
 =?UTF-8?q?=EC=9E=90=EB=8F=99=EC=B0=A8=20=EC=9D=B4=EB=A6=84=20=EC=9E=85?=
 =?UTF-8?q?=EB=A0=A5=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=B6=94=EA=B0=80=20?=
 =?UTF-8?q?=20=20=20=20=20-=20[x]=20=EC=89=BC=ED=91=9C=EB=A1=9C=20?=
 =?UTF-8?q?=EA=B5=AC=EB=B6=84=EB=90=9C=20=EC=9D=B4=EB=A6=84=20=EB=AC=B8?=
 =?UTF-8?q?=EC=9E=90=EC=97=B4=20=ED=8C=8C=EC=8B=B1=20=EB=A1=9C=EC=A7=81=20?=
 =?UTF-8?q?=EC=B6=94=EA=B0=80=20=20=20=20-=20[x]=20`GameSettings`=20?=
 =?UTF-8?q?=EC=88=98=EC=A0=95=20=20=20=20=20=20-=20[x]=20=EC=9E=90?=
 =?UTF-8?q?=EB=8F=99=EC=B0=A8=20=EC=9D=B4=EB=A6=84=20=EB=AA=A9=EB=A1=9D=20?=
 =?UTF-8?q?=ED=95=84=EB=93=9C=20=EC=B6=94=EA=B0=80=20=20=20=20=20=20-=20[x?=
 =?UTF-8?q?]=20=EC=83=9D=EC=84=B1=EC=9E=90=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 README.md                           | 12 +++----
 src/main/java/Car.java              | 11 ++-----
 src/main/java/GameSettings.java     | 33 ++++++++++++++++---
 src/main/java/InputView.java        | 10 ++++--
 src/main/java/Race.java             |  8 ++---
 src/test/java/CarTest.java          |  5 +--
 src/test/java/GameSettingsTest.java | 46 +++++++++++++++++++++++++++
 src/test/java/RaceTest.java         | 49 +++++++----------------------
 8 files changed, 105 insertions(+), 69 deletions(-)
 create mode 100644 src/test/java/GameSettingsTest.java

diff --git a/README.md b/README.md
index bf358def396..58a3e485f6b 100644
--- a/README.md
+++ b/README.md
@@ -79,12 +79,12 @@ ResultView : 결과를 출력
 
 3. **자동차 이름 입력**
 
-   - [ ] `InputView` 수정
-     - [ ] 자동차 이름 입력 메소드 추가
-     - [ ] 쉼표로 구분된 이름 문자열 파싱 로직 추가
-   - [ ] `GameSettings` 수정
-     - [ ] 자동차 이름 목록 필드 추가
-     - [ ] 생성자 수정
+   - [x] `InputView` 수정
+     - [x] 자동차 이름 입력 메소드 추가
+     - [x] 쉼표로 구분된 이름 문자열 파싱 로직 추가
+   - [x] `GameSettings` 수정
+     - [x] 자동차 이름 목록 필드 추가
+     - [x] 생성자 수정
 
 4. **우승자 판정**
 
diff --git a/src/main/java/Car.java b/src/main/java/Car.java
index 0636bc5354b..1b454d7663e 100644
--- a/src/main/java/Car.java
+++ b/src/main/java/Car.java
@@ -1,23 +1,16 @@
 public class Car {
 
-    @Deprecated
-    public static final String TEMP_CAR_NAME = "temp";
     private static final int MOVEMENT_THRESHOLD = 4;
     private final String name;
     private int position = 0;
 
-    @Deprecated
-    public Car() {
-        this.name = TEMP_CAR_NAME;
-    }
-
     public Car(String name) {
         validateName(name);
-        this.name = name;
+        this.name = name.trim();
     }
 
     private void validateName(String name) {
-        if (name == null || name.isBlank()) {
+        if (name == null || name.trim().isBlank()) {
             throw new IllegalArgumentException("Name cannot be blank");
         }
         if (name.length() > 5) {
diff --git a/src/main/java/GameSettings.java b/src/main/java/GameSettings.java
index 6c9d813371a..13fc0509e14 100644
--- a/src/main/java/GameSettings.java
+++ b/src/main/java/GameSettings.java
@@ -1,14 +1,39 @@
 public class GameSettings {
-    private final int carCount;
+
+    private final String[] carNames;
     private final int roundCount;
 
-    public GameSettings(int carCount, int roundCount) {
-        this.carCount = carCount;
+    public GameSettings(String[] carNames, int roundCount) {
+        validateCarNames(carNames);
+        validateRoundCount(roundCount);
+
+        this.carNames = carNames;
         this.roundCount = roundCount;
     }
 
+    private void validateCarNames(String[] carNames) {
+        if (carNames == null || carNames.length == 0) {
+            throw new IllegalArgumentException("자동차 이름 목록이 비어있습니다.");
+        }
+        for (String name : carNames) {
+            if (name == null || name.trim().isEmpty()) {
+                throw new IllegalArgumentException("자동차 이름은 비어있을 수 없습니다.");
+            }
+        }
+    }
+
+    private void validateRoundCount(int roundCount) {
+        if (roundCount < 1) {
+            throw new IllegalArgumentException("시도 횟수는 1 이상이어야 합니다.");
+        }
+    }
+
+    public String[] getCarNames() {
+        return carNames;
+    }
+
     public int getCarCount() {
-        return carCount;
+        return carNames.length;
     }
 
     public int getRoundCount() {
diff --git a/src/main/java/InputView.java b/src/main/java/InputView.java
index 3858ddbb538..fb593125348 100644
--- a/src/main/java/InputView.java
+++ b/src/main/java/InputView.java
@@ -8,9 +8,15 @@ public InputView() {
     }
 
     public GameSettings getGameSettings() {
-        int carCount = promptInt("자동차 대수는 몇 대 인가요?");
+        String inputCarNames = prompt("경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분).");
+        String[] carNames = inputCarNames.split(",");
         int roundCount = promptInt("시도할 회수는 몇 회 인가요?");
-        return new GameSettings(carCount, roundCount);
+        return new GameSettings(carNames, roundCount);
+    }
+
+    private String prompt(String message) {
+        System.out.println(message);
+        return scanner.nextLine();
     }
 
     private int promptInt(String message) {
diff --git a/src/main/java/Race.java b/src/main/java/Race.java
index ed061d05894..e6ac71c3ee8 100644
--- a/src/main/java/Race.java
+++ b/src/main/java/Race.java
@@ -10,14 +10,10 @@ public class Race {
     private int currentRound = 0;
 
     public Race(GameSettings settings) {
-        if (settings.getCarCount() < 1 || settings.getRoundCount() < 1) {
-            throw new IllegalArgumentException("Invalid game settings: " + settings);
-        }
-
         this.totalRounds = settings.getRoundCount();
         this.cars = new ArrayList<>();
-        for (int i = 0; i < settings.getCarCount(); i++) {
-            this.cars.add(new Car());
+        for (String carName : settings.getCarNames()) {
+            this.cars.add(new Car(carName));
         }
     }
 
diff --git a/src/test/java/CarTest.java b/src/test/java/CarTest.java
index fd02795c76d..2c2f5df8a76 100644
--- a/src/test/java/CarTest.java
+++ b/src/test/java/CarTest.java
@@ -12,10 +12,7 @@ class CarTest {
     @Test
     @DisplayName("자동차는 이름을 가질 수 있다.")
     void carHasName() {
-        Car car = new Car();
-        assertThat(car.getName()).isEqualTo(Car.TEMP_CAR_NAME);
-
-        car = new Car("MyCar");
+        Car car = new Car("MyCar");
         assertThat(car.getName()).isEqualTo("MyCar");
     }
 
diff --git a/src/test/java/GameSettingsTest.java b/src/test/java/GameSettingsTest.java
new file mode 100644
index 00000000000..d2ed7672682
--- /dev/null
+++ b/src/test/java/GameSettingsTest.java
@@ -0,0 +1,46 @@
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+class GameSettingsTest {
+
+    @Test
+    @DisplayName("자동차 이름 목록이 비어있으면 에러가 발생한다")
+    void emptyCarNamesListThrowsError() {
+        assertThatThrownBy(() -> new GameSettings(new String[0], 3)).isInstanceOf(IllegalArgumentException.class).hasMessage("자동차 이름 목록이 비어있습니다.");
+
+        assertThatThrownBy(() -> new GameSettings(null, 3)).isInstanceOf(IllegalArgumentException.class).hasMessage("자동차 이름 목록이 비어있습니다.");
+    }
+
+    @Test
+    @DisplayName("자동차 이름이 비어있으면 에러가 발생한다")
+    void emptyCarNameThrowsError() {
+        String[] carNamesWithBlank = {"car1", "", "car3"};
+        assertThatThrownBy(() -> new GameSettings(carNamesWithBlank, 3)).isInstanceOf(IllegalArgumentException.class).hasMessage("자동차 이름은 비어있을 수 없습니다.");
+
+        String[] carNamesWithNull = {"car1", null, "car3"};
+        assertThatThrownBy(() -> new GameSettings(carNamesWithNull, 3)).isInstanceOf(IllegalArgumentException.class).hasMessage("자동차 이름은 비어있을 수 없습니다.");
+    }
+
+    @Test
+    @DisplayName("시도 횟수가 1 미만이면 에러가 발생한다")
+    void roundCountLessThanOneThrowsError() {
+        String[] carNames = {"car1", "car2", "car3"};
+        assertThatThrownBy(() -> new GameSettings(carNames, 0)).isInstanceOf(IllegalArgumentException.class).hasMessage("시도 횟수는 1 이상이어야 합니다.");
+
+        assertThatThrownBy(() -> new GameSettings(carNames, -1)).isInstanceOf(IllegalArgumentException.class).hasMessage("시도 횟수는 1 이상이어야 합니다.");
+    }
+
+    @Test
+    @DisplayName("유효한 입력으로 GameSettings가 생성된다")
+    void validInputCreatesGameSettings() {
+        String[] carNames = {"car1", "car2", "car3"};
+        GameSettings settings = new GameSettings(carNames, 3);
+
+        assertThat(settings.getCarNames()).isEqualTo(carNames);
+        assertThat(settings.getCarCount()).isEqualTo(3);
+        assertThat(settings.getRoundCount()).isEqualTo(3);
+    }
+} 
\ No newline at end of file
diff --git a/src/test/java/RaceTest.java b/src/test/java/RaceTest.java
index d6b6e02c082..ac50043edcb 100644
--- a/src/test/java/RaceTest.java
+++ b/src/test/java/RaceTest.java
@@ -1,6 +1,5 @@
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
-import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import java.util.List;
 import org.junit.jupiter.api.DisplayName;
@@ -9,47 +8,20 @@
 class RaceTest {
 
     @Test
-    @DisplayName("자동차 개수는 양수여야 한다.")
-    void negativeOrZeroCarCountInputReturnsError() {
-        assertThrows(IllegalArgumentException.class, () -> {
-            new Race(new GameSettings(-1, 3));
-        });
-        assertThrows(IllegalArgumentException.class, () -> {
-            new Race(new GameSettings(0, 3));
-        });
-
-        Race race = new Race(new GameSettings(1, 3));
-        assertThat(race.getCarStatuses()).hasSize(1);
-    }
-
-    @Test
-    @DisplayName("경주 횟수는 양수여야 한다.")
-    void negativeOrZeroRaceCountInputReturnsError() {
-        assertThrows(IllegalArgumentException.class, () -> {
-            new Race(new GameSettings(5, -1));
-        });
-        assertThrows(IllegalArgumentException.class, () -> {
-            new Race(new GameSettings(5, 0));
-        });
-
-        assertDoesNotThrow(() -> {
-            new Race(new GameSettings(5, 1));
-        });
-    }
-
-    @Test
-    @DisplayName("경기 시작시 자동차의 위치는 0이다.")
+    @DisplayName("경기 시작시 자동차의 위치는 0이다")
     void carPositionsAtStartAreZero() {
-        Race race = new Race(new GameSettings(5, 3));
+        String[] carNames = {"car1", "car2", "car3", "car4", "car5"};
+        Race race = new Race(new GameSettings(carNames, 3));
         for (CarStatus carStatus : race.getCarStatuses()) {
             assertThat(carStatus.getPosition()).isZero();
         }
     }
 
     @Test
-    @DisplayName("한 라운드가 진행되면 자동차의 위치는 기존 위치이거나, 기존 위치 + 1이다.")
+    @DisplayName("한 라운드가 진행되면 자동차의 위치는 기존 위치이거나, 기존 위치 + 1이다")
     void carPositionsAfterOneRoundAreEitherSameOrIncremented() {
-        Race race = new Race(new GameSettings(5, 3));
+        String[] carNames = {"car1", "car2", "car3", "car4", "car5"};
+        Race race = new Race(new GameSettings(carNames, 3));
         List<CarStatus> initialStatuses = race.getCarStatuses();
 
         race.runRound();
@@ -61,12 +33,13 @@ void carPositionsAfterOneRoundAreEitherSameOrIncremented() {
     }
 
     @Test
-    @DisplayName("전체 라운드를 넘어가면 에러가 발생한다.")
+    @DisplayName("전체 라운드를 넘어가면 에러가 발생한다")
     void exceedingTotalRoundsThrowsError() {
-        Race race = new Race(new GameSettings(5, 3));
+        String[] carNames = {"car1", "car2", "car3", "car4", "car5"};
+        Race race = new Race(new GameSettings(carNames, 3));
         for (int i = 0; i < 3; i++) {
             race.runRound();
         }
-        assertThrows(IllegalStateException.class, race::runRound);
+        assertThatThrownBy(race::runRound).isInstanceOf(IllegalStateException.class).hasMessage("Race has already finished");
     }
 }

From 06ccfadb3c4435a0e0906358e1ae344b42ac4800 Mon Sep 17 00:00:00 2001
From: kjy2844 <kjy2844@kaist.ac.kr>
Date: Thu, 20 Mar 2025 17:14:40 +0900
Subject: [PATCH 5/9] =?UTF-8?q?feat=20:=20=EC=9A=B0=EC=8A=B9=EC=9E=90=20?=
 =?UTF-8?q?=ED=8C=90=EC=A0=95=20=20=20=20-=20[x]=20`Race`=20=ED=81=B4?=
 =?UTF-8?q?=EB=9E=98=EC=8A=A4=EC=97=90=20=EC=9A=B0=EC=8A=B9=EC=9E=90=20?=
 =?UTF-8?q?=ED=8C=90=EC=A0=95=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80=20?=
 =?UTF-8?q?=20=20=20=20=20-=20[x]=20`getWinners`=20=EB=A9=94=EC=86=8C?=
 =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80=20=20=20=20=20=20-=20[x]=20?=
 =?UTF-8?q?=EA=B0=80=EC=9E=A5=20=EB=A9=80=EB=A6=AC=20=EA=B0=84=20=EC=9E=90?=
 =?UTF-8?q?=EB=8F=99=EC=B0=A8=EB=93=A4=20=EC=B0=BE=EA=B8=B0=20=20=20=20-?=
 =?UTF-8?q?=20[x]=20`ResultView`=EC=97=90=20=EC=9A=B0=EC=8A=B9=EC=9E=90=20?=
 =?UTF-8?q?=EC=B6=9C=EB=A0=A5=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=B6=94?=
 =?UTF-8?q?=EA=B0=80=20=20=20=20-=20[x]=20`Game`=20=ED=81=B4=EB=9E=98?=
 =?UTF-8?q?=EC=8A=A4=20=EC=88=98=EC=A0=95=20=20=20=20=20=20-=20[x]=20?=
 =?UTF-8?q?=EA=B2=BD=EC=A3=BC=20=EC=A2=85=EB=A3=8C=20=ED=9B=84=20=EC=9A=B0?=
 =?UTF-8?q?=EC=8A=B9=EC=9E=90=20=EC=B6=9C=EB=A0=A5=20=EB=A1=9C=EC=A7=81=20?=
 =?UTF-8?q?=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 README.md                     | 12 ++++----
 src/main/java/Car.java        |  7 +++++
 src/main/java/Game.java       |  1 +
 src/main/java/Race.java       | 56 ++++++++++++++++++++++++++++++++---
 src/main/java/ResultView.java |  9 ++++++
 src/test/java/RaceTest.java   | 50 +++++++++++++++++++++++++++++++
 6 files changed, 125 insertions(+), 10 deletions(-)

diff --git a/README.md b/README.md
index 58a3e485f6b..0e14e04aa0c 100644
--- a/README.md
+++ b/README.md
@@ -88,12 +88,12 @@ ResultView : 결과를 출력
 
 4. **우승자 판정**
 
-   - [ ] `Race` 클래스에 우승자 판정 로직 추가
-     - [ ] `getWinners` 메소드 추가
-     - [ ] 가장 멀리 간 자동차들 찾기
-   - [ ] `ResultView`에 우승자 출력 메소드 추가
-   - [ ] `Game` 클래스 수정
-     - [ ] 경주 종료 후 우승자 출력 로직 추가
+   - [x] `Race` 클래스에 우승자 판정 로직 추가
+     - [x] `getWinners` 메소드 추가
+     - [x] 가장 멀리 간 자동차들 찾기
+   - [x] `ResultView`에 우승자 출력 메소드 추가
+   - [x] `Game` 클래스 수정
+     - [x] 경주 종료 후 우승자 출력 로직 추가
 
 5. **테스트 추가**
 
diff --git a/src/main/java/Car.java b/src/main/java/Car.java
index 1b454d7663e..1778e8f88fa 100644
--- a/src/main/java/Car.java
+++ b/src/main/java/Car.java
@@ -9,6 +9,13 @@ public Car(String name) {
         this.name = name.trim();
     }
 
+    // 테스트용 생성자
+    Car(String name, int position) {
+        validateName(name);
+        this.name = name.trim();
+        this.position = position;
+    }
+
     private void validateName(String name) {
         if (name == null || name.trim().isBlank()) {
             throw new IllegalArgumentException("Name cannot be blank");
diff --git a/src/main/java/Game.java b/src/main/java/Game.java
index 642d47e3ea3..c66c6d04fab 100644
--- a/src/main/java/Game.java
+++ b/src/main/java/Game.java
@@ -17,6 +17,7 @@ public void start() {
             race.runRound();
         }
         resultView.presentCars(race.getCarStatuses());
+        resultView.presentWinners(race.getWinners());
     }
 
     public static void main(String[] args) {
diff --git a/src/main/java/Race.java b/src/main/java/Race.java
index e6ac71c3ee8..aecfe9ba141 100644
--- a/src/main/java/Race.java
+++ b/src/main/java/Race.java
@@ -17,6 +17,13 @@ public Race(GameSettings settings) {
         }
     }
 
+    // 테스트용 생성자
+    Race(List<Car> cars, int totalRounds) {
+        this.cars = new ArrayList<>(cars);
+        this.totalRounds = totalRounds;
+        this.currentRound = totalRounds;  // 경주가 끝난 상태로 설정
+    }
+
     public List<CarStatus> getCarStatuses() {
         List<CarStatus> statuses = new ArrayList<>();
         for (Car car : cars) {
@@ -26,10 +33,7 @@ public List<CarStatus> getCarStatuses() {
     }
 
     public void runRound() {
-        if (!isRaceInProgress()) {
-            throw new IllegalStateException("Race has already finished");
-        }
-
+        validateRaceInProgress();
         for (Car car : cars) {
             car.move(random.nextInt(10));
         }
@@ -39,4 +43,48 @@ public void runRound() {
     public boolean isRaceInProgress() {
         return currentRound < totalRounds;
     }
+
+    private void validateRaceInProgress() {
+        if (!isRaceInProgress()) {
+            throw new IllegalStateException("Race has already finished");
+        }
+    }
+
+    private void validateRaceFinished() {
+        if (isRaceInProgress()) {
+            throw new IllegalStateException("Race is still in progress");
+        }
+    }
+
+    private int findMaxPosition() {
+        int maxPosition = 0;
+        for (Car car : cars) {
+            maxPosition = Math.max(maxPosition, car.getPosition());
+        }
+        return maxPosition;
+    }
+
+    private boolean isWinner(Car car, int maxPosition) {
+        return car.getPosition() == maxPosition;
+    }
+
+    private List<CarStatus> findWinnersWithPosition(int maxPosition) {
+        List<CarStatus> winners = new ArrayList<>();
+        for (Car car : cars) {
+            addWinnerIfQualified(winners, car, maxPosition);
+        }
+        return winners;
+    }
+
+    private void addWinnerIfQualified(List<CarStatus> winners, Car car, int maxPosition) {
+        if (isWinner(car, maxPosition)) {
+            winners.add(new CarStatus(car));
+        }
+    }
+
+    public List<CarStatus> getWinners() {
+        validateRaceFinished();
+        int maxPosition = findMaxPosition();
+        return findWinnersWithPosition(maxPosition);
+    }
 }
diff --git a/src/main/java/ResultView.java b/src/main/java/ResultView.java
index f1a27b1658e..25874674706 100644
--- a/src/main/java/ResultView.java
+++ b/src/main/java/ResultView.java
@@ -1,4 +1,5 @@
 import java.util.List;
+import java.util.StringJoiner;
 
 public class ResultView {
 
@@ -14,4 +15,12 @@ public void presentCars(List<CarStatus> cars) {
         }
         System.out.println();
     }
+
+    public void presentWinners(List<CarStatus> winners) {
+        StringJoiner joiner = new StringJoiner(", ");
+        for (CarStatus winner : winners) {
+            joiner.add(winner.getName());
+        }
+        System.out.println(joiner.toString() + "가 최종 우승했습니다.");
+    }
 }
diff --git a/src/test/java/RaceTest.java b/src/test/java/RaceTest.java
index ac50043edcb..743975e4b19 100644
--- a/src/test/java/RaceTest.java
+++ b/src/test/java/RaceTest.java
@@ -42,4 +42,54 @@ void exceedingTotalRoundsThrowsError() {
         }
         assertThatThrownBy(race::runRound).isInstanceOf(IllegalStateException.class).hasMessage("Race has already finished");
     }
+
+    @Test
+    @DisplayName("경주가 진행 중일 때 우승자를 조회하면 예외가 발생한다")
+    void getWinnersBeforeRaceFinishThrowsError() {
+        String[] carNames = {"car1", "car2"};
+        Race race = new Race(new GameSettings(carNames, 3));
+        race.runRound();  // 1라운드만 진행
+
+        assertThatThrownBy(race::getWinners)
+                .isInstanceOf(IllegalStateException.class)
+                .hasMessage("Race is still in progress");
+    }
+
+    @Test
+    @DisplayName("단독 우승자가 있는 경우 해당 자동차만 반환한다")
+    void getSingleWinner() {
+        // given
+        List<Car> cars = List.of(
+            new Car("car1", 5),
+            new Car("car2", 3),
+            new Car("car3", 4)
+        );
+        Race race = new Race(cars, 1);
+
+        // when
+        List<CarStatus> winners = race.getWinners();
+
+        // then
+        assertThat(winners).hasSize(1);
+        assertThat(winners.get(0).getName()).isEqualTo("car1");
+    }
+
+    @Test
+    @DisplayName("공동 우승자가 있는 경우 모든 우승자를 반환한다")
+    void getMultipleWinners() {
+        // given
+        List<Car> cars = List.of(
+            new Car("car1", 5),
+            new Car("car2", 5),
+            new Car("car3", 3)
+        );
+        Race race = new Race(cars, 1);
+
+        // when
+        List<CarStatus> winners = race.getWinners();
+
+        // then
+        assertThat(winners).hasSize(2);
+        assertThat(winners).extracting("name").containsExactlyInAnyOrder("car1", "car2");
+    }
 }

From 778c6c37413593a83bc9bb0893015386107dc378 Mon Sep 17 00:00:00 2001
From: kjy2844 <kjy2844@kaist.ac.kr>
Date: Thu, 20 Mar 2025 17:44:46 +0900
Subject: [PATCH 6/9] =?UTF-8?q?refactor=20:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?=
 =?UTF-8?q?=EC=9A=A9=20=EC=83=9D=EC=84=B1=EC=9E=90=20=EC=A0=9C=EA=B1=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 README.md                             | 23 +++++++--------
 src/main/java/.gitkeep                |  0
 src/main/java/Car.java                | 16 ++---------
 src/main/java/MoveStrategy.java       |  4 +++
 src/main/java/Race.java               | 16 +++++------
 src/main/java/RandomMoveStrategy.java | 11 +++++++
 src/test/java/CarTest.java            | 17 +++--------
 src/test/java/RaceTest.java           | 41 +++++++++++++++++++--------
 8 files changed, 67 insertions(+), 61 deletions(-)
 delete mode 100644 src/main/java/.gitkeep
 create mode 100644 src/main/java/MoveStrategy.java
 create mode 100644 src/main/java/RandomMoveStrategy.java

diff --git a/README.md b/README.md
index 0e14e04aa0c..b3a3f436430 100644
--- a/README.md
+++ b/README.md
@@ -95,19 +95,16 @@ ResultView : 결과를 출력
    - [x] `Game` 클래스 수정
      - [x] 경주 종료 후 우승자 출력 로직 추가
 
-5. **테스트 추가**
-
-   - [ ] `RaceTest`에 우승자 판정 테스트 추가
-     - [ ] 단일 우승자 케이스
-     - [ ] 다중 우승자 케이스
-   - [ ] `InputViewTest` 추가
-     - [ ] 자동차 이름 입력 테스트
-     - [ ] 잘못된 입력 처리 테스트
-
-6. **리팩토링 고려사항**
-   - [ ] `Car` 클래스에 `Position` 값 객체 도입 검토
-   - [ ] `CarName` 값 객체 도입 검토
-   - [ ] `CarStatus` DTO 도입 검토 (이름과 위치를 함께 전달하기 위해)
+### 개발 구조
+
+- **Game**: 게임의 전체 생명주기 관리 및 사용자 인터랙션 조정
+- **Race**: 경주 진행 상태 관리, 자동차 이동 처리, 우승자 판정
+- **GameSettings**: 게임 설정값(자동차 이름, 라운드 수) 검증 및 관리
+- **Car**: 자동차의 기본 속성(이름, 위치) 관리
+- **InputView**: 사용자 입력 처리 및 검증
+- **ResultView**: 게임 진행 상태 및 결과 출력
+- **CarStatus**: 자동차의 현재 상태를 불변 객체로 표현
+- **MoveStrategy**: 자동차 이동 전략 정의 (RandomMoveStrategy, FixedMoveStrategy)
 
 ### 프로그래밍 요구사항
 
diff --git a/src/main/java/.gitkeep b/src/main/java/.gitkeep
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/src/main/java/Car.java b/src/main/java/Car.java
index 1778e8f88fa..b0159bb98a8 100644
--- a/src/main/java/Car.java
+++ b/src/main/java/Car.java
@@ -1,6 +1,5 @@
 public class Car {
 
-    private static final int MOVEMENT_THRESHOLD = 4;
     private final String name;
     private int position = 0;
 
@@ -9,13 +8,6 @@ public Car(String name) {
         this.name = name.trim();
     }
 
-    // 테스트용 생성자
-    Car(String name, int position) {
-        validateName(name);
-        this.name = name.trim();
-        this.position = position;
-    }
-
     private void validateName(String name) {
         if (name == null || name.trim().isBlank()) {
             throw new IllegalArgumentException("Name cannot be blank");
@@ -25,12 +17,8 @@ private void validateName(String name) {
         }
     }
 
-    public void move(int seed) {
-        if (seed < 0 || seed > 9) {
-            throw new IllegalArgumentException("Invalid seed: " + seed);
-        }
-
-        if (seed >= MOVEMENT_THRESHOLD) {
+    public void move(boolean shouldMove) {
+        if (shouldMove) {
             position++;
         }
     }
diff --git a/src/main/java/MoveStrategy.java b/src/main/java/MoveStrategy.java
new file mode 100644
index 00000000000..944284c6f5c
--- /dev/null
+++ b/src/main/java/MoveStrategy.java
@@ -0,0 +1,4 @@
+@FunctionalInterface
+public interface MoveStrategy {
+    boolean shouldMove();
+} 
\ No newline at end of file
diff --git a/src/main/java/Race.java b/src/main/java/Race.java
index aecfe9ba141..53e8fde9d81 100644
--- a/src/main/java/Race.java
+++ b/src/main/java/Race.java
@@ -4,24 +4,22 @@
 
 public class Race {
 
-    private static final Random random = new Random();
+    private final MoveStrategy moveStrategy;
     private final int totalRounds;
     private final List<Car> cars;
     private int currentRound = 0;
 
     public Race(GameSettings settings) {
+        this(settings, new RandomMoveStrategy());
+    }
+
+    public Race(GameSettings settings, MoveStrategy moveStrategy) {
         this.totalRounds = settings.getRoundCount();
         this.cars = new ArrayList<>();
         for (String carName : settings.getCarNames()) {
             this.cars.add(new Car(carName));
         }
-    }
-
-    // 테스트용 생성자
-    Race(List<Car> cars, int totalRounds) {
-        this.cars = new ArrayList<>(cars);
-        this.totalRounds = totalRounds;
-        this.currentRound = totalRounds;  // 경주가 끝난 상태로 설정
+        this.moveStrategy = moveStrategy;
     }
 
     public List<CarStatus> getCarStatuses() {
@@ -35,7 +33,7 @@ public List<CarStatus> getCarStatuses() {
     public void runRound() {
         validateRaceInProgress();
         for (Car car : cars) {
-            car.move(random.nextInt(10));
+            car.move(moveStrategy.shouldMove());
         }
         currentRound++;
     }
diff --git a/src/main/java/RandomMoveStrategy.java b/src/main/java/RandomMoveStrategy.java
new file mode 100644
index 00000000000..727eb75d362
--- /dev/null
+++ b/src/main/java/RandomMoveStrategy.java
@@ -0,0 +1,11 @@
+import java.util.Random;
+
+public class RandomMoveStrategy implements MoveStrategy {
+    private static final int MOVE_THRESHOLD = 4;
+    private final Random random = new Random();
+
+    @Override
+    public boolean shouldMove() {
+        return random.nextInt(10) >= MOVE_THRESHOLD;
+    }
+} 
\ No newline at end of file
diff --git a/src/test/java/CarTest.java b/src/test/java/CarTest.java
index 2c2f5df8a76..8f34f00954a 100644
--- a/src/test/java/CarTest.java
+++ b/src/test/java/CarTest.java
@@ -5,7 +5,6 @@
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.CsvSource;
-import org.junit.jupiter.params.provider.ValueSource;
 
 class CarTest {
 
@@ -35,19 +34,11 @@ void carNameCannotExceed5Characters() {
     }
 
     @ParameterizedTest
-    @DisplayName("random값이 4 이상일 경우에 자동차의 위치는 1 추가되고, 4 미만일 경우 위치가 변하지 않는다")
-    @CsvSource({"0, 0", "1, 0", "2, 0", "3, 0", "4, 1", "5, 1", "6, 1", "7, 1", "8, 1", "9, 1"})
-    void carMovesAccordingToRandomValue(int seed, int expectedPosition) {
+    @DisplayName("shouldMove가 true일 경우 자동차의 위치는 1 추가되고, false일 경우 위치가 변하지 않는다")
+    @CsvSource({"false, 0", "true, 1"})
+    void carMovesAccordingToShouldMove(boolean shouldMove, int expectedPosition) {
         Car car = new Car("MyCar");
-        car.move(seed);
+        car.move(shouldMove);
         assertThat(car.getPosition()).isEqualTo(expectedPosition);
     }
-
-    @ParameterizedTest
-    @DisplayName("이동을 위한 숫자는 0에서 9 사이여야 한다")
-    @ValueSource(ints = {-1, 10})
-    void carMoveVariableIsBetween0And9(int invalidSeed) {
-        Car car = new Car("MyCar");
-        assertThatThrownBy(() -> car.move(invalidSeed)).isInstanceOf(IllegalArgumentException.class).hasMessage("Invalid seed: " + invalidSeed);
-    }
 }
diff --git a/src/test/java/RaceTest.java b/src/test/java/RaceTest.java
index 743975e4b19..1c841910cb2 100644
--- a/src/test/java/RaceTest.java
+++ b/src/test/java/RaceTest.java
@@ -59,14 +59,14 @@ void getWinnersBeforeRaceFinishThrowsError() {
     @DisplayName("단독 우승자가 있는 경우 해당 자동차만 반환한다")
     void getSingleWinner() {
         // given
-        List<Car> cars = List.of(
-            new Car("car1", 5),
-            new Car("car2", 3),
-            new Car("car3", 4)
-        );
-        Race race = new Race(cars, 1);
+        String[] carNames = {"car1", "car2", "car3"};
+        GameSettings settings = new GameSettings(carNames, 3);
+        Race race = new Race(settings, new FixedMoveStrategy(new boolean[]{true, false, false}));
 
         // when
+        race.runRound();
+        race.runRound();
+        race.runRound();
         List<CarStatus> winners = race.getWinners();
 
         // then
@@ -78,18 +78,35 @@ void getSingleWinner() {
     @DisplayName("공동 우승자가 있는 경우 모든 우승자를 반환한다")
     void getMultipleWinners() {
         // given
-        List<Car> cars = List.of(
-            new Car("car1", 5),
-            new Car("car2", 5),
-            new Car("car3", 3)
-        );
-        Race race = new Race(cars, 1);
+        String[] carNames = {"car1", "car2", "car3"};
+        GameSettings settings = new GameSettings(carNames, 3);
+        Race race = new Race(settings, new FixedMoveStrategy(new boolean[]{true, true, false}));
 
         // when
+        race.runRound();
+        race.runRound();
+        race.runRound();
         List<CarStatus> winners = race.getWinners();
 
         // then
         assertThat(winners).hasSize(2);
         assertThat(winners).extracting("name").containsExactlyInAnyOrder("car1", "car2");
     }
+
+    private static class FixedMoveStrategy implements MoveStrategy {
+        private final boolean[] moves;
+        private int index = 0;
+
+        FixedMoveStrategy(boolean[] moves) {
+            this.moves = moves;
+        }
+
+        @Override
+        public boolean shouldMove() {
+            if (index >= moves.length) {
+                index = 0;
+            }
+            return moves[index++];
+        }
+    }
 }

From 63dff0461e0347812b2e9883681d86f1f712f9e8 Mon Sep 17 00:00:00 2001
From: kjy2844 <kjy2844@kaist.ac.kr>
Date: Thu, 20 Mar 2025 17:49:21 +0900
Subject: [PATCH 7/9] =?UTF-8?q?refactor=20:=20=ED=8F=AC=EB=A7=B7=ED=8C=85?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/main/java/CarStatus.java          |  1 +
 src/main/java/Game.java               | 11 ++++++-----
 src/main/java/InputView.java          |  4 +++-
 src/main/java/MoveStrategy.java       |  1 +
 src/main/java/Race.java               |  1 -
 src/main/java/RandomMoveStrategy.java |  4 +++-
 src/test/java/RaceTest.java           |  5 +++--
 7 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/src/main/java/CarStatus.java b/src/main/java/CarStatus.java
index 1ba73da4c8f..41f0555525f 100644
--- a/src/main/java/CarStatus.java
+++ b/src/main/java/CarStatus.java
@@ -1,4 +1,5 @@
 public class CarStatus {
+
     private final String name;
     private final int position;
 
diff --git a/src/main/java/Game.java b/src/main/java/Game.java
index c66c6d04fab..6338bf72b85 100644
--- a/src/main/java/Game.java
+++ b/src/main/java/Game.java
@@ -1,4 +1,5 @@
 public class Game {
+
     private final InputView inputView;
     private final ResultView resultView;
 
@@ -7,6 +8,11 @@ public Game(InputView inputView, ResultView resultView) {
         this.resultView = resultView;
     }
 
+    public static void main(String[] args) {
+        Game game = new Game(new InputView(), new ResultView());
+        game.start();
+    }
+
     public void start() {
         GameSettings settings = inputView.getGameSettings();
         resultView.presentStartMessage();
@@ -19,9 +25,4 @@ public void start() {
         resultView.presentCars(race.getCarStatuses());
         resultView.presentWinners(race.getWinners());
     }
-
-    public static void main(String[] args) {
-        Game game = new Game(new InputView(), new ResultView());
-        game.start();
-    }
 }
diff --git a/src/main/java/InputView.java b/src/main/java/InputView.java
index fb593125348..fddb499cc3d 100644
--- a/src/main/java/InputView.java
+++ b/src/main/java/InputView.java
@@ -1,6 +1,8 @@
 import java.util.Scanner;
 
 public class InputView {
+
+    public static final String CAR_NAME_DELIMITER = ",";
     private final Scanner scanner;
 
     public InputView() {
@@ -9,7 +11,7 @@ public InputView() {
 
     public GameSettings getGameSettings() {
         String inputCarNames = prompt("경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분).");
-        String[] carNames = inputCarNames.split(",");
+        String[] carNames = inputCarNames.split(CAR_NAME_DELIMITER);
         int roundCount = promptInt("시도할 회수는 몇 회 인가요?");
         return new GameSettings(carNames, roundCount);
     }
diff --git a/src/main/java/MoveStrategy.java b/src/main/java/MoveStrategy.java
index 944284c6f5c..ad9e1fd17d9 100644
--- a/src/main/java/MoveStrategy.java
+++ b/src/main/java/MoveStrategy.java
@@ -1,4 +1,5 @@
 @FunctionalInterface
 public interface MoveStrategy {
+
     boolean shouldMove();
 } 
\ No newline at end of file
diff --git a/src/main/java/Race.java b/src/main/java/Race.java
index 53e8fde9d81..420ba8524ae 100644
--- a/src/main/java/Race.java
+++ b/src/main/java/Race.java
@@ -1,6 +1,5 @@
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Random;
 
 public class Race {
 
diff --git a/src/main/java/RandomMoveStrategy.java b/src/main/java/RandomMoveStrategy.java
index 727eb75d362..f639389ca85 100644
--- a/src/main/java/RandomMoveStrategy.java
+++ b/src/main/java/RandomMoveStrategy.java
@@ -1,11 +1,13 @@
 import java.util.Random;
 
 public class RandomMoveStrategy implements MoveStrategy {
+
+    public static final int RANDOM_NUMBER_RANGE = 10;
     private static final int MOVE_THRESHOLD = 4;
     private final Random random = new Random();
 
     @Override
     public boolean shouldMove() {
-        return random.nextInt(10) >= MOVE_THRESHOLD;
+        return random.nextInt(RANDOM_NUMBER_RANGE) >= MOVE_THRESHOLD;
     }
 } 
\ No newline at end of file
diff --git a/src/test/java/RaceTest.java b/src/test/java/RaceTest.java
index 1c841910cb2..b8f4c928366 100644
--- a/src/test/java/RaceTest.java
+++ b/src/test/java/RaceTest.java
@@ -51,8 +51,8 @@ void getWinnersBeforeRaceFinishThrowsError() {
         race.runRound();  // 1라운드만 진행
 
         assertThatThrownBy(race::getWinners)
-                .isInstanceOf(IllegalStateException.class)
-                .hasMessage("Race is still in progress");
+            .isInstanceOf(IllegalStateException.class)
+            .hasMessage("Race is still in progress");
     }
 
     @Test
@@ -94,6 +94,7 @@ void getMultipleWinners() {
     }
 
     private static class FixedMoveStrategy implements MoveStrategy {
+
         private final boolean[] moves;
         private int index = 0;
 

From 9e090bdd87f2126bd6911f7bbbabde249ed18093 Mon Sep 17 00:00:00 2001
From: kjy2844 <kjy2844@kaist.ac.kr>
Date: Mon, 24 Mar 2025 19:05:01 +0900
Subject: [PATCH 8/9] =?UTF-8?q?refactor=20:=20PR=20=EB=A6=AC=EB=B7=B0=20?=
 =?UTF-8?q?=EB=B0=98=EC=98=81=20-=20List<Car>=20->=20Cars?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/main/java/Car.java                |  6 ++-
 src/main/java/CarStatus.java          | 21 ++++++++++
 src/main/java/Cars.java               | 58 ++++++++++++++++++++++++++
 src/main/java/Game.java               | 29 +++++--------
 src/main/java/GameSettings.java       |  2 +-
 src/main/java/InputView.java          | 15 ++++---
 src/main/java/Race.java               | 47 +++------------------
 src/main/java/RandomMoveStrategy.java |  2 +-
 src/main/java/ResultView.java         |  9 ++--
 src/test/java/CarsTest.java           | 59 +++++++++++++++++++++++++++
 src/test/java/RaceTest.java           | 56 -------------------------
 11 files changed, 173 insertions(+), 131 deletions(-)
 create mode 100644 src/main/java/Cars.java
 create mode 100644 src/test/java/CarsTest.java

diff --git a/src/main/java/Car.java b/src/main/java/Car.java
index b0159bb98a8..d989069567d 100644
--- a/src/main/java/Car.java
+++ b/src/main/java/Car.java
@@ -9,7 +9,7 @@ public Car(String name) {
     }
 
     private void validateName(String name) {
-        if (name == null || name.trim().isBlank()) {
+        if (name == null || name.isBlank()) {
             throw new IllegalArgumentException("Name cannot be blank");
         }
         if (name.length() > 5) {
@@ -30,4 +30,8 @@ public String getName() {
     public int getPosition() {
         return position;
     }
+
+    public boolean isWinner(int maxPosition) {
+        return position == maxPosition;
+    }
 }
diff --git a/src/main/java/CarStatus.java b/src/main/java/CarStatus.java
index 41f0555525f..d511541e561 100644
--- a/src/main/java/CarStatus.java
+++ b/src/main/java/CarStatus.java
@@ -1,3 +1,5 @@
+import java.util.Objects;
+
 public class CarStatus {
 
     private final String name;
@@ -8,6 +10,12 @@ public CarStatus(Car car) {
         this.position = car.getPosition();
     }
 
+    // 테스트용 생성자
+    public CarStatus(String name, int position) {
+        this.name = name;
+        this.position = position;
+    }
+
     public String getName() {
         return name;
     }
@@ -15,4 +23,17 @@ public String getName() {
     public int getPosition() {
         return position;
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        CarStatus carStatus = (CarStatus) o;
+        return position == carStatus.position && Objects.equals(name, carStatus.name);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(name, position);
+    }
 } 
\ No newline at end of file
diff --git a/src/main/java/Cars.java b/src/main/java/Cars.java
new file mode 100644
index 00000000000..4be56846bbd
--- /dev/null
+++ b/src/main/java/Cars.java
@@ -0,0 +1,58 @@
+import java.util.ArrayList;
+import java.util.List;
+
+public class Cars {
+    private final List<Car> cars;
+
+    private Cars(List<Car> cars) {
+        validateCars(cars);
+        this.cars = new ArrayList<>(cars);
+    }
+
+    public static Cars fromNames(String[] carNames) {
+        List<Car> carList = new ArrayList<>();
+        for (String carName : carNames) {
+            carList.add(new Car(carName));
+        }
+        return new Cars(carList);
+    }
+
+    private void validateCars(List<Car> cars) {
+        if (cars == null || cars.isEmpty()) {
+            throw new IllegalArgumentException("자동차 목록이 비어있습니다.");
+        }
+    }
+
+    public List<CarStatus> getCarStatuses() {
+        List<CarStatus> statuses = new ArrayList<>();
+        for (Car car : cars) {
+            statuses.add(new CarStatus(car));
+        }
+        return statuses;
+    }
+
+    public void moveAll(MoveStrategy moveStrategy) {
+        for (Car car : cars) {
+            car.move(moveStrategy.shouldMove());
+        }
+    }
+
+    public int findMaxPosition() {
+        int maxPosition = 0;
+        for (Car car : cars) {
+            maxPosition = Math.max(maxPosition, car.getPosition());
+        }
+        return maxPosition;
+    }
+
+    public List<CarStatus> findWinners() {
+        int maxPosition = findMaxPosition();
+        List<CarStatus> winners = new ArrayList<>();
+        for (Car car : cars) {
+            if (car.isWinner(maxPosition)) {
+                winners.add(new CarStatus(car));
+            }
+        }
+        return winners;
+    }
+} 
\ No newline at end of file
diff --git a/src/main/java/Game.java b/src/main/java/Game.java
index 6338bf72b85..feaf8e05520 100644
--- a/src/main/java/Game.java
+++ b/src/main/java/Game.java
@@ -1,28 +1,19 @@
 public class Game {
-
-    private final InputView inputView;
-    private final ResultView resultView;
-
-    public Game(InputView inputView, ResultView resultView) {
-        this.inputView = inputView;
-        this.resultView = resultView;
-    }
-
-    public static void main(String[] args) {
-        Game game = new Game(new InputView(), new ResultView());
-        game.start();
-    }
-
     public void start() {
-        GameSettings settings = inputView.getGameSettings();
-        resultView.presentStartMessage();
+        GameSettings settings = InputView.getGameSettings();
+        ResultView.presentStartMessage();
 
         Race race = new Race(settings);
         while (race.isRaceInProgress()) {
-            resultView.presentCars(race.getCarStatuses());
+            ResultView.presentCars(race.getCarStatuses());
             race.runRound();
         }
-        resultView.presentCars(race.getCarStatuses());
-        resultView.presentWinners(race.getWinners());
+        ResultView.presentCars(race.getCarStatuses());
+        ResultView.presentWinners(race.getWinners());
+    }
+
+    public static void main(String[] args) {
+        Game game = new Game();
+        game.start();
     }
 }
diff --git a/src/main/java/GameSettings.java b/src/main/java/GameSettings.java
index 13fc0509e14..49cfa1e38f7 100644
--- a/src/main/java/GameSettings.java
+++ b/src/main/java/GameSettings.java
@@ -16,7 +16,7 @@ private void validateCarNames(String[] carNames) {
             throw new IllegalArgumentException("자동차 이름 목록이 비어있습니다.");
         }
         for (String name : carNames) {
-            if (name == null || name.trim().isEmpty()) {
+            if (name == null || name.isBlank()) {
                 throw new IllegalArgumentException("자동차 이름은 비어있을 수 없습니다.");
             }
         }
diff --git a/src/main/java/InputView.java b/src/main/java/InputView.java
index fddb499cc3d..0cf46245d57 100644
--- a/src/main/java/InputView.java
+++ b/src/main/java/InputView.java
@@ -1,27 +1,26 @@
 import java.util.Scanner;
 
 public class InputView {
+    private static final String CAR_NAME_DELIMITER = ",";
+    private static final Scanner scanner = new Scanner(System.in);
 
-    public static final String CAR_NAME_DELIMITER = ",";
-    private final Scanner scanner;
-
-    public InputView() {
-        this.scanner = new Scanner(System.in);
+    private InputView() {
+        // private 생성자로 인스턴스화 방지
     }
 
-    public GameSettings getGameSettings() {
+    public static GameSettings getGameSettings() {
         String inputCarNames = prompt("경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분).");
         String[] carNames = inputCarNames.split(CAR_NAME_DELIMITER);
         int roundCount = promptInt("시도할 회수는 몇 회 인가요?");
         return new GameSettings(carNames, roundCount);
     }
 
-    private String prompt(String message) {
+    private static String prompt(String message) {
         System.out.println(message);
         return scanner.nextLine();
     }
 
-    private int promptInt(String message) {
+    private static int promptInt(String message) {
         System.out.println(message);
         while (!scanner.hasNextInt()) {
             System.out.println("That's not a valid number!");
diff --git a/src/main/java/Race.java b/src/main/java/Race.java
index 420ba8524ae..27eb70b6fb4 100644
--- a/src/main/java/Race.java
+++ b/src/main/java/Race.java
@@ -1,11 +1,10 @@
-import java.util.ArrayList;
 import java.util.List;
 
 public class Race {
 
     private final MoveStrategy moveStrategy;
     private final int totalRounds;
-    private final List<Car> cars;
+    private final Cars cars;
     private int currentRound = 0;
 
     public Race(GameSettings settings) {
@@ -14,26 +13,17 @@ public Race(GameSettings settings) {
 
     public Race(GameSettings settings, MoveStrategy moveStrategy) {
         this.totalRounds = settings.getRoundCount();
-        this.cars = new ArrayList<>();
-        for (String carName : settings.getCarNames()) {
-            this.cars.add(new Car(carName));
-        }
+        this.cars = Cars.fromNames(settings.getCarNames());
         this.moveStrategy = moveStrategy;
     }
 
     public List<CarStatus> getCarStatuses() {
-        List<CarStatus> statuses = new ArrayList<>();
-        for (Car car : cars) {
-            statuses.add(new CarStatus(car));
-        }
-        return statuses;
+        return cars.getCarStatuses();
     }
 
     public void runRound() {
         validateRaceInProgress();
-        for (Car car : cars) {
-            car.move(moveStrategy.shouldMove());
-        }
+        cars.moveAll(moveStrategy);
         currentRound++;
     }
 
@@ -53,35 +43,8 @@ private void validateRaceFinished() {
         }
     }
 
-    private int findMaxPosition() {
-        int maxPosition = 0;
-        for (Car car : cars) {
-            maxPosition = Math.max(maxPosition, car.getPosition());
-        }
-        return maxPosition;
-    }
-
-    private boolean isWinner(Car car, int maxPosition) {
-        return car.getPosition() == maxPosition;
-    }
-
-    private List<CarStatus> findWinnersWithPosition(int maxPosition) {
-        List<CarStatus> winners = new ArrayList<>();
-        for (Car car : cars) {
-            addWinnerIfQualified(winners, car, maxPosition);
-        }
-        return winners;
-    }
-
-    private void addWinnerIfQualified(List<CarStatus> winners, Car car, int maxPosition) {
-        if (isWinner(car, maxPosition)) {
-            winners.add(new CarStatus(car));
-        }
-    }
-
     public List<CarStatus> getWinners() {
         validateRaceFinished();
-        int maxPosition = findMaxPosition();
-        return findWinnersWithPosition(maxPosition);
+        return cars.findWinners();
     }
 }
diff --git a/src/main/java/RandomMoveStrategy.java b/src/main/java/RandomMoveStrategy.java
index f639389ca85..41d27af2199 100644
--- a/src/main/java/RandomMoveStrategy.java
+++ b/src/main/java/RandomMoveStrategy.java
@@ -2,7 +2,7 @@
 
 public class RandomMoveStrategy implements MoveStrategy {
 
-    public static final int RANDOM_NUMBER_RANGE = 10;
+    private static final int RANDOM_NUMBER_RANGE = 10;
     private static final int MOVE_THRESHOLD = 4;
     private final Random random = new Random();
 
diff --git a/src/main/java/ResultView.java b/src/main/java/ResultView.java
index 25874674706..a2cabe71814 100644
--- a/src/main/java/ResultView.java
+++ b/src/main/java/ResultView.java
@@ -2,12 +2,15 @@
 import java.util.StringJoiner;
 
 public class ResultView {
+    private ResultView() {
+        // private 생성자로 인스턴스화 방지
+    }
 
-    public void presentStartMessage() {
+    public static void presentStartMessage() {
         System.out.println("실행 결과");
     }
 
-    public void presentCars(List<CarStatus> cars) {
+    public static void presentCars(List<CarStatus> cars) {
         for (CarStatus car : cars) {
             String positionIndicator = "-".repeat(car.getPosition() + 1);
             String output = String.format("%s : %s", car.getName(), positionIndicator);
@@ -16,7 +19,7 @@ public void presentCars(List<CarStatus> cars) {
         System.out.println();
     }
 
-    public void presentWinners(List<CarStatus> winners) {
+    public static void presentWinners(List<CarStatus> winners) {
         StringJoiner joiner = new StringJoiner(", ");
         for (CarStatus winner : winners) {
             joiner.add(winner.getName());
diff --git a/src/test/java/CarsTest.java b/src/test/java/CarsTest.java
new file mode 100644
index 00000000000..43f089c0e1b
--- /dev/null
+++ b/src/test/java/CarsTest.java
@@ -0,0 +1,59 @@
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+public class CarsTest {
+
+    @Test
+    @DisplayName("단독 우승자가 있는 경우 해당 자동차만 반환한다")
+    void getSingleWinner() {
+        // given
+        Cars cars = createCars("car1", "car2", "car3");
+        cars.moveAll(new FixedMoveStrategy(new boolean[]{true, false, false}));
+
+        // then
+        assertThat(cars.findWinners()).hasSize(1);
+        assertThat(cars.findWinners()).contains(createCarStatus("car1", 1));
+    }
+
+    @Test
+    @DisplayName("공동 우승자가 있는 경우 모든 우승자를 반환한다")
+    void getMultipleWinners() {
+        // given
+        Cars cars = createCars("car1", "car2", "car3");
+        cars.moveAll(new FixedMoveStrategy(new boolean[]{true, true, false}));
+
+        // then
+        assertThat(cars.findWinners()).hasSize(2);
+        assertThat(cars.findWinners()).contains(
+            createCarStatus("car1", 1),
+            createCarStatus("car2", 1)
+        );
+    }
+
+    private static class FixedMoveStrategy implements MoveStrategy {
+        private final boolean[] moves;
+        private int index = 0;
+
+        FixedMoveStrategy(boolean[] moves) {
+            this.moves = moves;
+        }
+
+        @Override
+        public boolean shouldMove() {
+            if (index >= moves.length) {
+                index = 0;
+            }
+            return moves[index++];
+        }
+    }
+
+    private Cars createCars(String... names) {
+        return Cars.fromNames(names);
+    }
+    
+    private CarStatus createCarStatus(String name, int position) {
+        return new CarStatus(name, position);
+    }
+}
diff --git a/src/test/java/RaceTest.java b/src/test/java/RaceTest.java
index b8f4c928366..a500b41beb8 100644
--- a/src/test/java/RaceTest.java
+++ b/src/test/java/RaceTest.java
@@ -54,60 +54,4 @@ void getWinnersBeforeRaceFinishThrowsError() {
             .isInstanceOf(IllegalStateException.class)
             .hasMessage("Race is still in progress");
     }
-
-    @Test
-    @DisplayName("단독 우승자가 있는 경우 해당 자동차만 반환한다")
-    void getSingleWinner() {
-        // given
-        String[] carNames = {"car1", "car2", "car3"};
-        GameSettings settings = new GameSettings(carNames, 3);
-        Race race = new Race(settings, new FixedMoveStrategy(new boolean[]{true, false, false}));
-
-        // when
-        race.runRound();
-        race.runRound();
-        race.runRound();
-        List<CarStatus> winners = race.getWinners();
-
-        // then
-        assertThat(winners).hasSize(1);
-        assertThat(winners.get(0).getName()).isEqualTo("car1");
-    }
-
-    @Test
-    @DisplayName("공동 우승자가 있는 경우 모든 우승자를 반환한다")
-    void getMultipleWinners() {
-        // given
-        String[] carNames = {"car1", "car2", "car3"};
-        GameSettings settings = new GameSettings(carNames, 3);
-        Race race = new Race(settings, new FixedMoveStrategy(new boolean[]{true, true, false}));
-
-        // when
-        race.runRound();
-        race.runRound();
-        race.runRound();
-        List<CarStatus> winners = race.getWinners();
-
-        // then
-        assertThat(winners).hasSize(2);
-        assertThat(winners).extracting("name").containsExactlyInAnyOrder("car1", "car2");
-    }
-
-    private static class FixedMoveStrategy implements MoveStrategy {
-
-        private final boolean[] moves;
-        private int index = 0;
-
-        FixedMoveStrategy(boolean[] moves) {
-            this.moves = moves;
-        }
-
-        @Override
-        public boolean shouldMove() {
-            if (index >= moves.length) {
-                index = 0;
-            }
-            return moves[index++];
-        }
-    }
 }

From c85d2919dcde99754c1e8a07db0919584048b724 Mon Sep 17 00:00:00 2001
From: kjy2844 <kjy2844@kaist.ac.kr>
Date: Mon, 24 Mar 2025 19:07:04 +0900
Subject: [PATCH 9/9] =?UTF-8?q?refactor=20:=20=ED=8F=AC=EB=A7=B7=ED=8C=85?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/main/java/CarStatus.java          | 10 +++++++---
 src/main/java/Cars.java               |  3 ++-
 src/main/java/Game.java               | 11 ++++++-----
 src/main/java/GameSettings.java       |  2 +-
 src/main/java/InputView.java          |  1 +
 src/main/java/MoveStrategy.java       |  2 +-
 src/main/java/RandomMoveStrategy.java |  2 +-
 src/main/java/ResultView.java         |  3 ++-
 src/test/java/CarTest.java            |  3 ++-
 src/test/java/CarsTest.java           | 22 ++++++++++------------
 src/test/java/GameSettingsTest.java   |  8 +++++---
 src/test/java/RaceTest.java           |  4 +---
 12 files changed, 39 insertions(+), 32 deletions(-)

diff --git a/src/main/java/CarStatus.java b/src/main/java/CarStatus.java
index d511541e561..d0302ba48e4 100644
--- a/src/main/java/CarStatus.java
+++ b/src/main/java/CarStatus.java
@@ -26,8 +26,12 @@ public int getPosition() {
 
     @Override
     public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
         CarStatus carStatus = (CarStatus) o;
         return position == carStatus.position && Objects.equals(name, carStatus.name);
     }
@@ -36,4 +40,4 @@ public boolean equals(Object o) {
     public int hashCode() {
         return Objects.hash(name, position);
     }
-} 
\ No newline at end of file
+}
diff --git a/src/main/java/Cars.java b/src/main/java/Cars.java
index 4be56846bbd..6a67f9fd04b 100644
--- a/src/main/java/Cars.java
+++ b/src/main/java/Cars.java
@@ -2,6 +2,7 @@
 import java.util.List;
 
 public class Cars {
+
     private final List<Car> cars;
 
     private Cars(List<Car> cars) {
@@ -55,4 +56,4 @@ public List<CarStatus> findWinners() {
         }
         return winners;
     }
-} 
\ No newline at end of file
+}
diff --git a/src/main/java/Game.java b/src/main/java/Game.java
index feaf8e05520..a5b0c4793ef 100644
--- a/src/main/java/Game.java
+++ b/src/main/java/Game.java
@@ -1,4 +1,10 @@
 public class Game {
+
+    public static void main(String[] args) {
+        Game game = new Game();
+        game.start();
+    }
+
     public void start() {
         GameSettings settings = InputView.getGameSettings();
         ResultView.presentStartMessage();
@@ -11,9 +17,4 @@ public void start() {
         ResultView.presentCars(race.getCarStatuses());
         ResultView.presentWinners(race.getWinners());
     }
-
-    public static void main(String[] args) {
-        Game game = new Game();
-        game.start();
-    }
 }
diff --git a/src/main/java/GameSettings.java b/src/main/java/GameSettings.java
index 49cfa1e38f7..1a457f068e9 100644
--- a/src/main/java/GameSettings.java
+++ b/src/main/java/GameSettings.java
@@ -39,4 +39,4 @@ public int getCarCount() {
     public int getRoundCount() {
         return roundCount;
     }
-} 
\ No newline at end of file
+}
diff --git a/src/main/java/InputView.java b/src/main/java/InputView.java
index 0cf46245d57..81afbe954db 100644
--- a/src/main/java/InputView.java
+++ b/src/main/java/InputView.java
@@ -1,6 +1,7 @@
 import java.util.Scanner;
 
 public class InputView {
+
     private static final String CAR_NAME_DELIMITER = ",";
     private static final Scanner scanner = new Scanner(System.in);
 
diff --git a/src/main/java/MoveStrategy.java b/src/main/java/MoveStrategy.java
index ad9e1fd17d9..82efa93af78 100644
--- a/src/main/java/MoveStrategy.java
+++ b/src/main/java/MoveStrategy.java
@@ -2,4 +2,4 @@
 public interface MoveStrategy {
 
     boolean shouldMove();
-} 
\ No newline at end of file
+}
diff --git a/src/main/java/RandomMoveStrategy.java b/src/main/java/RandomMoveStrategy.java
index 41d27af2199..87368c73a60 100644
--- a/src/main/java/RandomMoveStrategy.java
+++ b/src/main/java/RandomMoveStrategy.java
@@ -10,4 +10,4 @@ public class RandomMoveStrategy implements MoveStrategy {
     public boolean shouldMove() {
         return random.nextInt(RANDOM_NUMBER_RANGE) >= MOVE_THRESHOLD;
     }
-} 
\ No newline at end of file
+}
diff --git a/src/main/java/ResultView.java b/src/main/java/ResultView.java
index a2cabe71814..82f0332b796 100644
--- a/src/main/java/ResultView.java
+++ b/src/main/java/ResultView.java
@@ -2,6 +2,7 @@
 import java.util.StringJoiner;
 
 public class ResultView {
+
     private ResultView() {
         // private 생성자로 인스턴스화 방지
     }
@@ -24,6 +25,6 @@ public static void presentWinners(List<CarStatus> winners) {
         for (CarStatus winner : winners) {
             joiner.add(winner.getName());
         }
-        System.out.println(joiner.toString() + "가 최종 우승했습니다.");
+        System.out.println(joiner + "가 최종 우승했습니다.");
     }
 }
diff --git a/src/test/java/CarTest.java b/src/test/java/CarTest.java
index 8f34f00954a..91a5417a416 100644
--- a/src/test/java/CarTest.java
+++ b/src/test/java/CarTest.java
@@ -30,7 +30,8 @@ void carNameCannotBeBlank() {
     @Test
     @DisplayName("자동차 이름은 5자를 초과할 수 없다")
     void carNameCannotExceed5Characters() {
-        assertThatThrownBy(() -> new Car("123456")).isInstanceOf(IllegalArgumentException.class).hasMessage("Name cannot be longer than 5 characters");
+        assertThatThrownBy(() -> new Car("123456")).isInstanceOf(IllegalArgumentException.class)
+            .hasMessage("Name cannot be longer than 5 characters");
     }
 
     @ParameterizedTest
diff --git a/src/test/java/CarsTest.java b/src/test/java/CarsTest.java
index 43f089c0e1b..772b0b3c87d 100644
--- a/src/test/java/CarsTest.java
+++ b/src/test/java/CarsTest.java
@@ -26,13 +26,19 @@ void getMultipleWinners() {
 
         // then
         assertThat(cars.findWinners()).hasSize(2);
-        assertThat(cars.findWinners()).contains(
-            createCarStatus("car1", 1),
-            createCarStatus("car2", 1)
-        );
+        assertThat(cars.findWinners()).contains(createCarStatus("car1", 1), createCarStatus("car2", 1));
+    }
+
+    private Cars createCars(String... names) {
+        return Cars.fromNames(names);
+    }
+
+    private CarStatus createCarStatus(String name, int position) {
+        return new CarStatus(name, position);
     }
 
     private static class FixedMoveStrategy implements MoveStrategy {
+
         private final boolean[] moves;
         private int index = 0;
 
@@ -48,12 +54,4 @@ public boolean shouldMove() {
             return moves[index++];
         }
     }
-
-    private Cars createCars(String... names) {
-        return Cars.fromNames(names);
-    }
-    
-    private CarStatus createCarStatus(String name, int position) {
-        return new CarStatus(name, position);
-    }
 }
diff --git a/src/test/java/GameSettingsTest.java b/src/test/java/GameSettingsTest.java
index d2ed7672682..535482d9fc2 100644
--- a/src/test/java/GameSettingsTest.java
+++ b/src/test/java/GameSettingsTest.java
@@ -18,10 +18,12 @@ void emptyCarNamesListThrowsError() {
     @DisplayName("자동차 이름이 비어있으면 에러가 발생한다")
     void emptyCarNameThrowsError() {
         String[] carNamesWithBlank = {"car1", "", "car3"};
-        assertThatThrownBy(() -> new GameSettings(carNamesWithBlank, 3)).isInstanceOf(IllegalArgumentException.class).hasMessage("자동차 이름은 비어있을 수 없습니다.");
+        assertThatThrownBy(() -> new GameSettings(carNamesWithBlank, 3)).isInstanceOf(IllegalArgumentException.class)
+            .hasMessage("자동차 이름은 비어있을 수 없습니다.");
 
         String[] carNamesWithNull = {"car1", null, "car3"};
-        assertThatThrownBy(() -> new GameSettings(carNamesWithNull, 3)).isInstanceOf(IllegalArgumentException.class).hasMessage("자동차 이름은 비어있을 수 없습니다.");
+        assertThatThrownBy(() -> new GameSettings(carNamesWithNull, 3)).isInstanceOf(IllegalArgumentException.class)
+            .hasMessage("자동차 이름은 비어있을 수 없습니다.");
     }
 
     @Test
@@ -43,4 +45,4 @@ void validInputCreatesGameSettings() {
         assertThat(settings.getCarCount()).isEqualTo(3);
         assertThat(settings.getRoundCount()).isEqualTo(3);
     }
-} 
\ No newline at end of file
+}
diff --git a/src/test/java/RaceTest.java b/src/test/java/RaceTest.java
index a500b41beb8..e2ca442fd6c 100644
--- a/src/test/java/RaceTest.java
+++ b/src/test/java/RaceTest.java
@@ -50,8 +50,6 @@ void getWinnersBeforeRaceFinishThrowsError() {
         Race race = new Race(new GameSettings(carNames, 3));
         race.runRound();  // 1라운드만 진행
 
-        assertThatThrownBy(race::getWinners)
-            .isInstanceOf(IllegalStateException.class)
-            .hasMessage("Race is still in progress");
+        assertThatThrownBy(race::getWinners).isInstanceOf(IllegalStateException.class).hasMessage("Race is still in progress");
     }
 }