TIL
[250312 TIL] JAVA 키오스크 프로젝트 개선
도원좀비
2025. 3. 12. 19:37
📌 TIL (Today I Learned) - Java 키오스크 프로젝트 개선 🛠️
🍔 1. double 대신 Integer로 가격 타입 변경 (가격 단위 정리)
🔹 이전 코드 (double 사용)
private final Double price; // 가격을 double로 설정
❌ 문제점
- 부동소수점 연산 오차 발생 가능
- 가격에 소수점이 필요 없음에도 double을 사용하여 불필요한 메모리 사용
✅ 개선 코드 (Integer로 변경)
private final Integer price; // 가격을 Integer로 변경
💡 개선 효과
- 정확한 가격 계산 가능 (소수점 연산 문제 해결)
- 메모리 절약 (4바이트 vs 8바이트)
- 가독성 및 유지보수 용이
📂 관련 파일: MenuItem
🏷️ 2. Discount 클래스를 List 기반으로 변경 (할인 데이터 구조 개선)
🔹 이전 코드 (Discount[] 사용)
public static void printDiscountList(Discount[] discounts) {
IntStream.range(0, discounts.length)
.forEach(i -> System.out.println(
String.format("%d. %s || %.0f%%",
i + 1,
discounts[i].getDiscountCategory(),
discounts[i].getDiscountRate() * 100)
));
}
❌ 문제점
- Discount[] 배열은 가변성이 부족하고, 크기 변경이 어렵다.
- List<Discount>를 활용하면 더 유연하게 활용 가능.
✅ 개선 코드 (List<Discount> 사용)
public static void printDiscountList(List<Discount> discounts) {
IntStream.range(0, discounts.size())
.forEach(i -> System.out.println(
String.format("%d. %s || %.0f%%",
i + 1,
discounts.get(i).getDiscountCategory(),
discounts.get(i).getDiscountRate() * 100)
));
}
📌 개선 효과
- 가변성이 뛰어난 List 활용
- 배열보다 유지보수 편리
- 컬렉션 프레임워크 사용으로 일관성 유지
📂 관련 파일: Discount
🔄 3. Map 대신 List 기반의 장바구니 구현
🔹 이전 코드 (Map을 활용한 메뉴 장바구니 메뉴)
private final List<MenuItem> cartItems = new ArrayList<>();
// 장바구니에 메뉴 추가
public void addItem(MenuItem item) {
cartItems.add(item);
System.out.println(item.getName() + "이(가) 장바구니에 추가되었습니다.");
}
// 장바구니에서 특정 메뉴 제거
public void removeItem(int index) {
if (index >= 0 && index < cartItems.size()) {
MenuItem removedItem = cartItems.get(index);
cartItems.remove(index); // 삭제 메서드호출
System.out.println(removedItem.getName() + "이(가) 장바구니에서 삭제되었습니다.");
} else {
System.out.println("잘못된 선택입니다. 다시 입력하세요.");
}
}
// 장바구니 목록 출력
public void displayCart() {
if (cartItems.isEmpty()) {
System.out.println("장바구니가 비어 있습니다.");
return;
}
System.out.println("=== 장바구니 목록 ===");
AtomicInteger index = new AtomicInteger(1); //AtomicInteger로 forEach문 index 변경가능
// 중복된 메뉴 개수를 계산하고 정렬하여 출력
cartItems.stream()// 스트림으로 변환
.collect(Collectors.groupingBy(item -> item, Collectors.counting())) // 개수 미리 계산
.entrySet().stream() // Map을 스트림으로 변환
.sorted(Map.Entry.comparingByKey(Comparator.comparing(MenuItem::getName))) // 정렬 추가
.forEach(entry -> { // 최종 출력
MenuItem item = entry.getKey();
long count = entry.getValue();
double totalItemPrice = item.getPrice() * count;
System.out.printf("%d. %s | %d개 | W %.2f%n", index.getAndIncrement(), item.getName(), count, totalItemPrice);
});
System.out.println("총 금액: W " + calculateTotal());
}
❌ 문제점
- 같은 메뉴가 여러 번 추가되면 중복 항목을 직접 찾아서 개수를 세어야 함
- 특정 메뉴 삭제 시 모든 항목을 탐색해야 하는 비효율성
- 개수를 출력하려면 groupingBy()를 사용하여 추가적인 연산 필요
✅ 개선 코드 (가독성 향상 및 성능 개선)
public void removeItemByName(String itemName) {
Optional<MenuItem> removeTOItem = cartItems.keySet().stream()
.filter(item -> item.getName().equalsIgnoreCase(itemName))
.findFirst();
if(removeTOItem.isPresent()) {
removeItem(removeTOItem.get());
}else {
System.out.println("해당 메뉴가 장바구니에 없습니다.");
}
}
📌 개선 효과
- 같은 메뉴를 여러 번 추가해도 자동으로 개수 증가
- 삭제 시 특정 키(MenuItem)를 바로 찾아서 개수만 감소
- 총 금액 계산 및 출력이 더 직관적으로 가능
📂 관련 파일: Cart
📋 4. viewCart()의 입력 처리 개선 (메뉴 삭제 시 입력 오류 방지)
🔹 이전 코드 (숫자 입력만 받음)
int option = getValidIntInput(); // ❌ 문자열 입력 시 오류 발생
if (option == 1) {
System.out.print("삭제할 메뉴 이름을 입력하세요 ");
String itemName = scanner.nextLine().trim();
cart.removeItemByName(itemName);
}
❌ 문제점
- 사용자가 "감자 튀김" 같은 메뉴 이름을 입력하면 입력 오류 발생
- getValidIntInput()이 숫자만 받도록 구현되어 있어 문자열 입력 불가
✅ 개선 코드 (숫자 입력과 문자열 입력을 분리)
int option = getValidIntInput(); // ✅ 숫자 입력만 받음
if (returnHome(option)) return;
if (option == 1) {
System.out.print("삭제할 메뉴 이름을 입력하세요: ");
String itemName = scanner.nextLine().trim(); // ✅ 문자 입력 허용
cart.removeItemByName(itemName);
} else {
System.out.println("⚠️ 잘못된 입력입니다. 다시 선택해주세요.");
}
📌 개선 효과
- 숫자 입력 (1, 0, -1)과 메뉴 삭제 문자열 입력을 분리
- 입력 오류 방지 및 사용자 경험 향상
📂 관련 파일: Kiosk
🎯 5. getValidIntInput()에서 입력 예외 처리 강화 (잘못된 숫자 입력 처리)
🔹 이전 코드 (예외 처리 부족)
private int getValidIntInput() {
try {
int input = scanner.nextInt();
scanner.nextLine(); // 개행 문자 제거
return input;
} catch (InputMismatchException e) {
scanner.nextLine(); // 버퍼 비우기
System.out.println("유효하지 않은 입력입니다. 숫자를 입력하세요.");
return -1; // 잘못된 입력 시 기본값 반환
}
}
❌ 문제점
- scanner.nextInt()는 숫자 입력 후 개행 문자(\n)를 남겨서 다음 입력 시 문제 발생 가능
- 예외 발생 시 버퍼를 비우는 추가 코드(scanner.nextLine())가 필요
- 문자 입력 시 InputMismatchException 발생
✅ 개선 코드 (입력 흐름 유지 및 명확한 메시지 추가)
private int getValidIntInput() {
while (true) {
try {
int input = Integer.parseInt(scanner.nextLine().trim());
return input;
} catch (NumberFormatException e) {
System.out.println("유효하지 않은 입력입니다. 숫자를 입력하세요.");
}
}
}
📌 개선 효과
- scanner.nextInt() 대신 scanner.nextLine()을 사용하여 버퍼 문제 해결
- 예외 발생 시 루프를 돌면서 사용자가 숫자를 입력할 때까지 반복 요청
- 숫자가 아닌 입력을 받을 경우 NumberFormatException을 처리하여 프로그램이 중단되지 않도록 개선
- trim()을 사용하여 공백을 포함한 잘못된 입력 방지
📂 관련 파일: Kiosk
🛠️ 오늘의 개선 요약
✅ double price → Integer price로 변경하여 연산 오류 방지
✅ Discount[] → List<Discount>로 변경하여 더 유연한 데이터 구조 사용
✅ removeItemByName() 가독성 및 성능 개선
✅ viewCart()에서 숫자/문자 입력 오류 방지
✅ getValidIntInput()에서 예외 처리 강화