mirror of
https://github.com/ktds-dg0501/kt-event-marketing.git
synced 2025-12-06 08:06:25 +00:00
Outer sequence 다이어그램 수정
1. 고객참여플로우 - 재추첨 버튼 UI 요소 제거 2. 사용자인증플로우 - 로그인 input 전화번호 → 이메일/비밀번호로 변경 - 회원가입 시 이메일 중복검사 로직 추가 - 전화번호 중복검사도 유지 (이메일 검사 후 수행) 3. 성과분석플로우 - Redis Cache TTL 5분 → 1시간으로 변경 - 배치 수집 주기 10분 → 5분으로 변경 4. 이벤트생성플로우 - 회원/매장정보 조회를 FE에서 직접 수행 후 전달 - 이벤트 초안 데이터 Redis 저장 (draft:event 키) - 최종 승인 시에만 Event DB에 영구 저장 - AI Service 과거 이벤트 데이터 조회 로직 삭제 - 이미지 생성 요청 FE → Content Service 다이렉트 호출 - Job 상태 확인도 Content Service로 직접 조회 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
12baa4bc77
commit
eea1fff98c
@ -79,6 +79,40 @@ else 신규 참여인 경우
|
||||
deactivate CustomerFE
|
||||
end
|
||||
|
||||
== UFR-PART-020: 참여자 목록 조회 ==
|
||||
|
||||
Owner -> OwnerFE: 이벤트 상세 화면에서\n"참여자 목록" 탭 클릭
|
||||
activate OwnerFE
|
||||
|
||||
OwnerFE -> Gateway: GET /api/v1/events/{eventId}/participants\n?page=1&size=20
|
||||
activate Gateway
|
||||
|
||||
Gateway -> PartService: GET /events/{eventId}/participants\n?page=1&size=20
|
||||
activate PartService
|
||||
|
||||
PartService -> PartDB: 참여자 목록 조회\n(이벤트ID, 페이지네이션)\nORDER BY 참여일시 DESC
|
||||
activate PartDB
|
||||
PartDB --> PartService: 참여자 목록 반환\n(이름, 전화번호, 참여경로,\n응모번호, 참여일시)\n+ 총 참여자 수
|
||||
deactivate PartDB
|
||||
|
||||
PartService --> Gateway: 200 OK\n{participants[], totalCount, page, size}
|
||||
deactivate PartService
|
||||
|
||||
Gateway --> OwnerFE: 200 OK
|
||||
deactivate Gateway
|
||||
|
||||
OwnerFE -> Owner: 참여자 목록 화면 표시\n- 참여자 정보 테이블\n- 페이지네이션\n- 총 참여자 수\n- CSV 다운로드 버튼
|
||||
deactivate OwnerFE
|
||||
|
||||
note right of Owner
|
||||
참여자 정보:
|
||||
- 이름 (마스킹: 김**)
|
||||
- 전화번호 (마스킹: 010-****-1234)
|
||||
- 참여경로 (우리동네TV, Instagram 등)
|
||||
- 응모번호
|
||||
- 참여일시
|
||||
end note
|
||||
|
||||
== UFR-PART-030: 당첨자 추첨 ==
|
||||
|
||||
Owner -> OwnerFE: 이벤트 상세 화면에서\n"당첨자 추첨" 버튼 클릭
|
||||
@ -124,7 +158,7 @@ deactivate PartService
|
||||
Gateway --> OwnerFE: 200 OK
|
||||
deactivate Gateway
|
||||
|
||||
OwnerFE -> Owner: 당첨자 목록 화면 표시\n- 당첨자 정보 (이름, 전화번호, 응모번호)\n- "재추첨" 버튼\n- 추첨 완료 메시지
|
||||
OwnerFE -> Owner: 당첨자 목록 화면 표시\n- 당첨자 정보 (이름, 전화번호, 응모번호)\n- 추첨 완료 메시지
|
||||
deactivate OwnerFE
|
||||
|
||||
@enduml
|
||||
|
||||
@ -27,16 +27,27 @@ activate UserService
|
||||
|
||||
UserService -> UserService: 서버 측 유효성 검증\n(이름 2자 이상, 전화번호 형식 등)
|
||||
|
||||
UserService -> UserDB: 전화번호로 사용자 조회\n(중복 가입 확인)
|
||||
UserService -> UserDB: 이메일로 사용자 조회\n(중복 가입 확인)
|
||||
activate UserDB
|
||||
UserDB --> UserService: 기존 사용자 확인 결과
|
||||
deactivate UserDB
|
||||
|
||||
alt 중복 사용자 존재
|
||||
alt 이메일 중복 존재
|
||||
UserService --> Gateway: 400 Bad Request\n(이미 등록된 이메일)
|
||||
Gateway --> Frontend: 400 Bad Request
|
||||
Frontend --> User: "이미 가입된 이메일입니다"
|
||||
else 이메일 신규
|
||||
|
||||
UserService -> UserDB: 전화번호로 사용자 조회\n(중복 가입 확인)
|
||||
activate UserDB
|
||||
UserDB --> UserService: 기존 사용자 확인 결과
|
||||
deactivate UserDB
|
||||
|
||||
alt 전화번호 중복 존재
|
||||
UserService --> Gateway: 400 Bad Request\n(이미 등록된 전화번호)
|
||||
Gateway --> Frontend: 400 Bad Request
|
||||
Frontend --> User: "이미 가입된 전화번호입니다"
|
||||
else 신규 사용자
|
||||
else 신규 사용자
|
||||
|
||||
UserService -> UserService: 비밀번호 해싱\n(bcrypt, Cost Factor 10)
|
||||
|
||||
@ -68,6 +79,7 @@ else 신규 사용자
|
||||
|
||||
Frontend -> Gateway: 대시보드 화면으로 이동
|
||||
deactivate Frontend
|
||||
end
|
||||
end
|
||||
|
||||
== UFR-USER-020: 로그인 플로우 ==
|
||||
@ -75,19 +87,19 @@ end
|
||||
User -> Frontend: 로그인 화면 접근
|
||||
activate Frontend
|
||||
|
||||
User -> Frontend: 전화번호, 비밀번호 입력
|
||||
User -> Frontend: 이메일, 비밀번호 입력
|
||||
|
||||
Frontend -> Frontend: 클라이언트 측 유효성 검증\n(필수 필드 확인)
|
||||
Frontend -> Frontend: 클라이언트 측 유효성 검증\n(필수 필드 확인, 이메일 형식)
|
||||
|
||||
Frontend -> Gateway: POST /api/users/login\n(전화번호, 비밀번호)
|
||||
Frontend -> Gateway: POST /api/users/login\n(이메일, 비밀번호)
|
||||
activate Gateway
|
||||
|
||||
Gateway -> Gateway: Request 검증
|
||||
|
||||
Gateway -> UserService: POST /api/users/login\n(전화번호, 비밀번호)
|
||||
Gateway -> UserService: POST /api/users/login\n(이메일, 비밀번호)
|
||||
activate UserService
|
||||
|
||||
UserService -> UserDB: 전화번호로 사용자 조회\n(로그인 인증용)
|
||||
UserService -> UserDB: 이메일로 사용자 조회\n(로그인 인증용)
|
||||
activate UserDB
|
||||
UserDB --> UserService: 사용자 정보\n(user_id, password_hash, role)
|
||||
deactivate UserDB
|
||||
@ -95,7 +107,7 @@ deactivate UserDB
|
||||
alt 사용자 없음
|
||||
UserService --> Gateway: 401 Unauthorized\n(인증 실패)
|
||||
Gateway --> Frontend: 401 Unauthorized
|
||||
Frontend --> User: "전화번호 또는 비밀번호를\n확인해주세요"
|
||||
Frontend --> User: "이메일 또는 비밀번호를\n확인해주세요"
|
||||
else 사용자 존재
|
||||
|
||||
UserService -> UserService: 비밀번호 검증\n(bcrypt compare)
|
||||
@ -103,7 +115,7 @@ else 사용자 존재
|
||||
alt 비밀번호 불일치
|
||||
UserService --> Gateway: 401 Unauthorized\n(인증 실패)
|
||||
Gateway --> Frontend: 401 Unauthorized
|
||||
Frontend --> User: "전화번호 또는 비밀번호를\n확인해주세요"
|
||||
Frontend --> User: "이메일 또는 비밀번호를\n확인해주세요"
|
||||
else 비밀번호 일치
|
||||
|
||||
UserService -> UserService: JWT 토큰 생성\n(user_id, role=OWNER,\nexp=7일)
|
||||
|
||||
@ -7,7 +7,7 @@ actor "소상공인" as User
|
||||
participant "Frontend" as FE
|
||||
participant "API Gateway" as GW
|
||||
participant "Analytics Service" as Analytics
|
||||
participant "Redis Cache\n(TTL 5분)" as Redis
|
||||
participant "Redis Cache\n(TTL 1시간)" as Redis
|
||||
participant "Analytics DB" as AnalyticsDB
|
||||
participant "Kafka\n(Event Topics)" as Kafka
|
||||
|
||||
@ -37,7 +37,7 @@ deactivate Redis
|
||||
|
||||
note right of Analytics
|
||||
**Cache-Aside 패턴**
|
||||
- TTL: 5분
|
||||
- TTL: 1시간
|
||||
- 예상 크기: 5KB
|
||||
- 히트율 목표: 95%
|
||||
- 응답 시간: 0.5초
|
||||
@ -105,7 +105,7 @@ note right of Analytics
|
||||
**목업 데이터 활용**
|
||||
- 초기에는 목업 데이터로 시작
|
||||
- 점진적으로 실제 배치 작업 구현
|
||||
- 배치 주기: 10분마다 수집
|
||||
- 배치 주기: 5분마다 수집
|
||||
end note
|
||||
|
||||
|||
|
||||
@ -123,7 +123,7 @@ end note
|
||||
|||
|
||||
== 2.4. Redis 캐싱 및 응답 ==
|
||||
|
||||
Analytics -> Redis: 대시보드 데이터 캐시 저장\n(캐시키: analytics:dashboard:{eventId},\n값: 통합 데이터, TTL: 5분)
|
||||
Analytics -> Redis: 대시보드 데이터 캐시 저장\n(캐시키: analytics:dashboard:{eventId},\n값: 통합 데이터, TTL: 1시간)
|
||||
activate Redis
|
||||
Redis --> Analytics: OK
|
||||
deactivate Redis
|
||||
|
||||
@ -21,18 +21,20 @@ participant "배포 채널 APIs" as ChannelApis
|
||||
|
||||
== 1. 이벤트 목적 선택 (UFR-EVENT-020) ==
|
||||
User -> FE: 이벤트 목적 선택
|
||||
FE -> Gateway: POST /events/purposes\n{목적, userId}
|
||||
Gateway -> Event: 이벤트 목적 저장 요청
|
||||
Event -> UserSvc: GET /api/users/{userId}/store\n회원 및 매장정보 조회
|
||||
FE -> UserSvc: GET /api/users/{userId}/store\n회원 및 매장정보 조회
|
||||
activate UserSvc
|
||||
UserSvc -> UserDB: 사용자 및 매장 정보 조회
|
||||
activate UserDB
|
||||
UserDB --> UserSvc: 사용자, 매장 정보 반환
|
||||
deactivate UserDB
|
||||
UserSvc --> Event: 200 OK\n{userId, storeName, industry, address}
|
||||
UserSvc --> FE: 200 OK\n{userId, storeName, industry, address}
|
||||
deactivate UserSvc
|
||||
Event -> EventDB: 이벤트 목적 정보 저장\n(목적, 매장정보 저장)
|
||||
EventDB --> Event: 저장 완료
|
||||
FE -> Gateway: POST /events/purposes\n{목적, userId, storeName, industry, address}
|
||||
Gateway -> Event: 이벤트 목적 저장 요청
|
||||
Event -> Redis: 이벤트 목적 정보 저장\nKey: draft:event:{eventDraftId}\n(목적, 매장정보 저장)\nTTL: 24시간
|
||||
activate Redis
|
||||
Redis --> Event: 저장 완료
|
||||
deactivate Redis
|
||||
Event --> Gateway: 저장 완료\n{eventDraftId}
|
||||
Gateway --> FE: 200 OK
|
||||
FE --> User: AI 추천 화면으로 이동
|
||||
@ -49,9 +51,7 @@ FE --> User: "AI가 분석 중입니다..." (로딩)
|
||||
note over AI: Kafka Consumer\nai 이벤트 생성 topic 구독
|
||||
Kafka --> AI: Consume Job Message\n{jobId, eventDraftId, ...}
|
||||
|
||||
AI -> EventDB: 과거 이벤트 데이터 조회\n(업종, 지역 기반 통계 조회)
|
||||
EventDB --> AI: 이벤트 통계 데이터
|
||||
AI -> AIApi: 트렌드 분석 및 이벤트 추천 요청\n{목적, 업종, 지역, 과거데이터, 매장정보}\n[Circuit Breaker, Timeout: 5분]
|
||||
AI -> AIApi: 트렌드 분석 및 이벤트 추천 요청\n{목적, 업종, 지역, 매장정보}\n[Circuit Breaker, Timeout: 5분]
|
||||
AIApi --> AI: 3가지 추천안 + 트렌드 요약\n(예: "여름철 시원한 음료 선호도 증가")
|
||||
AI -> Redis: AI 추천 결과 저장\nKey: ai:event:{eventDraftId}\n(3가지 추천안, 트렌드 요약)\nTTL: 24시간
|
||||
Redis --> AI: 저장 완료
|
||||
@ -80,18 +80,20 @@ end
|
||||
User -> FE: 추천안 선택\n(제목/경품 커스텀)
|
||||
FE -> Gateway: PUT /events/drafts/{eventDraftId}\n{선택한 추천안, 커스텀 정보}
|
||||
Gateway -> Event: 선택 저장
|
||||
Event -> EventDB: 선택한 추천안 저장\n(이벤트 초안 업데이트)
|
||||
EventDB --> Event: 업데이트 완료
|
||||
Event -> Redis: 선택한 추천안 저장\nKey: draft:event:{eventDraftId}\n(이벤트 초안 업데이트)\nTTL: 24시간
|
||||
activate Redis
|
||||
Redis --> Event: 업데이트 완료
|
||||
deactivate Redis
|
||||
Event --> Gateway: 200 OK
|
||||
Gateway --> FE: 저장 완료
|
||||
FE --> User: 콘텐츠 생성 화면으로 이동
|
||||
|
||||
== 3. SNS 이미지 생성 - 비동기 처리 (UFR-CONT-010) ==
|
||||
User -> FE: 이미지 생성 요청
|
||||
FE -> Gateway: POST /api/events/{eventDraftId}/content-generation
|
||||
Gateway -> Event: 이미지 생성 요청
|
||||
Event -> Event: Job 생성\n{jobId, eventDraftId, status: PENDING}
|
||||
Event --> Gateway: Job 생성 완료\n{jobId, status: PENDING}
|
||||
FE -> Gateway: POST /api/content/images/{eventDraftId}/generate
|
||||
Gateway -> Content: 이미지 생성 요청
|
||||
Content -> Content: Job 생성\n{jobId, eventDraftId, status: PENDING}
|
||||
Content --> Gateway: Job 생성 완료\n{jobId, status: PENDING}
|
||||
Gateway --> FE: 202 Accepted\n{jobId}
|
||||
FE --> User: "이미지 생성 중..." (로딩)
|
||||
|
||||
@ -124,17 +126,17 @@ note over Content, Redis: 이미지 URL은 Redis에 저장\n- 최종 승인 시
|
||||
|
||||
group Polling으로 상태 확인
|
||||
loop 상태 확인 (최대 30초)
|
||||
FE -> Gateway: GET /jobs/{jobId}/status
|
||||
Gateway -> Event: Job 상태 조회
|
||||
Event -> Redis: Job 상태 조회\n(jobId로 상태 및 이미지 URL 조회)
|
||||
Redis --> Event: {status, imageUrls}
|
||||
FE -> Gateway: GET /api/content/jobs/{jobId}/status
|
||||
Gateway -> Content: Job 상태 조회
|
||||
Content -> Redis: Job 상태 조회\n(jobId로 상태 및 이미지 URL 조회)
|
||||
Redis --> Content: {status, imageUrls}
|
||||
|
||||
alt Job 완료
|
||||
Event --> Gateway: 200 OK\n{status: COMPLETED, imageUrls}
|
||||
Content --> Gateway: 200 OK\n{status: COMPLETED, imageUrls}
|
||||
Gateway --> FE: 이미지 URL 반환
|
||||
FE --> User: 3가지 스타일 카드 표시
|
||||
else Job 진행중
|
||||
Event --> Gateway: 200 OK\n{status: PENDING/PROCESSING}
|
||||
Content --> Gateway: 200 OK\n{status: PENDING/PROCESSING}
|
||||
Gateway --> FE: 진행중 상태
|
||||
note over FE: 2초 후 재요청
|
||||
end
|
||||
@ -144,8 +146,10 @@ end
|
||||
User -> FE: 스타일 선택 및 편집
|
||||
FE -> Gateway: PUT /events/drafts/{eventDraftId}/content\n{선택한 이미지, 편집내용}
|
||||
Gateway -> Event: 콘텐츠 선택 저장
|
||||
Event -> EventDB: 선택한 콘텐츠 저장\n(이벤트 초안 업데이트)
|
||||
EventDB --> Event: 업데이트 완료
|
||||
Event -> Redis: 선택한 콘텐츠 저장\nKey: draft:event:{eventDraftId}\n(이벤트 초안 업데이트)\nTTL: 24시간
|
||||
activate Redis
|
||||
Redis --> Event: 업데이트 완료
|
||||
deactivate Redis
|
||||
Event --> Gateway: 200 OK
|
||||
Gateway --> FE: 저장 완료
|
||||
FE --> User: 배포 채널 선택 화면으로 이동
|
||||
@ -157,6 +161,11 @@ Gateway -> Event: 최종 승인 및 배포 처리
|
||||
|
||||
note over Event: Redis 데이터를 Event DB에 영구 저장
|
||||
|
||||
Event -> Redis: 이벤트 초안 조회\nKey: draft:event:{eventDraftId}
|
||||
activate Redis
|
||||
Redis --> Event: 이벤트 초안 데이터\n(목적, 매장정보, 추천안, 콘텐츠)
|
||||
deactivate Redis
|
||||
|
||||
Event -> Redis: AI 추천 결과 조회\nKey: ai:event:{eventDraftId}
|
||||
activate Redis
|
||||
Redis --> Event: AI 추천 결과
|
||||
@ -167,7 +176,7 @@ activate Redis
|
||||
Redis --> Event: 이미지 URL 목록
|
||||
deactivate Redis
|
||||
|
||||
Event -> EventDB: 이벤트 정보 영구 저장\n(AI 추천, 이미지 URL, 배포 채널 포함)
|
||||
Event -> EventDB: 이벤트 정보 영구 저장\n(목적, 매장정보, AI 추천, 이미지 URL, 배포 채널 포함)
|
||||
EventDB --> Event: 저장 완료
|
||||
|
||||
Event -> EventDB: 이벤트 상태 변경\n(DRAFT → APPROVED로 업데이트)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user