[회고] 키오스크 과제 회고

wannabeing·2025년 3월 13일
1

SPARTA-회고

목록 보기
2/5

✅ 개요

  • 개발기간: 2025.03.11(화) ~ 2025.03.13(목)
  • 자바버전: OpenJDK 17
  • Java를 사용하여 구현된 콘솔 기반 키오스크 프로그램
  • 사용자가 메뉴를 조회하고 장바구니에 추가한 후 주문할 수 있는 기능을 제공
    • 주문 후 결제 및 장바구니 관리 기능 제공
  • 프로젝트 링크: GitHub Repository

✅ 요구사항 정의

📌 필수 기능

  • 상세메뉴의 이름, 가격, 설명을 저장하는 클래스
  • 상세 메뉴 항목을 관리하는 역할
  • List<MenuItem>을 관리하여 여러 개의 메뉴를 저장
  • 메뉴를 카테고리별로 관리 (예: 햄버거, 음료, 디저트)
  • 메뉴 카테고리를 반환하는 메서드 구현

Kiosk 클래스 (프로그램 흐름 제어)

  • start() 메서드로 키오스크 실행 및 반복문 관리
  • 콘솔에 메뉴를 출력하여 사용자에게 선택지를 제공
  • 사용자의 입력을 받아 메뉴 선택 또는 프로그램 종료
  • 특정 번호 (0) 입력 시 프로그램 종료
  • 유효하지 않은 입력값 입력 시 오류 메시지 출력

🚀 도전 기능 (추가 구현 가능)

장바구니(Cart) 및 구매하기 기능

  • 사용자가 선택한 상세 메뉴를 장바구니에 추가
  • 결제 시도 전에 장바구니 출력 (메뉴 이름, 가격, 수량, 총 금액 포함)
  • List를 사용하여 장바구니 데이터 관리
  • 결제 시도 시, 합산하여 총 금액을 출력하고 장바구니를 초기화

장바구니(Cart) 데이터 관리

  • 메뉴명, 수량, 가격 정보 저장
  • 상세 메뉴 선택 시 입력을 통해 추가/취소 가능
  • 장바구니에 담겨 있는 메뉴가 있다면, 장바구니 목록을 언제든지 확인 가능

사용자 할인(Discount) 기능 추가

  • 사용자 유형을 Enum으로 정의 (예: 국가유공자, 군인, 학생, 일반 고객)
  • 사용자가 주문할 때, 각 사용자 유형에 따라 할인율 적용
  • 할인율을 적용한 최종 금액 계산 및 출력

기타

  • 기존에 생성한 Menu의 MenuItem을 조회 할 때 스트림을 사용하여 출력하도록 수정
  • 기존 장바구니에서 특정 메뉴 빼기 기능을 통한 스트림 활용

✅ Keep

현재 프로젝트에서 만족했고, 앞으로의 훈련기간에서 지속하고 싶은 부분을 작성했다.

  • Enum, 스트림을 적절하게 적용해보았다고 생각한다.
  • 요구사항을 깊이 고민하고 구현하는 과정을 계속해서 깨닫고 있다.
  • 기존 튜터님들의 피드백을 통해 고민하고 코드를 작성하였고, 중간 점검때 좋은 피드백을 받을 수 있었다.
  • 오전시간에 집중이 안되서 팀원들과 마이크만 키고, 공부를 했는데 도움이 많이 되었다.
  • 앞으로 남은 훈련 과정에서도 주어진 과제에 적극적으로 임하며, 더 완성도 높은 결과물을 만들고 싶다.


✅ Problem

현재 프로젝트에서 어려웠던 점과 아쉬웠던 점을 작성했다.

- 1️⃣ 고민했던 부분

어디에서(속성/생성자) 초기화 하는 것이 적합할까?

public class Kiosk {
     private final List<Menu> menus;
 	
     OutputPrinter outputPrinter = new OutputPrinter();
     InputReader inputReader = new InputReader();
 
