Skip to content

Latest commit

Β 

History

35 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🍽️ restaurant-service

식당 정보, μ½”μŠ€ 메뉴, ν˜„μž₯ 체크인 흐름을 κ΄€λ¦¬ν•˜λŠ” μ„œλΉ„μŠ€μž…λ‹ˆλ‹€.
Miche-Let MSA ν™˜κ²½μ—μ„œ λ™μž‘ν•˜λ©°, Gateway / Eureka / PostgreSQL / Redis / Kafka / reservation-service 와 ν•¨κ»˜ μ‚¬μš©λ©λ‹ˆλ‹€.


πŸ“Œ Overview

restaurant-serviceλŠ” λ‹€μŒ 3κ°€μ§€ 도메인을 λ‹΄λ‹Ήν•©λ‹ˆλ‹€.

  • πŸͺ Restaurant

    • 식당 등둝 / λͺ©λ‘ 쑰회 / 검색 / 상세 쑰회
    • 식당 운영 정보 관리
    • μ˜ˆμ•½ μ˜€ν”ˆ μ‹œκ°, 평균 식사 μ‹œκ°„, μ˜μ—…μ‹œκ°„, 운영 μƒνƒœ 관리
  • 🍽️ Course

    • 식당별 μ½”μŠ€ 등둝 / 쑰회
    • μ½”μŠ€ 메뉴 νŒŒνŠΈμ™€ μ •λ ¬ μˆœμ„œ 관리
    • menus[] 기반 menuComposition μžλ™ 생성
    • μ™ΈλΆ€ μ‚¬μš©μžμš© μ½”μŠ€ λͺ©λ‘κ³Ό λ‚΄λΆ€ μ„œλΉ„μŠ€μš© μ½”μŠ€ μš”μ•½ 쑰회 뢄리
  • βœ… Check-in

    • 점주/κ΄€λ¦¬μž 체크인 μš”μ²­ 처리
    • reservation-service와 Feign 동기 ν†΅μ‹ μœΌλ‘œ μ˜ˆμ•½ μƒνƒœ 검증
    • 체크인 둜그 μ €μž₯
    • Kafka reservation.checked-in 이벀트 consume
    • reservationId κΈ°μ€€ 쀑볡 이벀트 λ°©μ–΄

🧱 Package Structure

src/main/java/com/michelet/restaurantservice
β”œβ”€ restaurant
β”‚  β”œβ”€ application
β”‚  β”‚  β”œβ”€ command
β”‚  β”‚  β”œβ”€ query
β”‚  β”‚  β”œβ”€ result
β”‚  β”‚  └─ service
β”‚  β”œβ”€ domain
β”‚  β”‚  β”œβ”€ exception
β”‚  β”‚  β”œβ”€ model
β”‚  β”‚  β”‚  └─ vo
β”‚  β”‚  └─ repository
β”‚  β”œβ”€ infrastructure
β”‚  β”‚  └─ persistence
β”‚  β”‚     └─ query
β”‚  └─ presentation
β”‚     β”œβ”€ controller.external
β”‚     β”œβ”€ controller.internal
β”‚     └─ dto
β”œβ”€ course
β”‚  β”œβ”€ application
β”‚  β”‚  β”œβ”€ command
β”‚  β”‚  β”œβ”€ result
β”‚  β”‚  └─ service
β”‚  β”œβ”€ domain
β”‚  β”‚  β”œβ”€ exception
β”‚  β”‚  β”œβ”€ model
β”‚  β”‚  └─ repository
β”‚  β”œβ”€ infrastructure
β”‚  β”‚  └─ persistence
β”‚  └─ presentation
β”‚     β”œβ”€ controller.external
β”‚     β”œβ”€ controller.internal
β”‚     └─ dto
β”œβ”€ checkin
β”‚  β”œβ”€ application
β”‚  β”‚  β”œβ”€ command
β”‚  β”‚  β”œβ”€ result
β”‚  β”‚  └─ service
β”‚  β”œβ”€ domain
β”‚  β”‚  β”œβ”€ exception
β”‚  β”‚  β”œβ”€ model
β”‚  β”‚  └─ repository
β”‚  β”œβ”€ infrastructure
β”‚  β”‚  β”œβ”€ client
β”‚  β”‚  β”œβ”€ kafka
β”‚  β”‚  └─ persistence
β”‚  └─ presentation
β”‚     β”œβ”€ controller.external
β”‚     └─ dto
β”œβ”€ global
β”‚  β”œβ”€ config
β”‚  └─ exception
β”œβ”€ health
β”‚  β”œβ”€ application
β”‚  └─ presentation
└─ RestaurantServiceApplication

