ewhk9887/korean_code_reviews_from_github huggingface dataset:
@@ -0,0 +1,35 @@
+package christmas.domain;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Stream;
+
+public enum Menu {
+
+    APPETIZER(List.of("양송이수프", "타파스", "시저샐러드"), List.of(6000, 5500, 8000)),
+    MAIN(List.of("티본스테이크", "바비큐립", "해산물파스타", "크리스마스파스타"), List.of(55000, 54000, 35000, 25000)),
+    DESSERT(List.of("초코케이크", "아이스크림"), List.of(15000, 5000)),
+    BEVERAGE(List.of("제로콜라", "레드와인", "샴페인"), List.of(3000, 60000, 25000));
+
+    private static final List<String> ALL_MENU = Stream.of(APPETIZER.menuName, MAIN.menuName,
+            DESSERT.menuName, BEVERAGE.menuName).flatMap(Collection::stream).toList();
+    private final List<String> menuName;
+    private final List<Integer> menuPrice;
+
+    Menu(List<String> menuName, List<Integer> menuPrice) {
+        this.menuName = menuName;
+        this.menuPrice = menuPrice;
+    }
+
+    public List<String> getMenuName() {
+        return menuName;
+    }
+
+    public List<Integer> getMenuPrice() {
+        return menuPrice;
+    }
+
+    public static boolean isExistMenu(String menu) {
+        return ALL_MENU.contains(menu);
+    }
+}

리뷰: 카테고리 안에 리스트를 가져가셨군요! 이부분에 대해서 함께 말씀 나눠보면 좋을거 같습니다
@@ -0,0 +1,25 @@
+package christmas.domain.event.badge;
+
+public class BenefitAmountEvent {
+
+    private static final String STAR_BADGE = "별";
+    private static final String TREE_BADGE = "트리";
+    private static final String SANTA_BADGE = "산타";
+    private static final String NONE = "없음";
+    private static final int STAR_STANDARD_AMOUNT = 5000;
+    private static final int TREE_STANDARD_AMOUNT = 10000;
+    private static final int SANTA_STANDARD_AMOUNT = 20000;
+
+    public String giveBadge(int benefitAmount) {
+        if (benefitAmount < STAR_STANDARD_AMOUNT) {
+            return NONE;
+        }
+        if (benefitAmount < TREE_STANDARD_AMOUNT) {
+            return STAR_BADGE;
+        }
+        if (benefitAmount < SANTA_STANDARD_AMOUNT) {
+            return TREE_BADGE;
+        }
+        return SANTA_BADGE;
+    }
+}

리뷰: 이부분 enum으로 가져가시는거에 대해서 어떻게 생각하시나요~?
@@ -0,0 +1,25 @@
+package christmas.domain.event.badge;
+
+public class BenefitAmountEvent {
+
+    private static final String STAR_BADGE = "별";
+    private static final String TREE_BADGE = "트리";
+    private static final String SANTA_BADGE = "산타";
+    private static final String NONE = "없음";
+    private static final int STAR_STANDARD_AMOUNT = 5000;
+    private static final int TREE_STANDARD_AMOUNT = 10000;
+    private static final int SANTA_STANDARD_AMOUNT = 20000;
+
+    public String giveBadge(int benefitAmount) {
+        if (benefitAmount < STAR_STANDARD_AMOUNT) {
+            return NONE;
+        }
+        if (benefitAmount < TREE_STANDARD_AMOUNT) {
+            return STAR_BADGE;
+        }
+        if (benefitAmount < SANTA_STANDARD_AMOUNT) {
+            return TREE_BADGE;
+        }
+        return SANTA_BADGE;
+    }
+}

리뷰: 아 저는 이부분의 조건을 복잡하게 가져갔었는데 지금 보니 그럴필요가 없었네요... 배워갑니다!
@@ -0,0 +1,7 @@
+package christmas.util;
+
+public class Constant {
+
+    public static final String DELIMITER_COMMA = ",";
+    public static final String DELIMITER_HYPHEN = "-";
+}

