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:
cherry2250 2025-10-23 15:10:30 +09:00
parent 12baa4bc77
commit eea1fff98c
4 changed files with 96 additions and 41 deletions

View File

@ -79,6 +79,40 @@ else 신규 참여인 경우
deactivate CustomerFE deactivate CustomerFE
end 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: 당첨자 추첨 == == UFR-PART-030: 당첨자 추첨 ==
Owner -> OwnerFE: 이벤트 상세 화면에서\n"당첨자 추첨" 버튼 클릭 Owner -> OwnerFE: 이벤트 상세 화면에서\n"당첨자 추첨" 버튼 클릭
@ -124,7 +158,7 @@ deactivate PartService
Gateway --> OwnerFE: 200 OK Gateway --> OwnerFE: 200 OK
deactivate Gateway deactivate Gateway
OwnerFE -> Owner: 당첨자 목록 화면 표시\n- 당첨자 정보 (이름, 전화번호, 응모번호)\n- "재추첨" 버튼\n- 추첨 완료 메시지 OwnerFE -> Owner: 당첨자 목록 화면 표시\n- 당첨자 정보 (이름, 전화번호, 응모번호)\n- 추첨 완료 메시지
deactivate OwnerFE deactivate OwnerFE
@enduml @enduml

View File

@ -27,16 +27,27 @@ activate UserService
UserService -> UserService: 서버 측 유효성 검증\n(이름 2자 이상, 전화번호 형식 등) UserService -> UserService: 서버 측 유효성 검증\n(이름 2자 이상, 전화번호 형식 등)
UserService -> UserDB: 전화번호로 사용자 조회\n(중복 가입 확인) UserService -> UserDB: 이메일로 사용자 조회\n(중복 가입 확인)
activate UserDB activate UserDB
UserDB --> UserService: 기존 사용자 확인 결과 UserDB --> UserService: 기존 사용자 확인 결과
deactivate UserDB deactivate UserDB
alt 중복 사용자 존재 alt 이메일 중복 존재
UserService --> Gateway: 400 Bad Request\n(이미 등록된 전화번호) UserService --> Gateway: 400 Bad Request\n(이미 등록된 이메일)
Gateway --> Frontend: 400 Bad Request Gateway --> Frontend: 400 Bad Request
Frontend --> User: "이미 가입된 전화번호입니다" Frontend --> User: "이미 가입된 이메일입니다"
else 신규 사용자 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 신규 사용자
UserService -> UserService: 비밀번호 해싱\n(bcrypt, Cost Factor 10) UserService -> UserService: 비밀번호 해싱\n(bcrypt, Cost Factor 10)
@ -68,6 +79,7 @@ else 신규 사용자
Frontend -> Gateway: 대시보드 화면으로 이동 Frontend -> Gateway: 대시보드 화면으로 이동
deactivate Frontend deactivate Frontend
end
end end
== UFR-USER-020: 로그인 플로우 == == UFR-USER-020: 로그인 플로우 ==
@ -75,19 +87,19 @@ end
User -> Frontend: 로그인 화면 접근 User -> Frontend: 로그인 화면 접근
activate 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 activate Gateway
Gateway -> Gateway: Request 검증 Gateway -> Gateway: Request 검증
Gateway -> UserService: POST /api/users/login\n(전화번호, 비밀번호) Gateway -> UserService: POST /api/users/login\n(이메일, 비밀번호)
activate UserService activate UserService
UserService -> UserDB: 전화번호로 사용자 조회\n(로그인 인증용) UserService -> UserDB: 이메일로 사용자 조회\n(로그인 인증용)
activate UserDB activate UserDB
UserDB --> UserService: 사용자 정보\n(user_id, password_hash, role) UserDB --> UserService: 사용자 정보\n(user_id, password_hash, role)
deactivate UserDB deactivate UserDB
@ -95,7 +107,7 @@ deactivate UserDB
alt 사용자 없음 alt 사용자 없음
UserService --> Gateway: 401 Unauthorized\n(인증 실패) UserService --> Gateway: 401 Unauthorized\n(인증 실패)
Gateway --> Frontend: 401 Unauthorized Gateway --> Frontend: 401 Unauthorized
Frontend --> User: "전화번호 또는 비밀번호를\n확인해주세요" Frontend --> User: "이메일 또는 비밀번호를\n확인해주세요"
else 사용자 존재 else 사용자 존재
UserService -> UserService: 비밀번호 검증\n(bcrypt compare) UserService -> UserService: 비밀번호 검증\n(bcrypt compare)
@ -103,7 +115,7 @@ else 사용자 존재
alt 비밀번호 불일치 alt 비밀번호 불일치
UserService --> Gateway: 401 Unauthorized\n(인증 실패) UserService --> Gateway: 401 Unauthorized\n(인증 실패)
Gateway --> Frontend: 401 Unauthorized Gateway --> Frontend: 401 Unauthorized
Frontend --> User: "전화번호 또는 비밀번호를\n확인해주세요" Frontend --> User: "이메일 또는 비밀번호를\n확인해주세요"
else 비밀번호 일치 else 비밀번호 일치
UserService -> UserService: JWT 토큰 생성\n(user_id, role=OWNER,\nexp=7일) UserService -> UserService: JWT 토큰 생성\n(user_id, role=OWNER,\nexp=7일)

