Participation Service 백엔드 개발 완료
주요 구현 사항:
- 이벤트 참여 등록 및 중복 검증 (Redis Cache + DB)
- 참여자 목록 조회 (필터링, 검색, 페이징)
- 당첨자 추첨 (Fisher-Yates Shuffle 알고리즘)
- Kafka 이벤트 발행 (ParticipantRegistered)
- Redis 캐싱으로 성능 최적화
- 전화번호 마스킹 (개인정보 보호)
- 전역 예외 처리 및 검증
기술 스택:
- Spring Boot 3.x + JPA
- MySQL (참여자, 추첨 로그)
- Redis (캐싱, 중복 검증)
- Kafka (이벤트 발행)
API 엔드포인트:
- POST /events/{eventId}/participate
- GET /events/{eventId}/participants
- GET /events/{eventId}/participants/search
- POST /events/{eventId}/draw-winners
- GET /events/{eventId}/winners
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
spring:
|
||||
application:
|
||||
name: participation-service
|
||||
|
||||
datasource:
|
||||
url: jdbc:mysql://${DB_HOST:localhost}:${DB_PORT:3306}/${DB_NAME:participation_db}?useSSL=false&serverTimezone=UTC&characterEncoding=UTF-8
|
||||
username: ${DB_USER:root}
|
||||
password: ${DB_PASSWORD:password}
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
hikari:
|
||||
maximum-pool-size: ${DB_POOL_SIZE:10}
|
||||
minimum-idle: ${DB_MIN_IDLE:5}
|
||||
connection-timeout: ${DB_CONN_TIMEOUT:30000}
|
||||
idle-timeout: ${DB_IDLE_TIMEOUT:600000}
|
||||
max-lifetime: ${DB_MAX_LIFETIME:1800000}
|
||||
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: ${JPA_DDL_AUTO:validate}
|
||||
show-sql: ${JPA_SHOW_SQL:false}
|
||||
properties:
|
||||
hibernate:
|
||||
format_sql: true
|
||||
use_sql_comments: true
|
||||
dialect: org.hibernate.dialect.MySQL8Dialect
|
||||
|
||||
# Redis Configuration
|
||||
data:
|
||||
redis:
|
||||
host: ${REDIS_HOST:localhost}
|
||||
port: ${REDIS_PORT:6379}
|
||||
password: ${REDIS_PASSWORD:}
|
||||
timeout: ${REDIS_TIMEOUT:3000}
|
||||
lettuce:
|
||||
pool:
|
||||
max-active: ${REDIS_POOL_MAX_ACTIVE:8}
|
||||
max-idle: ${REDIS_POOL_MAX_IDLE:8}
|
||||
min-idle: ${REDIS_POOL_MIN_IDLE:2}
|
||||
max-wait: ${REDIS_POOL_MAX_WAIT:3000}
|
||||
|
||||
# Kafka Configuration
|
||||
kafka:
|
||||
bootstrap-servers: ${KAFKA_BOOTSTRAP_SERVERS:localhost:9092}
|
||||
producer:
|
||||
key-serializer: org.apache.kafka.common.serialization.StringSerializer
|
||||
value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
|
||||
acks: ${KAFKA_PRODUCER_ACKS:all}
|
||||
retries: ${KAFKA_PRODUCER_RETRIES:3}
|
||||
properties:
|
||||
max.in.flight.requests.per.connection: 1
|
||||
enable.idempotence: true
|
||||
# Topic Names
|
||||
topics:
|
||||
participant-registered: participant-events
|
||||
|
||||
server:
|
||||
port: ${SERVER_PORT:8084}
|
||||
servlet:
|
||||
context-path: /
|
||||
error:
|
||||
include-message: always
|
||||
include-binding-errors: always
|
||||
|
||||
# Logging
|
||||
logging:
|
||||
level:
|
||||
root: ${LOG_LEVEL_ROOT:INFO}
|
||||
com.kt.event.participation: ${LOG_LEVEL_APP:DEBUG}
|
||||
org.springframework.data.redis: ${LOG_LEVEL_REDIS:INFO}
|
||||
org.springframework.kafka: ${LOG_LEVEL_KAFKA:INFO}
|
||||
pattern:
|
||||
console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
|
||||
file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
|
||||
file:
|
||||
name: ${LOG_FILE_PATH:./logs}/participation-service.log
|
||||
max-size: ${LOG_FILE_MAX_SIZE:10MB}
|
||||
max-history: ${LOG_FILE_MAX_HISTORY:30}
|
||||
|
||||
# Application-specific Configuration
|
||||
app:
|
||||
cache:
|
||||
duplicate-check-ttl: ${CACHE_DUPLICATE_TTL:604800} # 7 days in seconds
|
||||
participant-list-ttl: ${CACHE_PARTICIPANT_TTL:600} # 10 minutes in seconds
|
||||
lottery:
|
||||
algorithm: FISHER_YATES_SHUFFLE
|
||||
visit-bonus-weight: ${LOTTERY_VISIT_BONUS:2.0} # 매장 방문 고객 가중치
|
||||
security:
|
||||
phone-mask-pattern: "***-****-***" # 전화번호 마스킹 패턴
|
||||
Reference in New Issue
Block a user