이 레포는 팀 프로젝트로 진행한 식당 예약·결제 플랫폼에서
제가 맡았던 예약·결제 도메인을 중심으로 개인적으로 정리해 둔 버전입니다.
(원본 팀 프로젝트: 링크)
프로젝트 진행 일정, 와이어프레임, 협업 전략 등은 별도 문서에 정리했습니다.
👉 협업 아카이브 바로가기
- TablePick-Payment-Server
→ 예약 서비스와 분리된 결제 서버, Kafka 이벤트 및 외부 결제 API 처리 담당 - TablePick-External-Payment-API
→ 외부 결제 API 서버 시뮬레이션, 테스트 및 장애 대응 로직 검증용
TablePick은 대규모 트래픽을 처리할 수 있는 레스토랑 예약·결제 플랫폼입니다.
예약 슬롯 관리, 결제 처리, 성능 최적화를 중점적으로 개선했습니다.
- 알림(Alarm): 예약 스케줄링과 푸시 알림을 관리하며, 회원별 알림 내역을 제공합니다.
- 게시판(Board): 게시글 작성, 수정, 삭제 및 태그 관리 기능을 통해 커뮤니티를 운영할 수 있습니다.
- 회원(Member): 카카오·구글 소셜 로그인을 지원하고, 회원 정보 및 예약·게시글 내역을 조회·관리할 수 있습니다.
- 예약(Reservation): 사용자는 예약을 생성·취소하고, 가능한 예약 시간을 실시간으로 확인할 수 있습니다.
- 결제(Payment): 예약 과정과 연동된 결제 처리, 내역 조회, 결제 취소 기능을 제공합니다.
- 식당(Restaurant): 전체 식당 목록과 키워드·카테고리 기반 검색, 상세 조회 기능을 지원합니다.
> 원본 ERD : [ERDCloud 보기](https://www.erdcloud.com/d/pKQZMxpT7NpDe9wn9)
- Backend: Java 21, Spring Boot
- Infra / Data: Kafka, MySQL, Redis, Docker
- Testing / Observability: k6, Grafana, Prometheus
-
문제
-
해결
JdbcTemplate기반으로 전환하고 Batch(3000) 적용.
-
결과
방식 실행 시간 개선율 JPA + IDENTITY 2,010,952 ms - JdbcTemplate 73,243 ms 약 96.36% 개선 JdbcTemplate + Batch(3000) 48,092 ms 약 97.61% 개선 - 추가로 멀티스레드 병렬 처리 / 체크포인트 기반 롤백 설계안을 마련해 대규모 트래픽 대비.
-
추가 계획
- Spring Batch / Quartz로 삽입 스케줄링 최적화.
- 초대용량 환경에서는 Kafka 기반 비동기 처리 도입 검토.
-
문제
- 동시 요청 150명, 수용 인원 100명, 스레드풀 32 환경에서
동일 슬롯에 대해 공유락(S) → 배타락(X) 전환 시 충돌로 데드락 발생. saveAndFlush()적용으로 데드락은 해소했지만, 예약 수 불일치(정합성) 문제는 남아있었음.
- 동시 요청 150명, 수용 인원 100명, 스레드풀 32 환경에서
-
결과
- 락 전략:
- 낙관적 락 실행 시간: 3071ms
- 비관적 락 실행 시간: 909ms → 3.38배 개선
- 트랜잭션 범위 축소:
- 대기 시간 평균 40% 개선, 최대 50% 개선 (동시요청 20 기준)
- 락 전략:
-
장애 대비
- 결제 API 장애 시 전체 롤백 대신
3분 주기 보정 스케줄러를 통해 결제 ID 누락을 자동 보정 → 결과적 일관성 확보
- 결제 API 장애 시 전체 롤백 대신
-
추가 계획
- 락 경합 모니터링을 Grafana 대시보드에 시각화하여 SLA 관점에서 추적
- 분산 락(Redis 기반) 검토로 DB 락 부담 완화
- CQRS 패턴을 적용해 조회 부하와 예약/결제 트랜잭션 분리
-
배경
- 결제 장애가 예약 흐름 전체로 전파되는 문제가 있어, 관심사 분리(결제 서버 분리) 및 확장성 확보가 필요했습니다.
-
설계
- 예약 서비스 ↔ 결제 서비스 분리 배치.
- 동기 REST 호출 중심 흐름을 Saga(보상 트랜잭션) + Kafka 이벤트로 전환해 결제 지연/장애의 영향 범위를 축소.
- 핵심 이벤트
ReservationCreated→ 결제 요청PaymentSucceeded/Failed→ 예약 확정/보상(취소) 처리
- 멱등성 키(reservationId)로 중복 소비 방지, 파티션 키로 순서 보장(동일 예약 단위).
본 시스템은 예약과 결제가 분리된 구조로, **Saga 패턴(보상 트랜잭션)**을 적용하여 장애 전파를 최소화했습니다.
예약 요청 → 예약 서비스(DB 저장) → 결제 이벤트 발행 → 결제 서비스 → PG사 승인/취소 처리
결제 실패 이벤트 발생 시 → 예약 서비스에서 결제 취소/롤백 처리 → 데이터 정합성 보장
- 처리량(Request Rate): 126.8 r/s
- 평균 지연시간: 5초
- GitHub Actions 빌드 시간: 2분 41초
- 처리량(Request Rate): 93.2 r/s
- 평균 지연시간: 9초
- GitHub Actions 빌드 시간: 1분 46초
- 처리량(Request Rate): 285.39 r/s (약 2.9배 증가)
- 평균 지연시간: 1~2초
-
배경
- 기존 단일 서버 구조에서는 예약/결제 코드가 한 레포에 묶여 있어, 결제 로직 수정 시 전체 서버를 다시 빌드/배포해야 했음.
- 결제 서버를 별도 마이크로서비스로 분리하면서 독립 배포 가능.
-
결과 (GitHub Actions 빌드 시간 비교)
- 분리 전: 전체 서버 빌드/배포 2분 41초
- 분리 후: 결제 서버만 배포 → 1분 46초
결제 서버 분리를 통해 배포 속도가 약 35% 개선되었으며, 운영 시 장애 영향 범위도 축소.
-
안정성
- 재시도(Backoff) + DLQ: 일시 장애 시 자동 재처리, 영구 실패는 DLQ로 격리.
- Outbox 패턴(계획): DB 트랜잭션과 이벤트 발행을 분리·안정화(이벤트 유실/중복/순서 보장).
-
운영 포인트
- Topic/Partition:
payments토픽, 예약ID 기반 파티셔닝(동일 예약 순서 보장). - Idempotency:
reservationId+ 상태머신(READY→PAID/FAILED)로 중복 처리 차단. - 모니터링: 소비 지연(consumer lag), 재시도/실패율, DLQ 수치 대시보드화.
- Topic/Partition:
-
추가/고도화 계획
- Outbox를 트랜잭션 로그 테이블 기반으로 구현 + Outbox Relayer 배치.
- Exactly-once 흐름 강화: 소비측 멱등키 캐시/테이블, Producer idempotence 설정.
- 보상 트랜잭션 시나리오 문서화(부분 실패 케이스별 롤백/보상 단계).
- 부하 프로파일 확대: VU/러닝타임/에러율 스윗스팟 산출 후 오토스케일 기준 반영.
- 클라우드: AWS (단일 VPC, 동일 AZ)
- 애플리케이션
- 예약 서비스: EC2 t3.medium (2 vCPU, 4GiB)
- 결제 서비스: EC2 t3.medium (2 vCPU, 4GiB)
- 데이터베이스
- Amazon RDS for MySQL – db.t3.large (2 vCPU, 4GiB)
- 메시징
- Apache Kafka 클러스터 (단일 브로커) – EC2 (동일 VPC, 내부 통신)
- 오토스케일링: 비활성 (고정 인스턴스, 테스트 간 동일 조건 유지)
- k6 부하 테스트
- VU(가상사용자) = 5000
- 요청 패턴: 예약→결제 플로우 단일 엔드포인트 중심
- 각 시나리오 사전 워밍업 30s 후 측정(콜드 스타트 영향 최소화)
- DB 인덱스 최적화: 예약 슬롯/식당 데이터 조회 성능 개선
- Outbox 패턴 안정화: 이벤트 발행의 신뢰성 보장 (트랜잭션 경계 명확화)
- 데이터 정합성 보강: 예약 취소/결제 취소 시 트랜잭션 처리
- 에러 핸들링 강화: 외부 결제 API 장애 상황 시 재시도 & 보상 처리
https://drive.google.com/file/d/1ZoBAgl4vPlDY5-KWDxwHWnN-WZnCq-e9/view?usp=sharing







