TIL

[250313 TIL] 키오스크 기능 추가 및 개선

도원좀비 2025. 3. 13. 19:52

🛠 ReturnToHomeException을 활용한 홈 이동 구현

🔥 기존 문제점

  • 홈 이동(-1)을 선택했을 때, 단순히 start();로 새로운 start메서드를 호출
  • 기존 메서드는 종료되지 않고 계속 남아있어서 메모리 낭비 및 무한 루프 위험

💡 해결 방법

  • 홈 이동을 예외 처리(ReturnToHomeException)를 이용하여 강제 실행 흐름 종료
  • start()에서 try-catch를 사용하여 예외가 발생하면 홈으로 이동하도록 설정.
더보기

ReturnToHomeException.java

// 홈 이동 예외 클래스 생성
public class ReturnToHomeException extends RuntimeException {
    public ReturnToHomeException() {
        super("홈으로 이동");
    }
}

 

Kiosk.java

    // 뒤로 가기 및 홈 이동 처리
    private boolean checkNavigationOption(int option) {
        if (option == OPTION_HOME) {
            System.out.println("홈으로 이동합니다.");
            throw new ReturnToHomeException();
        }
        if (option == OPTION_BACK) {
            System.out.println("이전 화면으로 이동합니다.");
            return true;
        }
        return false;  // 홈으로 가지 않음
    }

 

🚫잘못된 해결법(재귀함수 오버플로우 발생가능)

 // 키오스크 메인 실행 메서드
    public void start() {
        try {


            while (true) {
                displayMainMenu(); // 메인 메뉴 출력
                System.out.print("메뉴를 선택해주세요 : ");
                int option = getValidIntInput(); // 사용자 입력 받기

                switch (option) {
                    case 1 -> selectCategory();  // 카테고리 선택
                    case 2 -> viewCart();        // 장바구니 보기
                    case 3 -> checkout();        // 주문하기
                    case 4 -> orderHistory.displayOrdersList(); // 주문 내역 출력
                    case 0 -> {                  // 종료
                        System.out.println("프로그램을 종료합니다.");
                        return;
                    }
                    default -> System.out.println("잘못된 입력입니다. 다시 선택해주세요.");
                }
            }
        } catch (ReturnToHomeException e) {
            // 홈 이동 예외 발생 시 start() 실행을 강제 종료
            System.out.println("\n 홈 화면으로 돌아갑니다.\n");
            start(); // 다시 start() 실행
        }
    }

 

🎯옳은 해결 법 재귀함수 문제 해결(새로 호출하는게 아닌 기존 start메서드 활용)

// 키오스크 메인 실행 메서드
public void start() {

    while (true) {
        try {
            displayMainMenu(); // 메인 메뉴 출력
            System.out.print("메뉴를 선택해주세요 : ");
            int option = getValidIntInput(); // 사용자 입력 받기

            switch (option) {
                case 1 -> selectCategory();  // 카테고리 선택
                case 2 -> viewCart();        // 장바구니 보기
                case 3 -> checkout();        // 주문하기
                case 4 -> orderHistory.displayOrdersList(); // 주문 내역 출력
                case 0 -> {                  // 종료
                    System.out.println("프로그램을 종료합니다.");
                    return;
                }
                default -> System.out.println("잘못된 입력입니다. 다시 선택해주세요.");
            }
        } catch (ReturnToHomeException e) {
            System.out.println("\n 홈 화면으로 돌아갑니다.\n");
        }
    }
}

홈 이동이 필요할 때 예외를 발생시키면, 모든 실행 흐름이 종료된 후 start()가 다시 실행되어 홈 화면으로 이동
무한 루프 위험이 제거되어 기존의 방식보다 훨씬 안전하게 실행된다.


💰 결제(PaymentMethod) 시스템

➕ 추가 기능

  • 결제 방식 선택 기능 추가
  • 할인 적용 기능 개선 (applyDiscount())
더보기

PamentMethod.java

package kioskLv6;

public enum PaymentMethod {
    CARD("카드"),
    CASH("현금"),
    MOBILE("모바일 결제");

    private final String method;


    PaymentMethod(String method) {
        this.method = method;
    }

    public String getMethod() {
        return method;
    }

    public static void displayPaymentOption() {
        int i = 1;
        for (PaymentMethod method : PaymentMethod.values()) {
            System.out.printf("%d. %s\n", i++, method.getMethod());
        }
    }
}

 


📝 4. 주문(Order) 및 주문 내역(OrderHistory) 기능

➕ 추가 기능

  • 주문 후 자동으로 영수증 출력
  • 주문 내역 확인 기능 추가
더보기

Order.java

package kioskLv6;

import java.util.LinkedHashMap;
import java.util.Map;

public class Order {
    // 속성
    private static Integer ORDER_SEQUENCE = 1;
    private final Integer orderNumber;
    private final Map<MenuItem, Integer> items;
    private final Discount discount;
    private final PaymentMethod paymentMethod;
    private final Double totalPrice;

    // 생성자
    public Order(Map<MenuItem, Integer> items, Discount discount, PaymentMethod paymentMethod, Double totalPrice) {
        this.orderNumber = ORDER_SEQUENCE++;
        this.items = new LinkedHashMap<>(items);
        this.discount = discount;
        this.paymentMethod = paymentMethod;
        this.totalPrice = totalPrice;
    }

    // 기능
    // 영수증 출력
    public void printReceipt() {
        System.out.println("\n===== 영수증 =====");
        System.out.println("주문 번호: " + orderNumber);
        items.forEach((item, count) ->
                System.out.printf("%s | %d개 | W %d\n",
                        item.getName(), count, item.getPrice() * count));
        System.out.println("------------------");
        System.out.println("할인: " + discount.getDiscountCategory());
        System.out.println("결제 방법: " + paymentMethod.getMethod());
        System.out.println("총 결제 금액: W " + totalPrice);
        System.out.println("=================\n");
    }
}

 

OrderHistory.java

package kioskLv6;

import java.util.LinkedHashMap;
import java.util.Map;

public class Order {
    // 속성
    private static Integer ORDER_SEQUENCE = 1;
    private final Integer orderNumber;
    private final Map<MenuItem, Integer> items;
    private final Discount discount;
    private final PaymentMethod paymentMethod;
    private final Double totalPrice;

    // 생성자
    public Order(Map<MenuItem, Integer> items, Discount discount, PaymentMethod paymentMethod, Double totalPrice) {
        this.orderNumber = ORDER_SEQUENCE++;
        this.items = new LinkedHashMap<>(items);
        this.discount = discount;
        this.paymentMethod = paymentMethod;
        this.totalPrice = totalPrice;
    }

    // 기능
    // 영수증 출력
    public void printReceipt() {
        System.out.println("\n===== 영수증 =====");
        System.out.println("주문 번호: " + orderNumber);
        items.forEach((item, count) ->
                System.out.printf("%s | %d개 | W %d\n",
                        item.getName(), count, item.getPrice() * count));
        System.out.println("------------------");
        System.out.println("할인: " + discount.getDiscountCategory());
        System.out.println("결제 방법: " + paymentMethod.getMethod());
        System.out.println("총 결제 금액: W " + totalPrice);
        System.out.println("=================\n");
    }
}

주문이 완료되면 자동으로 영수증을 출력하도록 개선
주문 내역(OrderHistory)를 통해 지난 주문을 확인할 수 있도록 구현