βš™οΈ Tech Stack

  • Java 17
  • Spring Boot 3.5.14
  • Spring Cloud 2025.0.1
  • Spring Data JPA
  • QueryDSL
  • PostgreSQL
  • Redis / Spring Cache
  • Kafka
  • OpenFeign
  • Eureka Client
  • Spring Boot Actuator
  • Micrometer Prometheus
  • Docker
  • GitHub Actions
  • AWS ECR / ECS

🧩 Domain Details

πŸͺ Restaurant

μ‹λ‹Ήμ˜ κΈ°λ³Έ 정보λ₯Ό κ΄€λ¦¬ν•©λ‹ˆλ‹€.

관리 ν•­λͺ©

  • 식당λͺ…
  • μ£Όμ†Œ
  • μ „ν™”λ²ˆν˜Έ
  • μ„€λͺ…
  • μ˜ˆμ•½ μ˜€ν”ˆ μ‹œκ°
  • 평균 식사 μ‹œκ°„
  • 운영 μƒνƒœ
  • μ˜μ—…μ‹œκ°„
  • 점주 ID

μ£Όμš” κΈ°λŠ₯

  • 식당 등둝
  • 식당 λͺ©λ‘/검색 쑰회
  • 식당 상세 쑰회
  • λ‚΄λΆ€ μ„œλΉ„μŠ€μš© 식당 단건 쑰회
  • 점주 ID κΈ°μ€€ 식당 ID 쑰회

μƒνƒœ

OPEN
CLOSED

🍽️ Course

식당별 μ½”μŠ€μ™€ μ½”μŠ€ 메뉴 ꡬ성을 κ΄€λ¦¬ν•©λ‹ˆλ‹€.

관리 ν•­λͺ©

  • μ½”μŠ€λͺ…
  • 가격
  • μ„Έμ…˜ νƒ€μž…
  • 판맀 μƒνƒœ
  • 메뉴 ꡬ성 λ¬Έμžμ—΄
  • κ΅¬μ‘°ν™”λœ μ½”μŠ€ 메뉴 λͺ©λ‘

μ£Όμš” κΈ°λŠ₯

  • μ½”μŠ€ 등둝
  • μ™ΈλΆ€ μ‚¬μš©μžμš© μ½”μŠ€ λͺ©λ‘ 쑰회
  • λ‚΄λΆ€ μ„œλΉ„μŠ€μš© μ½”μŠ€ μš”μ•½ λͺ©λ‘ 쑰회
  • menus[] 기반 menuComposition 생성

μ„Έμ…˜ νƒ€μž…

LUNCH
DINNER

μ½”μŠ€ μƒνƒœ

AVAILABLE
UNAVAILABLE

μ½”μŠ€ 메뉴 파트

AMUSE_BOUCHE
APPETIZER
FISH
MAIN
DESSERT

λ‚΄λΆ€ μ •μ±…

  • ν΄λΌμ΄μ–ΈνŠΈλŠ” menuComposition을 직접 μ „λ‹¬ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
  • μ„œλ²„κ°€ menus[]의 coursePart, menuName, sortOrderλ₯Ό κΈ°μ€€μœΌλ‘œ menuComposition을 μƒμ„±ν•©λ‹ˆλ‹€.
  • μ½”μŠ€ λ©”λ‰΄λŠ” course_id + sort_order 쑰합이 μœ μΌν•΄μ•Ό ν•©λ‹ˆλ‹€.

βœ… Check-in

점주의 ν˜„μž₯ 체크인 μš”μ²­μ„ μ²˜λ¦¬ν•©λ‹ˆλ‹€.

체크인 처리 흐름

OWNER / MASTER 체크인 μš”μ²­
↓
restaurant-service
↓ Feign
reservation-service μ˜ˆμ•½ 검증 및 μƒνƒœ λ³€κ²½
↓
restaurant-service check-in log μ €μž₯

검증 μ±…μž„

체크인 κ°€λŠ₯ μ—¬λΆ€λŠ” reservation-serviceκ°€ νŒλ‹¨ν•©λ‹ˆλ‹€.

  • μ˜ˆμ•½ 쑴재 μ—¬λΆ€
  • μ˜ˆμ•½ 식당 일치 μ—¬λΆ€
  • μ˜ˆμ•½ μƒνƒœ
  • 체크인 κ°€λŠ₯ μ‹œκ°„