리뷰: 해당 상수를 사용하시는 클래스에서 선언해주셔도 괜찮을거 같습니다!
@@ -0,0 +1,21 @@
+package christmas.util.validator;
+
+import java.util.regex.Pattern;
+
+public abstract class Validator {
+
+    protected abstract void validate(String input);
+
+    public void validateInputPattern(String input, String regex, String error) {
+        Pattern pattern = Pattern.compile(regex);
+        if (!pattern.matcher(input).matches()) {
+            throw new IllegalArgumentException(error);
+        }
+    }
+
+    public void validateNumberRange(int number, int minNumber, int maxNumber, String error) {
+        if (number < minNumber || number > maxNumber) {
+            throw new IllegalArgumentException(error);
+        }
+    }
+}

리뷰: 추상클래스를 사용하신거 좋네요!!
@@ -0,0 +1,52 @@
+package christmas.view;
+
+import static christmas.util.Constant.*;
+
+import camp.nextstep.edu.missionutils.Console;
+import christmas.util.validator.DateValidator;
+import christmas.util.validator.MenuValidator;
+import java.util.HashMap;
+import java.util.Map;
+
+public class InputView {
+
+    public int readDate() {
+        DateValidator validator = DateValidator.getValidator();
+        while (true) {
+            try {
+                String inputDate = input();
+                validator.validate(inputDate);
+                return Integer.parseInt(inputDate);
+            } catch (IllegalArgumentException error) {
+                System.out.println(error.getMessage());
+            }
+        }
+    }
+
+    public Map<String, Integer> readMenu() {
+        MenuValidator validator = MenuValidator.getValidator();
+        while (true) {
+            try {
+                String inputOrder = input();
+                validator.validate(inputOrder);
+                return getOrder(inputOrder);
+            } catch (IllegalArgumentException error) {
+                System.out.println(error.getMessage());
+            }
+        }
+    }
+
+    private Map<String, Integer> getOrder(String inputOrder) {
+        Map<String, Integer> order = new HashMap<>();
+        String[] menus = inputOrder.split(DELIMITER_COMMA);
+        for (String menu : menus) {
+            String[] menuInfo = menu.split(DELIMITER_HYPHEN);
+            order.put(menuInfo[0], Integer.parseInt(menuInfo[1]));
+        }
+        return order;
+    }
+
+    private String input() {
+        return Console.readLine();
+    }
+}

리뷰: 제가 컨트롤러에서 예외처리를 한 이유는 예를 들어 날짜를 검증할때 InputView에서는 문자값이 포함 되었는지에 대한 검증을, 도메인에서는 1~31 사이의 숫자인지 확인을 해야했기 때문이었습니다! 치우님처럼 도메인쪽에서 검증이 필요하지 않다면 View에서 예외처리를 하는 것도 괜찮은 방법인거 같습니다!
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8" />
+    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
+    <meta name="viewport" content="width=device-width, initial-scale=1" />
+    <meta name="theme-color" content="#000000" />
+    <meta
+      name="description"
+      content="Web site created using create-react-app"
+    />
+    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
+    <!--
+      manifest.json provides metadata used when your web app is installed on a
+      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
+    -->
+    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
+    <!--
+      Notice the use of %PUBLIC_URL% in the tags above.
+      It will be replaced with the URL of the `public` folder during the build.
+      Only files inside the `public` folder can be referenced from the HTML.
+
+      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
+      work correctly both with client-side routing and a non-root public URL.
+      Learn how to configure a non-root public URL by running `npm run build`.
+    -->
+    <title>React App</title>
+  </head>
+  <body>
+    <noscript>You need to enable JavaScript to run this app.</noscript>
+    <div id="root"></div>
+    <!--
+      This HTML file is a template.
+      If you open it directly in the browser, you will see an empty page.
+
+      You can add webfonts, meta tags, or analytics to this file.
+      The build step will place the bundled scripts into the <body> tag.
+
+      To begin the development, run `npm start` or `yarn start`.
+      To create a production bundle, use `npm run build` or `yarn build`.
+    -->
+  </body>
+</html>

리뷰: 아이콘이 포함된 태그는 투두앱과 큰 상관이 없다고생각하는데, 제거해도 좋지않을까 싶습니다!
@@ -0,0 +1,34 @@
+import { Navigate, createBrowserRouter } from "react-router-dom";
+import App from "./App";
+import SignIn from "./Page/Auth/SignIn";
+import SignUp from "./Page/Auth/SignUp";
+import ToDoList from "./Page/ToDos/ToDoList";
+
+const routes = [
+    {
+        path: "",
+        element: <App />,
+        children: [
+            {
+                path: "/",
+                element: <Navigate to="/signin" />,
+            },
+            {
+                path: "/signin",
+                element: <SignIn />,
+            },
+            {
+                path: "/signup",
+                element: <SignUp />,
+            },
+            {
+                path: "/todo",
+                element: <ToDoList />,
+            },
+        ],
+    },
+];
+
+const router = createBrowserRouter(routes);
+
+export default router;

