1. Auth
이메일 인증 — 코드 발송
sequenceDiagram
actor user
participant client
participant service
participant Redis
participant SMTP
user ->> client: 이메일 인증 요청
client ->> service: POST /auth/sign-up/email-verification (email)
alt 45초 이내 재요청
service ->> client: 429 Too Many Requests
client ->> user: "잠시 후 다시 시도해주세요." 표시
end
service ->> Redis: GET cooldown:{email}
Redis ->> service: null (쿨다운 없음)
service ->> Redis: SET code:{email} = 6자리코드 (TTL 5분)
service ->> Redis: SET cooldown:{email} = 1 (TTL 45초)
service ->> SMTP: SimpleMailMessage.send(email, code)
service ->> client: 200 OK
client ->> user: "인증 코드를 확인해 주세요." 표시
이메일 인증 — 코드 검증 & 토큰 발급
sequenceDiagram
actor user
participant client
participant service
participant Redis
user ->> client: 인증코드 입력
client ->> service: POST /auth/sign-up-verify/email-verification (email, code)
service ->> Redis: GET code:{email}
alt 코드 불일치 또는 만료
Redis ->> service: null or 다른 코드
service ->> client: 401 Unauthorized
client ->> user: "인증코드가 올바르지 않습니다." 표시
end
Redis ->> service: 저장된 코드 (일치)
service ->> Redis: DELETE code:{email}
service ->> Redis: SET verified:{UUID_token} = email (TTL 15분)
service ->> client: 200 OK (token)
client ->> user: 인증 완료 표시
일반 회원가입
sequenceDiagram
actor user
participant client
participant service
participant Redis
participant DB
user ->> client: 회원가입 버튼 클릭
client ->> service: POST /auth/sign-up/user (password, confirmPassword, ...) Header: X-Email-Verify-Token: Bearer {token}
service ->> Redis: GET verified:{token}
alt 토큰 만료 또는 없음
Redis ->> service: null
service ->> client: 401 Unauthorized
client ->> user: "인증 토큰이 만료되었습니다." 표시
end
Redis ->> service: email (유효한 토큰)
service ->> Redis: DELETE verified:{token}
alt 비밀번호 불일치
service ->> client: 400 BadRequest
client ->> user: "비밀번호 확인이 일치하지 않습니다." 표시
end
service ->> DB: existsByUsername(email)
alt 이미 가입된 이메일
DB ->> service: true
service ->> client: 409 Conflict
client ->> user: "이미 가입한 계정입니다." 표시
end
DB ->> service: false
service ->> DB: INSERT INTO users (Users.createConsumer(...))
DB ->> service: userId
service ->> client: 201 Created (userId)
client ->> user: "회원가입 성공" 표시
호스트 회원가입
sequenceDiagram
actor user
participant client
participant service
participant DB
user ->> client: 호스트 회원가입 버튼 클릭
client ->> service: POST /auth/sign-up/host (businessNumber, ...)
service ->> DB: existsByBusinessNumber(businessNumber)
alt 이미 등록된 사업자번호
DB ->> service: true
service ->> client: 409 Conflict
client ->> user: "이미 등록된 사업자번호입니다." 표시
end
DB ->> service: false
service ->> service: nextHostUsername() momentixHost0001! 형식 순차 생성
service ->> DB: INSERT INTO users (Users.createHost(...))
DB ->> service: userId
service ->> client: 201 Created (username, password)
client ->> user: "회원가입 성공, ID와 PW가 동일합니다. 변경해주세요." 표시
일반로그인
sequenceDiagram
actor user
participant client
participant service
participant DB
user ->> client: 로그인 버튼 클릭
client ->> service: POST /auth/sign-in (username, password)
service ->> DB: SELECT * FROM users WHERE username = {username}
alt 존재하지 않는 계정
DB ->> service: Optional.empty()
service ->> client: 404 NotFound
client ->> user: "존재하지 않는 사용자입니다." 표시
end
alt 비밀번호 불일치
DB ->> service: SignIn entity
service ->> client: 400 BadRequest
client ->> user: "비밀번호가 올바르지 않습니다." 표시
end
DB ->> service: SignIn entity (일치)
service ->> service: createAccessToken(userId, username, role) 유효 30분
service ->> service: createRefreshToken(userId) 유효 7일
service ->> client: 200 OK (accessToken) Set-Cookie: REFRESH_TOKEN httpOnly
client ->> user: "로그인 성공" 표시
JWT 토큰 발급
sequenceDiagram
actor user
participant client
participant service
user ->> client: 토큰 재발급 요청
client ->> service: POST /auth/refresh (Cookie: REFRESH_TOKEN={refreshToken})
alt 쿠키 없음 또는 빈 값
service ->> client: 401 Unauthorized
client ->> user: "다시 로그인해 주세요." 표시
end
alt 유효하지 않거나 refresh 타입 아님
service ->> client: 401 Unauthorized
client ->> user: "다시 로그인해 주세요." 표시
end
service ->> service: getUserIdFromToken(refreshToken)
service ->> service: createAccessToken(userId, username, role) 유효 30분
service ->> client: 200 OK (newAccessToken)
client ->> user: 새 accessToken 저장
로그아웃
sequenceDiagram
actor user
participant client
participant service
user ->> client: 로그아웃 버튼 클릭
client ->> service: POST /auth/sign-out Header: Authorization Bearer {accessToken}
service ->> service: ResponseCookie REFRESH_TOKEN maxAge=0
service ->> client: 204 No Content Set-Cookie: REFRESH_TOKEN= maxAge=0
client ->> user: "로그아웃되었습니다." 표시
카카오 로그인 — 리다이렉트
sequenceDiagram
actor user
participant client
participant service
participant Kakao
user ->> client: 카카오 로그인 버튼 클릭
client ->> service: GET /auth/sign-in/kakao
service ->> service: state = UUID.randomUUID()
service ->> service: session["OAUTH_STATE_KAKAO"] = state
service ->> client: 302 Redirect kauth.kakao.com/oauth/authorize?client_id=...&state=...
client ->> Kakao: 브라우저 리다이렉트
Kakao ->> user: 카카오 로그인/동의 화면 표시
카카오 로그인 — 콜백 & JWT 발급
sequenceDiagram
actor user
participant client
participant service
participant Kakao
participant DB
user ->> Kakao: 로그인/동의 완료
Kakao ->> client: 302 Redirect /auth/sign-in/callback/kakao?code=...&state=...
client ->> service: GET /auth/sign-in/callback/kakao (code, state)
service ->> service: session["OAUTH_STATE_KAKAO"] 검증 (CSRF 방지)
alt state 불일치
service ->> client: 400 BadRequest
client ->> user: "잘못된 요청입니다." 표시
end
service ->> Kakao: POST kauth.kakao.com/oauth/token (code, client_id, ...)
Kakao ->> service: access_token
service ->> Kakao: GET kapi.kakao.com/v2/user/me (access_token)
Kakao ->> service: email, nickname
service ->> DB: SELECT * FROM users WHERE username = {email}
alt 신규 유저
DB ->> service: Optional.empty()
service ->> DB: INSERT INTO users (nickname, role=CONSUMER)
end
DB ->> service: Users entity
service ->> service: createAccessToken(userId, email, role)
service ->> service: createRefreshToken(userId)
service ->> client: 200 OK (accessToken, refreshToken, provider: KAKAO)
client ->> user: 로그인 완료
네이버 로그인 — 리다이렉트