diff --git a/README.md b/README.md
index 32b16cd0..1fe627a9 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
 
 - `Application` : 로또 실행을 담당하는 진입점 클래스
 
-## model
+## domain
 
 - `Price` : 구매 가격 VO
 
@@ -13,21 +13,21 @@
 - `LottoNumber` : 로또 번호 VO
 - `Lotto` : 로또 객체
 - `Lottos` : 여러 개의 Lotto 객체를 관리하는 일급 컬렉션
-- `LottoResult` : 로또 결과 VO
+- `LottoResult` : 로또 당첨 결과 객체
+- `LottoCount` : 로또 구매 개수 VO
 
 #### constant
 
-- `LottoBoundary` : 로또 경계값 상수
-- `LottoMatch` : 로또 당첨 결과 상수
+- `WinningRank` : 당첨 순위 Enum
 
-## view
+## io
 
 - `InputView` : 입력을 담당하는 클래스
 - `OutputView` : 출력을 담당하는 클래스
 
-## controller
+## game
 
-- `LottoController` : 로또 전체 흐름을 제어하는 클래스
+- `LottoGame` : 로또 게임을 담당하는 클래스
 
 
 
@@ -44,23 +44,23 @@
 
 ```java
 구입금액을 입력해 주세요.
-14000
-
-14개를 구매했습니다.
-[8,21,23,41,42,43]
-[3,5,11,16,32,38]
-[7,11,16,35,36,44]
-[1,8,11,31,41,42]
-[13,14,16,38,42,45]
-[7,11,30,40,42,43]
-[2,13,22,32,38,45]
-[23,25,33,36,39,41]
-[1,3,5,14,22,45]
-[5,9,38,41,43,44]
-[2,8,9,18,19,21]
-[13,14,18,21,23,35]
-[17,21,29,37,42,45]
-[3,8,27,30,35,44]
+        14000
+
+        14개를 구매했습니다.
+        [8,21,23,41,42,43]
+        [3,5,11,16,32,38]
+        [7,11,16,35,36,44]
+        [1,8,11,31,41,42]
+        [13,14,16,38,42,45]
+        [7,11,30,40,42,43]
+        [2,13,22,32,38,45]
+        [23,25,33,36,39,41]
+        [1,3,5,14,22,45]
+        [5,9,38,41,43,44]
+        [2,8,9,18,19,21]
+        [13,14,18,21,23,35]
+        [17,21,29,37,42,45]
+        [3,8,27,30,35,44]
 ```
 
 ### 새로운 프로그래밍 요구사항
@@ -90,34 +90,34 @@
 
 ```java
 구입금액을 입력해 주세요.
-14000
-
-14개를 구매했습니다.
-[8,21,23,41,42,43]
-[3,5,11,16,32,38]
-[7,11,16,35,36,44]
-[1,8,11,31,41,42]
-[13,14,16,38,42,45]
-[7,11,30,40,42,43]
-[2,13,22,32,38,45]
-[23,25,33,36,39,41]
-[1,3,5,14,22,45]
-[5,9,38,41,43,44]
-[2,8,9,18,19,21]
-[13,14,18,21,23,35]
-[17,21,29,37,42,45]
-[3,8,27,30,35,44]
-
-지난 주 당첨 번호를 입력해 주세요.
-1,2,3,4,5,6
-
-당첨 통계
----------
-3개 일치(5000원)-1개
-4개 일치(50000원)-0개
-5개 일치(1500000원)-0개
-6개 일치(2000000000원)-0개
-총 수익률은0.35입니다.(기준이 1이기 때문에 결과적으로 손해라는 의미임)
+        14000
+
+        14개를 구매했습니다.
+        [8,21,23,41,42,43]
+        [3,5,11,16,32,38]
+        [7,11,16,35,36,44]
+        [1,8,11,31,41,42]
+        [13,14,16,38,42,45]
+        [7,11,30,40,42,43]
+        [2,13,22,32,38,45]
+        [23,25,33,36,39,41]
+        [1,3,5,14,22,45]
+        [5,9,38,41,43,44]
+        [2,8,9,18,19,21]
+        [13,14,18,21,23,35]
+        [17,21,29,37,42,45]
+        [3,8,27,30,35,44]
+
+        지난 주 당첨 번호를 입력해 주세요.
+        1,2,3,4,5,6
+
+        당첨 통계
+        ---------
+        3개 일치(5000원)-1개
+        4개 일치(50000원)-0개
+        5개 일치(1500000원)-0개
+        6개 일치(2000000000원)-0개
+        총 수익률은0.35입니다.(기준이 1이기 때문에 결과적으로 손해라는 의미임)
 
 ```
 
@@ -130,47 +130,106 @@
 
 - 2등을 위한 보너스볼을 추첨한다.
 - 당첨 통계에 2등을 추가한다.
-  - 2등 당첨 조건은 당첨 번호 5개 일치 + 보너스 볼 일치다.
+    - 2등 당첨 조건은 당첨 번호 5개 일치 + 보너스 볼 일치다.
 
-실행 결과
+
+- 실행 결과
 
 위 요구사항에 따라 14000원 어치 로또를 구매하였을 경우 프로그램을 실행한 결과는 다음과 같다.
 
 ```java
 구입금액을 입력해 주세요.
-14000
-
-14개를 구매했습니다.
-[8,21,23,41,42,43]
-[3,5,11,16,32,38]
-[7,11,16,35,36,44]
-[1,8,11,31,41,42]
-[13,14,16,38,42,45]
-[7,11,30,40,42,43]
-[2,13,22,32,38,45]
-[23,25,33,36,39,41]
-[1,3,5,14,22,45]
-[5,9,38,41,43,44]
-[2,8,9,18,19,21]
-[13,14,18,21,23,35]
-[17,21,29,37,42,45]
-[3,8,27,30,35,44]
-
-지난 주 당첨 번호를 입력해 주세요.
-1,2,3,4,5,6
-
-보너스 볼을 입력해 주세요.
-7
-
-당첨 통계
----------
-3개 일치(5000원)-1개
-4개 일치(50000원)-0개
-5개 일치(1500000원)-0개
-5개 일치,보너스 볼 일치(30000000원)-0개
-6개 일치(2000000000원)-0개
-총 수익률은0.35입니다.(기준이 1이기 때문에 결과적으로 손해라는 의미임)
+        14000
+
+        14개를 구매했습니다.
+        [8,21,23,41,42,43]
+        [3,5,11,16,32,38]
+        [7,11,16,35,36,44]
+        [1,8,11,31,41,42]
+        [13,14,16,38,42,45]
+        [7,11,30,40,42,43]
+        [2,13,22,32,38,45]
+        [23,25,33,36,39,41]
+        [1,3,5,14,22,45]
+        [5,9,38,41,43,44]
+        [2,8,9,18,19,21]
+        [13,14,18,21,23,35]
+        [17,21,29,37,42,45]
+        [3,8,27,30,35,44]
+
+        지난 주 당첨 번호를 입력해 주세요.
+        1,2,3,4,5,6
+
+        보너스 볼을 입력해 주세요.
+        7
+
+        당첨 통계
+        ---------
+        3개 일치(5000원)-1개
+        4개 일치(50000원)-0개
+        5개 일치(1500000원)-0개
+        5개 일치,보너스 볼 일치(30000000원)-0개
+        6개 일치(2000000000원)-0개
+        총 수익률은0.35입니다.(기준이 1이기 때문에 결과적으로 손해라는 의미임)
 ```
 
 ### 새로운 프로그래밍 요구사항
+
 Java Enum을 적용한다.
+
+### 4단계 - 로또 수동 구매
+
+- 현재 로또 생성기는 자동 생성 기능만 제공한다. 사용자가 수동으로 추첨 번호를 입력할 수 있도록 해야 한다.
+- 입력한 금액, 자동 생성 숫자, 수동 생성 번호를 입력하도록 해야 한다.
+
+실행 결과
+
+- 위 요구사항에 따라 14000원 어치 중 수동 3개, 자동 11개를 구매한 경우 프로그램을 실행한 결과는 다음과 같다.
+
+```java
+구입금액을 입력해 주세요.
+        14000
+
+        수동으로 구매할 로또 수를 입력해 주세요.
+        3
+
+        수동으로 구매할 번호를 입력해 주세요.
+        8,21,23,41,42,43
+        3,5,11,16,32,38
+        7,11,16,35,36,44
+
+        수동으로 3장,자동으로 11개를 구매했습니다.
+        [8,21,23,41,42,43]
+        [3,5,11,16,32,38]
+        [7,11,16,35,36,44]
+        [1,8,11,31,41,42]
+        [13,14,16,38,42,45]
+        [7,11,30,40,42,43]
+        [2,13,22,32,38,45]
+        [23,25,33,36,39,41]
+        [1,3,5,14,22,45]
+        [5,9,38,41,43,44]
+        [2,8,9,18,19,21]
+        [13,14,18,21,23,35]
+        [17,21,29,37,42,45]
+        [3,8,27,30,35,44]
+
+        지난 주 당첨 번호를 입력해 주세요.
+        1,2,3,4,5,6
+
+        보너스 볼을 입력해 주세요.
+        7
+
+        당첨 통계
+        ---------
+        3개 일치(5000원)-1개
+        4개 일치(50000원)-0개
+        5개 일치(1500000원)-0개
+        5개 일치,보너스 볼 일치(30000000원)-0개
+        6개 일치(2000000000원)-0개
+        총 수익률은0.35입니다.(기준이 1이기 때문에 결과적으로 손해라는 의미임)
+```
+
+### 5단계 - 리팩터링
+
+- 기존 프로그래밍 요구사항을 다시 한번 확인하고, 학습 테스트를 통해 학습한 내용을 반영한다.
diff --git a/src/main/java/org/duckstudy/Application.java b/src/main/java/org/duckstudy/Application.java
index 811618ef..6fcc749d 100644
--- a/src/main/java/org/duckstudy/Application.java
+++ b/src/main/java/org/duckstudy/Application.java
@@ -2,17 +2,17 @@
 
 import java.io.BufferedReader;
 import java.io.InputStreamReader;