restaurant-serviceλŠ” 식당 쑴재 여뢀와 점주 κΆŒν•œμ„ ν™•μΈν•˜κ³ , μ˜ˆμ•½ μƒνƒœ 변경은 reservation-service에 μœ„μž„ν•©λ‹ˆλ‹€.

체크인 둜그

p_restaurant_checkin_log에 체크인 이λ ₯을 μ €μž₯ν•©λ‹ˆλ‹€.

  • restaurantId
  • reservationId
  • visitDate
  • status
  • checkedInBy
  • checkedInAt

쀑볡 λ°©μ–΄

  • μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 레벨: reservationId κΈ°μ€€ κΈ°μ‘΄ 체크인 둜그 확인
  • DB 레벨: reservation_id unique constraint

πŸš€ Redis Cache

반볡 쑰회 κ°€λŠ₯성이 높은 API에 Redis Cache-Aside νŒ¨ν„΄μ„ μ μš©ν•©λ‹ˆλ‹€.

적용 λŒ€μƒ

Cache Name API Key
restaurantDetail GET /api/v1/restaurants/{restaurantId} restaurant:detail:{restaurantId}
restaurantCourses GET /api/v1/restaurants/{restaurantId}/courses restaurant:courses:{restaurantId}

Cache-Aside 흐름

쑰회 μš”μ²­
↓
Redis μΊμ‹œ 확인
↓
cache hit  β†’ DB 쑰회 없이 λ°˜ν™˜
cache miss β†’ DB 쑰회 ν›„ Redis μ €μž₯

TTL μ„€μ •

cache:
  ttl:
    restaurant-detail: ${CACHE_TTL_RESTAURANT_DETAIL:300}
    restaurant-courses: ${CACHE_TTL_RESTAURANT_COURSES:300}

직렬화 μ •μ±…

GenericJackson2JsonRedisSerializerλ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.
record DTO 역직렬화 문제λ₯Ό λ°©μ§€ν•˜κΈ° μœ„ν•΄ ObjectMapper에 νƒ€μž… 정보λ₯Ό ν¬ν•¨ν•˜λ„λ‘ μ„€μ •ν•˜κ³ , BasicPolymorphicTypeValidator둜 ν—ˆμš© νŒ¨ν‚€μ§€λ₯Ό μ œν•œν•©λ‹ˆλ‹€.


πŸ“© Kafka Integration

reservation-serviceμ—μ„œ λ°œν–‰ν•œ 체크인 μ™„λ£Œ 이벀트λ₯Ό consumeν•©λ‹ˆλ‹€.

Topic

reservation.checked-in

Consumer Group

restaurant-service-check-in-consumer

Event Payload

{
  "eventId": "uuid",
  "eventType": "CHECK_IN_COMPLETED",
  "reservationId": "uuid",
  "restaurantId": "uuid",
  "visitDate": "yyyy-MM-dd",
  "checkedInBy": "uuid",
  "checkedInAt": "yyyy-MM-dd'T'HH:mm:ss",
  "eventCreatedAt": "yyyy-MM-dd'T'HH:mm:ss"
}

처리 μ •μ±…

  1. 이벀트 νƒ€μž…μ΄ CHECK_IN_COMPLETED인지 검증
  2. ν•„μˆ˜ ν•„λ“œ λˆ„λ½ μ—¬λΆ€ 검증
  3. reservationId κΈ°μ€€ 체크인 둜그 쑴재 μ—¬λΆ€ 확인
  4. 이미 μ‘΄μž¬ν•˜λ©΄ 쀑볡 이벀트둜 νŒλ‹¨ν•˜κ³  skip
  5. μ‘΄μž¬ν•˜μ§€ μ•ŠμœΌλ©΄ 식당 쑴재 μ—¬λΆ€ 확인 ν›„ check-in log μ €μž₯
  6. λ™μ‹œ 처리 쀑 unique constraint 좩돌이 λ°œμƒν•˜λ©΄ 쀑볡 이벀트둜 νŒλ‹¨ν•˜κ³  skip

πŸ”— Feign Client

체크인 μš”μ²­ μ‹œ reservation-service λ‚΄λΆ€ APIλ₯Ό ν˜ΈμΆœν•©λ‹ˆλ‹€.