리뷰: 오 라우터를 중첩해서 작성할수도 있군요..!
@@ -0,0 +1,34 @@
+import { Navigate, createBrowserRouter } from "react-router-dom";
+import App from "./App";
+import SignIn from "./Page/Auth/SignIn";
+import SignUp from "./Page/Auth/SignUp";
+import ToDoList from "./Page/ToDos/ToDoList";
+
+const routes = [
+    {
+        path: "",
+        element: <App />,
+        children: [
+            {
+                path: "/",
+                element: <Navigate to="/signin" />,
+            },
+            {
+                path: "/signin",
+                element: <SignIn />,
+            },
+            {
+                path: "/signup",
+                element: <SignUp />,
+            },
+            {
+                path: "/todo",
+                element: <ToDoList />,
+            },
+        ],
+    },
+];
+
+const router = createBrowserRouter(routes);
+
+export default router;

리뷰: errorBoundary나 errorElement를 사용해보는 것이 어떨까요?
잘못된 url로 접근시 현재는 앱이 망가지는 상황인데 최소한의 안전장치가 Route단에 있으면 좋을 것 같습니다 👍
@@ -0,0 +1,94 @@
+import axios from "axios";
+
+const baseURL = "https://www.pre-onboarding-selection-task.shop";
+
+export const signUp = async (data) => {
+    try {
+        const response = await axios.post(
+            `${baseURL}/auth/signup`,
+            { email: data.email, password: data.password },
+            {
+                headers: { "Content-Type": "application/json" },
+            }
+        );
+        return response.status;
+    } catch (e) {
+        console.log(e.response.message);
+    }
+};
+
+export const signin = async (data) => {
+    try {
+        const response = await axios.post(
+            `${baseURL}/auth/signin`,
+            { email: data.email, password: data.password },
+            {
+                headers: { "Content-Type": "application/json" },
+            }
+        );
+        if (response.status === 200) {
+            const { access_token } = response.data;
+            localStorage.setItem("token", access_token);
+            return access_token;
+        }
+    } catch (e) {
+        return e;
+    }
+};
+
+export const createTodo = async (todo) => {
+    const data = { todo };
+    try {
+        const response = await axios.post(`${baseURL}/todos`, data, {
+            headers: {
+                "Content-Type": "application/json",
+                Authorization: `Bearer ${localStorage.getItem("token")}`,
+            },
+        });
+        return response.data;
+    } catch (error) {
+        console.log(error);
+    }
+};
+
+export const getTodos = async () => {
+    try {
+        const response = await axios.get(`${baseURL}/todos`, {
+            headers: {
+                "Content-Type": "application/json",
+                Authorization: `Bearer ${localStorage.getItem("token")}`,
+            },
+        });
+        return response.data;
+    } catch (e) {
+        console.log(e);
+    }
+};
+
+export const deleteTodo = async (id) => {
+    try {
+        const response = await axios.delete(`${baseURL}/todos/${id}`, {
+            headers: {
+                Authorization: `Bearer ${localStorage.getItem("token")}`,
+            },
+        });
+        return response.status;
+    } catch (e) {
+        console.log(e);
+    }
+};
+
+export const updateTodo = async (data, id) => {
+    console.log(data);
+    try {
+        const response = await axios.put(`${baseURL}/todos/${id}`, data, {
+            headers: {
+                "Content-Type": "application/json",
+                Authorization: `Bearer ${localStorage.getItem("token")}`,
+            },
+        });
+        return response.data;
+    } catch (e) {
+        console.log(e);
+    }
+};

