[프로젝트 회고] 당일 남는 음식을 싸게 구매할 수 있는 서비스
- 프로젝트명: 꿀띱(KKULDDIP)
- 기간: 7.7 - 8.17 (총 6주)
- 나의 역할: 백엔드 리더
SSAFY 2학기 과정중 공통 프로젝트 기간에 개발한 서비스.
원래 공통 프로젝트를 7주 진행하는 걸로 알았는데 이번에는 6주로 진행되었다.
1주차와 2주차에는 싸피 강의 듣기, 그라운드 룰 정하기, 컨벤션 정하기, 기획 구체화 등 기본적인 것들을 하느라 사실상 개발 가능한 시간은 4주 남짓이었다.
싸피를 하면서 진행하는 프로젝트들에서 개인적인 목표는 '내가 해보지 않은 것들을 적극적으로 시도하고, 해본 것들은 이해도를 높이자' 이다.
이번 프로젝트는 내 목표를 충족시키기에 아주 좋은 기회였다.
'음식을 구매한다' 는 주문, 결제가 포함된 context이다. 평소 유튜브에서 여러 서비스 기업의 컨퍼런스를 즐겨보는 나로서는 적용시켜 보기에 아주 좋은 연습의 장이 될 것이라 생각했다.
따라서 이번에 DDD(Domain Driven Design)를 일부 도메인에 적용했다.
왜 전체로 적용시키지 않았냐면 우리 팀은 전공 3명 그리고 비전공 3명, 포지션은 백엔드 3(전공 2, 비전공1) / 프론트엔드 2(비전공 2) / 풀스택 1(전공 1)으로 이루어져 있었다. 백엔드를 개발한지 오래되지 않았거나 거의 처음인 사람들이 대부분이여서 레이어드 아키텍처도 사용하는게 시간적으로 그렇고 잘 알려주고 이끌기에 좋을 것이라 판단했다.
기획
기존에 존재하는 럭키밀(https://luckymeal.io/)과 거의 동일한 서비스이다.
차이점
- 럭키밀은 랜덤 럭키백 하나만 존재. 꿀띱은 다양한 상품을 판매할 수 있음. 즉, 랜덤뿐만 아니라 지정된 상품을 싸게 팔 수도 있다. (자유도 $\uparrow$)
- AI를 활용한 매출 분석 서비스 제공 (매출 예측, 재고 관리 등)
- 라이브 방송을 통한 홍보
ERD 설계

주문, 결제, FCM 푸시 알림, 가게 관리, 상품 관리, 리뷰, 스트리밍, 쿠폰 기능 등이 있다보니 테이블이 엄청 많다..
초반에 완벽하게 설계하기 보다는 80~90%를 작성해놓고 나머지 사소한 것들은 개발하면서 회의를 통해 수정하거나 추가했다. 새로 접하는 도메인/기술이다 보니 시행착오를 겪을 수 밖에 없을 것이라 예상했다.
아키텍처

(+ 사진에는 없지만 openVidu도 있다)
싸피에서 주는 EC2 한 대에 모두 올라갔다.(m6g.xlarge였나..? 그래도 나름 괜찮은 거 할당해 준다.)
시간상 MVP를 뽑아내는 거에 집중했기에 모놀리식으로 스프링 부트 어플리케이션을 올렸다(올려야만 했다..)
아키텍처 그리려고 백엔드 팀과 함께 cloudcraft를 처음 사용해봤는데 동시작업 쪽에 문제가 많아 아쉬웠다. 계속 롤백되고 그런 점이 있었음.. 혼자 그리는 것은 쾌적했다.
인프라 구축
백엔드 관련 인프라 대부분을 내가 담당했다. 방학 때, 홈 클라우드를 구축한 경험이 아주 큰 도움이 됐다.
인프라도 새로운 것들을 하려고 노력했다.
크게 나눠보면 다음과 같다.
- Gitlab CI
- Jenkins + Blue/Green deployment
- DB
- Monitoring (Prometheus / Grafana)
Gitlab CI
깃랩CI는 깃허브 액션과 다르게 CI서버를 무료로 주지 않는다. 그래서 gitlab runner라는 걸 ec2에 설치해서 해당 샌드박스안에서 ci를 돌아가게 해야한다. 이거는 그냥 딸깍 딸깍이라 쉬웠다.
CI는 간단하게 구성했다. MR이 올라오거나 주요 브랜치에 푸시되었을 때, gradle clean build --refresh-dependencies 이 성공하는지 확인하는 파이프라인만 만들었다.
Jenkins + Blue/Green deployment
간단하게 gitlab ci로 도커 이미지 만들고 기존 도커 컨테이너 내리고 새로운 컨테이너 올리는 방식으로 해도 됐지만 무중단 배포를 통해 사용자(여기선 프론트엔드)가 불편을 느끼게 만들고 싶지 않았다. 그래서 간단한 블루/그린 배포를 택했다.
총 3개의 파이프라인을 구성했다.
- 빌드 테스트
- 도커 이미지 빌드
- 배포 시도

빌드테스트에선 웹훅을 통해 develop 브랜치에 대한 push events가 도착하면 clone => build => 공유 디렉토리로 빌드된 jar파일 복사 순으로 스테이지를 구성했다.
도커 이미지 빌드에선 공유 디렉토리에 있는 jar파일을 가지고 Dockerfile을 작성하고 도커 이미지를 빌드한다.
배포 시도 부분이 가장 까다로웠다. 다음과 같이 작성했다.
- nginx conf 파일, docker-compose 파일, deploy 쉘스크립트가 있는 브랜치 clone
- nginx 설치/상태 확인
- jenkins credentials file을 .env로 저장
- deploy.sh 실행
- 현재 활성 환경 확인 (Blue인지 Green인지)
- 새로 활성화 될 환경 docker-compose up
- 헬스 체크 (3초 간격으로 최대 30번 시도)
- 정상 구동 시, nginx conf 파일 복사 후 심볼릭 링크 생성
- nginx -t 통과 시, nginx reload
- 이전 환경 종료
- 상태 최종 확인
DB
Mysql 8.0과 Redis 모두 도커로 올리지 않고 네이티브로 설치했다. 모놀리식이므로 오케스트레이션할 필요성을 못느꼈고, 굳이 도커를 거침으로써 성능을 down시킬 필요 없다고 판단했다.
Monitoring (Prometheus / Grafana)

이것도 딸깍 딸깍이라 하는건 쉬웠다.
기본 대시보드는 19004번을 import했고, Request count와 Response Time 쿼리를 수정했다.
DDD를 적용해보며
처음보는 여러 용어들이 마구 쏟아져 나왔다.
- 유비쿼터스 언어 (Ubiquitous Language)
- 애그리거트 (Aggregate)
- 바운디드 컨텍스트 (Bounded Context)
- 4계층 (Presentation / Application / Domain / Infrastructure)
등등... 이해하는 데에 매우 애를 먹었다. 지금도 완벽하게 이해는 못한 것 같지만 어느정도 감이 생겼다. 다음 프로젝트에도 계속 적용해보며 이해도를 더욱 높이려고 한다.
바운디드 컨텍스트의 경계를 어디까지 해야하는지, 애그리거트 루트를 어떻게 만들어야 할지, 각 계층의 패키지 구조를 어떻게 잡아야 할지,, 고민의 연속이었다.
주문 관련한 대표적인 서비스 '배달의 민족'의 WOOWACON을 보면서 각종 도메인을 이해하려 했다.
아래 자료들을 통해 많은 부분들을 배울 수 있었다.
https://youtu.be/704qQs6KoUk?si=Dz4enQmKDm66LS_g
https://youtu.be/BnS6343GTkY?si=YRbXlT7JFCaOuk4c
https://youtu.be/sLG5n_pXWK0?si=FhruDrGdWoSsgXBX
https://tech.kakaopay.com/post/backend-domain-driven-design/
카카오페이 여신코어 DDD(Domain Driven Design, 도메인 주도 설계)로 구축하기 | 카카오페이 기술 블로
카카오페이의 여신업무 내재화 프로젝트를 DDD를 적용하여 구축한 내용을 공유하고자 합니다.
tech.kakaopay.com
https://youtu.be/dG2Dr3jhSZg?si=wRamESAw5Y0xxshs
https://youtu.be/mSpaws5bDTc?si=cIPElS96__G5MR7H
위의 자료들이 지금 프로젝트에서 가장 큰 도움이 되었던 것 같고, 이외에도 많은 동영상들을 시청한 게 있는데 그것들은 MSA나 다른 도메인과 관련된 것들이라 해당 포스트에선 첨부하지 않겠다.
토스
https://youtube.com/@toss_official
우아한테크
https://youtube.com/@woowatech
당근테크
https://youtube.com/@daangntech
네이버d2
https://youtube.com/@naver_d2
카카오테크
https://youtube.com/@kakaotech
위 채널들에 재미있는 주제들이 많으니 들어가서 시청하면 좋을 것 같다!
Order 도메인
개발하면서 가장 머리가 아프면서도 재밌었던 부분이었다. 내가 처음부터 맡았던 부분이라 가장 신경을 많이 썼다.
개발하기에 앞서 러프하게 주문 플로우부터 작성해봤다.
1. 사용자로부터 주문 요청
- 주문 생성
- 할인된 가격 검증
- 가게에서 적용한 판매가
- 사용된 쿠폰이 올바른지
결제 요청 (비동기)- 주문 상태 변경 (결제 Pending)
- 사용자에게 결제하라고 응답 반환 → 이제 프론트에서 결제 페이지로 이동
2. 결제 완료 이벤트 수신
- 이벤트의 주문 번호로 Order Entity 찾기
- 주문 상태 변경 (결제 완료 — 주문 확인 중_사장님)
- Store 쪽으로 해당 주문 확정 요청
- 푸시 알림 요청 (system → store)
- 푸시 알림 요청 (system → user)
3. 주문 확정 이벤트 수신
- 이벤트의 주문 번호로 Order Entity 찾기
- 주문 상태 변경 (주문 완료)
- 푸시 알림 요청 (system → user)
초기에는 픽업 완료까지는 미처 고려하지 못했는데, 고려한 후에도 위 플로우는 변하지 않았고 4. 픽업 완료 이벤트 수신부만 추가됐다.
주문 플로우를 먼저 생각하니까 애그리거트 루트와 도메인 모델을 우려와 달리 수월하게 작성할 수 있었던 것 같다.
Payment 도메인과 Notification 도메인
이 도메인들은 다른 전공자분이 작업해 놓은걸 내가 중간에 이어 받았다. 담당자분이 기획하시면서 초기에 간단하게 테스트용(클로드(클로드 코드 아님)로 쌩 복사/붙여넣기 바이브 코딩하신 걸로 추정)으로 만들어 둔걸 또 클로드를 활용해 DDD로 변환해 놓으셨었는데 상당 부분 마음에 들지 않아 리팩토링을 진행했다.
덕분에 토스 페이먼츠와 FCM을 학습할 수 있어 오히려 좋았다?
주문 생성과 결제 관련해서 요청이 연속으로 두 번오면 동일한 주문이 두 개 생성(orderId는 다름)되거나, 주문 상태가 이상하게 바뀌는 경우(토스 페이먼츠 confirm 할 때, 같은 orderId로 진입하면 하나가 이미 처리중이라 fail 되는 문제)가 있었다. 처음엔 JPA @Version을 이용한 낙관적 락을 생각해봤는데 애초에 요청 처리 순서는 뭐 어떻게 할 수 없어서 근본적인 원인을 제거할 수 없다고 판단했다. 그래서 Redis를 이용해 분산락 개념을 응용하여 critical section을 보호할 수 있게 했다.
푸시 알림의 경우, 카프카를 쓰고 싶었는데 시간이 부족해 Redis Z-Set(발송시간을 score로 함)을 이용해서 메시지 큐를 구현했다.
마치며
본문에는 적진 않았지만 이것저것 많이 시도한게 많다. (가상 스레드, 인덱싱 등)
코드 레빗
SSAFY Git은 사설 깃랩이라 코드 레빗을 못쓸줄알았는데, 어찌저찌 되더라. 덕분에 MR이 올라왔을 때, 각 담당자가 1차적으로 코드 레빗의 피드백을 반영하고 2차로 Human Review를 진행할 수 있었다.
바이브 코딩
이번 프로젝트에 Claude Code를 처음 써봤는데, planning mode 너무 좋은 것 같다. 이게 아니었다면 기간 내에 MVP를 뽑아내지 못했을 것 같다. 물론, 자동 반영 모드로 안하고 하나하나 승인 모드로 하는게 좋은 것 같다. 내가 의도한 대로 작성하고 있는지, 원한 게 아니라면 내가 만족할 때까지 추가 지시 사항을 내릴 수 있다.
이로써 가지고 있는 AI/ide는 GPT, Cursor, Claude, Kiro ...
주로 사용하는 건 GPT5와 Claude code이다. GPT5는 긴 호흡의 코딩보다는 짧은 코드/에러/잡 지식?에 사용하기 좋고, 클로드 코드는 개발에 사용하기 적합한 것 같다.
아쉬운 점
기획을 너무 크게 잡은 것 같아 다소 완성도가 떨어지는 서비스를 만든 것 같다.
DDD를 적용하고 각 도메인 간의 결합도를 느슨하게 가져가고 싶었는데, 시간도 부족했고 모놀리식으로 구성되어 있어 다른 BC의 레파지토리를 직접 호출하는 경우가 많아졌다.
Order도메인과 Payment 도메인의 주문/결제/확정 까지는 Event로 처리하여 나중에 메시지큐를 사용할 수 있을 때 빠르게 끊어낼 수 있도록 만들었는데, 다른 것들은 개발 막바지로 갈 수록 일단 기능 완성에 치중하여 다른 도메인의 Repository를 DI해와 기능을 구현했다.
다음 프로젝트는 기획의 볼륨을 줄이고 완성도를 높이는 방향으로 진행해, DDD(+ hexagonal)를 더욱 잘 쓸 수 있도록 만들고 기술적으로도 다양한 시도를 해보려 한다.
빠르게 MVP를 뽑아내서 여러 사용자에게 피드백 받고 디벨롭도 할 예정이다.
이를 위해, 인프라도 dev/prod 나눠서 해보려 한다.
재밌었다!
'개발 > 프로젝트 로그' 카테고리의 다른 글
| JetBrains IDE 백준 플러그인 BOJ Helper 개발 (0) | 2026.03.02 |
|---|---|
| 나만의 티스토리 블로그 스킨 제작기 (0) | 2026.01.02 |
| 사설 클라우드 구축하기 - 2 (WireGuard) (4) | 2025.07.03 |
| 사설 클라우드 구축하기 - 1 (1) | 2025.06.29 |
| [프로젝트 회고] 실시간 여행 계획 협업 웹앱 (2) | 2025.06.06 |