@startuml 사용자인증플로우
!theme mono

title KT AI 기반 소상공인 이벤트 자동 생성 서비스 - 사용자 인증 플로우 (외부 시퀀스)

actor "사용자\n(소상공인)" as User
participant "Frontend\n(Web/Mobile)" as Frontend
participant "API Gateway" as Gateway
participant "User Service" as UserService
database "User DB\n(PostgreSQL)" as UserDB

== UFR-USER-010: 회원가입 플로우 ==

User -> Frontend: 회원가입 화면 접근
activate Frontend

User -> Frontend: 회원 정보 입력\n(이름, 전화번호, 이메일, 비밀번호,\n매장명, 업종, 주소, 사업자번호)
Frontend -> Frontend: 클라이언트 측 유효성 검증\n(이메일 형식, 비밀번호 8자 이상 등)

Frontend -> Gateway: POST /api/users/register\n(회원 정보)
activate Gateway

Gateway -> Gateway: Request 검증\n(필수 필드, 데이터 타입)

Gateway -> UserService: POST /api/users/register\n(회원 정보)
activate UserService

UserService -> UserService: 서버 측 유효성 검증\n(이름 2자 이상, 전화번호 형식 등)

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 -> 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(AES-256)

    UserService -> UserDB: 트랜잭션 시작
    activate UserDB

    UserService -> UserDB: 사용자 정보 저장\n(이름, 전화번호, 이메일,\n비밀번호해시, 생성일시)
    UserDB --> UserService: user_id 반환

    UserService -> UserDB: 매장 정보 저장\n(사용자ID, 매장명, 업종,\n주소, 암호화된사업자번호,\n영업시간)
    UserDB --> UserService: store_id 반환

    UserService -> UserDB: 트랜잭션 커밋
    deactivate UserDB

    UserService -> UserService: JWT 토큰 생성\n(user_id, role=OWNER,\nexp=7일)

    UserService --> Gateway: 201 Created\n(JWT 토큰, 사용자 정보)
    deactivate UserService

    Gateway --> Frontend: 201 Created\n(JWT 토큰, 사용자 정보)
    deactivate Gateway

    Frontend -> Frontend: JWT 토큰 저장\n(LocalStorage 또는 Cookie)

    Frontend --> User: "회원가입이 완료되었습니다"

    Frontend -> Gateway: 대시보드 화면으로 이동
    deactivate Frontend
    end
end

== UFR-USER-020: 로그인 플로우 ==

User -> Frontend: 로그인 화면 접근
activate Frontend

User -> Frontend: 이메일, 비밀번호 입력

Frontend -> Frontend: 클라이언트 측 유효성 검증\n(필수 필드 확인, 이메일 형식)

Frontend -> Gateway: POST /api/users/login\n(이메일, 비밀번호)
activate Gateway

Gateway -> Gateway: Request 검증

Gateway -> UserService: POST /api/users/login\n(이메일, 비밀번호)
activate UserService

UserService -> UserDB: 이메일로 사용자 조회\n(로그인 인증용)
activate UserDB
UserDB --> UserService: 사용자 정보\n(user_id, password_hash, role)
deactivate UserDB

alt 사용자 없음
    UserService --> Gateway: 401 Unauthorized\n(인증 실패)
    Gateway --> Frontend: 401 Unauthorized
    Frontend --> User: "이메일 또는 비밀번호를\n확인해주세요"
else 사용자 존재

    UserService -> UserService: 비밀번호 검증\n(bcrypt compare)

    alt 비밀번호 불일치
        UserService --> Gateway: 401 Unauthorized\n(인증 실패)
        Gateway --> Frontend: 401 Unauthorized
        Frontend --> User: "이메일 또는 비밀번호를\n확인해주세요"
    else 비밀번호 일치

        UserService -> UserService: JWT 토큰 생성\n(user_id, role=OWNER,\nexp=7일)

        UserService -> UserDB: 최종 로그인 시각 업데이트\n(현재 시각으로 갱신)
        activate UserDB
        UserDB --> UserService: 업데이트 완료
        deactivate UserDB

        UserService --> Gateway: 200 OK\n(JWT 토큰, 사용자 정보)
        deactivate UserService

        Gateway --> Frontend: 200 OK\n(JWT 토큰, 사용자 정보)
        deactivate Gateway

        Frontend -> Frontend: JWT 토큰 저장\n(LocalStorage 또는 Cookie)

        Frontend --> User: 로그인 성공

        Frontend -> Gateway: 대시보드 화면으로 이동
        deactivate Frontend
    end
end

== UFR-USER-040: 로그아웃 플로우 ==

User -> Frontend: 프로필 탭 접근
activate Frontend

User -> Frontend: "로그아웃" 버튼 클릭

Frontend -> Frontend: 확인 다이얼로그 표시\n"로그아웃 하시겠습니까?"

User -> Frontend: "확인" 클릭

Frontend -> Gateway: POST /api/users/logout\nAuthorization: Bearer {JWT}
activate Gateway

Gateway -> Gateway: JWT 토큰 검증

Gateway -> UserService: POST /api/users/logout\n(JWT 토큰)
activate UserService

UserService -> UserService: JWT 토큰 블랙리스트에 추가\n(만료 시까지 유효)

UserService --> Gateway: 200 OK\n(로그아웃 성공)
deactivate UserService

Gateway --> Frontend: 200 OK
deactivate Gateway

Frontend -> Frontend: JWT 토큰 삭제\n(LocalStorage 또는 Cookie)

Frontend --> User: "안전하게 로그아웃되었습니다"

Frontend -> Gateway: 로그인 화면으로 이동
deactivate Frontend

@enduml
