키오스크 프로그램 구현

kkomin·2023년 7월 28일

Kotlin

목록 보기
7/7

1. 필요한 기능 💭

필요한 기능의 요구사항을 먼저 정리하자.

요구사항1 : 메인 메뉴판 화면

  • 메뉴 선택시 상세 메뉴화면으로 이동

  • 잘못된 번호 선택 시 예외처리

  • 프로그램 종료을 위한 번호 정의

요구사항2 : 메뉴 종류마다 나뉜 메뉴판 화면

  • 메뉴 종류 선택 시 메뉴 종류로 나뉜 화면으로 이동

  • 메뉴명 및 가격

  • 뒤로가기 번호 정의

  • 결재 선택 시 최종 결제

  • 선택하지 않은 상태로 결재 선택 시 예외처리

  • 선택 후 결제 취소 시 메인화면으로 이동

요구사항3 : 메뉴 선택

  • 메뉴 다중 선택 가능 (공백으로 구분)
  • 메뉴 선택 시 해당하는 메뉴의 정수형 이외의 값은 예외처리

요구사항4 : 결제

  • 가지고 있는 자산 입력
  • 자산 입력시 정수형 이외는 예외처리
  • 자산에 따라 선택한 메뉴 결제 성공 or 실패
  • 결제완료 전까지 3초의 시간 (3초 + 결제중 + 3초 + 결제 유무)

2. 메뉴 설정 🤤

키오스크 메뉴로는 근처에서 많이 볼 수 있는 카페 체인점인 투썸플레이스를 주제로 잡았다. 그렇지만 메뉴가 워낙 많아 간략히 줄였음.


3. 프로그램 구현

(1) 여러가지 메뉴 입력

여러가지 메뉴를 입력할 경우를 위해 메뉴 선택 후 수량을 입력하는 방법도 있지만, 공백으로 분리해서 메뉴를 입력하고 이 입력된 메뉴들을 리스트로 반환하는 방법을 선택했다. 입력값을 공백으로 분리해서 입력하는 것을 나중에도 자주 쓰일 것 같았기 때문에 이 방법을 선택했다.

  println("\n주문하실 메뉴를 선택하세요 (여러가지일 경우 띄어쓰기로 구분)")
  var selectedItems = readLine()?.split(" ") ?: emptyList()

split(" ")을 통해 입력값을 공백으로 분리하는데, 입력값이 null이면 리스트를 비우도록 설정하고 이 selectedItems라는 변수로 설정했다.


오류 발생 👾

공백으로 분리해서 입력하는 것은 성공했으나, Coffee 메뉴에서의 7. 카푸치노(ICE)를 선택했을 때 장바구니에 담기는 것이 아니라 리스트 중에 없다고 인식한 후, 예외처리를 해버리는 오류가 발생했다.

카푸치노 아이스를 인식하지 못하는 것 뿐만 아니라, 다른메뉴에서는 선택할 수 있는 최대 번호보다 1 높은 번호를 선택했을 때도 장바구니로 넘어가버리는 문제가 발생했다.


오류 해결 🤖

menuSelection 함수에서 장바구니에 메뉴를 추가할 때 올바른 메뉴의 번호가 아닌 경우에만 오류가 발생하도록 설정되어 있었다.