     public Kiosk(){
         menus = new ArrayList<>();
         ...

- 1️⃣ 피드백

튜터님께 받은 피드백 & 구글링을 해본 결과,
적합한 쪽은 생성자에 초기화 하는 쪽이다.

1. 생성자가 2개 이상 존재할 경우,
   직접 주입 시에는 불필요한 속성들이 초기화 되고, 메모리가 낭비된다.
   따라서 생성자에서 필요할 때만 초기화해서, 메모리 사용을 최소화한다.
   
2. `final` 필드를 활용할 수 있다.
   직접 주입은 객체 생성 이후 reflection으로 우회해서 강제로 값을 할당한다고 한다.
   private 선언된 필드의 값을 강제로 변경하는 것은 캡슐화를 깨는 것이고,
   Java의 컨벤션을 우회하는 행위이다.
   인텔리제이어서도 직접 주입은 권장하지 않는다고 한다.

- 1️⃣ 해결 방안

public class Kiosk {
	 // private을 사용하여 외부에서 직접 접근 못하게 하며,
     // final을 사용하여 초기화 이후, 값을 재할당하지 못하게 설정
     private final List<Menu> menus;
     private final OutputPrinter outputPrinter;
     private final InputReader inputReader
 
     public Kiosk(){
     	 // 객체가 생성될 때, 초기화
         menus = new ArrayList<>();
         outputPrinter = new OutputPrinter();
         inputPrinter = new InputReader();
         ...

- 2️⃣ 고민했던 부분

@Override
public String toString() {
	return name + " | W " + price + " | " + description;
}

toString()을 위에처럼 사용해도 될까?
toString()은 객체의 고유정보를 출력할 때 사용한다고 해서 오버라이딩에서 사용했었다.

2️⃣ 피드백 및 해결방안

결론은 다른 메서드를 활용하라는 것이었다.
해당 내용처럼 사용할 수는 있지만, 나는 사용자에게 출력할 용도로 사용하고 있었다는 것이 문제였다. 개발하면서 내부적으로 확인하는 용도이므로
출력목적의 getFormattedString() 메서드를 생성하였다.

public String getFormattedString(){
	return name +
    " | W " +
    price +
    " | " +
    description;
}

- 3️⃣ 고민했던 부분

2번에서 이어지는 고민이다.
튜터님께서 + 로 문자열을 더하는 것보다 String.format() or StringBuilder를 사용해보는 것을 권유해주셨다.

- 3️⃣ 피드백 및 해결방안

[JAVA] StringBuilder을 JAVA
구글링을 하여 위에처럼 정리를 해봤고, 나는 StringBuilder를 적용해보았다.

String 연산을 효율/효과적으로 처리하기 위해 StringBuilder를 사용했고,
setLength(0)로 초기화하여 이전 데이터를 제거하였다.
기존 + 보다는 가독성이 좋아진 거 같다. ㅎㅎ

public void printInputPrompt(InputPrompt promptType) {
	stringBuilder.setLength(0);

	stringBuilder
    		.append("\n➡️ 선택창")
            .append(promptType.getMessage().isEmpty()
            	? ""
                : " (" + promptType.getMessage() + ")")
            .append(": ");
        
     System.out.print(stringBuilder);
}

- 4️⃣ 고민했던 부분

src
├── handler                     # 🛠 기능을 담당하는 핸들러 (핵심 로직)
│   ├── MenuHandler.java        # 메뉴 조회 및 장바구니 추가 기능
│   └── OrderHandler.java       # 주문 및 장바구니 관리 기능
│
├── io                          # 📥 입출력 관련 클래스 모음
│   ├── input                   # 입력 관련
│   │   └── InputReader.java    # 입력 처리 클래스
│   │
│   └── output                  # 출력 관련
│       ├── OutputPrinter.java  # 출력 처리 클래스
│       ├── InputPrompt.java    # 입력 프롬프트 선택 메시지 Enum
│       └── TextColor.java      # 색상 텍스트 Enum
│
├── model                       # 🏗 데이터 구조 및 핵심 객체
│   ├── Cart.java               # 장바구니 클래스
│   ├── Discount.java           # 할인 정책 Enum
│   ├── Kiosk.java              # 키오스크 클래스
│   ├── Menu.java               # 메뉴 클래스
│   └── MenuItem.java           # 상세 메뉴 클래스
│
├── Main.java                   # ✅ Main()
└── README.md                   # 📖 리드미
    public void initializeSpartaMenu(){
        // 햄버거 메뉴 설정
        Menu burgerMenu = new Menu("Burgers");
        burgerMenu.addMenuItem(new MenuItem("ShackBurger", 6.9, "토마토, 양상추, 쉑소스가 토핑된 치즈버거"));

        // 음료수 메뉴 설정
        Menu drinkMenu = new Menu("Drinks");
        drinkMenu.addMenuItem(new MenuItem("Coke/ZeroCoke", 3.0, "클래식한 코카콜라 또는 제로콜라"));

        // 사이드 메뉴 설정
        Menu sideMenu = new Menu("Desserts");
        sideMenu.addMenuItem(new MenuItem("Corn Salad", 3.0, "달콤한 옥수수와 부드러운 마요네즈가 어우러져 크리미하고 상큼한 맛"));

        menus.add(burgerMenu);
        menus.add(drinkMenu);
        menus.add(sideMenu);
    }

프로젝트 구조(+파일/메서드 이름) 및 해당 메서드에 대해서 고민을 했다.
위는 최종 프로젝트 구조와 키오스크 클래스에 있는 메서드이다.

프로젝트 구조는 최대한 객체지향적으로 추상화한다고 했고..
파일이름은 뭔가 아쉬운 느낌이다. 🥲

initializeSpartaMenu()의 경우,
아직 DB를 다루지 않으니 데이터를 직접 넣어주는 메서드인데..
키오스크 클래스가 아닌 다른 곳에서 불러오고 싶었다.

- 4️⃣ 피드백 및 해결방안

1) initializeSpartaMenu() 메서드에 대한 피드백
그렇게 생각하는 것이 맞고, 지금은 이상하다고만 생각하고 넘겨도 충분하다고 말씀해주셨다. 😃

2) 프로젝트 구조 및 파일명 피드백
기능별로? 잘 나누었다는 피드백을 받았다.
파일명도 충분히 보고 예상이 간다고 말씀해주셨다. 😃

또한 과제를 깊게 파다보면 끝이 없으니, 어느정도 구현을 하고
자바 공부를 더욱 깊게 하라는 피드백을 받았다.
그게 맞는 것 같다! 자바를 더욱 열심히 자바야겠다.


✅ Try

다음 프로젝트에서 시도해볼 점들을 작성했다.

  • 과제에만 몰입하다 보니 다른 것들을 놓친 것 같다...
  • Enum, 람다, 제네릭에 대해 공부
  • TIL 작성 밀리지 말기!
  • 내 코드의 구조와 동작원리를 명확히 이해하고, 설명하기

출처

인프런 회고문화
생성자 주입을 사용해야 하는 이유

profile
wannabe---ing

0개의 댓글