리뷰: 반복되는 baseUrl과 header는 axios instance와 axios interceptor로 줄일 수 있을것 같아요!
@@ -0,0 +1,66 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import {
+  RouterProvider,
+  createBrowserRouter,
+  redirect,
+} from 'react-router-dom';
+import Signin from './pages/Signin';
+import Signup from './pages/Signup';
+import { GlobalStyle } from './styles/GlobalStyle';
+import Todo from './pages/Todo';
+
+const redirectToSignIn = () => redirect('/signin');
+
+const privateMiddleware = () => {
+  const jwt = localStorage.getItem('access_token');
+
+  if (jwt) {
+    return true;
+  }
+
+  return redirect('/signin');
+};
+
+const publicMiddleware = () => {
+  const jwt = localStorage.getItem('access_token');
+
+  if (jwt) {
+    return redirect('/todo');
+  }
+
+  return true;
+};
+
+const router = createBrowserRouter([
+  {
+    path: '/todo',
+    element: <Todo />,
+    loader: privateMiddleware,
+  },
+  {
+    path: '/signin',
+    element: <Signin />,
+    loader: publicMiddleware,
+  },
+  {
+    path: '/signup',
+    element: <Signup />,
+    loader: publicMiddleware,
+  },
+  {
+    path: '*',
+    loader: redirectToSignIn,
+  },
+]);
+
+const root = ReactDOM.createRoot(
+  document.getElementById('root') as HTMLElement,
+);
+
+root.render(
+  <React.StrictMode>
+    <GlobalStyle />
+    <RouterProvider router={router} />
+  </React.StrictMode>,
+);

리뷰: useEffect가 아닌 router에서 rediret 처리하신 것 너무 좋은 것 같습니다! 🎉
@@ -8,14 +8,16 @@
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
+import javax.persistence.Table;
 import lombok.Builder;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
 
 @Entity
+@Table(name = "used_restroom")
 @Getter
 @NoArgsConstructor