// 기존코드
else if (menuMap.keys.contains(itemNum)) {
	val menuItem = menuMap[menuNumber]!!.find { it.id == itemNum }
    ...

👉 기존 코드 특징

  • menuMap의 키 집합에 itemNum이 포함되어 있는지 확인

  • menuMap.keys는 menuMap의 모든 키들을 반환하는 Set
    (집합에는 중복된 값이 존재❌ , 순서 보장❌)

  • 특정 메뉴 리스트에 대해서 조건 확인하는 방식을 사용하는 경우 유용
    (MenuMap이 변경되거나 새로 카테고리가 추가되어도 코드 수정 불필요)

// 수정된 코드
else if (menuMap[menuNumber]?.any { it.id == itemNum } == true) {
	val menuItem = menuMap[menuNumber]?.find { it.id == itemNum }
    ...

👉 수정된 코드 특징

  • menuNumber에 해당하는 메뉴 리스트를 가져와 포함된 리스트에 포함된 메뉴들 중 itemNum과 일치하는 메뉴가 있는지 확인

  • menuMap[menuNumber] : menuNumber에 해당하는 리스트 반환
    (menuNumber이 menuMap에 존재❌ : null 반환, ?.을 이용해 안전하게 접근)

  • any {it.id == itemNum} : 해당 리스트에 포함된 데이터 중 itemNum과 일치하는지 파악


(2) 클래스화

각 기능별로 클래스를 설계하고 이 클래스들의 메소드를 정의하고 이를 통해 이전의 코드를 개선한다.

🐤 data class MenuItem

  • id : 메뉴 번호
  • name : 메뉴 이름
  • price : 메뉴 가격

🐤 class MenuCategroy

Coffee, NonCoffee, Ade, Smoothie, Tea, Dessert 메뉴 카테고리 별로 메뉴 항목 리스트로 저장

🐤 class subMenuCategory(categoryNumber : Int)

메뉴 카테고리 번호를 받아 해당 카테고리의 메뉴 항목 리스트 반환

🐤 class OrderSystem

  • MenuCategory : MenuCategory 클래스 인스턴스
  • cartItem : 장바구니 (MutableList)
  • selectMenu(MenuNumber:Int) : 입력받은 메뉴 카테고리 번호의 해당 카테고리 메뉴 항목 선택 가능
  • completeOrder() : 장바구니에 담긴 메뉴 항목 출력

🐤 class Order

  • firstMenu() : 매장 이용 방법 선택
  • mainMenu() : 주문할 메뉴 카테고리 선택, selectMenu() 메소드 호출(메뉴 항목 선택)

오류 발생

내가 기존에 메뉴들을 선택하고 나서 추가주문을 선택 후 메인 메뉴로 돌아가는 것까지는 성공했지만, 추가로 메뉴를 선택하면 이전에 선택해서 장바구니에 들어갔던 목록들이 없어지고 새로 추가한 메뉴들만 장바구니에 담기는 현상이 발생했다.

장바구니를 초기화 하는 코드가 있었는데, 이 부분이 혹시 다른 코드에도 영향을 준걸까 ? 🤔

  val totalPrice = cartItem.sumBy { it.price }
  val price = cartItem.map { it.price }
  val selectedName = cartItem.map { it.name }
  val selectedMutableList = selectedName.joinToString(", ")
  val choice = readLine()?.toIntOrNull()

  when(choice) {
  // 1, 2 선택 시 실행 코드

      3 -> {
          println("----------------------------------------")
          println("주 문 취 소")
          println("----------------------------------------\n")
          cartItem.clear()
          Order().mainMenu()
          break
          }
          else -> {
              println("잘못 입력하셨습니다. 다시 입력해주세요.")
              continue
          }

          ...

확인해봤지만, 주문을 취소할 경우에만 장바구니를 초기화하고 새로 시작하기 때문에 초기화 부분은 문제가 되지 않았다.

그렇다면 대체 뭘까? 싶어서 다시 코드를 뜯어보니, 장바구니가 초기화 되는 것이 아니라 장바구니에 들어간 리스트를 새로운 장바구니가 추가되어 기존 장바구니가 덮어씌워진 것!!

즉, 초기화가 되는 것이 아니라 덮어쓰기가 된 것...

  // 기존코드
   when(input){
      in 1..6 -> {
      OrderSystem().selectMenu(input!!)
      }
      ...
  // 수정된 코드
   when(input){
      in 1..6 -> {
      selectMenu(input!!)
      }
      ...

OrderSystem 내부에서cartItem을 초기화하지 않고 Order 클래스에서 OrderSystem을 상속받아 재사용하도록 설정했는데, 재사용하는 것이 아니라 Order클래스에서 바로 사용하도록 되어있던 것이다.


4. 마무리

프로젝트를 하면서 클래스화 하고 상속관계를 파악해서 만드는데 에러가 계속 발생하기도 하고 클래스화 및 상속관계를 파악하는 방법을 구글링해도 안나와서 이 부분에서만 이틀 걸려버렸다.

전체 코드는 GitHub 에 올려두었으니 참고하면 좋을 것 같다.

profile
소소한 코딩 일기

0개의 댓글