Kiosk Project |
---|
콘솔 화면 |
⚒ 프로젝트
1. 프로젝트 이름
" Kiosk Project "
2. 프로젝트 소개
- 해당 프로젝트는 사용자의 입력을 받아 주문을 처리하는 Kiosk Java Project 입니다.
- 최종 결과물은
level7
패키지이기 때문에level7
패키지 참고 부탁드립니다.
3. 주요 프로젝트 패키지
1) level7
패키지
- [도전] level2 을 구현한 패키지입니다.
- src/level7/Main.java 를 실행 시키면 키오스크를 실행할 수 있습니다.
Main.java
: 키오스크를 실행하는 클래스Menu.java
: Menu 를 관리하는 클래스MenuItem
: MenuItem 을 관리하는 클래스Cart.java
: 장바구니 를 관리하는 클래스CartItem
: 장바구니 속 MenuItem 을 관리하는 클래스Kiosk
: Menu 정보를 담고 있으며, 키오스크 역할을 담당하는 클래스Discount
:Eunm
을 활용하여 사용자별 Discount Type 을 담고 있는 클래스
2) io
패키지
Input
: 입력을 담당하는 클래스Output
: 출력을 담당하는 클래스
🌟 프로젝트의 주요 기능
level7
패키지 를 중심으로 설명했습니다.
1) 메뉴 관리
- 키오스크는 Menu와 MenuItem을 사용하여 다양한 카테고리(버거, 음료, 디저트)에 속하는 메뉴 항목들을 제공합니다.
2) 장바구니 관리
- 사용자는 원하는 메뉴를 장바구니에 추가하거나 삭제할 수 있으며, 장바구니에서 주문을 확인하고 최종 결제를 처리할 수 있습니다.
3) 주문 및 결제
- 주문은 메뉴 항목을 선택하여 장바구니에 추가하는 방식으로 이루어지며, 최종적으로 사용자는 장바구니의 항목들을 확인하고 결제할 수 있습니다.
4) 할인 적용
- 주문을 결제할 때, 사용자가 선택한 할인 유형(국가유공자, 군인, 학생 등)에 맞춰 할인율을 적용합니다.
- 할인율은 Discount Enum을 사용하여 적용됩니다.
5) 입력/출력:
- 시스템은 Input 클래스를 통해 사용자 입력을 받으며, Output 클래스를 통해 시스템의 상태나 결과를 출력합니다.
📑 요구사항
[ 🐣 필수 기능 🐣 ]
Lv 1. 기본적인 키오스크 프로그래밍
1) Scanner 를 활용한 입력
int inputNumber = sc.nextInt();
를 통하여 사용자를 입력을 활용
2) 반복문과 조건문을 활용한 입력 처리
while
이용하여0(Exit)
입력 전까지 반복Switch
이용하여 사용자의 입력에 따라 조작
Lv2. 객체 지향 설계를 적용한 햄버거 메뉴의 클래스 관리
1) 클래스에 요구사항에 따른 필드값이 존재하는가
MenuItem.java
에Field
값 [menuName
,menuPrice
,menuDescription
] 선언
2) List 와 new 키워드를 활용했는가
List<MenuItem> menuItems = new ArrayList<>();
를 통해List
선언add(new MenuItem())
를 코드를 통하여 적절히new
키워드 활용
Lv3. 객체 지향 설계를 적용한 순서 제어의 클래스 관리
1) Kiosk 클래스 생성 및 활용
MenuItem
을 관리하는 리스트Field
로 존재Kiosk(List<MenuItem> menuItems)
생성자를 통해 값을 할당
2) start()
메서드 활용한 입/출력 및 종료 흐름 처리
Main.java
가 관리하던 입력과 반복문 로직을start()
함수로 관리
Lv 4. 객체 지향 설계를 적용한 음식 메뉴와 주문 내역의 클래스 기반 관리
1) Menu 클래스를 활용한 메뉴 카테고리 관리 및 MenuItem 리스트 포함 여부
Menu.java
클래스를 생성 후Menu
를 관리List<MenuItem> menuItems = new ArrayList<>();
를 통하여MenuItem
리스트를Field
로 선언menu.menuItems.add(new MenuItem())
를 통하여Menu
속에 포함된List<MenuItem>
에MenuItem
객체 삽입
2) 메뉴 카테고리 이름을 반환하는 메서드 구현 여부
getCategoryName()
함수를 통하여 카테고리 이름 반환
Lv 5. 캡슐화 적용
1) 접근 제한자 활용
Field
로 선언된 지역 변수들을Default
->private
변경- 일부
Field
는final
로 선언.
2) Getter/Setter 를 활용해 데이터에 접근 여부
getCategoryName()
등 여러 개의Getter
함수 생성addMenuItems()
등 여러 개의Setter
함수 생성
[ 🐔 도전 기능 🐔 ]
Lv 1. 장바구니 및 구매하기 기능 추가
1) 장바구니 기능 추가 여부
Cart.java
를 통하여 장바구니 객체 관리CartItem.java
를 통하여 장바구니이 포함된item
객체 관리
2) 주문 흐름 동작 여부
- [메인메뉴] ➡ [메인메뉴 선택] ➡ [서브메뉴] ➡ [서브메뉴 선택] ➡ [장바구니 추가 여부] ➡ [장바구니 추가]
- [메인메뉴] ➡ [장바구니 확인] ➡ [주문하기] ➡ [장바구니 초기화]
3) 잘못된 입력값에 대한 예외처리 여부
IndexOutOfBoundsException
: 범위 밖의 값을 받았을 경우 예외 발생cart.cartItemsNotEmpty()
: 장바구니가 없을 경우 Main Menu 에서 접근 불가InputMismatchException
,NullPointerException
,NumberFormatException
:Input.java
클래스에서 재귀
Lv 2. Enum, 람다 & 스트림을 활용한 주문 및 장바구니 관리
1) Enum 을 활용한 사용자 유형별 할인율 관리 여부
Discount.java
에서enum
을 관리Kiosk.java
에서enum
을 활용하여 사용자 유형별 할인율 관리
2) 람다/스트림을 활용한 장바구니 조회 기능 여부
Menu.java
클래스에서showMenuItems()
함수를 이용하여 리스트를 순차적으로 조회Kiosk.java
클래스에서determineDiscount()
함수를 이용하여enum Type
을 순차적으로 조회Cart.java
클래스에서removeCartItems()
함수를 이용하여 장바구니에서 특정 메뉴 빼기 기능
"도전과제 Lv.2 를 기준으로 작성되었습니다."
📂 Cart
🛒 Cart.java
1. 필드
Map<String, CartItem> cartItemMap
: 장바구니에 담긴 메뉴 아이템과 수량을 관리하는 맵.
2. addCartItems(MenuItem menuItem)
- 메뉴 항목을 장바구니에 추가.
- 이미 장바구니에 있으면 수량만 추가, 없으면 새로 추가.
3. showCartItems()
- 장바구니의 모든 아이템을 출력.
- 각 메뉴 이름, 가격, 수량을 출력하고 총 금액도 계산하여 표시.
4. getTotalPrice()
- 장바구니에 담긴 모든 아이템의 총 가격을 계산
5. isCartNotEmpty()
- 장바구니가 비어 있지 않으면
true
, 비어 있으면false
반환
6. clearCartItems()
- 장바구니를 비우는 기능
7. removeCartItems()
- 장바구니에서 특정 메뉴를 삭제.
- 메뉴가 없으면 재입력 요청.
🛒 CartItem.java
1. 필드
menuItem
:MenuItem
객체 (메뉴 항목)itemQuantity
: 항목의 수량, 기본값은1
2. 생성자
CartItem(MenuItem menuItem)
:MenuItem
을 받아menuItem
필드 초기화
3. Getter 메서드
getMenuItem()
:MenuItem
객체 반환getCartItemName()
: 메뉴 이름 반환getItemQuantity()
: 항목 수량 반환
4. Setter 메서드
addCartItemQuantity()
: 항목 수량 1 증가
5. 장바구니 항목 출력
showAllCartItems()
: "메뉴 이름, 가격, 설명, 수량"을 출력 형식에 맞춰 표시
📂 Menu
🍽️ Menu.java
1. 필드
categoryName
: 메뉴 카테고리 이름menuItems
:MenuItem
객체들을 담는 리스트
2. 생성자
Menu(String categoryName)
: 카테고리 이름을 받아categoryName
필드 초기화
3. Getter 메서드
getMenuItems()
:MenuItem
객체들이 담긴 리스트 반환getCategoryName()
: 메뉴 카테고리 이름 반환showMenuItems()
: 메뉴 항목을 순차적으로 번호와 함께 출력
4. 메뉴 선택 출력 (displaySelectedMenu(Integer index)
)
- 사용자가 선택한 메뉴 인덱스가 유효하면 선택된 메뉴 출력
- 유효하지 않으면 범위 초과 메시지 출력
5. Setter 메서드
addMenuItems(MenuItem menuItem)
: 새로운MenuItem
을 메뉴에 추가
🍔 MenuItem.java
1. 필드
menuName
: 메뉴 이름menuPrice
: 메뉴 가격menuDescription
: 메뉴 설명
2. 생성자
MenuItem(String menuName, Integer menuPrice, String menuDescription)
: 메뉴 이름, 가격, 설명을 받아menuName
,menuPrice
,menuDescription
필드 초기화
3. Getter 메서드
getMenuPrice()
: 메뉴 가격 반환.getMenuDescription()
: 메뉴 설명 반환.getMenuName()
: 메뉴 이름 반환.
4. 메뉴 출력 형식 지정
menuFormatString(boolean gap)
gap = true
: 일정한 간격을 주어 메뉴 이름, 가격, 설명 출력gap = false
: 간격 없이 메뉴 이름, 가격, 설명을 출력
📂 etc
⚡ Main.java
Kiosk
를 실행시켜주는 클래스
📱 Kiosk.java
1.필드
menus
(List
2. 생성자
Kiosk()
:menus
필드를 초기화하는 생성자.initMenus()
메서드를 호출하여 메뉴들을 초기화합니다.
3. 메서드
initMenus()
: 기본 메뉴와 메뉴 항목을 초기화하여menus
리스트를 반환.start()
: 키오스크 메인 루프. 사용자 입력을 받아 메인 메뉴와 서브 메뉴를 처리.showAllCategory()
: 모든 메뉴 카테고리를 출력.getSpecificMenus(Integer index)
: 인덱스를 받아 특정 메뉴를 반환.getSpecificMenuItem(Menu menu, Integer index)
: 특정 메뉴의 항목을 반환.showMainMenu(Cart cart, Menu menu)
: 메인 메뉴를 출력. 장바구니 상태에 따라 출력 항목이 달라짐.showSubMenu(Menu menu)
: 선택한 메뉴의 서브 메뉴를 출력.confirmOrReturn(Cart cart)
: 장바구니에서 주문을 확정하거나, 메뉴로 돌아가거나, 항목을 삭제할 수 있는 기능.determineDiscount(Cart cart)
: 사용자 유형에 맞는 할인율을 적용하고 최종 금액을 계산.processSubMenuSelection(Menu menu, Cart cart)
: 서브 메뉴에서 항목을 선택하고 장바구니에 추가하는 처리.processCartInput(Menu menu, int orderMenuItem, Cart cart)
: 장바구니에 메뉴 항목을 추가할지 결정하는 함수.
💸 Dicount.java
- enum
1. 필드
userType
: 할인 대상의 사용자 유형 (예: 국가유공자, 군인, 학생, 일반인).type
: 할인 대상의 유형 번호.rate
: 할인율 (예: 0.9는 10% 할인).
2. 생성자
Discount(int type, String userType, Double rate)
: 할인 정보를 초기화하는 생성자
3. 메서드
getUserType()
: 할인 대상의 사용자 유형을 반환getRate()
: 할인율을 반환getType()
: 할인 유형 번호를 반환getPercent()
: 할인율을 백분율로 계산하여 반환
️️🪢 데이터 흐름 (Data Flow)
1. Kiosk 객체 생성 및 시작
main()
: Kiosk 클래스의start()
메서드가 호출되면서 키오스크 시스템이 시작됩니다.
2. 메뉴 초기화
initMenus()
: Kiosk 클래스는initMenus()
메서드에서 각 메뉴 카테고리 (버거, 음료, 디저트)를 초기화하고, 각 카테고리에는 여러 메뉴 항목이 추가됩니다.
3. 메인 메뉴 출력 및 사용자 입력 처리
start()
: 메인 메뉴가 출력되고, 사용자는 카테고리를 선택합니다.- 선택한 카테고리별로 해당 메뉴 항목이 출력되며, 사용자는 원하는 메뉴를 장바구니에 추가하거나 취소할 수 있습니다.
4. 하위 메뉴 처리
processSubMenuSelection()
: 사용자가 메뉴 항목을 선택하면 해당 항목을 장바구니에 추가할지 취소할지 결정합니다.
5. 장바구니 확인 및 최종 주문 처리
confirmOrReturn()
: 사용자가 장바구니를 확인하고 주문을 최종적으로 확정하거나 취소할 수 있습니다.- 주문 확정 시, 할인 적용 여부가 결정됩니다.
6. 할인 적용
determineDiscount()
: 사용자가 선택한 할인 종류에 따라 할인율이 적용되며, 해당 할인율에 맞춰 최종 가격이 계산됩니다.
7. 장바구니 취소 및 비우기:
- 사용자는 장바구니를 비우거나 특정 항목을 삭제할 수 있습니다.
다른 패키지 설명
1) level1
패키지
- [필수] level1 을 구현한 패키지입니다.
- src/level1/Main.java 를 실행 시키면 키오스크를 실행할 수 있습니다.
Main.java
: 키오스크 역할을 담당하고, 실행하는 클래스
2) level2
패키지
- [필수] level2 을 구현한 패키지입니다.
- src/level2/Main.java 를 실행 시키면 키오스크를 실행할 수 있습니다.
Main.java
: 메뉴 정보를 담고 있으며, 키오스크 역할을 담당하고 실행하는 클래스MenuItem
: MenuItem 을 관리하는 클래스
3) level3
패키지
- [필수] level3 을 구현한 패키지입니다.
- src/level3/Main.java 를 실행 시키면 키오스크를 실행할 수 있습니다.
Main.java
: 메뉴 정보를 담고 있으며, 키오스크를 실행하는 클래스MenuItem
: MenuItem 을 관리하는 클래스Kiosk
: 키오스크 역할을 담당하는 클래스
4) level4
패키지
- [필수] level4 을 구현한 패키지입니다.
- src/level4/Main.java 를 실행 시키면 키오스크를 실행할 수 있습니다.
Main.java
: 메뉴 정보를 담고 있으며, 키오스크를 실행하는 클래스Menu.java
: Menu 를 관리하는 클래스MenuItem
: MenuItem 을 관리하는 클래스Kiosk
: 키오스크 역할을 담당하는 클래스
5) level5
패키지
- [필수] level5 을 구현한 패키지입니다.
- src/level5/Main.java 를 실행 시키면 키오스크를 실행할 수 있습니다.
Main.java
: 메뉴 정보를 담고 있으며, 키오스크를 실행하는 클래스Menu.java
: Menu 를 관리하는 클래스MenuItem
: MenuItem 을 관리하는 클래스Kiosk
: 키오스크 역할을 담당하는 클래스
6) level6
패키지
- [도전] level1 을 구현한 패키지입니다.
- src/level6/Main.java 를 실행 시키면 키오스크를 실행할 수 있습니다.
Main.java
: 메뉴 정보를 담고 있으며, 키오스크를 실행하는 클래스Menu.java
: Menu 를 관리하는 클래스MenuItem
: MenuItem 을 관리하는 클래스Cart.java
: 장바구니 를 관리하는 클래스CartItem
: 장바구니 속 MenuItem 을 관리하는 클래스Kiosk
: 키오스크 역할을 담당하는 클래스
📚 Stacks
✔️ Environment
✔️ Project
✅ 프로젝트 회고
객체 지향에 대해 생각하면서 과제를 진행했던 거 같습니다.
1. 코드를 작성해서 구현은 할 수는 있는데, 깔끔한 코드를 작성하는 것이 힘들었습니다.
- 구현을 해내는 것은 쉬웠다. 구현을 해내는 것은 정말 3일 안에 끝났던 거 같다.
- 하지만, 어떻게하면 직관적이고 유지보수성이 좋게 코딩할 수 있을까? 를 많이 고민했던 거 같다.
- 물론 내가 완성해낸 결과물이 직관적이고 유지보수성을 신경쓴 코드냐 물어보면 그렇지 않을 것이지만,, 아직까지는 깔끔한 코드를 짜는 것이 어려운 거 같다.
2. 기능을 구현할 때에 함수는 하나의 기능 만을 담당하게 만드는 것이 중요하다고 하는데, 하나의 기능 만을 담당하게 하는 게 어려웠습니다.
- 1번과 연관된 회고일 수는 있다. 그러나, 분기문과 반복문, 조건문을 깔끔하게 만드는 것과 함수 안에 한 가지의 기능만을 담는 건 또 다른 내용일 것이다. 아직까지는 "다른 기능" 이라는 부분에서 개념적으로 부족한 거 같다.
- 장바구니를 관리하는 함수 라고 해도, 이 안에는 장바구니를 추가하고, 삭제하고 조회하는 3가지의 기능이 있을 수 있지 않나? 우리가 여기서 추가,삭제, 조회 말고도 다른 기능을 추가해볼 수도 있다. (그러니까 코드를 하다보면 이런 다양한 기능들이 추가된 다는 것이다.)
- 그러면 처음에는 관리하는 함수 하나에서 여러가지 기능을 동작했다면, 점점 기능이 생길 때 마다 함수 밖으로 빼고, 클래스로 빼고, 이런 식으로 점점 기능들이 분산화 되는데 또 막상 복잡해 보이는 코드처럼 보였다. 이게 참.. 어려웠다.
- 그래서 기능을 분리할 때 중요한 점 중 하나가 해당 기능 함수의 이름을 직관적으로 짓는 것이다. 이번에는 파파고를 켜두고 직관적인 이름을 지을려고 열심히 노력했다. 하지만,, 아직은 부족한 거 같다.
3. Switch 문을 줄이고 싶었으나, 줄이지 못했습니다.
- 내가 이번 과제에서 제일 못했던 부분이 이 부분이 아닐까 싶다. Switch 문을 연사로 쓴 것. 물론 추후에는 조금씩 줄여나가기는 했지만 필요할 수 밖에 없어 다소 난잡한 코드가 되지 않았나? 생각은 든다.
4. 스트림 및 람다를 활용한 장바구니 조회 기능
도전 기능 가이드에서 " 스트림 및 람다를 활용한 장바구니 조회 기능 " 이 부분이 있었는데.
CartItem 의 Private 한 속성들을 Cart 에서 하나씩 값을 가져오는 것 보다는 CartItem 의 Private 한 속성은 CartItem 에서 출력만 해주는 형식으로 접근(Getter 를 활용하는 것이 더 객체지향적이라고 생각했습니다.
그리하여 해당 부분은 Stream 을 활용하여 각각의 값을 접근하는 것보다는 forEach에 간략화된된 람다표현식을 활용하여 출력했습니다.
해당 부분이 정말 객체지향적인 생각이 아닐까 싶다 ?
5. 도전 Lv2. 이전 단계에서는 try 문에서 예외를 throw에서 흐름을 제어 했었는데, 리팩토링, 코드리뷰 하는 과정에서 이러한 Throw를 통한 예외 처리가 왜 하면 안되는지 깨달은 거 같습니다.
정말 내가 이번 프로젝트에서 잘못했던 부분 탑이다. (Switch 보다 더 👿)
그때 당시에는 흐름을 제어하고, 같은 곳에서 같은 print 문을 주고 싶어서(단순하게만 동작해주고 싶어서) 그랬던 거 같은데.
조금만 생각해도 에러를 던지는 게 정말 맞을까? 라는 생각을 해야하는데.
아마 throw 라는 부분을 너무 크게 생각하지 않았던 거 같다. 지금은 왜 throw 로 흐름 제어를 하면 안 되는지 잘 안다..
6. Menu 와 MenuItem 을 이렇게 클래스로 구분하는 것이 이번 과제에서 요구하는 바와 일치하는지 궁금합니다. 또한 Cart 와 CartItem 을 구분한 것 역시 이번 과제에서 요구하는 바와 일치하는 지 궁금합니다.
- 나는 객체 지향 설계가 목표인 이번 과제에서 내가 오래 생각했던 부분이다.
- 처음에 Menu 라는 아이를 어떻게 MenuItem 과 연결할까? 에 대해서 고민 많이 했다.
- 나도 처음에는 당연히 MenuItem 에 Menu의 카테고리를 포함하면 연결은 되지 않을까? 싶었다.
- 하지만, 그렇게 되면 Menu 와 MenuItem 을 구분하는게 의미가 없지 않는가 싶었다.
- 지금은 아직 피드백을 받지 않아 어떻게 될지는 모르겠으나. 일단 내 생각은 이러했다.
마지막 피드백을 받으러 갔을 때, Cart에서 List 보다는 HashMap을 이용하여 Category를 키 값으로 CartItem 을 값으로 바꾸는게 어떻겠냐라고 하셨다. 처음에는 오래 걸릴까봐 조금 겁이 났지만, 빨리 끝났다 ? 항상 느끼는게 막상 해보면 해볼만 하다는 거다. 코드리뷰도 3번이나 받았지만 결국은 다 바꾸어보았지 않은가 😤😤
'백엔드 부트캠프 > TIL' 카테고리의 다른 글
[내일배움캠프Spring-17일차] 코드 리펙토링 (4) | 2025.03.12 |
---|---|
[내일배움캠프Spring-16일차] 키오스크 문제 (도전과제) (0) | 2025.03.11 |
[내일배움캠프Spring-15일차] Kiosk Issue (2) | 2025.03.10 |
[내일배움캠프Spring-14일차] 키오스크 문제 (1단계-4단계) (0) | 2025.03.07 |
[내일배움캠프Spring-13일차] Thread (1) | 2025.03.06 |