Reservation Client

PATCH /internal/reservations/check-in

전달 정보

  • reservationId
  • restaurantId
  • checkedInBy
  • X-User-Id
  • X-User-Role

μ‹€νŒ¨ λ§€ν•‘

reservation-service 응닡 restaurant-service 처리
404 μ˜ˆμ•½ μ—†μŒ
400 μ˜ˆμ•½ 체크인 처리 μ‹€νŒ¨
409 μ˜ˆμ•½ 체크인 좩돌
기타 Feign 였λ₯˜ 잘λͺ»λœ reservation-service 응닡

πŸ” Authentication / Authorization

μ™ΈλΆ€ APIλŠ” Gatewayλ₯Ό 톡해 μ§„μž…ν•˜λ©°, 인증 μ»¨ν…μŠ€νŠΈλŠ” common-auth λͺ¨λ“ˆμ„ 톡해 μ „λ‹¬λ©λ‹ˆλ‹€.

μ£Όμš” Role

  • USER
  • OWNER
  • MASTER

κΆŒν•œ μ •μ±…

κΈ°λŠ₯ ν—ˆμš© Role
식당 등둝 OWNER
식당 λͺ©λ‘/검색 쑰회 USER, OWNER, MASTER
식당 상세 쑰회 USER, OWNER, MASTER
μ½”μŠ€ 등둝 OWNER
μ½”μŠ€ λͺ©λ‘ 쑰회 USER, OWNER
체크인 처리 OWNER, MASTER

🌐 External API

Restaurant API

Base Path: /api/v1/restaurants

Method Path Description
POST /api/v1/restaurants 식당 등둝
GET /api/v1/restaurants 식당 λͺ©λ‘/검색 쑰회
GET /api/v1/restaurants/{restaurantId} 식당 상세 쑰회
GET /api/v1/restaurants/health restaurant-service health 확인

Search Parameters

Parameter Required Description
keyword false 식당λͺ… 검색어
region false μ£Όμ†Œ 기반 μ§€μ—­ 검색어
status false 식당 μƒνƒœ ν•„ν„° (OPEN, CLOSED)
page false νŽ˜μ΄μ§€ 번호
size false νŽ˜μ΄μ§€ 크기
sort false μ •λ ¬ κΈ°μ€€

Course API

Base Path: /api/v1/restaurants/{restaurantId}/courses

Method Path Description
POST /api/v1/restaurants/{restaurantId}/courses μ½”μŠ€ 등둝
GET /api/v1/restaurants/{restaurantId}/courses μ™ΈλΆ€ μ‚¬μš©μžμš© μ½”μŠ€ λͺ©λ‘ 쑰회

Check-in API

Base Path: /api/v1/restaurants

Method Path Description
PATCH /api/v1/restaurants/{restaurantId}/reservations/{reservationId}/check-in μ˜ˆμ•½ 체크인 처리

πŸ”— Internal API

Restaurant Internal API

Base Path: /internal/v1/restaurants

Method Path Description
GET /internal/v1/restaurants/{restaurantId} λ‚΄λΆ€ 식당 단건 쑰회
GET /internal/v1/restaurants/owners/{ownerId}/id 점주 ID κΈ°μ€€ 식당 ID 쑰회

Course Internal API

Base Path: /internal/v1/restaurants/{restaurantId}/courses

Method Path Description
GET /internal/v1/restaurants/{restaurantId}/courses λ‚΄λΆ€ μ½”μŠ€ μš”μ•½ λͺ©λ‘ 쑰회

🧾 Request Examples

식당 등둝

{
  "name": "MicheLet Dining",
  "address": "μ„œμšΈνŠΉλ³„μ‹œ 강남ꡬ ν…Œν—€λž€λ‘œ 123",
  "phone": "02-1234-5678",
  "description": "νŒŒμΈλ‹€μ΄λ‹ λ ˆμŠ€ν† λž‘",
  "reservationOpenAt": "10:00:00",
  "avgMealDurationMin": 90,
  "status": "OPEN",
  "businessHours": "MON-FRI 11:00-20:00 / SAT,SUN CLOSED"
}

μ½”μŠ€ 등둝