-public class UsedRestroom {
+public class UsedRestroom extends BaseEntity {
 
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
@@ -28,9 +30,29 @@ public class UsedRestroom {
   @Column(name = "restroom_id")
   private Long restroomId;
 
+  @Column(name = "is_reviewed")
+  private boolean isReviewed;
+
+  @Column(name = "review_id")
+  private Long reviewId;
+
   @Builder
   public UsedRestroom(User user, long restroomId) {
     this.user = user;
     this.restroomId = restroomId;
+    this.isReviewed = false;
+    this.reviewId = (long) -1;
+  }
+
+  // 리뷰 등록 후 isReview true + reviewId 등록
+  public void EnrollReview(Long reviewId) {
+    this.reviewId = reviewId;
+    this.isReviewed = true;
+  }
+
+  // 리뷰 삭제 후 isReview false + reviewId 삭제
+  public void DeleteReview() {
+    this.reviewId = (long) -1;
+    this.isReviewed = false;
   }
 }
\ No newline at end of file

리뷰: isReviewed 부분 기본값을 false로 둬야하니까 그냥 파라미터로 안받고 false로 할라했는데 혹시 형 코드에서 이 Builder 사용하는 부분 있어??
@@ -8,14 +8,16 @@
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
+import javax.persistence.Table;
 import lombok.Builder;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
 
 @Entity
+@Table(name = "used_restroom")
 @Getter
 @NoArgsConstructor
-public class UsedRestroom {
+public class UsedRestroom extends BaseEntity {
 
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
@@ -28,9 +30,29 @@ public class UsedRestroom {
   @Column(name = "restroom_id")
   private Long restroomId;
 
+  @Column(name = "is_reviewed")
+  private boolean isReviewed;
+
+  @Column(name = "review_id")
+  private Long reviewId;
+
   @Builder
   public UsedRestroom(User user, long restroomId) {
     this.user = user;
     this.restroomId = restroomId;
+    this.isReviewed = false;
+    this.reviewId = (long) -1;
+  }
+
+  // 리뷰 등록 후 isReview true + reviewId 등록
+  public void EnrollReview(Long reviewId) {
+    this.reviewId = reviewId;
+    this.isReviewed = true;
+  }
+
+  // 리뷰 삭제 후 isReview false + reviewId 삭제
+  public void DeleteReview() {
+    this.reviewId = (long) -1;
+    this.isReviewed = false;
   }
 }
\ No newline at end of file

리뷰: 사용하는 부분 없어서 false로 받도록 수정했어
@@ -0,0 +1,29 @@
+# This file configures the analyzer, which statically analyzes Dart code to
+# check for errors, warnings, and lints.
+#
+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
+# invoked from the command line by running `flutter analyze`.
+
+# The following line activates a set of recommended lints for Flutter apps,
+# packages, and plugins designed to encourage good coding practices.
+include: package:flutter_lints/flutter.yaml
+
+linter:
+  # The lint rules applied to this project can be customized in the
+  # section below to disable rules from the `package:flutter_lints/flutter.yaml`
+  # included above or to enable additional rules. A list of all available lints
+  # and their documentation is published at
+  # https://dart-lang.github.io/linter/lints/index.html.
+  #
+  # Instead of disabling a lint rule for the entire project in the
+  # section below, it can also be suppressed for a single line of code
+  # or a specific dart file by using the `// ignore: name_of_lint` and
+  # `// ignore_for_file: name_of_lint` syntax on the line or in the file
+  # producing the lint.
+  rules:
+    require_trailing_commas: true
+    # avoid_print: false  # Uncomment to disable the `avoid_print` rule
+    # prefer_single_quotes: true  # Uncomment to enable the `prefer_single_quotes` rule
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options

리뷰: 아래 내용을 추가 하신 뒤 project root 에서 `dart fix --apply` 를 수행하시면 대부분의 
 경우에 `,` 를 붙여서 좀 더 깔끔한 formatting 을 하실 수 있습니다. 
파일 저장할 때마다 자동으로 적용되는거라 한번 해두면 귀찮게 `,` 를 수동으로 안붙여도 편하게 사용하실 수 있어요. 리뷰를 할때도 위젯의 구분이 명확해서 훨씬 수월해지게 됩니다. 
```dart
// analysis_options.yaml
linter:
  rules:
    require_trailing_commas: true
```
@@ -13,7 +13,7 @@ private LottoTicket(final List<LottoNumber> numbers) {
         validateCountOfNumbers(numbers);
         validateDuplicateNumbers(numbers);
 
-        this.numbers = numbers;
+        this.numbers = numbers.stream().sorted().collect(Collectors.toList());
     }
 
     public static LottoTicket create() {
@@ -32,9 +32,7 @@ private static List<LottoNumber> generate() {
         List<LottoNumber> shuffledList = LottoNumber.all();
         Collections.shuffle(shuffledList);
 
-        return shuffledList.subList(0, 6).stream()
-                .sorted()
-                .collect(Collectors.toList());
+        return shuffledList.subList(0, 6).stream().collect(Collectors.toList());
     }
 
     private void validateCountOfNumbers(final List<LottoNumber> numbers) {
@@ -56,7 +54,7 @@ public int getTheNumberOfCommonNumbers(final LottoTicket winningTicket) {
     }
 
     public boolean hasNumber(final LottoNumber bonus) {
-        return numbers.stream().anyMatch(n -> n.equals(bonus));
+        return numbers.contains(bonus);
     }
 
     public List<LottoNumber> getNumbers() {

리뷰: 이번 수정 범위가 아니어서 코멘트를 남길 수 없어 여기에 대신 남깁니다.
`LottoTicket`의 23라인에 있는 정적 팩터리 메서드는 현재 생성자로 완전히 대체 가능해 보이는데 따로 존재하는 이유가 있을까요?
또한 31라인 `generate()` 메서드는 `LottoTicket`이 담당해야 하는 책임으로 적절한지도 고민해 보시면 좋을 것 같아요!
@@ -1,29 +1,40 @@
 package lotto;
 
-import lotto.domain.*;
+import lotto.domain.LottoGame;
+import lotto.domain.LottoPrize;
+import lotto.domain.LottoTicket;
+import lotto.domain.WinningLotto;
 import lotto.view.LottoInputView;
 import lotto.view.LottoResultView;
 
+import java.util.ArrayList;
 import java.util.List;
 
 public class LottoGameApplication {
 
     public static void main(String[] args) {
-        int moneyForTicket = LottoInputView.getMoneyForTicket();
-        List<LottoTicket> tickets = LottoGame.buy(moneyForTicket);
-
-        LottoResultView.printTickets(tickets);
-
-        if (tickets.isEmpty()) {
-            return;
+        try {
+            List<List<Integer>> numbersForManualTicket = new ArrayList<>();
+            int moneyForTicket = LottoInputView.getMoneyForTicket();
+            int numberOfManualTickets = LottoInputView.getNumberOfManualTicket();
+            if (numberOfManualTickets > 0) {
+                numbersForManualTicket = LottoInputView.getLottoTicketNumbers(numberOfManualTickets);
+            }
+            List<LottoTicket> tickets = LottoGame.buy(moneyForTicket, numbersForManualTicket);
+
+            LottoResultView.printTickets(tickets, numberOfManualTickets);
+
+            if (tickets.isEmpty()) {
+                return;
+            }
+
+            WinningLotto lastWeekWinningLotto = new WinningLotto(LottoInputView.getLastWeekWinnerNumber(), LottoInputView.getLastWeekBonusNumber());
+            List<LottoPrize> prizes = lastWeekWinningLotto.prizes(tickets);
+
+            LottoResultView.printResult(prizes, tickets.size());
+        } catch (Exception e) {
+            System.out.println(e.getMessage());
         }
 
-        LottoTicket lastWeekWinnerTicket = LottoTicket.createFromIntegerList(LottoInputView.getLastWeekWinnerNumber());
-        LottoNumber lastWeekBonusNumber = new LottoNumber(LottoInputView.getLastWeekBonusNumber());
-        WinningLotto lastWeekWinningLotto = new WinningLotto(lastWeekWinnerTicket, lastWeekBonusNumber);
-
-        List<LottoPrize> prizes = lastWeekWinningLotto.prizes(tickets);
-
-        LottoResultView.printResult(prizes, tickets.size());
     }
 }

리뷰: `numbersForManualTicket`이 이렇게 맨 위에 미리 선언되어야 할 필요가 있을까요?
@@ -1,29 +1,40 @@
 package lotto;
 
-import lotto.domain.*;
+import lotto.domain.LottoGame;
+import lotto.domain.LottoPrize;
+import lotto.domain.LottoTicket;
+import lotto.domain.WinningLotto;
 import lotto.view.LottoInputView;
 import lotto.view.LottoResultView;
 
+import java.util.ArrayList;
 import java.util.List;
 
 public class LottoGameApplication {
 
     public static void main(String[] args) {
-        int moneyForTicket = LottoInputView.getMoneyForTicket();
-        List<LottoTicket> tickets = LottoGame.buy(moneyForTicket);
-
-        LottoResultView.printTickets(tickets);
-
-        if (tickets.isEmpty()) {
-            return;
+        try {
+            List<List<Integer>> numbersForManualTicket = new ArrayList<>();
+            int moneyForTicket = LottoInputView.getMoneyForTicket();
+            int numberOfManualTickets = LottoInputView.getNumberOfManualTicket();
+            if (numberOfManualTickets > 0) {
+                numbersForManualTicket = LottoInputView.getLottoTicketNumbers(numberOfManualTickets);
+            }
+            List<LottoTicket> tickets = LottoGame.buy(moneyForTicket, numbersForManualTicket);
+
+            LottoResultView.printTickets(tickets, numberOfManualTickets);
+
+            if (tickets.isEmpty()) {
+                return;
+            }
+
+            WinningLotto lastWeekWinningLotto = new WinningLotto(LottoInputView.getLastWeekWinnerNumber(), LottoInputView.getLastWeekBonusNumber());
+            List<LottoPrize> prizes = lastWeekWinningLotto.prizes(tickets);
+
+            LottoResultView.printResult(prizes, tickets.size());
+        } catch (Exception e) {
+            System.out.println(e.getMessage());
         }
 
-        LottoTicket lastWeekWinnerTicket = LottoTicket.createFromIntegerList(LottoInputView.getLastWeekWinnerNumber());
-        LottoNumber lastWeekBonusNumber = new LottoNumber(LottoInputView.getLastWeekBonusNumber());
-        WinningLotto lastWeekWinningLotto = new WinningLotto(lastWeekWinnerTicket, lastWeekBonusNumber);
-
-        List<LottoPrize> prizes = lastWeekWinningLotto.prizes(tickets);
-
-        LottoResultView.printResult(prizes, tickets.size());
     }
 }

리뷰: <img width="648" alt="스크린샷 2022-11-16 오전 1 49 53" src="https://user-images.githubusercontent.com/18049492/201978579-7de023e7-aadc-418e-8102-b5c6e23888ae.png">

현재 메인 메서드의 길이가 너무 길어진 상황이네요. 쉽지 않은 일이지만, 전체적인 흐름을 파악하기 쉽도록 개선할 방법은 없을지 고민해 보셔도 좋을 것 같아요.