책이랑 강의로 객체지향 패러다임에 대해 공부하며 직접적으로 문제 하나에 대해 처음부터 끝까지 코드를 작성하는 연습을 진행해야겠다는 생각이 들었다. 계속 개념적으로만 학습을 진행해 실제 구현을 해나갈 때 어떤 고민들과 문제점을 마주치는지 경험하고자 레스토랑 음식 주문 시스템을 구현해 보기로 결정했다.
관련 레포지토리는 아래 링크를 참고해 주세요. 문제의 요구사항은 생성형 AI가 일부 만들어줘서 제시된 스켈레톤 코드를 필수적으로 구현하려 하진 않았고, 핵심 기능에 해당하는 입출력 예시와 요구사항을 만족시키도록 코드를 작성하였습니다.
GitHub - HeeChanN/oop-food-order-management-system: OOP 연습(2) - 레스토랑 주문 시스템
OOP 연습(2) - 레스토랑 주문 시스템. Contribute to HeeChanN/oop-food-order-management-system development by creating an account on GitHub.
github.com
또한, 코드 작성 같은 경우 블로그글에 옮기는 것보다 깃허브를 통해 한번에 그 로직을 보는 것이 더 좋다는 생각이 들어 블로그 글에는 코드를 담지 않았습니다. 대신, 구현을 하며 여러 번 변경했던 도메인 모델을 자세하게 적으려고 노력했습니다! 따라서, 코드에 대해 궁금하시다면 블로그글의 도메인 모델을 바탕으로 깃허브를 참고해 주세요!
1. 객체 식별 및 객체가 알아야 할 정보 파악
가장 먼저 객체를 식별하는 것부터 진행했다. 문제의 요구사항을 보며 필요한 객체들을 파악했고 제시된 스켈레톤 코드도 참고하며 해당 객체들이 요구사항에서 어떤 역할을 진행하고 있는지를 파악하며 필요한 정보들에 대해 정리했다. 정리한 내용은 다음과 같다.
- 레스토랑 (메뉴판, 주문 리스트)
- 메뉴판 (메뉴 요소)
- 메뉴 요소 ( 메뉴 이름, 메뉴 가격, 메뉴 타입, 메뉴 설명, 조리시간, 재고)
- 주문 ( 장바구니, 메뉴 관련 정보, 주문 번호, 주문 시간, 전체 금액)
- 결제 ( 결제 수단, 결제 정보)
- 고객 ( 담은 메뉴, 가진 금액)
- 장바구니 ( 담은 메뉴 정보 )
초기에는 레스토랑이라는 객체를 생각하지 못했고 결제라는 객체는 필요하다고 생각했지만 실제 구현에는 만들지 않았다. 위 객체들은 처음부터 모두 식별한 것은 아니고 도메인 모델을 만들어가며 최종적으로 나온 객체 요소들이다. 뭔가 이렇게 작성하고 나니 연결하지 않은 ERD를 만든 것 같기도 한데.. 그래도 객체 각각에 책임을 할당하려면 각 객체가 알고 있는 정보까지는 알아야 한다는 생각으로 위와 같이 정리하였다.
2. 주문 관련 책임 할당
가장 먼저 주문 로직에 대한 도메인 모델을 만들며 각 객체에게 책임을 할당해 보았다.
주문 로직에 대한 요구사항은 다음과 같다.
고객이 주문 기능을 사용하면 y를 입력할 때까지 주문을 계속할 수 있고 n을 누르면 지금까지 주문한 내역을 고객에게 보여주고 장바구니를 고객에게 전달한다.
따라서 이를 바탕으로 고객이 시스템에 전달하는 요청을 다음과 같이 생각했다.

메시지 송시자 입장에서 행위에 이름을 짓는 다면 주문하라가 가장 적절하지 않을까?라는 생각으로 이름을 지었다. 이때, 처음에는 메뉴판을 주문이 갖고 있어야 한다고 생각을 해, 메뉴 주문과 관련된 가장 많은 정보를 아는 객체는 주문 객체라고 판단하였고, 그 결과 아래와 같이 책임을 할당하였다.

주문이 메시지를 받으면 주문이 알아야 하는 정보는 메뉴에 대한 정보다. 따라서 주문은 메뉴 요소에 대한 정보 전문가인 메뉴판에게 메뉴 요소를 알려달라고 해야 한다.

주문은 메시지에 대한 응답으로 받은 메뉴를 장바구니에 추가하고 고객에게 관련한 응답을 보낸다. 메뉴 요소의 경우 총 4가지 종류가 존재하고 각각의 메뉴 타입 별로 기존 필드에서 확장한 정보를 갖고 있다.
→ 공통 필드, 메서드가 존재하고 서브타입의 메뉴들은 서로 다른 기능을 가진다.
따라서, 공통 필드는 인터페이스로 작성하는 것이 불가능하니 추상 클래스로 추상화 진행하였다. ( 문제의 스켈레톤 코드를 살짝 참고하기도 하였습니다.)
첫 도메인 모델은 여기까지 생각하였고 바로 코드를 작성하였다. 이때까지는 엄청 단순한데?라는 생각으로 시작했다.
코드를 작성하며 추가 로직을 발견하였고 내가 만든 도메인 모델은 이 추가 로직의 책임을 고려하지 않고 있다는 것을 발견할 수 있었다. 발견한 추가로직은 다음과 같다.
-> 주문 객체는 메뉴판 객체에게 메뉴 요소에 대해 주문 가능한지 여부를 받아야 한다.
-> 메뉴판 객체는 각 메뉴에게 지금 주문 가능한지를 물어봐야 한다.
-> 주문 객체는 주문 가능한 메뉴라면 장바구니에 담아야 한다.
그에 따라, 도메인 모델을 아래와 같이 수정하게 되었다. 물론 아래 도메인 모델도 최종 도메인 모델은 아니다.. 그래도, 중간에 발견한 책임들을 통해 장바구니 객체와 메뉴 요소라는 객체를 발견할 수 있었고 이를 바탕으로 객체가 가지고 있는 정보에 따라 책임을 나눌 수 있었다.