{
  "name": "Dinner Course",
  "price": 150000,
  "sessionType": "DINNER",
  "status": "AVAILABLE",
  "menus": [
    {
      "coursePart": "AMUSE_BOUCHE",
      "menuName": "ν•œμš° 타λ₯΄νƒ€λ₯΄",
      "sortOrder": 1
    },
    {
      "coursePart": "APPETIZER",
      "menuName": "제철 μƒλŸ¬λ“œ",
      "sortOrder": 2
    },
    {
      "coursePart": "FISH",
      "menuName": "제철 생선 ꡬ이",
      "sortOrder": 3
    },
    {
      "coursePart": "MAIN",
      "menuName": "μ–‘κ°ˆλΉ„",
      "sortOrder": 4
    },
    {
      "coursePart": "DESSERT",
      "menuName": "바닐라 무슀",
      "sortOrder": 5
    }
  ]
}

πŸ§ͺ Test

ν…ŒμŠ€νŠΈλŠ” μ•„λž˜ μ˜μ—­μ„ ν¬ν•¨ν•©λ‹ˆλ‹€.

  • βœ… Restaurant Query Service Test
  • βœ… Restaurant Controller Test
  • βœ… Restaurant Internal Controller Test
  • βœ… Course Command Service Test
  • βœ… Course Query Service Test
  • βœ… Course Controller Test
  • βœ… Course Internal Controller Test
  • βœ… CheckInCompletedEventHandler Test
  • βœ… CheckInCompletedEventConsumer Test
  • βœ… Redis Cache Test
  • βœ… QueryDSL Repository Test

μ‹€ν–‰

./gradlew clean test

πŸ§ͺ HTTP Scenario Test

HTTP Client 기반 MVP / λ°°ν¬ν™˜κ²½ ν…ŒμŠ€νŠΈ νŒŒμΌμ„ μ œκ³΅ν•©λ‹ˆλ‹€.

src/test/http
β”œβ”€ checkin-event-outbox-run.http
β”œβ”€ checkin-event-outbox-setup.http
β”œβ”€ restaurant-cache.http
└─ restaurant-internal.http

src/test/mvp
β”œβ”€ owner.http
β”œβ”€ user.http
β”œβ”€ owner-checkin.http
β”œβ”€ prod-restaurant-api-scenario.http
β”œβ”€ prod-full-checkin-e2e.http
└─ sql
   β”œβ”€ seed_mvp_data.sql
   └─ reset_mvp_data.sql

λ°°ν¬ν™˜κ²½ μ‹œλ‚˜λ¦¬μ˜€

  • OWNER νšŒμ›κ°€μž… / 둜그인
  • 식당 등둝
  • μ½”μŠ€ 등둝
  • USER νšŒμ›κ°€μž… / 둜그인
  • 식당 λͺ©λ‘ 쑰회
  • 식당 상세 쑰회
  • μ½”μŠ€ λͺ©λ‘ 쑰회
  • νƒ€μž„μŠ¬λ‘― 생성 / 쑰회
  • λŒ€κΈ°μ—΄ μž…μž₯
  • μ˜ˆμ•½ 생성
  • 체크인 처리
  • 쀑볡 체크인 확인

체크인 ν…ŒμŠ€νŠΈ μ£Όμ˜μ‚¬ν•­

체크인은 μ˜ˆμ•½ μ‹œμž‘ μ‹œκ° κΈ°μ€€ μ œν•œλœ μ‹œκ°„ μ•ˆμ—μ„œλ§Œ κ°€λŠ₯ν•©λ‹ˆλ‹€.
λ°°ν¬ν™˜κ²½ ν…ŒμŠ€νŠΈμ—μ„œλŠ” ν˜„μž¬ ν•œκ΅­ μ‹œκ°„ κΈ°μ€€μœΌλ‘œ slotStartTime을 μ„€μ •ν•˜κ³ , νƒ€μž„μŠ¬λ‘― 쑰회 κ²°κ³Όμ—μ„œ μ •ν™•νžˆ μΌμΉ˜ν•˜λŠ” timeSlotIdλ₯Ό μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.


πŸ“Š Load Test

k6 기반 쑰회 API λΆ€ν•˜ν…ŒμŠ€νŠΈ 슀크립트λ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€.

load-tests/restaurant
β”œβ”€ restaurant-read-as-is.js
└─ restaurant-read-to-be-cache.js

ν…ŒμŠ€νŠΈ λͺ©μ 

  • Redis μΊμ‹œ 적용 μ „/ν›„ 쑰회 μ„±λŠ₯ 비ꡐ
  • 반볡 쑰회 μ‹œ DB select κ°μ†Œ μ—¬λΆ€ 확인
  • cache hit/miss μ§€ν‘œ 확인
  • p95 / p99 응닡 μ‹œκ°„ 확인

