세션 정보 참조 가이드
dictionary-app은 로그인 세션 사용자 정보를 useSessionStore(zustand, localStorage 영속화)에 두고, 어느
컴포넌트에서든 이 훅으로 읽는다. 스토어 자체의 전체 정의는 스토어
가이드의 useSessionStore 항목 참고 — 이 문서는
“참조해서 쓰는” 소비 패턴에 집중한다.
화면에서 세션 정보 참조하기
Section titled “화면에서 세션 정보 참조하기”- 사용자 이름 표시 + 게스트 배지 —
sessionUser가 없으면(비로그인) 아무 것도 렌더링하지 않는다.layout/header/Header.tsx import {Badge, Flex, Text} from '@chakra-ui/react'import {useSessionStore} from '@/hooks'export const Header = () => {const {sessionUser} = useSessionStore()return (<Flex as="header">{sessionUser && (<Flex align="center" gap={3} ml="auto">{sessionUser.guestYn === 'Y' && (<Badge colorPalette="orange" variant="subtle" size="sm">게스트</Badge>)}<Text fontSize="sm" color="fg">{sessionUser.userNm}님</Text></Flex>)}</Flex>)} - 게스트 계정 여부로 메뉴 항목을 필터링한다.
components/organisms/menu/Menu.tsx import {useSessionStore} from '@/hooks'export const Menu = ({items, depth = 0}: MenuProps) => {const {sessionUser} = useSessionStore()const isGuest = sessionUser?.guestYn === 'Y'const visibleItems = isGuest? items.filter((item) => item.menuName !== GUEST_HIDDEN_MENU_NAME): itemsreturn <>{/* visibleItems 렌더링 */}</>} adminYn/guestYn처럼 값이'Y'/'N'문자열이라는 점에 주의한다 — boolean이 아니라 백엔드SessionUserDTO의 원본 타입 그대로다.
서버 세션 재확인 — useSessionFindQuery
Section titled “서버 세션 재확인 — useSessionFindQuery”localStorage에 남은 로그인 상태만 믿지 않고, 주기적으로GET /v1/auth/find-session을 호출해 서버 세션이 실제로 살아있는지 확인한다. 401이 아닌 에러(네트워크 순단 등)는 “로그인되지 않음”으로 취급하지 않도록 구분해서 반환한다.hooks/queries/useSessionFindQuery.ts 5 collapsed linesimport {useQuery} from '@tanstack/react-query'import {isUnauthorizedError} from '@/utils'import {useAuthApi} from '../apis'const SESSION_CHECK_INTERVAL_MS = 1000 * 60 * 5export const useSessionFindQuery = () => {const {findSession} = useAuthApi()const {data: sessionUser,isLoading: isSessionChecking,error: sessionError,} = useQuery({queryKey: ['auth', 'session'],queryFn: ({signal}) => findSession(signal),retry: false,refetchInterval: SESSION_CHECK_INTERVAL_MS,})const isSessionExpired = isUnauthorizedError(sessionError)return {sessionUser, isSessionChecking, isSessionExpired}}- 이 훅은 인증 가드(
RequireAuth)가 소비한다 — 확인에 성공하면useSessionStore를 최신화하고, 401이면 비운다. 전체 코드는 스토어 가이드의useSessionStore사용 예 참고.
응답마다 만료 시각 갱신 — useAxiosInterceptor
Section titled “응답마다 만료 시각 갱신 — useAxiosInterceptor”- 백엔드는 모든 API 응답 봉투에
expiresAt(슬라이딩 세션의 실제 만료 시각)을 함께 내려준다 — 어느 API를 호출했는지와 무관하게 매 응답마다 이 값으로 세션 스토어를 최신화해야 실제 서버 값과 어긋나지 않는다.hooks/useAxiosInterceptor.ts instance.interceptors.response.use((response) => {const expiresAt = (response.data as ResponseDto<unknown> | undefined)?.expiresAtif (expiresAt !== undefined) {setExpiresAt(expiresAt)}return response},(error) => {if (isUnauthorizedError(error)) {removeSessionUser()queryClient.clear()navigate('/login', {replace: true})}return Promise.reject(error)},) - 401 응답을 받으면(진짜 세션 만료) 세션 스토어를 비우고 react-query 캐시를 초기화한 뒤
/login으로 이동한다 — Header의 수동 로그아웃 처리와 동일한 절차다.