3. 결제 로직 책임 할당
다음은 결제 관련 책임 할당이다. 요구사항으로는 "고객이 선택한 메뉴들 (주문)에 대해 결제를 진행해야 한다"이다. 선택한 메뉴의 경우 주문 객체가 알고 있다.
이 상황에서 똑같이 고객은 시스템에 결제하라라는 요청을 보내는 것으로 시작한다고 생각했다.

이 상황에서 주문 객체가 고객이 선택한 메뉴를 가장 잘 알고 있으니 결제 요청을 받는 객체는 주문 객체라고 생각했다.

주문 목록을 가장 잘 알고 있는 객체는 장바구니 객체다. 주문 객체는 장바구니 객체에게 주문 목록들에 대한 총가격을 요청해야 한다. 총가격을 얻은 뒤에는 결제 수단을 바탕으로 결제를 진행해야 한다. 그 도메인 모델을 그러보면 아래와 같다.

위와 같이 작성하고 코드를 작성하기 시작했는데, 코드를 작성하다 보니 주문 객체는 주문을 받고 주문리스트를 관리하는 책임 이외에 주문에 대한 결제 요청까지 진행해야 하는 너무 많은 책임이 존재한다는 것을 발견하였다. 따라서 아래와 같이 레스토랑이라는 객체를 만들어 해결하였습니다.
레스토랑 객체의 경우 고객과 가장 가까이서 소통하는 객체로 주문 생성, 결제 요청 같은 고객의 요청을 받는 객체로 앞서 만들었던 주문 로직의 도메인 모델에도 추가된다.

하지만, 이렇게 수정을 진행해도 실제 코드를 작성할 때 매끄럽게 작성되지는 않았다. 이 부분에서 정말 고민을 많이 했는데, 아마 지금 와서 생각해 보면, 그 이유는 주문 로직에서 갖고 있었던 메뉴판과 레스토랑이 갖게 된 결제 로직이 현재의 도메인 모델에는 맞지 않아서였을 것 같다.
그래서 수정하게 된 것은 먼저 메뉴판을 알고 있는 객체는 주문 객체가 아니라 레스토랑이 되어야 맞겠다는 생각으로 주문에 대한 도메인 모델을 수정하였고 결제 수단 같은 경우도 주문이 가격에 대한 정보를 관리하고 결제를 처리하는 게 맞다는 생각으로 결제 도메인 모델을 수정하였다. 그 결과 최종 도메인 모델들은 다음과 같다.


4. 메뉴판 보기 책임 할당
요구사항을 보면 주문 로직과 결제로직 이외에도 메뉴판을 보여주는 로직도 존재한다. 해당 요구사항의 경우 이미 만들어진 도메인 모델에 책임만 할당하면 해결이 되어서 아래와 같이 바로 도메인 모델을 만들 수 있었고 구현 같은 경우도 어렵지 않게 진행할 수 있었습니다.

5. 아쉬웠던 점
가장 아쉬웠던 것은 이번 주부터 진행하려고 한 개인 프로젝트 때문에 입출력 처리와, 예외처리와 관련해서 코드를 제대로 작성하지 못했다는 점이다. 사실 핵심 로직에 대해서 열심히 작성하면서 이번에는 콘솔 입출력을 담당하는 클래스도 분리하고 예외를 처리해 주는 클래스도 만들어보고 싶었지만.. 주어진 시간에는 불가능한 작업이었다. 아마 개인 프로젝트를 진행하고 이후에 관련해서 부족했던 부분을 리팩토링을 통해 개선하고 핵심 로직 이외에 추가로 구현해야 하는 기능들에 대해서 추가해 보며 코드를 개선해 나갈 것 같다.
이번에 직접 아무 도움 없이 혼자 주어진 기본 요구사항을 만족하도록 코드를 구현해 보면서 실제 내가 공부한 이론을 적용해 본다는 관점에서 재미있게 코드를 작성했던 것 같다. 또, 작성하면서 책을 읽으며 정리했던 내용을 계속 참고했던 것을 보면 이후에도 여러 번 다른 좋은 주제를 바탕으로 객체지향 프로그래밍을 연습해야겠다는 생각이 들었다.
'Java' 카테고리의 다른 글
| 코딩 테스트에서 잘못 사용했던 Object.clone() (0) | 2025.11.04 |
|---|---|
| 디자인 패턴 : 빌더 & 싱글톤 패턴 구현해보기 (with. 이펙티브 자바) (0) | 2025.10.28 |
| 빠트렸던 Java 개념 복습하기 (0) | 2025.09.30 |
| 객체지향 학습 (1) (0) | 2025.09.09 |