-import org.duckstudy.controller.LottoController;
-import org.duckstudy.view.InputView;
-import org.duckstudy.view.OutputView;
+import org.duckstudy.game.LottoGame;
+import org.duckstudy.io.InputView;
+import org.duckstudy.io.OutputView;
 
 public class Application {
     public static void main(String[] args) {
         BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
         OutputView outputView = new OutputView();
-        InputView inputView = new InputView(bufferedReader, outputView);
+        InputView inputView = new InputView(bufferedReader);
 
-        LottoController lottoController = new LottoController(outputView, inputView);
-        lottoController.run();
+        LottoGame lottoGame = new LottoGame(outputView, inputView);
+        lottoGame.run();
     }
 }
diff --git a/src/main/java/org/duckstudy/controller/LottoController.java b/src/main/java/org/duckstudy/controller/LottoController.java
deleted file mode 100644
index 6d570936..00000000
--- a/src/main/java/org/duckstudy/controller/LottoController.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.duckstudy.controller;
-
-import org.duckstudy.model.Price;
-import org.duckstudy.model.lotto.Lotto;
-import org.duckstudy.model.lotto.LottoNumber;
-import org.duckstudy.model.lotto.LottoResult;
-import org.duckstudy.model.lotto.Lottos;
-import org.duckstudy.view.InputView;
-import org.duckstudy.view.OutputView;
-
-public class LottoController {
-
-    private final OutputView outputView;
-    private final InputView inputView;
-
-    public LottoController(OutputView outputView, InputView inputView) {
-        this.outputView = outputView;
-        this.inputView = inputView;
-    }
-
-    public void run() {
-        Price price = createPrice();
-        Lottos lottos = Lottos.generateLottosByPrice(price);
-        outputView.printLottos(lottos);
-
-        Lotto winningLotto = createWinningLotto();
-        LottoNumber bonusNumber = createBonusNumber(winningLotto);
-
-        getWinningResult(price, lottos, winningLotto, bonusNumber);
-    }
-
-    private Price createPrice() {
-        try {
-            Price price = new Price(inputView.inputPrice());
-            price.validateInputPrice();
-            return price;
-        } catch (IllegalArgumentException e) {
-            outputView.printException(e);
-            return createPrice();
-        }
-    }
-
-    private Lotto createWinningLotto() {
-        try {
-            return Lotto.from(inputView.inputWinningLotto());
-        } catch (IllegalArgumentException e) {
-            outputView.printException(e);
-            return createWinningLotto();
-        }
-    }
-
-    private LottoNumber createBonusNumber(Lotto winningLotto) {
-        LottoNumber bonusNumber = LottoNumber.valueOf(inputView.inputBonusNumber());
-        if (winningLotto.containsNumber(bonusNumber)) {
-            outputView.printExceptionForBonusNumber();
-            return createBonusNumber(winningLotto);
-        }
-        outputView.printExceptionForBonusNumber();
-        return bonusNumber;
-    }
-
-    private void getWinningResult(Price price, Lottos lottos, Lotto winningLotto, LottoNumber bonusNumber) {
-        LottoResult result = createLottoResult(lottos, winningLotto, bonusNumber);
-
-        calculateProfitRate(price, result);
-    }
-
-    private LottoResult createLottoResult(Lottos lottos, Lotto winningLotto, LottoNumber bonusNumber) {
-        LottoResult result = lottos.accumulateLottoResult(winningLotto, bonusNumber);
-        outputView.printLottoResult(result);
-        return result;
-    }
-
-    private void calculateProfitRate(Price price, LottoResult result) {
-        double profitRate = price.calculateProfitRate(result);
-        outputView.printTotalProfit(profitRate);
-    }
-}
diff --git a/src/main/java/org/duckstudy/model/Price.java b/src/main/java/org/duckstudy/domain/Price.java
similarity index 64%
rename from src/main/java/org/duckstudy/model/Price.java
rename to src/main/java/org/duckstudy/domain/Price.java
index e1184485..f06c63d5 100644
--- a/src/main/java/org/duckstudy/model/Price.java
+++ b/src/main/java/org/duckstudy/domain/Price.java
@@ -1,8 +1,9 @@
-package org.duckstudy.model;
+package org.duckstudy.domain;
 
 import java.util.Objects;