πŸ“ˆ Monitoring

Actuator와 Prometheus endpointλ₯Ό λ…ΈμΆœν•©λ‹ˆλ‹€.

/actuator/health
/actuator/metrics
/actuator/prometheus

Prometheus / Grafanaμ—μ„œ μ•„λž˜ μ§€ν‘œλ₯Ό 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

  • HTTP request count
  • JVM heap / non-heap memory
  • CPU
  • HikariCP connection pool
  • Redis cache hit/miss
  • Kafka consumer μƒνƒœ

πŸ› οΈ Local Development

1. ν•„μˆ˜ μ„ ν–‰ μ„œλΉ„μŠ€

μ•„λž˜ μ„œλΉ„μŠ€κ°€ λ¨Όμ € μ‹€ν–‰λ˜μ–΄ μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€.

  • PostgreSQL
  • Redis
  • Kafka
  • Eureka Server 선택
  • API Gateway 선택
  • reservation-service 선택

체크인 APIλ₯Ό λ‘œμ»¬μ—μ„œ μ‹€μ œλ‘œ κ²€μ¦ν•˜λ €λ©΄ reservation-serviceκ°€ ν•„μš”ν•©λ‹ˆλ‹€.


2. ν™˜κ²½ λ³€μˆ˜ μ€€λΉ„

.env.example κΈ°μ€€μœΌλ‘œ ν•„μš”ν•œ κ°’μž…λ‹ˆλ‹€.

SPRING_PROFILES_ACTIVE=local

SERVER_PORT=19300

DB_URL=jdbc:postgresql://localhost:5432/michelet_db
DB_USERNAME=your_db_username
DB_PASSWORD=your_db_password

POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_DB=michelet_db
POSTGRES_USER=your_db_username
POSTGRES_PASSWORD=your_db_password

REDIS_HOST=localhost
REDIS_PORT=6379

EUREKA_CLIENT_ENABLED=false
EUREKA_DEFAULT_ZONE=http://localhost:8761/eureka/

EUREKA_ENABLED=false
EUREKA_HOST=localhost
EUREKA_PORT=8761

FEIGN_RESERVATION_SERVICE_URL=http://localhost:19500

INTERNAL_AUTH_SECRET=your_internal_auth_secret_at_least_32_bytes
JWT_SECRET=your_jwt_secret_at_least_32_bytes

KAFKA_BOOTSTRAP_SERVERS=localhost:9092
KAFKA_CONSUMER_GROUP_ID=restaurant-service-check-in-consumer
KAFKA_TOPIC_RESERVATION_CHECK_IN_COMPLETED=reservation.checked-in
KAFKA_LISTENER_AUTO_STARTUP=true

CACHE_TTL_RESTAURANT_DETAIL=300
CACHE_TTL_RESTAURANT_COURSES=300

ν™˜κ²½ λ³€μˆ˜ μ„€λͺ…

λ³€μˆ˜λͺ… μ„€λͺ…
SPRING_PROFILES_ACTIVE ν™œμ„± profile (local, docker, prod)
SERVER_PORT restaurant-service μ‹€ν–‰ 포트
DB_URL local/docker profile DB URL
DB_USERNAME local/docker profile DB μ‚¬μš©μžλͺ…
DB_PASSWORD local/docker profile DB λΉ„λ°€λ²ˆν˜Έ
POSTGRES_HOST prod profile PostgreSQL host
POSTGRES_PORT prod profile PostgreSQL port
POSTGRES_DB prod profile PostgreSQL database
POSTGRES_USER prod profile PostgreSQL μ‚¬μš©μžλͺ…
POSTGRES_PASSWORD prod profile PostgreSQL λΉ„λ°€λ²ˆν˜Έ
REDIS_HOST Redis host
REDIS_PORT Redis port
EUREKA_CLIENT_ENABLED local/docker profile Eureka client ν™œμ„±ν™” μ—¬λΆ€
EUREKA_DEFAULT_ZONE local/docker profile Eureka server URL
EUREKA_ENABLED prod profile Eureka client ν™œμ„±ν™” μ—¬λΆ€
EUREKA_HOST prod profile Eureka host
EUREKA_PORT prod profile Eureka port
FEIGN_RESERVATION_SERVICE_URL reservation-service 직접 호좜 URL. λΉ„μ›Œλ‘λ©΄ Eureka name 기반 호좜
INTERNAL_AUTH_SECRET λ‚΄λΆ€ API 인증 secret
JWT_SECRET JWT secret
KAFKA_BOOTSTRAP_SERVERS Kafka bootstrap servers
KAFKA_CONSUMER_GROUP_ID Kafka consumer group id
KAFKA_TOPIC_RESERVATION_CHECK_IN_COMPLETED 체크인 μ™„λ£Œ 이벀트 topic
KAFKA_LISTENER_AUTO_STARTUP Kafka listener μžλ™ μ‹œμž‘ μ—¬λΆ€
CACHE_TTL_RESTAURANT_DETAIL 식당 상세 μΊμ‹œ TTL seconds
CACHE_TTL_RESTAURANT_COURSES μ½”μŠ€ λͺ©λ‘ μΊμ‹œ TTL seconds

