[Error] 키오스크 트러블 슈팅 1 - 상태 패턴
enum 상수과 switch문으로 관리하던 상태에서 상태 패턴 적용 해보는 것도 괜찮을 것 같다고 하셔서 검색 후 내 코드에 적용해 보았다. 기존에 키오스크 실질적인 기능을 담당하는 start() 메소드가
devz0.tistory.com
[Error] 키오스크 트러블 슈팅 2 -책임 분리
이전 글에서 이어지는 내용 [Error] 키오스크 트러블 슈팅 1enum 상수과 switch문으로 관리하던 상태에서 상태 패턴 적용 해보는 것도 괜찮을 것 같다고 하셔서 검색 후 내 코드에 적용해 보았다. 기
devz0.tistory.com
오래되긴 했지만 API 만들어본 경험이 있어서 과제 로직 구현 자체는 어렵지 않았다. 객체 지향 적인 코드 흐름 문제 제외하고 가장 생각을 많이 했던 부분은 장바구니 필드 타입이다. 총 3가지 구조를 생각해봤고 어떤 결론을 도출했는지 작성하려고 한다.
List
private final List<CartItem> cart = new ArrayList<>();
장점
- 구조가 단순하다. (add, remove만으로 관리 가능)
- 순서가 유지되므로 출력이 쉽다.
- 작은 규모의 장바구니에서는 직관적이다.
단점
- 중복 메뉴 처리가 어렵다.
- 같은 메뉴를 다시 추가하면 수량만 늘려야 하는데 매번 O(n) 순회가 필요하다.
- 메뉴 이름으로 삭제, 조회 등 조건 기반 접근이 불편하다.
리스트는 동일한 메뉴의 수량을 관리하기엔 비효율적이라고 생각했다.
Map<MenuItem, Integer>
private final Map<MenuItem, Integer> cart = new HashMap<>();
장점
- 메뉴를 Key로 사용해 중복 없이 관리 가능.
- 수량(Integer)만 더하거나 빼면 되므로 단순
단점
- 값이 단순한 Integer라서 행동 로직이 없다.
- 수량 제한, 가격 계산, 할인 로직 등을 Cart가 전부 처리해야 함.
- 장바구니 항목마다 별도 동작(수량 제한, 옵션, 가격 계산)을 넣기 어려움.
- Cart 클래스가 무거워질 수 있음
- 이후 옵션, 토핑, 할인율 등 기능이 생기면 구조 전체를 변경
Map이 방향은 맞는 것 같지만 데이터 중심적 설계가 된다고 생각했다.
Map<MenuItem, CartItem>
private final Map<MenuItem, CartItem> cart = new HashMap<>();
장점
- 메뉴별 수량, 가격, 이름 등 정보를 하나의 객체(CartItem)로 묶을 수 있다.
- 메서드까지 함께 캡슐화 가능
increaseQuantity(), getMenuPrice(), decreaseQuantity() 등 - 중복 메뉴 자동 통합 compute() 메서드 사용 가능
- compute() :먼저 키가 존재하지 않으면 주어진 키와 값을 맵에 추가.키가 이미 존재한다면, 기존 값과 새로운 값을 연산하여 맵에 저장
- Cart는 단순히 전체 장바구니를 관리하고 각 CartItem이 자신의 책임(수량, 가격 등)을 관리한다.
- 코드의 응집도 ↑, 결합도 ↓
단점
- 구조가 조금 더 복잡 (객체 설계를 미리 생각해야 한다.)
- 작은 규모에서는 다소 과함.
| 비교 | List | Map<Menuitem, Integer> | Map<Menuitem, Cartitem> |
| 중복 메뉴 관리 | ❌ | ✅ | ✅ |
| 조회 효율성 | O(n) | O(1) | O(1) |
| 수량 로직 위치 | Cart | Cart | CartItem |
| 확장성 (할인/옵션..etc) | ❌ | ❌ | ✅ |
| 유지보수성 | ⚪ | ⚪ | ✅ |
데이터와 행위가 함께 일어나는 객체 중심의 설계로 변화에 유연해 장바구니가 커지더라도 조회 효율(map)이 유지되고 추후 할인, 옵션 기능이 늘어나도 구조를 바꿀 필요가 없다고 생각해서 cart 필드 타입을 Map<Menuitem, Cartitem>으로 정했다
‼️ 나중에 알게된 사항
과제 제출까지 끝냈는데 문득 파이썬 딕셔너리는 key에 immutable한 객체만 올 수 있는데 비슷한 자료형인 java의Map key에는 왜 컬렉션이 올 수 있을 까 궁금해졌다. 자바는 객체가 equals/hashCode를 구현하고 있기 때문에 HashMap이 그걸 이용해서 키 비교를 할 수 있다. !!!!!! 기용님 동등성 동일성 세션에서 배웠던 내용..
지금 내 코드는 같은 MenuItem 인스턴스를 계속 사용하고 있기 때문에 객체 주소가 같아서 도전과제2 특정 메뉴 이름 검색 기능 구현할때도 HashMap이 키를 정상 인식한다. 하지만 name같은 단순 필드는 식별가능한 고유의 key가 아니기 때문에 잘못된 버그가 발생할 가능성이 있다. 나중에 DB연동해서 API 구현할때는 각 엔티티마다 PK값(ID)이 존재할테니 그걸로 안전하게 사용해볼 예정이다.
또한 CartItem 필드에 이미 MenuItem 필드가 존재한다. 그래서 지금 프로젝트에서 좋은 장바구니 설계는 Map<String, CartItem> 이라고 생각한다. 이 필드로 변경하더라도 Cart의 책임에는 전혀 영향이 없다. 불변자료형이라 equals와 hashcode 재정의해줄 필요도 없고 ID가 없는 단계에서는 가장 버그 적은 단순한 구조라고 생각한다.
너무 복잡하게 생각하다보니 꼬여버린 것 같다. 그래도 이렇게도 생각해보고 저렇게도 생각해보고 이경우에 일어날 수있는 버그들을 알게된 것에 의미를 둔다. 리팩토링은 피드백을 받고 할지 일단 생각해보려고한다 완료!!
'Dev. > Error.' 카테고리의 다른 글
| [Error] 일정 트러블 슈팅 (1) | 2025.11.05 |
|---|---|
| [Error] 자바에서 객체의 동등성과 동일성 문제 (0) | 2025.10.29 |
| [Error] 키오스크 트러블 슈팅 2 -책임 분리 (0) | 2025.10.27 |
| [Error] 키오스크 트러블 슈팅 1 - 상태 패턴 (0) | 2025.10.25 |
| [Error] 계산기 만들기 트러블 슈팅 (0) | 2025.10.17 |