View File

@ -7,7 +7,7 @@ actor "소상공인" as User
participant "Frontend" as FE participant "Frontend" as FE
participant "API Gateway" as GW participant "API Gateway" as GW
participant "Analytics Service" as Analytics 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 "Analytics DB" as AnalyticsDB
participant "Kafka\n(Event Topics)" as Kafka participant "Kafka\n(Event Topics)" as Kafka
@ -37,7 +37,7 @@ deactivate Redis
note right of Analytics note right of Analytics
**Cache-Aside 패턴** **Cache-Aside 패턴**
- TTL: 5분 - TTL: 1시간
- 예상 크기: 5KB - 예상 크기: 5KB
- 히트율 목표: 95% - 히트율 목표: 95%
- 응답 시간: 0.5초 - 응답 시간: 0.5초
@ -105,7 +105,7 @@ note right of Analytics
**목업 데이터 활용** **목업 데이터 활용**
- 초기에는 목업 데이터로 시작 - 초기에는 목업 데이터로 시작
- 점진적으로 실제 배치 작업 구현 - 점진적으로 실제 배치 작업 구현
- 배치 주기: 10분마다 수집 - 배치 주기: 5분마다 수집
end note end note
||| |||
@ -123,7 +123,7 @@ end note
||| |||
== 2.4. Redis 캐싱 및 응답 == == 2.4. Redis 캐싱 및 응답 ==
Analytics -> Redis: 대시보드 데이터 캐시 저장\n(캐시키: analytics:dashboard:{eventId},\n값: 통합 데이터, TTL: 5분) Analytics -> Redis: 대시보드 데이터 캐시 저장\n(캐시키: analytics:dashboard:{eventId},\n값: 통합 데이터, TTL: 1시간)
activate Redis activate Redis
Redis --> Analytics: OK Redis --> Analytics: OK
deactivate Redis deactivate Redis

View File