3. application μ„€μ •

application.yaml

  • μ„œλΉ„μŠ€λͺ…: restaurant-service
  • κΈ°λ³Έ server port: 19300
  • Redis cache μ‚¬μš©
  • Kafka consumer κΈ°λ³Έ μ„€μ •
  • Actuator / Prometheus endpoint λ…ΈμΆœ

application-local.yaml

  • local profile DB μ—°κ²°
  • Redis host κΈ°λ³Έκ°’: localhost
  • JPA ddl-auto: update
  • SQL 둜그 좜λ ₯
  • Eureka client κΈ°λ³Έ λΉ„ν™œμ„±ν™”

application-prod.yml

  • prod profile DB URL을 POSTGRES_HOST, POSTGRES_PORT, POSTGRES_DB둜 μ‘°ν•©
  • HikariCP pool size ν™˜κ²½λ³€μˆ˜ 기반 μ„€μ •
  • Redis / Kafka / Eureka / Feign / Cache TTL ν™˜κ²½λ³€μˆ˜ 기반 μ„€μ •
  • Prometheus metrics λ…ΈμΆœ

▢️ Run

Gradle μ‹€ν–‰

./gradlew bootRun

Profile μ§€μ • μ‹€ν–‰

SPRING_PROFILES_ACTIVE=local ./gradlew bootRun

λ˜λŠ” IntelliJμ—μ„œ RestaurantServiceApplication을 μ‹€ν–‰ν•©λ‹ˆλ‹€.


🐳 Docker

Build

docker build -t restaurant-service:local .

Run

docker run --rm -p 19300:19300 \
  --env-file .env.example \
  restaurant-service:local

Dockerfile은 multi-stage buildλ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.

Gradle JDK 17 builder stage
↓
bootJar 생성
↓
Eclipse Temurin JRE 17 runtime stage
↓
app.jar μ‹€ν–‰

πŸš€ CI/CD

GitHub Actions 기반 CI/CDλ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€.

CI-PROD

Pull Request / Push
↓
JDK 17 μ„€μ •
↓
Gradle test
↓
Docker image build
↓
ECR push
  • 이미지 νƒœκ·ΈλŠ” commit SHA μ•ž 7자리λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.
  • AWS 인증은 OIDC Role 기반으둜 μ²˜λ¦¬ν•©λ‹ˆλ‹€.

CD-PROD

CI-PROD 성곡
↓
ECR image 쑴재 확인
↓
ν˜„μž¬ ECS Task Definition 쑰회
↓
μƒˆ Task Definition revision 생성
↓
ECS Service update
↓
services-stable λŒ€κΈ°

배포 μ‹œ container environment에 DB, Redis, Kafka, Eureka, cache TTL 값을 μ£Όμž…ν•©λ‹ˆλ‹€.


🧠 Design Notes

MSA Boundary

restaurant-serviceλŠ” 식당/μ½”μŠ€/체크인 둜그λ₯Ό μ†Œμœ ν•©λ‹ˆλ‹€.
μ˜ˆμ•½ μƒνƒœμ˜ source of truthλŠ” reservation-serviceκ°€ μ†Œμœ ν•©λ‹ˆλ‹€.

체크인 μš”μ²­μ€ restaurant-serviceμ—μ„œ λ°›μ§€λ§Œ, μ˜ˆμ•½ μƒνƒœ 검증과 μƒνƒœ 변경은 reservation-service에 μœ„μž„ν•©λ‹ˆλ‹€.


