Files
frontend/docs/session-extend-confirm-guide.md
T

6.8 KiB

세션 연장 Confirm 적용 가이드

1) 목적과 원칙

JWT 만료 5분 전에 "로그인을 연장하시겠습니까?" confirm을 띄우고, 선택에 따라 세션을 연장하는 UX를 서비스 앱에 적용하기 위한 가이드입니다.

이 문서는 서비스별 인증 처리 리팩토링 가이드의 후속 단계입니다.

핵심 원칙:

  • confirm UX는 @common/components Header의 useSessionExtendConfirm이 담당한다.
  • confirm 확인 → authService.silentRefresh()
  • confirm 취소 → authService.declineSessionExtend()
  • 앱은 ConfirmProvider 계층과 authService 주입을 맞춘다.

적용 완료: cs, as, st


2) 선행 조건

리팩토링 가이드 체크리스트를 통과한 서비스만 진행한다.

항목 리팩토링 가이드
authService (silentRefresh, declineSessionExtend) 4-4
BaseLayout에 authService 주입 4-7

3) 목표 아키텍처

3-1. 레이어 책임

레이어 위치 역할
JWT 시간 계산 @common/auth jwt-utils.ts getRemainingMs, confirm 버퍼 상수
토큰·정리 @common/auth token-manager.ts setToken, clearRefreshTimer, clearAuthToken
API 오케스트레이션 entities/auth/api/auth-service.ts silentRefresh, declineSessionExtend
confirm UX @common/components Header 카운트다운 + 5분 전 confirm
앱 진입점 entities/auth/lib/auth-wrapper.tsx auth 체크, auth:logout
레이아웃 layout / BaseLayout wrapper authService → Header
UI 쉘 app/providers/app-provider.tsx ConfirmProvider, ConfirmDialog

3-2. 런타임 흐름

sequenceDiagram
  participant Login as authService.login
  participant Header as Header
  participant User as 사용자
  participant API as authService.silentRefresh

  Login->>Login: setToken
  Header->>Header: confirm 예약(exp - 5분)
  Note over Header: 만료 5분 전
  Header->>User: 로그인을 연장하시겠습니까?
  alt 확인
    User->>API: silentRefresh()
    API->>API: setToken
    Header->>Header: confirm 타이머 재설정
  else 취소
    Header->>Header: declineSessionExtend()
  end
시점 동작 담당
로그인 / silentRefresh 성공 토큰 저장 authService
만료 5분 전 confirm 표시 Header → useSessionExtendConfirm
confirm 확인 silentRefresh + confirm 타이머 재설정 Header → authService.silentRefresh
confirm 취소 declineSessionExtend Header → authService.declineSessionExtend
토큰 완전 만료 logout Header

4) 공통 계약

4-1. 시간 버퍼 (getRemainingMs)

파일: packages/common/auth/jwt-utils.ts

export const SESSION_EXTEND_CONFIRM_BUFFER_MS = 5 * 60_000; // confirm: 만료 5분 전

getRemainingMs(token, SESSION_EXTEND_CONFIRM_BUFFER_MS); // → confirm 타이머 delay
getRemainingMs(token, 0) > 0; // → 토큰 미만료 여부

4-2. Header ↔ AuthService

공통 Header가 아래처럼 연결한다.

useSessionExtendConfirm({
  enabled:
    mounted &&
    isLoggedIn &&
    !viewOnly &&
    !!authService &&
    !isAtLoginRedirectUrl(getAuthLoginRedirectUrl()),
  getAccessToken: () => getCookie(appConfig.CLAIM_NAME ?? ""),
  silentRefresh: authService?.silentRefresh ?? (async () => {}),
  declineSessionExtend: authService?.declineSessionExtend ?? (() => {}),
});

4-3. Provider 계층

ConfirmProvider
  └─ AuthWrapper
       └─ … → BaseLayout → Header
       └─ ConfirmDialog

5) 적용 순서

5-1. AppProvider — ConfirmProvider 마운트

파일: app/providers/app-provider.tsx

<ConfirmProvider>
  <AuthWrapper>
    {children}
    <ConfirmDialog />
  </AuthWrapper>
</ConfirmProvider>

참고: apps/cs/src/app/providers/app-provider.tsx

5-2. BaseLayout — authService 전달

import { authService } from "@/entities/auth";

<BaseLayout authService={authService} /* ... */>
  {children}
</BaseLayout>

5-3. authService — declineSessionExtend

리팩토링 4-4에서 이미 구현했다면 확인만 한다.

export const authService: AuthService = {
  login,
  silentRefresh,
  declineSessionExtend: clearRefreshTimer,
  logout,
};

6) 엣지 케이스

상황 동작
토큰 유효 시간 < 5분 진입 즉시 confirm
confirm 취소 declineSessionExtend() + 동일 JWT에 재표시 안 함
confirm 확인 silentRefresh() → 새 토큰 기준 confirm 타이머 재설정
silentRefresh 실패 auth:logout → AuthWrapper 리다이렉트
로그아웃 clearAuthToken, 훅 cleanup
페이지 새로고침 Header가 confirm 타이머 재예약

7) 적용 체크리스트

  • ConfirmProvider > AuthWrapper > BaseLayout > Header 계층
  • ConfirmDialog가 ConfirmProvider 하위에 마운트됨
  • BaseLayout에 authService 전달
  • authService.declineSessionExtend 구현
  • 만료 5분 전 confirm 노출
  • 확인 클릭 시 SILENT_REFRESH 호출
  • 취소 후 세션이 연장되지 않음

8) 검증 방법

  1. 로그인 후 JWT exp가 5분 이내가 되도록 대기하거나 테스트 토큰 사용
  2. confirm 문구 "로그인을 연장하시겠습니까?" 표시 확인
  3. 확인 → Network에서 SILENT_REFRESH PUT, 쿠키 갱신, confirm 재예약
  4. 취소 → 만료 시 로그아웃/리다이렉트
  5. 새로고침 후 confirm 타이머 복구

9) 참고 구현

앱 auth-service BaseLayout / layout AppProvider
as (기준) apps/as/src/entities/auth/api/auth-service.ts apps/as/src/app/layouts/base-layout.tsx (동등 Provider)
cs apps/cs/src/entities/auth/api/auth-service.ts apps/cs/app/(main)/(with-base-layout)/layout.tsx apps/cs/src/app/providers/app-provider.tsx
st apps/st/src/entities/auth/api/auth-service.ts apps/st/app/(main)/(with-base-layout)/layout.tsx (동등 Provider)

공통:

  • packages/common/components/src/ui/header/index.tsx
  • packages/common/components/src/lib/use-session-extend-confirm.ts

10) 관련 문서