-import org.duckstudy.model.lotto.LottoResult;
-import org.duckstudy.model.lotto.constant.WinningRank;
+import org.duckstudy.domain.lotto.LottoCount;
+import org.duckstudy.domain.lotto.LottoResult;
+import org.duckstudy.domain.lotto.constant.WinningRank;
 
 public class Price {
 
@@ -13,16 +14,16 @@ public class Price {
 
     private final int value;
 
-    public Price(int price) {
+    public Price(final int price) {
         validatePrice(price);
         this.value = price;
     }
 
-    public static Price initialize() {
+    public static Price zero() {
         return new Price(INCLUSIVE_MIN_PRICE);
     }
 
-    private void validatePrice(int price) {
+    private void validatePrice(final int price) {
         if (price < INCLUSIVE_MIN_PRICE) {
             throw new IllegalArgumentException(String.format("가격은 %d원 이상이어야 합니다.", INCLUSIVE_MIN_PRICE));
         }
@@ -34,41 +35,36 @@ public void validateInputPrice() {
         }
     }
 
-    public Price addPrice(int value) {
+    public Price addPrice(final int value) {
         return new Price(this.value + value);
     }
 
-    public Price multiplyTimes(int times) {
-        return new Price(value * times);
-    }
-
-    public double divideByPrice(Price divisor) {
+    public double divideByPrice(final Price divisor) {
         checkIfZero(divisor.getValue());
         return (double) value / divisor.getValue();
     }
 
-    private void checkIfZero(int divisor) {
+    private void checkIfZero(final int divisor) {
         if (divisor == ZERO) {
             throw new IllegalArgumentException(String.format("%d으로 나눌 수 없습니다.", ZERO));
         }
     }
 
-    public int calculateLottoCount() {
+    public LottoCount calculateLottoCount() {
         checkIfZero(LOTTO_PRICE);
-        return value / LOTTO_PRICE;
+        return new LottoCount(value / LOTTO_PRICE);
     }
 
-    public double calculateProfitRate(LottoResult result) {
-        Price profit = Price.initialize();
+    public double calculateProfitRate(final LottoResult result) {
+        Price profit = Price.zero();
         for (WinningRank winningRank : WinningRank.values()) {
-            profit = profit.accumulateProfit(winningRank, result.getMatchingCount(winningRank.getKey()));
+            profit = profit.accumulateProfit(winningRank.getPrice(), result.getMatchingCount(winningRank));
         }
         return profit.divideByPrice(this) * PERCENT_BASE;
     }
 
-    private Price accumulateProfit(WinningRank winningRank, int count) {
-        return this.addPrice(winningRank.getPrice())
-                .multiplyTimes(count);
+    private Price accumulateProfit(final int price, final int count) {
+        return this.addPrice(price * count);
     }
 
     public int getValue() {
diff --git a/src/main/java/org/duckstudy/model/lotto/Lotto.java b/src/main/java/org/duckstudy/domain/lotto/Lotto.java
similarity index 53%
rename from src/main/java/org/duckstudy/model/lotto/Lotto.java
rename to src/main/java/org/duckstudy/domain/lotto/Lotto.java
index aeeef811..a8e43748 100644
--- a/src/main/java/org/duckstudy/model/lotto/Lotto.java
+++ b/src/main/java/org/duckstudy/domain/lotto/Lotto.java
@@ -1,40 +1,42 @@
-package org.duckstudy.model.lotto;
+package org.duckstudy.domain.lotto;
 
 import static java.util.Collections.shuffle;
 import static java.util.stream.Collectors.collectingAndThen;
 import static java.util.stream.Collectors.toList;
-import static org.duckstudy.model.lotto.constant.LottoNumberRange.END_INCLUSIVE_NUMBER;
-import static org.duckstudy.model.lotto.constant.LottoNumberRange.START_INCLUSIVE_NUMBER;
+import static java.util.stream.Collectors.toSet;
+import static org.duckstudy.domain.lotto.LottoNumber.END_INCLUSIVE_NUMBER;
+import static org.duckstudy.domain.lotto.LottoNumber.START_INCLUSIVE_NUMBER;
 
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.stream.Collector;
 import java.util.stream.IntStream;
 import java.util.stream.Stream;
 
 public class Lotto {
 
-    private static final List NUMBERS;
+    private static final Set NUMBERS;
     private static final int LOTTO_SIZE = 6;
 
     static {
-        NUMBERS = IntStream.range(START_INCLUSIVE_NUMBER.getValue(), END_INCLUSIVE_NUMBER.getValue() + 1)
+        NUMBERS = IntStream.range(START_INCLUSIVE_NUMBER, END_INCLUSIVE_NUMBER + 1)
                 .boxed()
-                .toList();
+                .collect(toSet());
     }
 
-    private final List lotto;
+    private final Set lotto;
 
-    public Lotto(List lotto) {
+    public Lotto(final Set lotto) {
         validateLottoSize(lotto);
-        validateDuplicate(lotto);
-        this.lotto = Collections.unmodifiableList(lotto);
+        this.lotto = new HashSet<>(lotto);
     }
 
-    public static Lotto from(List values) {
+    public static Lotto from(final Set values) {
         return new Lotto(values.stream()
                 .map(LottoNumber::valueOf)
-                .collect(toList()));
+                .collect(toSet()));
     }
 
     public static Lotto createRandomLotto() {
@@ -43,7 +45,7 @@ public static Lotto createRandomLotto() {
                 .limit(LOTTO_SIZE)
                 .sorted()
                 .map(LottoNumber::valueOf)
-                .collect(toList()));
+                .collect(toSet()));
     }
 
     private static Collector> getCollector() {
@@ -54,30 +56,24 @@ public static Lotto createRandomLotto() {
                 });
     }
 
-    public int countMatchingNumber(Lotto compareLotto) {
+    public int countMatchingNumber(final Lotto compareLotto) {
         return lotto.stream()
                 .filter(lottoNumber -> compareLotto.getLotto().contains(lottoNumber))
                 .toList()
                 .size();
     }
 
-    public boolean containsNumber(LottoNumber lottoNumber) {
+    public boolean containsNumber(final LottoNumber lottoNumber) {
         return lotto.contains(lottoNumber);
     }
 
-    private void validateLottoSize(List lotto) {
+    private void validateLottoSize(final Set lotto) {
         if (lotto.size() != LOTTO_SIZE) {
-            throw new IllegalArgumentException(String.format("로또 번호는 %d개여야 합니다.", LOTTO_SIZE));
+            throw new IllegalArgumentException(String.format("로또 번호는 중복되지 않은 %d개여야 합니다.\n", LOTTO_SIZE));
         }
     }
 
-    private void validateDuplicate(List lotto) {
-        if (lotto.stream().distinct().count() != LOTTO_SIZE) {
-            throw new IllegalArgumentException("로또 번호는 중복되지 않아야 합니다.");
-        }
-    }
-
-    public List getLotto() {
-        return lotto;
+    public Set getLotto() {
+        return Collections.unmodifiableSet(lotto);
     }
 }
diff --git a/src/main/java/org/duckstudy/domain/lotto/LottoCount.java b/src/main/java/org/duckstudy/domain/lotto/LottoCount.java
new file mode 100644
index 00000000..7bf975eb
--- /dev/null
+++ b/src/main/java/org/duckstudy/domain/lotto/LottoCount.java
@@ -0,0 +1,50 @@
+package org.duckstudy.domain.lotto;
+
+import java.util.Objects;
+
+public class LottoCount {
+
+    private final int count;
+
+    public LottoCount(final int count) {
+        validateLottoCount(count);
+        this.count = count;
+    }
+
+    private void validateLottoCount(final int count) {
+        if (count < 0) {
+            throw new IllegalArgumentException("로또 개수는 0개 이상이어야 합니다.");
+        }
+    }
+
+    public void validateManualLottoCount(final LottoCount totalLottoCount) {
+        if (count > totalLottoCount.getCount()) {
+            throw new IllegalArgumentException("수동으로 구매할 로또 수가 전체 로또 수를 초과합니다.\n");
+        }
+    }
+
+    public LottoCount subtract(final LottoCount lottoCount) {
+        return new LottoCount(count - lottoCount.count);
+    }
+
+    public int getCount() {
+        return count;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        LottoCount that = (LottoCount) o;
+        return count == that.count;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(count);
+    }
+}
diff --git a/src/main/java/org/duckstudy/model/lotto/LottoNumber.java b/src/main/java/org/duckstudy/domain/lotto/LottoNumber.java
similarity index 55%
rename from src/main/java/org/duckstudy/model/lotto/LottoNumber.java
rename to src/main/java/org/duckstudy/domain/lotto/LottoNumber.java
index 62a18119..d51dac4f 100644
--- a/src/main/java/org/duckstudy/model/lotto/LottoNumber.java
+++ b/src/main/java/org/duckstudy/domain/lotto/LottoNumber.java
@@ -1,7 +1,4 @@
-package org.duckstudy.model.lotto;
-
-import static org.duckstudy.model.lotto.constant.LottoNumberRange.END_INCLUSIVE_NUMBER;
-import static org.duckstudy.model.lotto.constant.LottoNumberRange.START_INCLUSIVE_NUMBER;
+package org.duckstudy.domain.lotto;
 
 import java.util.List;
 import java.util.Objects;
@@ -9,31 +6,33 @@
 
 public class LottoNumber {
 
+    public static final int START_INCLUSIVE_NUMBER = 1;
+    public static final int END_INCLUSIVE_NUMBER = 45;
     private static final List cache;
 
     static {
-        cache = IntStream.range(0, END_INCLUSIVE_NUMBER.getValue())
-                .mapToObj(i -> new LottoNumber(START_INCLUSIVE_NUMBER.getValue() + i))
+        cache = IntStream.range(0, END_INCLUSIVE_NUMBER)
+                .mapToObj(i -> new LottoNumber(START_INCLUSIVE_NUMBER + i))
                 .toList();
     }
 
     private final int value;
 
-    private LottoNumber(int number) {
+    private LottoNumber(final int number) {
         this.value = number;
     }
 
-    public static LottoNumber valueOf(int number) {
+    public static LottoNumber valueOf(final int number) {
         validateNumber(number);
 
-        return cache.get(number - START_INCLUSIVE_NUMBER.getValue());
+        return cache.get(number - START_INCLUSIVE_NUMBER);
     }
 
-    private static void validateNumber(int number) {
-        if (number < START_INCLUSIVE_NUMBER.getValue() || number > END_INCLUSIVE_NUMBER.getValue()) {
+    private static void validateNumber(final int number) {
+        if (number < START_INCLUSIVE_NUMBER || number > END_INCLUSIVE_NUMBER) {
             throw new IllegalArgumentException(
-                    String.format("로또 번호는 %d 이상 %d 이하의 숫자여야 합니다.", START_INCLUSIVE_NUMBER.getValue(),
-                            END_INCLUSIVE_NUMBER.getValue()));
+                    String.format("로또 번호는 %d 이상 %d 이하의 숫자여야 합니다.", START_INCLUSIVE_NUMBER,
+                            END_INCLUSIVE_NUMBER));
         }
     }
 
diff --git a/src/main/java/org/duckstudy/domain/lotto/LottoResult.java b/src/main/java/org/duckstudy/domain/lotto/LottoResult.java
new file mode 100644
index 00000000..a44d7c3e
--- /dev/null
+++ b/src/main/java/org/duckstudy/domain/lotto/LottoResult.java
@@ -0,0 +1,48 @@
+package org.duckstudy.domain.lotto;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.duckstudy.domain.lotto.constant.WinningRank;
+
+public class LottoResult {
+
+    public static final int DEFAULT_FREQUENCY = 1;
+    public static final int DEFAULT_VALUE = 0;
+
+    private final Map result;
+
+    public LottoResult(final Map result) {
+        this.result = new HashMap<>(result);
+    }
+
+    public static LottoResult createLottoResult(final Lotto lotto, final Lotto winningLotto,
+                                                final LottoNumber bonusNumber) {
+        int matchingCount = lotto.countMatchingNumber(winningLotto);
+        boolean matchBonus = lotto.containsNumber(bonusNumber);
+
+        WinningRank winningRank = WinningRank.findByMatchCountAndBonus(matchingCount, matchBonus);
+
+        return new LottoResult(Map.of(winningRank, DEFAULT_FREQUENCY));
+    }
+
+    public LottoResult merge(final LottoResult other) {
+        return new LottoResult(Stream.of(this.result, other.result)
+                .flatMap(map -> map.entrySet().stream())
+                .collect(Collectors.toMap(
+                        Map.Entry::getKey,
+                        Map.Entry::getValue,
+                        Integer::sum
+                )));
+    }
+
+    public int getMatchingCount(final WinningRank winningRank) {
+        return result.getOrDefault(winningRank, DEFAULT_VALUE);
+    }
+
+    public Map getResult() {
+        return Collections.unmodifiableMap(result);
+    }
+}
diff --git a/src/main/java/org/duckstudy/model/lotto/Lottos.java b/src/main/java/org/duckstudy/domain/lotto/Lottos.java
similarity index 55%
rename from src/main/java/org/duckstudy/model/lotto/Lottos.java
rename to src/main/java/org/duckstudy/domain/lotto/Lottos.java
index 9c4690e3..9a40e2b9 100644
--- a/src/main/java/org/duckstudy/model/lotto/Lottos.java
+++ b/src/main/java/org/duckstudy/domain/lotto/Lottos.java
@@ -1,41 +1,41 @@
-package org.duckstudy.model.lotto;
+package org.duckstudy.domain.lotto;
 
 import static java.util.stream.Collectors.collectingAndThen;
 import static java.util.stream.Collectors.toList;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Stream;
-import org.duckstudy.model.Price;
 
 public class Lottos {
 
     private final List lottos;
 
-    public Lottos(List lottos) {
-        this.lottos = Collections.unmodifiableList(lottos);
+    public Lottos(final List lottos) {
+        this.lottos = new ArrayList<>(lottos);
     }
 
-    public static Lottos generateLottosByPrice(Price price) {
-        int lottoCount = price.calculateLottoCount();
-
+    public static Lottos generateLottos(final int lottoCount) {
         return Stream.generate(Lotto::createRandomLotto)
                 .limit(lottoCount)
                 .collect(collectingAndThen(toList(), Lottos::new));
     }
 
-    public LottoResult accumulateLottoResult(Lotto winningLotto, LottoNumber bonusNumber) {
+    public LottoResult accumulateLottoResult(final Lotto winningLotto, final LottoNumber bonusNumber) {
         return lottos.stream()
                 .map(lotto -> LottoResult.createLottoResult(lotto, winningLotto, bonusNumber))
                 .reduce(new LottoResult(Map.of()), LottoResult::merge);
     }
 
-    public List getLottos() {
-        return lottos;
+    public Lottos merge(final Lottos other) {
+        return new Lottos(Stream.of(this.lottos, other.lottos)
+                .flatMap(List::stream)
+                .collect(toList()));
     }
 
-    public int getSize() {
-        return lottos.size();
+    public List getLottos() {
+        return Collections.unmodifiableList(lottos);
     }
 }
diff --git a/src/main/java/org/duckstudy/domain/lotto/constant/WinningRank.java b/src/main/java/org/duckstudy/domain/lotto/constant/WinningRank.java
new file mode 100644
index 00000000..0abbac9c
--- /dev/null
+++ b/src/main/java/org/duckstudy/domain/lotto/constant/WinningRank.java
@@ -0,0 +1,45 @@
+package org.duckstudy.domain.lotto.constant;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.BiPredicate;
+
+public enum WinningRank {
+
+    NONE(List.of(0, 1, 2), 0, (matchCount, matchBonus) -> matchCount < 3),
+    FIFTH(List.of(3), 5_000, (matchCount, matchBonus) -> matchCount == 3),
+    FOURTH(List.of(4), 50_000, (matchCount, matchBonus) -> matchCount == 4),
+    THIRD(List.of(5), 1_500_000, (matchCount, matchBonus) -> matchCount == 5 && !matchBonus),
+    SECOND(List.of(5), 30_000_000, (matchCount, matchBonus) -> matchCount == 5 && matchBonus),
+    FIRST(List.of(6), 2_000_000_000, (matchCount, matchBonus) -> matchCount == 6);
+
+    private final List matchCount;
+    private final int price;
+    private final BiPredicate isMatchPredicate;
+
+    WinningRank(final List matchCount, final int price,
+                final BiPredicate isMatchPredicate) {
+        this.matchCount = matchCount;
+        this.price = price;
+        this.isMatchPredicate = isMatchPredicate;
+    }
+
+    public static WinningRank findByMatchCountAndBonus(final int matchCount, final boolean matchBonus) {
+        return Arrays.stream(values())
+                .filter(winningLank -> winningLank.isMatch(matchCount, matchBonus))
+                .findFirst()
+                .orElseThrow(() -> new IllegalArgumentException("적절한 당첨 등수를 찾을 수 없습니다."));
+    }
+
+    private boolean isMatch(final int matchCount, final boolean matchBonus) {
+        return isMatchPredicate.test(matchCount, matchBonus);
+    }
+
+    public List getMatchCount() {
+        return matchCount;
+    }
+
+    public int getPrice() {
+        return price;
+    }
+}
diff --git a/src/main/java/org/duckstudy/game/LottoGame.java b/src/main/java/org/duckstudy/game/LottoGame.java
new file mode 100644
index 00000000..b06cd180
--- /dev/null
+++ b/src/main/java/org/duckstudy/game/LottoGame.java
@@ -0,0 +1,123 @@
+package org.duckstudy.game;
+
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import org.duckstudy.domain.Price;
+import org.duckstudy.domain.lotto.Lotto;
+import org.duckstudy.domain.lotto.LottoCount;
+import org.duckstudy.domain.lotto.LottoNumber;
+import org.duckstudy.domain.lotto.LottoResult;
+import org.duckstudy.domain.lotto.Lottos;
+import org.duckstudy.io.InputView;
+import org.duckstudy.io.OutputView;
+
+public class LottoGame {
+
+    private final OutputView outputView;
+    private final InputView inputView;
+
+    public LottoGame(final OutputView outputView, final InputView inputView) {
+        this.outputView = outputView;
+        this.inputView = inputView;
+    }
+
+    public void run() {
+        Price price = createPrice();
+        Lottos totalLottos = createTotalLottos(price);
+
+        Lotto winningLotto = createWinningLotto();
+        LottoNumber bonusNumber = createBonusNumber(winningLotto);
+
+        printWinningResult(price, totalLottos, winningLotto, bonusNumber);
+    }
+
+    private Lottos createTotalLottos(final Price price) {
+        LottoCount totalLottoCount = price.calculateLottoCount();
+        LottoCount manualLottoCount = createManualLottoCount(totalLottoCount);
+        Lottos manualLottos = createManualLottos(manualLottoCount.getCount());
+
+        LottoCount autoLottoCount = totalLottoCount.subtract(manualLottoCount);
+        Lottos autoLottos = Lottos.generateLottos(autoLottoCount.getCount());
+        Lottos totalLottos = manualLottos.merge(autoLottos);
+
+        outputView.printLottos(manualLottoCount.getCount(), autoLottoCount.getCount(), totalLottos);
+        return totalLottos;
+    }
+
+    private Price createPrice() {
+        outputView.printInputPrice();
+        try {
+            Price price = new Price(inputView.inputPrice());
+            price.validateInputPrice();
+            return price;
+        } catch (IllegalArgumentException e) {
+            outputView.printException(e);
+            return createPrice();
+        }
+    }
+
+    private Lottos createManualLottos(final int manualLottoCount) {
+        outputView.printInputManualLotto();
+
+        return new Lottos(IntStream.range(0, manualLottoCount)
+                .mapToObj(i -> createManualLotto())
+                .collect(Collectors.toList()));
+    }
+
+    private LottoCount createManualLottoCount(final LottoCount lottoCount) {
+        outputView.printInputManualLottoCount();
+        try {
+            LottoCount manualLottoCount = new LottoCount(inputView.inputManualLottoCount());
+            manualLottoCount.validateManualLottoCount(lottoCount);
+            return manualLottoCount;
+        } catch (IllegalArgumentException e) {
+            outputView.printException(e);
+            return createManualLottoCount(lottoCount);
+        }
+    }
+
+    private Lotto createManualLotto() {
+        try {
+            return Lotto.from(inputView.inputManualLotto());
+        } catch (IllegalArgumentException e) {
+            outputView.printException(e);
+            return createManualLotto();
+        }
+    }
+
+    private Lotto createWinningLotto() {
+        outputView.printInputWinningLotto();
+        try {
+            return Lotto.from(inputView.inputWinningLotto());
+        } catch (IllegalArgumentException e) {
+            outputView.printException(e);
+            return createWinningLotto();
+        }
+    }
+
+    private LottoNumber createBonusNumber(final Lotto winningLotto) {
+        outputView.printInputBonusNumber();
+        try {
+            LottoNumber bonusNumber = LottoNumber.valueOf(inputView.inputBonusNumber());
+            validateBonusNumber(winningLotto, bonusNumber);
+            return bonusNumber;
+        } catch (IllegalArgumentException e) {
+            outputView.printException(e);
+            return createBonusNumber(winningLotto);
+        }
+    }
+
+    private void validateBonusNumber(final Lotto winningLotto, final LottoNumber bonusNumber) {
+        if (winningLotto.containsNumber(bonusNumber)) {
+            throw new IllegalArgumentException("당첨 번호와 중복되는 보너스 볼은 입력할 수 없습니다.");
+        }
+    }
+
+    private void printWinningResult(Price price, Lottos totalLottos, Lotto winningLotto, LottoNumber bonusNumber) {
+        LottoResult lottoResult = totalLottos.accumulateLottoResult(winningLotto, bonusNumber);
+        outputView.printLottoResult(lottoResult);
+
+        double profitRate = price.calculateProfitRate(lottoResult);
+        outputView.printTotalProfit(profitRate);
+    }
+}
diff --git a/src/main/java/org/duckstudy/view/InputView.java b/src/main/java/org/duckstudy/io/InputView.java
similarity index 57%
rename from src/main/java/org/duckstudy/view/InputView.java
rename to src/main/java/org/duckstudy/io/InputView.java
index faf356c7..fec048bd 100644
--- a/src/main/java/org/duckstudy/view/InputView.java
+++ b/src/main/java/org/duckstudy/io/InputView.java
@@ -1,22 +1,21 @@
-package org.duckstudy.view;
+package org.duckstudy.io;
+
+import static java.util.stream.Collectors.toSet;
 
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.util.Arrays;
-import java.util.List;
+import java.util.Set;
 
 public class InputView {
 
     private final BufferedReader bufferedReader;
-    private final OutputView outputView;
 
-    public InputView(BufferedReader bufferedReader, OutputView outputView) {
+    public InputView(BufferedReader bufferedReader) {
         this.bufferedReader = bufferedReader;
-        this.outputView = outputView;
     }
 
     public int inputPrice() {
-        outputView.printInputPrice();
         try {
             return Integer.parseInt(bufferedReader.readLine());
         } catch (NumberFormatException | IOException e) {
@@ -24,9 +23,7 @@ public int inputPrice() {
         }
     }
 
-    public List inputWinningLotto() {
-        outputView.printInputWinningLotto();
-
+    public Set inputWinningLotto() {
         try {
             return inputLottoNumber();
         } catch (NumberFormatException | IOException e) {
@@ -34,20 +31,34 @@ public List inputWinningLotto() {
         }
     }
 
-    private List inputLottoNumber() throws IOException {
+    private Set inputLottoNumber() throws IOException {
         return Arrays.stream(bufferedReader.readLine().split(","))
                 .map(String::trim)
                 .map(Integer::parseInt)
-                .toList();
+                .collect(toSet());
     }
 
     public int inputBonusNumber() {
-        outputView.printInputBonusNumber();
+        try {
+            return Integer.parseInt(bufferedReader.readLine());
+        } catch (NumberFormatException | IOException e) {
+            throw new NumberFormatException("숫자만 입력 가능합니다.");
+        }
+    }
 
+    public int inputManualLottoCount() {
         try {
             return Integer.parseInt(bufferedReader.readLine());
         } catch (NumberFormatException | IOException e) {
             throw new NumberFormatException("숫자만 입력 가능합니다.");
         }
     }
+
+    public Set inputManualLotto() {
+        try {
+            return inputLottoNumber();
+        } catch (NumberFormatException | IOException e) {
+            throw new NumberFormatException("숫자만 입력 가능합니다.\n");
+        }
+    }
 }
diff --git a/src/main/java/org/duckstudy/io/OutputView.java b/src/main/java/org/duckstudy/io/OutputView.java
new file mode 100644
index 00000000..7beca5ab
--- /dev/null
+++ b/src/main/java/org/duckstudy/io/OutputView.java
@@ -0,0 +1,92 @@
+package org.duckstudy.io;
+
+import static org.duckstudy.domain.lotto.constant.WinningRank.NONE;
+import static org.duckstudy.domain.lotto.constant.WinningRank.SECOND;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import org.duckstudy.domain.lotto.Lotto;
+import org.duckstudy.domain.lotto.LottoNumber;
+import org.duckstudy.domain.lotto.LottoResult;
+import org.duckstudy.domain.lotto.Lottos;
+import org.duckstudy.domain.lotto.constant.WinningRank;
+
+public class OutputView {
+
+    public void printInputPrice() {
+        System.out.println("구입금액을 입력해 주세요.");
+    }
+
+    public void printException(final Exception e) {
+        System.out.println(e.getMessage());
+    }
+
+    public void printLottos(final int manualLottoCount, final int autoLottoCount, final Lottos lottos) {
+        System.out.printf("\n수동으로 %d개, 자동으로 %d개를 구매했습니다.\n", manualLottoCount, autoLottoCount);
+        lottos.getLottos()
+                .forEach(this::printLotto);
+    }
+
+    private void printLotto(final Lotto lotto) {
+        System.out.println(lotto.getLotto()
+                .stream()
+                .map(LottoNumber::getValue)
+                .sorted()
+                .map(String::valueOf)
+                .collect(Collectors.joining(", ", "[", "]")));
+    }
+
+    public void printInputWinningLotto() {
+        System.out.println("\n지난 주 당첨 번호를 입력해 주세요.");
+    }
+
+    public void printInputBonusNumber() {
+        System.out.println("\n보너스 볼을 입력해 주세요.");
+    }
+
+    public void printLottoResult(final LottoResult result) {
+        System.out.println("\n당첨 통계");
+        System.out.println("---------");
+        iterateLottoResult(result);
+    }
+
+    private void iterateLottoResult(final LottoResult result) {
+        for (WinningRank winningRank : WinningRank.values()) {
+            printMatchingResult(result, winningRank);
+        }
+        System.out.println();
+    }
+
+    private void printMatchingResult(final LottoResult result, final WinningRank winningRank) {
+        if (winningRank == NONE) {
+            return;
+        }
+
+        List matchCounts = winningRank.getMatchCount();
+        int price = winningRank.getPrice();
+
+        String matchPriceMessage = getMatchPrice(winningRank, matchCounts.get(0), price);
+        int matchingCount = result.getMatchingCount(winningRank);
+
+        System.out.println(matchPriceMessage + matchingCount + "개");
+    }
+
+    private String getMatchPrice(final WinningRank winningRank, final int cnt, final int price) {
+        if (winningRank == SECOND) {
+            return String.format("%d개 일치, 보너스 볼 일치(%d원)- ", cnt, price);
+        }
+        return String.format("%d개 일치 (%d원)- ", cnt, price);
+    }
+
+    public void printTotalProfit(final double totalProfitRate) {
+        System.out.printf("총 수익률은 %.2f입니다.\n", totalProfitRate);
+    }
+
+    public void printInputManualLottoCount() {
+        System.out.println("\n수동으로 구매할 로또 수를 입력해 주세요.");
+    }
+
+    public void printInputManualLotto() {
+        System.out.println("\n수동으로 구매할 번호를 입력해 주세요.");
+    }
+}
diff --git a/src/main/java/org/duckstudy/model/lotto/LottoResult.java b/src/main/java/org/duckstudy/model/lotto/LottoResult.java
deleted file mode 100644
index ec43bcc3..00000000
--- a/src/main/java/org/duckstudy/model/lotto/LottoResult.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.duckstudy.model.lotto;
-
-import java.util.Collections;
-import java.util.Map;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import org.duckstudy.model.lotto.constant.WinningRank;
-
-public class LottoResult {
-
-    public static final int DEFAULT_FREQUENCY = 1;
-    public static final int DEFAULT_VALUE = 0;
-
-    private final Map result;
-
-    public LottoResult(Map result) {
-        this.result = Collections.unmodifiableMap(result);
-    }
-
-    public static LottoResult createLottoResult(Lotto lotto, Lotto winningLotto, LottoNumber bonusNumber) {
-        int matchingCount = lotto.countMatchingNumber(winningLotto);
-        boolean matchBonus = lotto.containsNumber(bonusNumber);
-
-        int key = WinningRank.findByMatchCountAndBonus(matchingCount, matchBonus)
-                .getKey();
-
-        return new LottoResult(Map.of(key, DEFAULT_FREQUENCY));
-    }
-
-    public LottoResult merge(LottoResult other) {
-        return new LottoResult(Stream.of(this.result, other.result)
-                .flatMap(map -> map.entrySet().stream())
-                .collect(Collectors.toMap(
-                        Map.Entry::getKey,
-                        Map.Entry::getValue,
-                        Integer::sum
-                )));
-    }
-
-    public int getMatchingCount(int count) {
-        return result.getOrDefault(count, DEFAULT_VALUE);
-    }
-
-    public Map getResult() {
-        return result;
-    }
-}
diff --git a/src/main/java/org/duckstudy/model/lotto/constant/LottoNumberRange.java b/src/main/java/org/duckstudy/model/lotto/constant/LottoNumberRange.java
deleted file mode 100644
index f499c792..00000000
--- a/src/main/java/org/duckstudy/model/lotto/constant/LottoNumberRange.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.duckstudy.model.lotto.constant;
-
-public enum LottoNumberRange {
-
-    START_INCLUSIVE_NUMBER(1),
-    END_INCLUSIVE_NUMBER(45);
-
-    private final int value;
-
-    LottoNumberRange(int value) {
-        this.value = value;
-    }
-
-    public int getValue() {
-        return value;
-    }
-}
diff --git a/src/main/java/org/duckstudy/model/lotto/constant/WinningRank.java b/src/main/java/org/duckstudy/model/lotto/constant/WinningRank.java
deleted file mode 100644
index 277b72ce..00000000
--- a/src/main/java/org/duckstudy/model/lotto/constant/WinningRank.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.duckstudy.model.lotto.constant;
-
-import java.util.stream.Stream;
-
-public enum WinningRank {
-
-    NONE(0, 0, 0),
-    FIFTH(3, 5000, 3),
-    FOURTH(4, 50000, 4),
-    THIRD(5, 1500000, 5),
-    SECOND(5, 30000000, -5),
-    FIRST(6, 2000000000, 6);
-
-    private final int matchCount;
-    private final int price;
-    private final int key;
-
-    WinningRank(int matchCount, int price, int key) {
-        this.matchCount = matchCount;
-        this.price = price;
-        this.key = key;
-    }
-
-    public static WinningRank findByMatchCountAndBonus(int matchCount, boolean matchBonus) {
-        if (matchCount == SECOND.getMatchCount() && matchBonus) {
-            return SECOND;
-        }
-        return Stream.of(values())
-                .filter(winningLank -> winningLank.getMatchCount() == matchCount)
-                .findFirst()
-                .orElse(NONE);
-    }
-
-    public int getMatchCount() {
-        return matchCount;
-    }
-
-    public int getPrice() {
-        return price;
-    }
-
-    public int getKey() {
-        return key;
-    }
-}
diff --git a/src/main/java/org/duckstudy/view/OutputView.java b/src/main/java/org/duckstudy/view/OutputView.java
deleted file mode 100644
index 460b6960..00000000
--- a/src/main/java/org/duckstudy/view/OutputView.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package org.duckstudy.view;
-
-import static org.duckstudy.model.lotto.constant.WinningRank.NONE;
-import static org.duckstudy.model.lotto.constant.WinningRank.SECOND;
-
-import java.util.stream.Collectors;
-import org.duckstudy.model.lotto.Lotto;
-import org.duckstudy.model.lotto.LottoNumber;
-import org.duckstudy.model.lotto.LottoResult;
-import org.duckstudy.model.lotto.Lottos;
-import org.duckstudy.model.lotto.constant.WinningRank;
-
-public class OutputView {
-
-    public void printInputPrice() {
-        System.out.println("구입금액을 입력해 주세요.");
-    }
-
-    public void printException(Exception e) {
-        System.out.println(e.getMessage());
-    }
-
-    public void printLottos(Lottos lottos) {
-        System.out.printf("\n%d개를 구매했습니다.\n", lottos.getSize());
-        lottos.getLottos()
-                .forEach(this::printLotto);
-    }
-
-    private void printLotto(Lotto lotto) {
-        System.out.println(lotto.getLotto()
-                .stream()
-                .map(LottoNumber::getValue)
-                .map(String::valueOf)
-                .collect(Collectors.joining(", ", "[", "]")));
-    }
-
-    public void printInputWinningLotto() {
-        System.out.println("\n지난 주 당첨 번호를 입력해 주세요.");
-    }
-
-    public void printInputBonusNumber() {
-        System.out.println("\n보너스 볼을 입력해 주세요.");
-    }
-
-    public void printLottoResult(LottoResult result) {
-        System.out.println("\n당첨 통계");
-        System.out.println("---------");
-        iterateLottoResult(result);
-    }
-
-    private void iterateLottoResult(LottoResult result) {
-        for (WinningRank winningRank : WinningRank.values()) {
-            printMatchingResult(result, winningRank);
-        }
-        System.out.println();
-    }
-
-    private void printMatchingResult(LottoResult result, WinningRank winningRank) {
-        if (winningRank == NONE) {
-            return;
-        }
-
-        int cnt = winningRank.getMatchCount();
-        int key = winningRank.getKey();
-        int price = winningRank.getPrice();
-
-        String matchPriceMessage = getMatchPrice(winningRank, cnt, price);
-        int matchingCount = result.getMatchingCount(key);
-
-        System.out.println(matchPriceMessage + matchingCount + "개");
-    }
-
-    private String getMatchPrice(WinningRank winningRank, int cnt, int price) {
-        if (winningRank == SECOND) {
-            return String.format("%d개 일치, 보너스 볼 일치(%d원)- ", cnt, price);
-        }
-        return String.format("%d개 일치 (%d원)- ", cnt, price);
-    }
-
-    public void printTotalProfit(double totalProfitRate) {
-        System.out.printf("총 수익률은 %.2f입니다.\n", totalProfitRate);
-    }
-
-    public void printExceptionForBonusNumber() {
-        System.out.println("보너스 볼은 당첨 번호와 중복되면 안됩니다.");
-    }
-}
diff --git a/src/test/java/org/duckstudy/model/PriceTest.java b/src/test/java/org/duckstudy/domain/PriceTest.java
similarity index 65%
rename from src/test/java/org/duckstudy/model/PriceTest.java
rename to src/test/java/org/duckstudy/domain/PriceTest.java
index df9875ab..7fb21d70 100644
--- a/src/test/java/org/duckstudy/model/PriceTest.java
+++ b/src/test/java/org/duckstudy/domain/PriceTest.java
@@ -1,4 +1,4 @@
-package org.duckstudy.model;
+package org.duckstudy.domain;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.AssertionsForClassTypes.assertThatCode;
@@ -6,8 +6,8 @@
 
 import java.util.HashMap;
 import java.util.Map;
-import org.duckstudy.model.lotto.LottoResult;
-import org.duckstudy.model.lotto.constant.WinningRank;
+import org.duckstudy.domain.lotto.LottoResult;
+import org.duckstudy.domain.lotto.constant.WinningRank;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
@@ -38,27 +38,57 @@ void validateFailWhenPriceIsLessThanZero() {
     }
 
     @Nested
-    @DisplayName("가격 계산 테스트")
-    class PriceCalculateTest {
+    @DisplayName("입력 가격 검증 테스트")
+    class InputPriceValidationTest {
 
         @Test
-        @DisplayName("가격을 더한다")
-        void addPrice() {
+        @DisplayName("입력 가격이 양수일 경우 성공한다")
+        void validateInputPriceSuccessWhenPriceIsEqualOrGreaterThanZero() {
 
-            Price price = new Price(1000);
+            Price price = new Price(1);
 
-            Price result = price.addPrice(2000);
+            assertThatCode(price::validateInputPrice)
+                    .doesNotThrowAnyException();
+        }
 
-            assertThat(result).isEqualTo(new Price(3000));
+        @Test
+        @DisplayName("입력 가격이 0 이하일 경우 예외가 발생한다")
+        void validateInputPriceFailWhenPriceIsZero() {
+
+            Price price = new Price(0);
+
+            assertThatThrownBy(price::validateInputPrice)
+                    .isExactlyInstanceOf(IllegalArgumentException.class)
+                    .hasMessage("가격은 0원 이상이어야 합니다.\n");
+        }
+    }
+
+    @Nested
+    @DisplayName("가격 생성 테스트")
+    class PriceCreationTest {
+
+        @Test
+        @DisplayName("0원으로 가격을 생성하면 성공한다")
+        void createPriceWhenZero() {
+
+            Price price = Price.zero();
+
+            assertThat(price).isEqualTo(new Price(0));
         }
+    }
+
+
+    @Nested
+    @DisplayName("가격 계산 테스트")
+    class PriceCalculateTest {
 
         @Test
-        @DisplayName("가격을 곱한다")
-        void multiplyPrice() {
+        @DisplayName("가격을 더한다")
+        void addPrice() {
 
             Price price = new Price(1000);
 
-            Price result = price.multiplyTimes(3);
+            Price result = price.addPrice(2000);
 
             assertThat(result).isEqualTo(new Price(3000));
         }
@@ -96,18 +126,18 @@ void calculateLottoCountWhenInputPrice() {
 
             Price price = new Price(10000);
 
-            assertThat(price.calculateLottoCount()).isEqualTo(10);
+            assertThat(price.calculateLottoCount().getCount()).isEqualTo(10);
         }
 
         @Test
         @DisplayName("로또 수익률을 계산한다")
         void calculateProfitRate() {
             Price purchasePrice = new Price(15000);
-            Map result = new HashMap<>();
-            result.put(WinningRank.FIRST.getKey(), 1);
+            Map result = new HashMap<>();
+            result.put(WinningRank.SECOND, 1);
             LottoResult lottoResult = new LottoResult(result);
 
-            assertThat(purchasePrice.calculateProfitRate(lottoResult)).isEqualTo(1.3333333333333334E7);
+            assertThat(purchasePrice.calculateProfitRate(lottoResult)).isEqualTo(200000.0);
         }
     }
 }
diff --git a/src/test/java/org/duckstudy/domain/lotto/LottoCountTest.java b/src/test/java/org/duckstudy/domain/lotto/LottoCountTest.java
new file mode 100644
index 00000000..535bdde3
--- /dev/null
+++ b/src/test/java/org/duckstudy/domain/lotto/LottoCountTest.java
@@ -0,0 +1,79 @@
+package org.duckstudy.domain.lotto;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+@DisplayName("로또 개수 테스트")
+class LottoCountTest {
+
+    @Nested
+    @DisplayName("로또 개수 생성 테스트")
+    class LottoCountCreationTest {
+
+        @Test
+        @DisplayName("로또 개수를 입력하면 로또 개수를 생성한다")
+        public void createLottoCountWhenInputCount() {
+
+            assertThatCode(() -> new LottoCount(10))
+                    .doesNotThrowAnyException();
+        }
+
+        @Test
+        @DisplayName("로또 개수가 음수일 경우 예외가 발생한다")
+        public void createLottoCountFailWhenCountIsLessThanZero() {
+
+            assertThatThrownBy(() -> new LottoCount(-1))
+                    .isExactlyInstanceOf(IllegalArgumentException.class)
+                    .hasMessage("로또 개수는 0개 이상이어야 합니다.");
+        }
+    }
+
+    @Nested
+    @DisplayName("수동 로또 개수 검증 테스트")
+    class ManualLottoCountValidationTest {
+
+        @Test
+        @DisplayName("수동으로 구매할 로또 수가 전체 로또 수를 초과하지 않으면 성공한다")
+        public void validateManualLottoCountSuccessWhenManualLottoCountIsNotGreaterThanTotalLottoCount() {
+
+            LottoCount manualLottoCount = new LottoCount(10);
+            LottoCount totalLottoCount = new LottoCount(15);
+
+            assertThatCode(() -> manualLottoCount.validateManualLottoCount(totalLottoCount))
+                    .doesNotThrowAnyException();
+        }
+
+        @Test
+        @DisplayName("수동으로 구매할 로또 수가 전체 로또 수를 초과하면 예외가 발생한다")
+        public void validateManualLottoCountFailWhenManualLottoCountIsGreaterThanTotalLottoCount() {
+
+            LottoCount manualLottoCount = new LottoCount(20);
+            LottoCount totalLottoCount = new LottoCount(15);
+
+            assertThatThrownBy(() -> manualLottoCount.validateManualLottoCount(totalLottoCount))
+                    .isExactlyInstanceOf(IllegalArgumentException.class)
+                    .hasMessage("수동으로 구매할 로또 수가 전체 로또 수를 초과합니다.\n");
+        }
+    }
+
+    @Nested
+    @DisplayName("로또 개수 계산 테스트")
+    class LottoCountCalculateTest {
+
+        @Test
+        @DisplayName("로또 개수를 뺀다")
+        public void subtractLottoCount() {
+
+            LottoCount lottoCount = new LottoCount(10);
+
+            LottoCount result = lottoCount.subtract(new LottoCount(5));
+
+            assertThat(result).isEqualTo(new LottoCount(5));
+        }
+    }
+}
diff --git a/src/test/java/org/duckstudy/model/lotto/LottoNumberTest.java b/src/test/java/org/duckstudy/domain/lotto/LottoNumberTest.java
similarity index 97%
rename from src/test/java/org/duckstudy/model/lotto/LottoNumberTest.java
rename to src/test/java/org/duckstudy/domain/lotto/LottoNumberTest.java
index 88376eb6..311e24fd 100644
--- a/src/test/java/org/duckstudy/model/lotto/LottoNumberTest.java
+++ b/src/test/java/org/duckstudy/domain/lotto/LottoNumberTest.java
@@ -1,4 +1,4 @@
-package org.duckstudy.model.lotto;
+package org.duckstudy.domain.lotto;
 
 import static org.assertj.core.api.Assertions.assertThatCode;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
diff --git a/src/test/java/org/duckstudy/model/lotto/LottoResultTest.java b/src/test/java/org/duckstudy/domain/lotto/LottoResultTest.java
similarity index 51%
rename from src/test/java/org/duckstudy/model/lotto/LottoResultTest.java
rename to src/test/java/org/duckstudy/domain/lotto/LottoResultTest.java
index 12624b4b..1be0dbcb 100644
--- a/src/test/java/org/duckstudy/model/lotto/LottoResultTest.java
+++ b/src/test/java/org/duckstudy/domain/lotto/LottoResultTest.java
@@ -1,10 +1,10 @@
-package org.duckstudy.model.lotto;
+package org.duckstudy.domain.lotto;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
-import java.util.List;
 import java.util.Map;
-import org.duckstudy.model.lotto.constant.WinningRank;
+import java.util.Set;
+import org.duckstudy.domain.lotto.constant.WinningRank;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Test;
 
@@ -12,29 +12,29 @@
 class LottoResultTest {
 
     @Test
-    @DisplayName("로또 결과를 생성한다")
+    @DisplayName("로또 당첨 결과를 생성한다")
     void createLottoResult() {
 
-        Lotto lotto = Lotto.from(List.of(1, 2, 3, 4, 5, 7));
-        Lotto winningLotto = Lotto.from(List.of(1, 2, 3, 4, 5, 6));
+        Lotto lotto = Lotto.from(Set.of(1, 2, 3, 4, 5, 7));
+        Lotto winningLotto = Lotto.from(Set.of(1, 2, 3, 4, 5, 6));
         LottoNumber bonusNumber = LottoNumber.valueOf(7);
 
         LottoResult lottoResult = LottoResult.createLottoResult(lotto, winningLotto, bonusNumber);
 
         assertThat(lottoResult.getResult())
-                .containsEntry(WinningRank.SECOND.getKey(), 1);
+                .containsEntry(WinningRank.SECOND, 1);
     }
 
     @Test
-    @DisplayName("로또 결과를 병합한다")
+    @DisplayName("로또 당첨 결과를 병합한다")
     void mergeLottoResult() {
 
-        LottoResult lottoResult1 = new LottoResult(Map.of(3, 2));
-        LottoResult lottoResult2 = new LottoResult(Map.of(3, 1));
+        LottoResult lottoResult1 = new LottoResult(Map.of(WinningRank.FIFTH, 2));
+        LottoResult lottoResult2 = new LottoResult(Map.of(WinningRank.FIFTH, 1));
 
         LottoResult mergedLottoResult = lottoResult1.merge(lottoResult2);
 
         assertThat(mergedLottoResult.getResult())
-                .containsEntry(3, 3);
+                .containsEntry(WinningRank.FIFTH, 3);
     }
 }
diff --git a/src/test/java/org/duckstudy/model/lotto/LottoTest.java b/src/test/java/org/duckstudy/domain/lotto/LottoTest.java
similarity index 71%
rename from src/test/java/org/duckstudy/model/lotto/LottoTest.java
rename to src/test/java/org/duckstudy/domain/lotto/LottoTest.java
index ee561748..9c5c69ef 100644
--- a/src/test/java/org/duckstudy/model/lotto/LottoTest.java
+++ b/src/test/java/org/duckstudy/domain/lotto/LottoTest.java
@@ -1,10 +1,11 @@
-package org.duckstudy.model.lotto;
+package org.duckstudy.domain.lotto;
 
+import static java.util.stream.Collectors.toSet;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatCode;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
-import java.util.List;
+import java.util.Set;
 import java.util.stream.Stream;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
@@ -25,9 +26,9 @@ class LottoCreationFromLottoNumberTest {
             @DisplayName("로또를 생성한다")
             void createLottoSuccess() {
 
-                List lottoNumbers = Stream.of(1, 2, 3, 4, 5, 6)
+                Set lottoNumbers = Stream.of(1, 2, 3, 4, 5, 6)
                         .map(LottoNumber::valueOf)
-                        .toList();
+                        .collect(toSet());
 
                 assertThatCode(() -> new Lotto(lottoNumbers))
                         .doesNotThrowAnyException();
@@ -37,26 +38,26 @@ void createLottoSuccess() {
             @DisplayName("로또를 생성할 때 6개의 로또 번호가 아니면 예외를 발생한다")
             void createLottoFailWhenSizeIsNotSix() {
 
-                List lottoNumbers = List.of(
+                Set lottoNumbers = Set.of(
                         LottoNumber.valueOf(1)
                 );
 
                 assertThatThrownBy(() -> new Lotto(lottoNumbers))
                         .isInstanceOf(IllegalArgumentException.class)
-                        .hasMessage("로또 번호는 6개여야 합니다.");
+                        .hasMessage("로또 번호는 중복되지 않은 6개여야 합니다.\n");
             }
 
             @Test
             @DisplayName("로또를 생성할 때 중복된 로또 번호가 있으면 예외를 발생한다")
             void createLottoFailWhenDuplicateNumberExists() {
 
-                List lottoNumbers = Stream.of(1, 1, 2, 3, 4, 5)
+                Set lottoNumbers = Stream.of(1, 1, 2, 3, 4, 5)
                         .map(LottoNumber::valueOf)
-                        .toList();
+                        .collect(toSet());
 
                 assertThatThrownBy(() -> new Lotto(lottoNumbers))
                         .isInstanceOf(IllegalArgumentException.class)
-                        .hasMessage("로또 번호는 중복되지 않아야 합니다.");
+                        .hasMessage("로또 번호는 중복되지 않은 6개여야 합니다.\n");
             }
         }
 
@@ -68,26 +69,17 @@ class LottoCreationFromIntegerTest {
             @DisplayName("로또를 생성한다")
             void createLottoSuccess() {
 
-                assertThatCode(() -> Lotto.from(List.of(1, 2, 3, 4, 5, 6)))
+                assertThatCode(() -> Lotto.from(Set.of(1, 2, 3, 4, 5, 6)))
                         .doesNotThrowAnyException();
             }
 
             @Test
-            @DisplayName("로또를 생성할 때 6개의 로또 번호가 아니면 예외를 발생한다")
+            @DisplayName("로또를 생성할 때 중복되지 않은 6개의 로또 번호가 아니면 예외를 발생한다")
             void createLottoFailWhenSizeIsNotSix() {
 
-                assertThatThrownBy(() -> Lotto.from(List.of(1)))
-                        .isInstanceOf(IllegalArgumentException.class)
-                        .hasMessage("로또 번호는 6개여야 합니다.");
-            }
-
-            @Test
-            @DisplayName("로또를 생성할 때 중복된 로또 번호가 있으면 예외를 발생한다")
-            void createLottoFailWhenDuplicateNumberExists() {
-
-                assertThatThrownBy(() -> Lotto.from(List.of(1, 1, 3, 4, 5, 6)))
+                assertThatThrownBy(() -> Lotto.from(Set.of(1)))
                         .isInstanceOf(IllegalArgumentException.class)
-                        .hasMessage("로또 번호는 중복되지 않아야 합니다.");
+                        .hasMessage("로또 번호는 중복되지 않은 6개여야 합니다.\n");
             }
         }
 
@@ -113,8 +105,8 @@ class LottoComparisonTest {
         @DisplayName("일치하는 로또 번호의 개수를 반환한다")
         void countMatchingNumber() {
 
-            Lotto lotto = Lotto.from(List.of(1, 2, 3, 4, 5, 6));
-            Lotto compareLotto = Lotto.from(List.of(1, 2, 3, 7, 8, 9));
+            Lotto lotto = Lotto.from(Set.of(1, 2, 3, 4, 5, 6));
+            Lotto compareLotto = Lotto.from(Set.of(1, 2, 3, 7, 8, 9));
 
             assertThat(lotto.countMatchingNumber(compareLotto)).isEqualTo(3);
         }
@@ -128,7 +120,7 @@ class LottoContainsTest {
         @DisplayName("로또 번호가 포함되어 있는지 확인한다")
         void containsNumber() {
 
-            Lotto lotto = Lotto.from(List.of(1, 2, 3, 4, 5, 6));
+            Lotto lotto = Lotto.from(Set.of(1, 2, 3, 4, 5, 6));
             LottoNumber lottoNumber = LottoNumber.valueOf(3);
 
             assertThat(lotto.containsNumber(lottoNumber)).isTrue();
diff --git a/src/test/java/org/duckstudy/domain/lotto/LottosTest.java b/src/test/java/org/duckstudy/domain/lotto/LottosTest.java
new file mode 100644
index 00000000..f5681802
--- /dev/null
+++ b/src/test/java/org/duckstudy/domain/lotto/LottosTest.java
@@ -0,0 +1,87 @@
+package org.duckstudy.domain.lotto;
+
+import static java.util.Map.entry;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.duckstudy.domain.lotto.constant.WinningRank.FIRST;
+import static org.duckstudy.domain.lotto.constant.WinningRank.NONE;
+import static org.duckstudy.domain.lotto.constant.WinningRank.SECOND;
+
+import java.util.List;
+import java.util.Set;
+import org.duckstudy.domain.Price;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+@DisplayName("로또 테스트")
+class LottosTest {
+
+    @Nested
+    @DisplayName("로또 묶음 생성 테스트")
+    class LottosCreationTest {
+
+        @Test
+        @DisplayName("구매 개수를 입력하면 가격에 맞는 로또 묶음을 생성한다")
+        void createLottosWhenInputPrice() {
+
+            Price purchasePrice = new Price(10000);
+            int lottoCount = purchasePrice.calculateLottoCount()
+                    .getCount();
+
+            Lottos lottos = Lottos.generateLottos(lottoCount);
+
+            assertThat(lottos.getLottos()).hasSize(10);
+        }
+    }
+
+    @Nested
+    @DisplayName("로또 당첨 결과 테스트")
+    class LottosWinningTest {
+
+        @Test
+        @DisplayName("당첨된 로또 번호와 보너스 번호를 입력하면 당첨된 로또 묶음의 결과를 계산한다")
+        void calculateWinningResultWhenInputWinningLotto() {
+
+            Lotto winningLotto = Lotto.from(Set.of(1, 2, 3, 4, 5, 6));
+            LottoNumber bonusNumber = LottoNumber.valueOf(7);
+            Lottos totalLottos = new Lottos(List.of(
+                    winningLotto,
+                    Lotto.from(Set.of(1, 2, 3, 4, 5, 7)),
+                    Lotto.from(Set.of(8, 9, 10, 11, 12, 13)),
+                    Lotto.from(Set.of(14, 15, 16, 17, 18, 19)),
+                    Lotto.from(Set.of(20, 21, 22, 23, 24, 25))
+            ));
+
+            LottoResult lottoResult = totalLottos.accumulateLottoResult(winningLotto, bonusNumber);
+
+            assertThat(lottoResult.getResult())
+                    .containsExactly(
+                            entry(NONE, 3),
+                            entry(SECOND, 1),
+                            entry(FIRST, 1)
+                    );
+        }
+    }
+
+    @Nested
+    @DisplayName("로또 묶음 병합 테스트")
+    class LottosMergeTest {
+
+        @Test
+        @DisplayName("로또 묶음을 병합하면 하나의 로또 묶음으로 생성한다")
+        void mergeLottos() {
+
+            Lottos lottos1 = new Lottos(List.of(
+                    Lotto.from(Set.of(1, 2, 3, 4, 5, 6))
+            ));
+
+            Lottos lottos2 = new Lottos(List.of(
+                    Lotto.from(Set.of(7, 8, 9, 10, 11, 12))
+            ));
+
+            Lottos mergedLottos = lottos1.merge(lottos2);
+
+            assertThat(mergedLottos.getLottos()).hasSize(2);
+        }
+    }
+}
diff --git a/src/test/java/org/duckstudy/domain/lotto/constant/WinningRankTest.java b/src/test/java/org/duckstudy/domain/lotto/constant/WinningRankTest.java
new file mode 100644
index 00000000..c14997d4
--- /dev/null
+++ b/src/test/java/org/duckstudy/domain/lotto/constant/WinningRankTest.java
@@ -0,0 +1,33 @@
+package org.duckstudy.domain.lotto.constant;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.stream.Stream;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+@DisplayName("당첨 순위 테스트")
+class WinningRankTest {
+
+    @DisplayName("당첨 횟수와 보너스 볼 여부를 입력하면 당첨 순위를 반환한다")
+    @ParameterizedTest
+    @MethodSource("generateMatchCountAndMatchBonus")
+    void findWinningRankSuccess(int matchCount, boolean matchBonus,
+                                WinningRank expected) {
+        assertThat(WinningRank.findByMatchCountAndBonus(matchCount, matchBonus))
+                .isEqualTo(expected);
+    }
+
+    static Stream generateMatchCountAndMatchBonus() {
+        return Stream.of(
+                Arguments.of(0, false, WinningRank.NONE),
+                Arguments.of(3, false, WinningRank.FIFTH),
+                Arguments.of(4, false, WinningRank.FOURTH),
+                Arguments.of(5, false, WinningRank.THIRD),
+                Arguments.of(5, true, WinningRank.SECOND),
+                Arguments.of(6, false, WinningRank.FIRST)
+        );
+    }
+}
diff --git a/src/test/java/org/duckstudy/model/lotto/LottosTest.java b/src/test/java/org/duckstudy/model/lotto/LottosTest.java
deleted file mode 100644
index d71b4715..00000000
--- a/src/test/java/org/duckstudy/model/lotto/LottosTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package org.duckstudy.model.lotto;
-
-import static java.util.Map.entry;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.duckstudy.model.lotto.constant.WinningRank.FIRST;
-import static org.duckstudy.model.lotto.constant.WinningRank.NONE;
-import static org.duckstudy.model.lotto.constant.WinningRank.SECOND;
-
-import java.util.List;
-import org.duckstudy.model.Price;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-
-@DisplayName("로또 테스트")
-class LottosTest {
-
-    @Nested
-    @DisplayName("로또 묶음 생성 테스트")
-    class LottosCreationTest {
-
-        @Test
-        @DisplayName("구매 가격을 입력하면 가격에 맞는 로또 묶음을 생성한다")
-        void createLottosWhenInputPrice() {
-
-            Price purchasePrice = new Price(10000);
-
-            Lottos lottos = Lottos.generateLottosByPrice(purchasePrice);
-
-            assertThat(lottos.getLottos()).hasSize(10);
-        }
-    }
-
-    @Nested
-    @DisplayName("로또 당첨 결과 테스트")
-    class LottosWinningTest {
-
-        @Test
-        @DisplayName("당첨된 로또 번호와 보너스 번호를 입력하면 당첨된 로또 묶음의 결과를 계산한다")
-        void calculateWinningResultWhenInputWinningLotto() {
-
-            Lotto winningLotto = Lotto.from(List.of(1, 2, 3, 4, 5, 6));
-            LottoNumber bonusNumber = LottoNumber.valueOf(7);
-            Lottos totalLottos = new Lottos(List.of(
-                    winningLotto,
-                    Lotto.from(List.of(1, 2, 3, 4, 5, 7)),
-                    Lotto.from(List.of(8, 9, 10, 11, 12, 13)),
-                    Lotto.from(List.of(14, 15, 16, 17, 18, 19)),
-                    Lotto.from(List.of(20, 21, 22, 23, 24, 25))
-            ));
-
-            LottoResult lottoResult = totalLottos.accumulateLottoResult(winningLotto, bonusNumber);
-
-            assertThat(lottoResult.getResult())
-                    .containsExactly(
-                            entry(NONE.getKey(), 3),
-                            entry(SECOND.getKey(), 1),
-                            entry(FIRST.getKey(), 1)
-                    );
-        }
-    }
-}