@ -21,18 +21,20 @@ participant "배포 채널 APIs" as ChannelApis
== 1. 이벤트 목적 선택 (UFR-EVENT-020) == == 1. 이벤트 목적 선택 (UFR-EVENT-020) ==
User -> FE: 이벤트 목적 선택 User -> FE: 이벤트 목적 선택
FE -> Gateway: POST /events/purposes\n{목적, userId} FE -> UserSvc: GET /api/users/{userId}/store\n회원 및 매장정보 조회
Gateway -> Event: 이벤트 목적 저장 요청
Event -> UserSvc: GET /api/users/{userId}/store\n회원 및 매장정보 조회
activate UserSvc activate UserSvc
UserSvc -> UserDB: 사용자 및 매장 정보 조회 UserSvc -> UserDB: 사용자 및 매장 정보 조회
activate UserDB activate UserDB
UserDB --> UserSvc: 사용자, 매장 정보 반환 UserDB --> UserSvc: 사용자, 매장 정보 반환
deactivate UserDB deactivate UserDB
UserSvc --> Event: 200 OK\n{userId, storeName, industry, address} UserSvc --> FE: 200 OK\n{userId, storeName, industry, address}
deactivate UserSvc deactivate UserSvc
Event -> EventDB: 이벤트 목적 정보 저장\n(목적, 매장정보 저장) FE -> Gateway: POST /events/purposes\n{목적, userId, storeName, industry, address}
EventDB --> Event: 저장 완료 Gateway -> Event: 이벤트 목적 저장 요청
Event -> Redis: 이벤트 목적 정보 저장\nKey: draft:event:{eventDraftId}\n(목적, 매장정보 저장)\nTTL: 24시간
activate Redis
Redis --> Event: 저장 완료
deactivate Redis
Event --> Gateway: 저장 완료\n{eventDraftId} Event --> Gateway: 저장 완료\n{eventDraftId}
Gateway --> FE: 200 OK Gateway --> FE: 200 OK
FE --> User: AI 추천 화면으로 이동 FE --> User: AI 추천 화면으로 이동
@ -49,9 +51,7 @@ FE --> User: "AI가 분석 중입니다..." (로딩)
note over AI: Kafka Consumer\nai 이벤트 생성 topic 구독 note over AI: Kafka Consumer\nai 이벤트 생성 topic 구독
Kafka --> AI: Consume Job Message\n{jobId, eventDraftId, ...} Kafka --> AI: Consume Job Message\n{jobId, eventDraftId, ...}
AI -> EventDB: 과거 이벤트 데이터 조회\n(업종, 지역 기반 통계 조회) AI -> AIApi: 트렌드 분석 및 이벤트 추천 요청\n{목적, 업종, 지역, 매장정보}\n[Circuit Breaker, Timeout: 5분]
EventDB --> AI: 이벤트 통계 데이터
AI -> AIApi: 트렌드 분석 및 이벤트 추천 요청\n{목적, 업종, 지역, 과거데이터, 매장정보}\n[Circuit Breaker, Timeout: 5분]
AIApi --> AI: 3가지 추천안 + 트렌드 요약\n(예: "여름철 시원한 음료 선호도 증가") AIApi --> AI: 3가지 추천안 + 트렌드 요약\n(예: "여름철 시원한 음료 선호도 증가")
AI -> Redis: AI 추천 결과 저장\nKey: ai:event:{eventDraftId}\n(3가지 추천안, 트렌드 요약)\nTTL: 24시간 AI -> Redis: AI 추천 결과 저장\nKey: ai:event:{eventDraftId}\n(3가지 추천안, 트렌드 요약)\nTTL: 24시간
Redis --> AI: 저장 완료 Redis --> AI: 저장 완료
@ -80,18 +80,20 @@ end
User -> FE: 추천안 선택\n(제목/경품 커스텀) User -> FE: 추천안 선택\n(제목/경품 커스텀)
FE -> Gateway: PUT /events/drafts/{eventDraftId}\n{선택한 추천안, 커스텀 정보} FE -> Gateway: PUT /events/drafts/{eventDraftId}\n{선택한 추천안, 커스텀 정보}
Gateway -> Event: 선택 저장 Gateway -> Event: 선택 저장
Event -> EventDB: 선택한 추천안 저장\n(이벤트 초안 업데이트) Event -> Redis: 선택한 추천안 저장\nKey: draft:event:{eventDraftId}\n(이벤트 초안 업데이트)\nTTL: 24시간
EventDB --> Event: 업데이트 완료 activate Redis
Redis --> Event: 업데이트 완료
deactivate Redis
Event --> Gateway: 200 OK Event --> Gateway: 200 OK
Gateway --> FE: 저장 완료 Gateway --> FE: 저장 완료
FE --> User: 콘텐츠 생성 화면으로 이동 FE --> User: 콘텐츠 생성 화면으로 이동
== 3. SNS 이미지 생성 - 비동기 처리 (UFR-CONT-010) == == 3. SNS 이미지 생성 - 비동기 처리 (UFR-CONT-010) ==
User -> FE: 이미지 생성 요청 User -> FE: 이미지 생성 요청
FE -> Gateway: POST /api/events/{eventDraftId}/content-generation FE -> Gateway: POST /api/content/images/{eventDraftId}/generate
Gateway -> Event: 이미지 생성 요청 Gateway -> Content: 이미지 생성 요청
Event -> Event: Job 생성\n{jobId, eventDraftId, status: PENDING} Content -> Content: Job 생성\n{jobId, eventDraftId, status: PENDING}
Event --> Gateway: Job 생성 완료\n{jobId, status: PENDING} Content --> Gateway: Job 생성 완료\n{jobId, status: PENDING}
Gateway --> FE: 202 Accepted\n{jobId} Gateway --> FE: 202 Accepted\n{jobId}
FE --> User: "이미지 생성 중..." (로딩) FE --> User: "이미지 생성 중..." (로딩)
@ -124,17 +126,17 @@ note over Content, Redis: 이미지 URL은 Redis에 저장\n- 최종 승인 시
group Polling으로 상태 확인 group Polling으로 상태 확인
loop 상태 확인 (최대 30초) loop 상태 확인 (최대 30초)
FE -> Gateway: GET /jobs/{jobId}/status FE -> Gateway: GET /api/content/jobs/{jobId}/status
Gateway -> Event: Job 상태 조회 Gateway -> Content: Job 상태 조회
Event -> Redis: Job 상태 조회\n(jobId로 상태 및 이미지 URL 조회) Content -> Redis: Job 상태 조회\n(jobId로 상태 및 이미지 URL 조회)
Redis --> Event: {status, imageUrls} Redis --> Content: {status, imageUrls}
alt Job 완료 alt Job 완료
Event --> Gateway: 200 OK\n{status: COMPLETED, imageUrls} Content --> Gateway: 200 OK\n{status: COMPLETED, imageUrls}
Gateway --> FE: 이미지 URL 반환 Gateway --> FE: 이미지 URL 반환
FE --> User: 3가지 스타일 카드 표시 FE --> User: 3가지 스타일 카드 표시
else Job 진행중 else Job 진행중
Event --> Gateway: 200 OK\n{status: PENDING/PROCESSING} Content --> Gateway: 200 OK\n{status: PENDING/PROCESSING}
Gateway --> FE: 진행중 상태 Gateway --> FE: 진행중 상태
note over FE: 2초 후 재요청 note over FE: 2초 후 재요청
end end
@ -144,8 +146,10 @@ end
User -> FE: 스타일 선택 및 편집 User -> FE: 스타일 선택 및 편집
FE -> Gateway: PUT /events/drafts/{eventDraftId}/content\n{선택한 이미지, 편집내용} FE -> Gateway: PUT /events/drafts/{eventDraftId}/content\n{선택한 이미지, 편집내용}
Gateway -> Event: 콘텐츠 선택 저장 Gateway -> Event: 콘텐츠 선택 저장
Event -> EventDB: 선택한 콘텐츠 저장\n(이벤트 초안 업데이트) Event -> Redis: 선택한 콘텐츠 저장\nKey: draft:event:{eventDraftId}\n(이벤트 초안 업데이트)\nTTL: 24시간
EventDB --> Event: 업데이트 완료 activate Redis
Redis --> Event: 업데이트 완료
deactivate Redis
Event --> Gateway: 200 OK Event --> Gateway: 200 OK
Gateway --> FE: 저장 완료 Gateway --> FE: 저장 완료
FE --> User: 배포 채널 선택 화면으로 이동 FE --> User: 배포 채널 선택 화면으로 이동
@ -157,6 +161,11 @@ Gateway -> Event: 최종 승인 및 배포 처리
note over Event: Redis 데이터를 Event DB에 영구 저장 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} Event -> Redis: AI 추천 결과 조회\nKey: ai:event:{eventDraftId}
activate Redis activate Redis
Redis --> Event: AI 추천 결과 Redis --> Event: AI 추천 결과
@ -167,7 +176,7 @@ activate Redis
Redis --> Event: 이미지 URL 목록 Redis --> Event: 이미지 URL 목록
deactivate Redis deactivate Redis
Event -> EventDB: 이벤트 정보 영구 저장\n(AI 추천, 이미지 URL, 배포 채널 포함) Event -> EventDB: 이벤트 정보 영구 저장\n(목적, 매장정보, AI 추천, 이미지 URL, 배포 채널 포함)
EventDB --> Event: 저장 완료 EventDB --> Event: 저장 완료
Event -> EventDB: 이벤트 상태 변경\n(DRAFT → APPROVED로 업데이트) Event -> EventDB: 이벤트 상태 변경\n(DRAFT → APPROVED로 업데이트)