Feign + Kafka μ—­ν•  뢄리

μ¦‰μ‹œ 응닡이 ν•„μš”ν•œ 체크인 검증은 Feign 동기 ν†΅μ‹ μœΌλ‘œ μ²˜λ¦¬ν•©λ‹ˆλ‹€.
체크인 μ™„λ£Œ 이벀트 기반 둜그 μ €μž₯은 Kafka 비동기 consume으둜 μ²˜λ¦¬ν•©λ‹ˆλ‹€.

μ¦‰μ‹œ 검증: Feign
이벀트 처리: Kafka
쀑볡 λ°©μ–΄: reservationId κΈ°μ€€ idempotency

Redis Cache-Aside

식당 상세 / μ½”μŠ€ λͺ©λ‘ μ‘°νšŒλŠ” 반볡 쑰회 κ°€λŠ₯성이 λ†’κΈ° λ•Œλ¬Έμ— Redis Cache-Aside νŒ¨ν„΄μ„ μ μš©ν•©λ‹ˆλ‹€.

  • cache hit: DB μ ‘κ·Ό 없이 응닡
  • cache miss: DB 쑰회 ν›„ Redis μ €μž₯

record DTO 역직렬화 이슈λ₯Ό λ°©μ§€ν•˜κΈ° μœ„ν•΄ Redis value serializer의 νƒ€μž… 정보 섀정을 λͺ…μ‹œν•©λ‹ˆλ‹€.


Soft Delete

곡톡 BaseEntityλ₯Ό μ‚¬μš©ν•˜λ©°, μ£Όμš” μ‘°νšŒμ—μ„œλŠ” μ‚­μ œλ˜μ§€ μ•Šμ€ 데이터 κΈ°μ€€μœΌλ‘œ μ²˜λ¦¬ν•©λ‹ˆλ‹€.


Check-in Log Unique Constraint

ν•˜λ‚˜μ˜ μ˜ˆμ•½μ— λŒ€ν•΄ 체크인 λ‘œκ·ΈλŠ” ν•œ 번만 μ €μž₯λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.

uk_checkin_log_reservation_id

Kafka μž¬μ „λ‹¬μ΄λ‚˜ λ™μ‹œ consume μƒν™©μ—μ„œλ„ reservationId κΈ°μ€€μœΌλ‘œ 쀑볡 μ €μž₯을 λ°©μ–΄ν•©λ‹ˆλ‹€.


πŸ“‚ Project Files

.
β”œβ”€ build.gradle
β”œβ”€ settings.gradle
β”œβ”€ Dockerfile
β”œβ”€ .env.example
β”œβ”€ load-tests
β”‚  └─ restaurant
β”œβ”€ src
β”‚  β”œβ”€ main
β”‚  β”‚  β”œβ”€ java
β”‚  β”‚  └─ resources
β”‚  └─ test
β”‚     β”œβ”€ http
β”‚     β”œβ”€ java
β”‚     β”œβ”€ mvp
β”‚     └─ resources
└─ gradle

βœ… Summary

이 μ„œλΉ„μŠ€λŠ” λ‹€μŒμ„ μ±…μž„μ§‘λ‹ˆλ‹€.

  • πŸͺ 식당 κΈ°λ³Έ 정보 관리
  • 🍽️ 식당 μ½”μŠ€ 및 μ½”μŠ€ 메뉴 관리
  • πŸ” μ‚¬μš©μžμš© 식당/μ½”μŠ€ 쑰회
  • πŸ”— λ‚΄λΆ€ μ„œλΉ„μŠ€μš© 식당/μ½”μŠ€ 쑰회
  • βœ… μ˜ˆμ•½ 연동 체크인 처리
  • πŸ“© Kafka 체크인 μ™„λ£Œ 이벀트 consume
  • 🧱 reservationId κΈ°μ€€ 체크인 둜그 쀑볡 λ°©μ–΄
  • πŸš€ Redis Cache-Aside 기반 쑰회 μ„±λŠ₯ κ°œμ„ 
  • πŸ“Š Prometheus/Grafana 기반 λͺ¨λ‹ˆν„°λ§ μ§€ν‘œ λ…ΈμΆœ
  • πŸ§ͺ HTTP Client 기반 λ°°ν¬ν™˜κ²½ API μ‹œλ‚˜λ¦¬μ˜€ 검증

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages