Skip to content

Repository files navigation

reservation-service

예약 생명주기를 담당하는 Spring Boot 기반 마이크로서비스입니다.대량의 동시 예약 신청 트래픽을 제어하기 위해 Redisson 분산 락 아키텍처를 도입했으며,예약 성공 및 상태 변경 시 아웃박스(Outbox) 패턴을 통해 이벤트를 발행합니다.

주요 기능

  • 상품 생성 Kafka 이벤트 수신 후 예약 자동 생성
  • 예약 목록/단건 상세 조회 REST API 제공
  • 분산 락(Redisson) 기반 안전한 동시 예약 신청 제어
  • 구매자/판매자 상호 예약 확정 및 취소 처리
  • 트랜잭션 보장(Outbox 패턴)을 통한 예약 완료/취소/실패 이벤트 발행
  • Promtail 호환 설정을 통한 분산 로그 수집

기술 스택

  • Java 21
  • Spring Boot 3.5.13
  • Spring Cloud 2025.0.2
  • Spring Data JPA
  • Querydsl 6.8
  • Spring Data Redis & Redisson
  • Spring Kafka
  • Eureka Client
  • Spring Security & JWT
  • PostgreSQL
  • Docker, Docker Compose
  • Grafana Alloy (Promtail config format)

프로젝트 구조

src/main/java/org/pgsg/reservation
├── application      # 유스케이스, 서비스, 포트, 커맨드/결과 DTO
├── domain           # 예약 도메인 모델, 값 객체, 도메인 예외
├── infrastructure   # JPA 레포지토리 구현체, Kafka, Redis 인프라 어댑터
└── presentation     # REST 컨트롤러, API 요청/응답 DTO, 분산 락 제어 패사드

사전 준비

  • JDK 21
  • Docker, Docker Compose
  • GitHub Package Registry 접근 권한
  • 실행 환경에 맞는 Config Server, Eureka, Kafka, DB 설정

org.pgsg:common 패키지를 GitHub Package Registry에서 내려받기 때문에 Gradle 인증 정보가 필요합니다.

# ~/.gradle/gradle.properties
gpr.user=GITHUB_USERNAME
gpr.token=GITHUB_TOKEN

또는 환경변수로 지정할 수 있습니다.

export GPR_USER=GITHUB_USERNAME
export GPR_TOKEN=GITHUB_TOKEN

설정

애플리케이션은 기본적으로 .env, Config Server, Eureka를 사용합니다.

spring:
  application:
    name: reservation-service
  profiles:
    active: kafka, topics, dev
  config:
    import:
      - "optional:file:.env[.properties]"
      - "optional:configserver:"

로컬 또는 배포 환경에서는 다음 값이 필요합니다.

변수 설명
SERVER_IP Eureka 서버 URL 목록
SERVER_PORT 외부 포트 바인딩용 변수
DB_NAME 연결 및 생성 대상 PostgreSQL 데이터베이스 이름
DB_USERNAME PostgreSQL 데이터베이스 사용자명
DB_PASSWORD PostgreSQL 데이터베이스 접근 비밀번호
REDIS_HOST 분산 락 및 캐시용 Redis 컨테이너 접속 호스트명
MANAGEMENT_ZIPKIN_TRACING_ENDPOINT 트레이싱 수집용 외부 Zipkin API 엔드포인트 URL
KAFKA_SSL_PATH 컨테이너 내부에 마운트되는 Kafka SSL truststore 파일 경로
AR_IMAGE_PATH Google Artifact Registry 등 도커 이미지 배포 저장소 경로
IMAGE_TAG 도커 이미지 빌드 및 배포용 태그 버전
GPR_USER GitHub Package Registry 사용자명
GPR_TOKEN GitHub Package Registry 토큰

Kafka topic 설정은 Config Server 또는 활성 프로필 설정에서 제공되어야 합니다.

설정 키 설명
prod-reservation-completed 예약 완료 이벤트 발행 topic
prod-reservation-cancelled 예약 취소 이벤트 발행 topic
prod-reservation-tradefail 거래 실패로 인한 예약 실패 처리 수신 topic
prod-product-created 상품 생성 이벤트 수신 topic
prod-product-failed 상품 생성 실패 이벤트 수신 topic

Docker 실행

로컬 Docker Compose는 trade-service와 로그 수집용 Alloy 컨테이너를 함께 실행합니다.

docker compose up --build

기본 포트 매핑은 다음과 같습니다.

대상 포트
Host 19020
Container 8085

Compose 실행 전 외부 네트워크가 필요합니다.

docker network create pgsg-network

Docker 빌드 시 ~/.gradle/gradle.properties가 BuildKit secret으로 전달됩니다.

API

예약 생성

POST /api/v1/reservations

예약 목록 조회

GET /api/v1/reservations?page=0&size=10
  • page: 0 이상의 페이지 번호
  • size: 1 이상의 페이지 크기 (기본값: 10)
  • sellerName: 판매자 이름 필터 (선택)
  • buyerName: 구매자 이름 필터 (선택)
  • productName: 상품명 필터 (선택)
  • status: 예약 상태 필터 (선택)
  • productId: 상품 ID 필터 (선택)

예약 상세 목록 조회

GET /api/v1/reservations/{reservationId}

예약 신청

PATCH /api/v1/reservations/{reservationId}

구매자 사유 취소

PATCH /api/v1/reservations/{reservationId}/cancel/buyer

결제 완료

PATCH /api/v1/reservations/{reservationId}/paymentconfirm

판매자 사유 취소

PATCH /api/v1/reservations/{reservationId}/cancel/seller

예약 만료 (관리자)

PATCH /api/v1/reservations/{reservationId}/expire

예약 완료

PATCH /api/v1/reservations/{reservationId}/complete

거래 완료

PATCH /api/v1/reservations/{reservationId}/tradeconfirm

예약 및 거래 상태 관리 로직

  • 인증 사용자 기반 상태 저장: Bearer Token을 이용해 요청한 현재 사용자의 권한을 검증하고,해당 예약건에 대한 구매자 또는 판매자의 개별 상태를 저장합니다.

최종 예 완료 및 이벤트 발행 조건 (COMPLETED):

  • 구매자의 결제 완료(paymentconfirm)와 판매자의 채팅 수락(complete) 두 개의 상호 확정이 모두 이루어져야 합니다.
  • 구매자와 판매자가 모두 예약 완료 처리를 마치는 시점에 최종적으로 거래 상태가 COMPLETED로 전환되며, 외부 서비스 전파를 위한 예약 완료 이벤트 발행이 요청됩니다.

이벤트 흐름

수신 이벤트

prod-product-created topic의 상품 타임 이벤트를 수신해 예약를 생성합니다.

{
	"productId": "00000000-0000-0000-0000-000000000000",
	"name": "상품명",
	"price": 10000,
	"endTime": [ 2026,5,21,12,24,41 ],
	"sellerId": "00000000-0000-0000-0000-000000000000",
	"sellerName": "판매자"
}

prod-trade-completed topic의 거래 완료 이벤트를 수신해 예약은 완료합니다.

{
	"tradeId": "00000000-0000-0000-0000-000000000000",
	"reservationId": "00000000-0000-0000-0000-000000000000",
  "productId": "00000000-0000-0000-0000-000000000000"
}

발행 이벤트

서비스는 common 모듈의 Outbox 이벤트를 통해 다음 이벤트 등록을 요청합니다.

  • 예약 완료: prod-reservation-completed
  • 예약 취소: prod-reservation-cancelled
  • 예약 실패: prod-reservation-tradefail

로그 수집

promtail-config.ymldeploy/promtail-config.yml/logs/*.log 파일을 수집해 Loki 엔드포인트로 전송합니다. 로컬 Compose와 운영 Compose 모두 Grafana Alloy를 Promtail config format으로 실행합니다.

배포

운영 Compose 파일은 deploy/docker-compose.prod.yaml에 있습니다.

docker compose -f deploy/docker-compose.prod.yaml up -d

운영 환경에서는 다음 경로를 사용합니다.

경로 용도
/opt/reservation-service/ssl Kafka SSL 인증서
/opt/reservation-service/logs 애플리케이션 로그
/opt/reservation-service/promtail-config.yml 로그 수집 설정

테스트

./gradlew test

테스트는 도메인 모델, 애플리케이션 서비스, 영속성 어댑터, Kafka Consumer, 컨트롤러, 아키텍처 규칙을 검증합니다.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages