diff --git a/README.md b/README.md
index 4f55778fe..0ee9cb2fd 100644
--- a/README.md
+++ b/README.md
@@ -1,144 +1,53 @@
# 미션 - 숫자 야구
-## 🔍 진행 방식
-
-- 미션은 **기능 요구 사항, 프로그래밍 요구 사항, 과제 진행 요구 사항** 세 가지로 구성되어 있다.
-- 세 개의 요구 사항을 만족하기 위해 노력한다. 특히 기능을 구현하기 전에 기능 목록을 만들고, 기능 단위로 커밋 하는 방식으로 진행한다.
-- 기능 요구 사항에 기재되지 않은 내용은 스스로 판단하여 구현한다.
-
-## 📮 미션 제출 방법
-
-- 미션 구현을 완료한 후 GitHub을 통해 제출해야 한다.
- - GitHub을 활용한 제출 방법은 [프리코스 과제 제출](https://github.com/woowacourse/woowacourse-docs/tree/master/precourse) 문서를 참고해
- 제출한다.
-- GitHub에 미션을 제출한 후 [우아한테크코스 지원](https://apply.techcourse.co.kr) 사이트에 접속하여 프리코스 과제를 제출한다.
- - 자세한 방법은 [제출 가이드](https://github.com/woowacourse/woowacourse-docs/tree/master/precourse#제출-가이드) 참고
- - **Pull Request만 보내고 지원 플랫폼에서 과제를 제출하지 않으면 최종 제출하지 않은 것으로 처리되니 주의한다.**
-
-## 🚨 과제 제출 전 체크 리스트 - 0점 방지
-
-- 기능 구현을 모두 정상적으로 했더라도 **요구 사항에 명시된 출력값 형식을 지키지 않을 경우 0점으로 처리**한다.
-- 기능 구현을 완료한 뒤 아래 가이드에 따라 테스트를 실행했을 때 모든 테스트가 성공하는지 확인한다.
-- **테스트가 실패할 경우 0점으로 처리**되므로, 반드시 확인 후 제출한다.
-
-### 테스트 실행 가이드
-
-- 터미널에서 Mac 또는 Linux 사용자의 경우 `./gradlew clean test` 명령을 실행하고,
- Windows 사용자의 경우 `gradlew.bat clean test` 또는 `./gradlew.bat clean test` 명령을 실행할 때 모든 테스트가 아래와 같이 통과하는지 확인한다.
-
-```
-BUILD SUCCESSFUL in 0s
-```
-
----
-
-## 🚀 기능 요구 사항
-
-기본적으로 1부터 9까지 서로 다른 수로 이루어진 3자리의 수를 맞추는 게임이다.
-
-- 같은 수가 같은 자리에 있으면 스트라이크, 다른 자리에 있으면 볼, 같은 수가 전혀 없으면 낫싱이란 힌트를 얻고, 그 힌트를 이용해서 먼저 상대방(컴퓨터)의 수를 맞추면 승리한다.
- - 예) 상대방(컴퓨터)의 수가 425일 때
- - 123을 제시한 경우 : 1스트라이크
- - 456을 제시한 경우 : 1볼 1스트라이크
- - 789를 제시한 경우 : 낫싱
-- 위 숫자 야구 게임에서 상대방의 역할을 컴퓨터가 한다. 컴퓨터는 1에서 9까지 서로 다른 임의의 수 3개를 선택한다. 게임 플레이어는 컴퓨터가 생각하고 있는 서로 다른 3개의 숫자를 입력하고, 컴퓨터는 입력한
- 숫자에 대한
- 결과를 출력한다.
-- 이 같은 과정을 반복해 컴퓨터가 선택한 3개의 숫자를 모두 맞히면 게임이 종료된다.
-- 게임을 종료한 후 게임을 다시 시작하거나 완전히 종료할 수 있다.
-- 사용자가 잘못된 값을 입력할 경우 `IllegalArgumentException`을 발생시킨 후 애플리케이션은 종료되어야 한다.
-
-### 입출력 요구 사항
-
-#### 입력
-
-- 서로 다른 3자리의 수
-- 게임이 끝난 경우 재시작/종료를 구분하는 1과 2 중 하나의 수
-
-#### 출력
-
-- 입력한 수에 대한 결과를 볼, 스트라이크 개수로 표시
-
-```
-1볼 1스트라이크
-```
-
-- 하나도 없는 경우
-
-```
-낫싱
-```
-
-- 3개의 숫자를 모두 맞힐 경우
-
-```
-3스트라이크
-3개의 숫자를 모두 맞히셨습니다! 게임 종료
-```
-
-- 게임 시작 문구 출력
-
-```
-숫자 야구 게임을 시작합니다.
-```
-
-#### 실행 결과 예시
-
-```
-숫자 야구 게임을 시작합니다.
-숫자를 입력해주세요 : 123
-1볼 1스트라이크
-숫자를 입력해주세요 : 145
-1볼
-숫자를 입력해주세요 : 671
-2볼
-숫자를 입력해주세요 : 216
-1스트라이크
-숫자를 입력해주세요 : 713
-3스트라이크
-3개의 숫자를 모두 맞히셨습니다! 게임 종료
-게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.
-1
-숫자를 입력해주세요 : 123
-1볼
-...
-```
-
----
-
-## 🎯 프로그래밍 요구 사항
-
-- Kotlin 1.9.0에서 실행 가능해야 한다. **Kotlin 1.9.0에서 정상적으로 동작하지 않을 경우 0점 처리한다.**
-- **Java 코드가 아닌 Kotlin 코드로만 구현해야 한다.**
-- 프로그램 실행의 시작점은 `Application`의 `main()`이다.
-- `build.gradle(.kts)`을 변경할 수 없고, 외부 라이브러리를 사용하지 않는다.
-- [Kotlin 코드 컨벤션](https://github.com/woowacourse/woowacourse-docs/tree/main/styleguide/kotlin) 가이드를 준수하며 프로그래밍한다.
-- 프로그램 종료 시 `System.exit()`를 호출하지 않는다.
-- 프로그램 구현이 완료되면 `ApplicationTest`의 모든 테스트가 성공해야 한다. **테스트가 실패할 경우 0점 처리한다.**
-- 프로그래밍 요구 사항에서 달리 명시하지 않는 한 파일, 패키지 이름을 수정하거나 이동하지 않는다.
-
-### 라이브러리
-
-- `camp.nextstep.edu.missionutils`에서 제공하는 `Randoms` 및 `Console` API를 사용하여 구현해야 한다.
- - Random 값 추출은 `camp.nextstep.edu.missionutils.Randoms`의 `pickNumberInRange()`를 활용한다.
- - 사용자가 입력하는 값은 `camp.nextstep.edu.missionutils.Console`의 `readLine()`을 활용한다.
-
-#### 사용 예시
-
-```kotlin
-val computer = mutableListOf()
-while (computer.size() < 3) {
- val randomNumber = Randoms.pickNumberInRange(1, 9)
- if (!computer.contains(randomNumber)) {
- computer.add(randomNumber)
- }
-}
-```
-
----
-
-## ✏️ 과제 진행 요구 사항
-
-- 미션은 [kotlin-baseball](https://github.com/woowacourse-precourse/kotlin-baseball-6) 저장소를 Fork & Clone해 시작한다.
-- **기능을 구현하기 전 `docs/README.md`에 구현할 기능 목록을 정리**해 추가한다.
-- 과제 진행 및 제출 방법은 [프리코스 과제 제출](https://github.com/woowacourse/woowacourse-docs/tree/master/precourse) 문서를 참고한다.
+## 📚 프로젝트 목표
+- 주어진 요구 사항을 만족시키는 코드를 작성한다.
+- 확장 및 유지 보수의 편의성을 고려하여 리팩토링이 가능한 코드를 작성한다.
+- 가독성을 고려한 코드를 작성한다.
+- 협업을 가정하여 커밋 및 코드 컨벤션을 지킨다.
+
+## ✨ 기능 목록
+- 컴퓨터의 3자리 수
+- 사용자의 입력
+- 옳지 않은 입력에 대한 예외 처리
+- 채점
+- 힌트
+- 정답시 게임 종료
+- 메세지 출력
+
+## 🎨 설계
+
+
+### 역할에 따라 클래스 분리
+- GameManager: 게임의 전체 화면 관리
+- InputManager: 사용자 Input 관리
+- Computer Class: 컴퓨터 객체
+- User Class: 사용자 객체
+- Referee Class: 판정 관리
+
+### 입력 관리
+- 컴퓨터 숫자
+ - mutableList 타입
+ - Randoms.pickNumberInRange() 사용
+ - getNumberList()로 반환
+- 사용자 숫자
+ - mutableList 타입
+ - Console.readLine() 사용
+ - validateUserNums() - 유효성 검사
+ - getNumberList()로 반환
+- 재실행 숫자
+ - Int
+ - validateFinishNums() - 유효성 검사
+ - getFinishNumber()로 반환
+
+### 예외 처리
+- IllegalArgumentException 발생
+- 사용자 숫자 입력
+ - 공백 검사
+ - 중복 검사
+ - 0 미포함
+ - 3자리
+ - Int 변환 가능
+- 재실행 숫자 입력
+ - 공백 검사
+ - 1 혹은 2 외의 값인지
diff --git a/src/main/kotlin/baseball/Application.kt b/src/main/kotlin/baseball/Application.kt
index 148d75cc3..68b742643 100644
--- a/src/main/kotlin/baseball/Application.kt
+++ b/src/main/kotlin/baseball/Application.kt
@@ -1,5 +1,6 @@
package baseball
fun main() {
- TODO("프로그램 구현")
-}
+ val gameManager = GameManager()
+ gameManager.execute()
+}
\ No newline at end of file
diff --git a/src/main/kotlin/baseball/Computer.kt b/src/main/kotlin/baseball/Computer.kt
new file mode 100644
index 000000000..cb641433f
--- /dev/null
+++ b/src/main/kotlin/baseball/Computer.kt
@@ -0,0 +1,17 @@
+package baseball
+
+import camp.nextstep.edu.missionutils.Randoms
+
+class Computer {
+ // 컴퓨터 숫자 랜덤 초기화(중복 제외) - GameManager class의 initComputer()에서 호출
+ fun getNumberList(): MutableList {
+ val mutableList = mutableListOf()
+ while (mutableList.size < 3) {
+ val element = Randoms.pickNumberInRange(1, 9)
+ if (!mutableList.contains(element)) {
+ mutableList.add(element)
+ }
+ }
+ return mutableList
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/baseball/GameManager.kt b/src/main/kotlin/baseball/GameManager.kt
new file mode 100644
index 000000000..16f3a3321
--- /dev/null
+++ b/src/main/kotlin/baseball/GameManager.kt
@@ -0,0 +1,78 @@
+package baseball
+
+class GameManager {
+ private val computerNumberList = mutableListOf()
+ private val userNumberList = mutableListOf()
+ private var state = INIT
+ private var result = INIT
+
+ // 프로그램 실행
+ fun execute() {
+ showExecuteMessage()
+ while (state) {
+ playGame()
+ finish()
+ }
+ }
+
+ private fun playGame() {
+ initComputer()
+ while (result) {
+ initUser()
+ getResult()
+ }
+ }
+
+ // 컴퓨터 숫자 초기화
+ private fun initComputer() {
+ val computer = Computer()
+ if (computerNumberList.isNotEmpty()) computerNumberList.clear()
+ computerNumberList.addAll(computer.getNumberList())
+ }
+
+ // 유저 숫자 입력
+ private fun initUser() {
+ val user = User()
+ if (userNumberList.isNotEmpty()) userNumberList.clear()
+ showInputMessage()
+ userNumberList.addAll(user.getNumberList())
+ }
+
+ // 채점 기능 - playGame() while문 탈출 기여
+ private fun getResult() {
+ val referee = Referee()
+ result = !(referee.getResult(computerNumberList, userNumberList))
+ }
+
+ // 재실행 분기문 - execute() while문 탈출 기여
+ private fun finish() {
+ val user = User()
+ showFinishMessage()
+ val finishNumber = user.getFinishNumber()
+ if (finishNumber == 1) restart()
+ else exit()
+ }
+
+ // 게임 재실행 - const 변수 초기화
+ private fun restart() {
+ result = INIT
+ state = RESTART
+ }
+
+ // 게임 종료 - false
+ private fun exit() {
+ state = EXIT
+ }
+
+ private fun showExecuteMessage() {
+ println("숫자 야구를 시작합니다.")
+ }
+
+ private fun showInputMessage() {
+ print("숫자를 입력해주세요 : ")
+ }
+
+ private fun showFinishMessage() {
+ println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.")
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/baseball/InputManager.kt b/src/main/kotlin/baseball/InputManager.kt
new file mode 100644
index 000000000..a3db5e5c1
--- /dev/null
+++ b/src/main/kotlin/baseball/InputManager.kt
@@ -0,0 +1,37 @@
+package baseball
+
+// 유효성 검사(사용자 숫자)
+fun isValidateInputStringForGame(input: String) {
+ // 빈 문자열 확인
+ if (input.isBlank()) throw IllegalArgumentException("input string is empty")
+ // 3자리 수 길이 확인
+ if (input.length != 3) throw IllegalArgumentException("input string's length is not suitable")
+ // 0 포함 확인
+ if (input.contains('0')) throw IllegalArgumentException("input string should not contains '0'")
+ // 숫자 변환 가능 여부
+ if (input.toIntOrNull() == null) throw IllegalArgumentException("input string is not parseable")
+ // 중복값 확인
+ if (isDuplicated(input)) throw IllegalArgumentException("number is duplicated in input string")
+}
+
+// 중복 검사(사용자 숫자)
+fun isDuplicated(input: String): Boolean {
+ input.forEachIndexed { index, num ->
+ var count = 0
+ for (j in index..input.lastIndex) {
+ if (num == input[j]) {
+ count++
+ }
+ }
+ if (count > 1) return true
+ }
+ return false
+}
+
+// 유효성 검사(재실행 숫자)
+fun isValidateInputStringForFinish(input: String) {
+ // 빈 문자열 확인
+ if (input.isBlank()) throw IllegalArgumentException("input string is empty")
+ // 1 또는 2 외의 값 확인
+ if (input != "1" && input != "2") throw IllegalArgumentException("input string is not available value")
+}
\ No newline at end of file
diff --git a/src/main/kotlin/baseball/Referee.kt b/src/main/kotlin/baseball/Referee.kt
new file mode 100644
index 000000000..68b9d1fea
--- /dev/null
+++ b/src/main/kotlin/baseball/Referee.kt
@@ -0,0 +1,42 @@
+package baseball
+
+// 채점 기능 클래스
+class Referee {
+ private var strike = 0
+ private var ball = 0
+
+ // 채점 기능
+ fun getResult(computerNums: MutableList, userNums: MutableList): Boolean {
+ strike = 0
+ ball = 0
+
+ computerNums.forEachIndexed { i, computerNum ->
+ userNums.forEachIndexed { j, userNum ->
+ if (computerNum == userNum) {
+ if (i == j) strike++
+ else ball++
+ }
+ }
+ }
+
+ return if (strike == 3) {
+ showCorrectMessage()
+ true
+ } else {
+ showHintMessage()
+ false
+ }
+ }
+
+ private fun showCorrectMessage() {
+ println("${strike}스트라이크")
+ println("3개의 숫자를 모두 맞히셨습니다! 게임 종료")
+ }
+
+ private fun showHintMessage() {
+ if (strike > 0 && ball > 0) println("${ball}볼 ${strike}스트라이크")
+ else if (strike == 0 && ball > 0) println("${ball}볼")
+ else if (strike > 0 && ball == 0) println("${strike}스트라이크")
+ else println("낫싱")
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/baseball/User.kt b/src/main/kotlin/baseball/User.kt
new file mode 100644
index 000000000..13264758a
--- /dev/null
+++ b/src/main/kotlin/baseball/User.kt
@@ -0,0 +1,21 @@
+package baseball
+
+import camp.nextstep.edu.missionutils.Console
+
+class User {
+ // 사용자 숫자 입력 - GameManager class의 initUser()에서 호출
+ fun getNumberList(): MutableList {
+ val mutableList = mutableListOf()
+ val input = Console.readLine()
+ isValidateInputStringForGame(input)
+ input.forEach { mutableList.add(it.digitToInt()) }
+ return mutableList
+ }
+
+ // 재실행 숫자 입력 - GameManager class의 finish()에서 호출
+ fun getFinishNumber(): Int {
+ val input = Console.readLine()
+ isValidateInputStringForFinish(input)
+ return input.toInt()
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/baseball/constants.kt b/src/main/kotlin/baseball/constants.kt
new file mode 100644
index 000000000..3098cd5a0
--- /dev/null
+++ b/src/main/kotlin/baseball/constants.kt
@@ -0,0 +1,6 @@
+package baseball
+
+// GameManager class 내 execute() while문과 playGame() while문의 상수 사용
+const val INIT = true
+const val RESTART = true
+const val EXIT = false
\ No newline at end of file