본문으로 건너뛰기

라우팅

이 페이지는 프론트엔드 라우팅 영역에 대한 레퍼런스 문서입니다. Lumie는 Next.js App Router만 사용합니다. 라우트 그룹이 주요 사용자 영역을 나누고, 레이아웃이 접근 제어를 담당하며, app/api/[...path]/route.ts는 브라우저의 모든 API 호출이 통과하는 동일 출처 프록시입니다.

소스 경로

경로역할
lumie-frontend/app/page.tsx호스트를 기준으로 동작하는 사이트 루트. canonical host에서는 Lumie 마케팅 홈을 렌더링하고, 신뢰된 커스텀 도메인에서는 /에서 테넌트 랜딩을 렌더링합니다.
lumie-frontend/app/(marketing)//about, /pricing, /features, /blog 같은 canonical 공개 마케팅 페이지
lumie-frontend/app/(auth)/로그인과 OWNER 회원가입 진입점
lumie-frontend/app/(onboarding)/layout.tsxOWNER 온보딩 가드와 리다이렉트
lumie-frontend/app/admin/layout.tsxstaff 전용 가드와 로그인 후 복귀 경로 처리
lumie-frontend/app/dashboard/layout.tsx학생 전용 서버 가드와 대시보드 셸
lumie-frontend/app/dashboard/assignments/page.tsx/dashboard/assignments에 마운트되는 학생 과제 목록 라우트
lumie-frontend/app/dashboard/assignments/[id]/page.tsx/dashboard/assignments/[id]에 마운트되는 학생 과제 상세 라우트
lumie-frontend/app/auth/callback/page.tsx레거시 콜백 링크를 비밀번호 로그인 모달 플로우로 돌려보내는 전환용 호환 라우트
lumie-frontend/app/auth/refresh/page.tsx무중단 refresh 경계
lumie-frontend/app/[customId]/page.tsx공개 학원 랜딩 페이지
lumie-frontend/app/api/[...path]/route.tsNEXT_PUBLIC_API_BASE로 향하는 동일 출처 프록시
lumie-frontend/proxy.ts커스텀 도메인 host 고정, root auth URL 정규화, 닫힌 상태로 실패 커스텀 도메인 라우팅, 라우트 트리가 렌더링되기 전의 인증 라우팅 게이트
lumie-frontend/src/shared/lib/customDomain.tsedge-safe 커스텀 도메인 host, env map, 대체 해석 헬퍼
lumie-frontend/src/shared/lib/serverCustomDomain.ts신뢰된 커스텀 도메인 테넌트 header를 읽는 server component 헬퍼
lumie-frontend/src/shared/config/env.ts브라우저 기준 API base. ENV.API_URL/api로 고정됩니다.
lumie-frontend/src/features/auth/login/ui/LoginForm.tsx테넌트 인지 ID/비밀번호 로그인 폼
lumie-frontend/src/features/auth/register/ui/RegisterForm.tsx학원별 진입점의 공유 인증 모달에서 사용하는 학생 셀프 등록 폼
lumie-frontend/src/features/auth/register-owner/ui/OwnerRegisterForm.tsx/signup에 마운트되는 다단계 OWNER 등록 흐름
lumie-frontend/src/entities/session/api/getServerUser.ts보호 레이아웃이 사용하는 서버 측 /v1/me 읽기
lumie-frontend/src/entities/session/model/onboarding.ts인증 후 기본 redirect의 역할 기반 로직
lumie-frontend/src/entities/assignment/api/student-queries.ts/v1/assignments/me, /v1/assignments/{id}/me, PUT /v1/assignments/{id}/me/submission용 React Query hook
lumie-frontend/src/entities/tenant/api/queries.tsusePublicTenantAuthContext()가 서버에서 주입한 테넌트 데이터, path custom ID, 커스텀 도메인 host에서 인증 테넌트 컨텍스트를 해석
lumie-frontend/src/entities/tenant/providers/PublicTenantContextHydrator.tsx/:customId 페이지와 커스텀 도메인 root rendering에서 서버가 해석한 공개 테넌트를 공유 인증 모달에 노출하는 클라이언트 브리지
lumie-frontend/src/entities/tenant/lib/useTenantCustomIdFromPath.tspathname에서 클라이언트 측 테넌트 custom ID 파싱
lumie-frontend/src/shared/lib/tenantRedirect.ts커스텀 도메인, canonical custom ID, 루트 대체 리디렉션을 만드는 인증 경계 로그인 URL 빌더
lumie-frontend/src/shared/lib/sessionCache.ts공유 API 코드가 사용하는 캐시된 세션 및 테넌트 리디렉션 컨텍스트 브리지
lumie-frontend/src/shared/lib/authRedirectReason.tsAUTH_017 같은 백엔드 인증 실패 코드를 URL-safe 인증 안내 사유로 매핑
lumie-frontend/src/shared/api/serverFetch.ts/api를 다시 통과하는 SSR fetch 경계
lumie-frontend/src/features/assignment-management/list-student-assignments//dashboard/assignments용 학생 과제 목록 카드와 지표
lumie-frontend/src/features/assignment-management/view-student-assignment/학생 과제 상세, 제출, 결과 컴포넌트
lumie-frontend/src/widgets/student-sidebar/ui/StudentSidebar.tsx/dashboard/assignments용 학생 대시보드 내비게이션 진입점

라우트 그룹과 주요 경로

경로 형태목적비고
/공개 사이트 루트 또는 커스텀 도메인 테넌트 랜딩app/page.tsx에 구현됩니다. canonical host는 공유 헤더와 푸터가 있는 Lumie 마케팅 홈을 렌더링하고, 신뢰된 커스텀 도메인은 Lumie 마케팅 chrome 없이 테넌트 랜딩을 렌더링합니다.
/about, /pricing, /features, /blog 같은 마케팅 경로canonical 공개 사이트 페이지공유 헤더와 푸터를 가진 app/(marketing) 아래 구현
/login인증 진입점LoginForm의 테넌트 인지 ID/비밀번호 로그인 폼을 사용합니다.
/signupOWNER 회원가입 진입점app/(auth)/signup/page.tsxOwnerRegisterForm을 렌더링합니다. 학생 셀프 등록은 tenant별 진입점의 공유 인증 모달로 노출됩니다.
/onboardingOWNER 온보딩 흐름app/(onboarding)/layout.tsx에서 보호
/admin/...staff 및 학원 운영app/admin/layout.tsx에서 보호
/dashboard/...학생 경험app/dashboard/layout.tsx에서 보호한 뒤 자체 클라이언트 레이아웃과 사이드바 셸로 렌더링
/dashboard/assignments학생 과제 목록StudentAssignmentListPage를 렌더링하고 동일 출처 프록시를 통해 GET /v1/assignments/me를 호출
/dashboard/assignments/[id]학생 과제 상세 및 제출 흐름StudentAssignmentDetailPage를 렌더링하고 GET /v1/assignments/{id}/me를 읽으며 PUT /v1/assignments/{id}/me/submission으로 제출
/auth/callback전환용 호환 리다이렉트app/auth/callback/page.tsx는 레거시 링크를 위한 tombstone 라우트입니다. callbackUrl을 검증한 뒤, 활성 OAuth 또는 SSO 완료 플로우가 아니라 비밀번호 로그인으로 리다이렉트합니다.
/auth/refresh무중단 refresh 브리지refresh 쿠키는 있지만 access token을 다시 세워야 할 때 사용
/:customId공개 학원 랜딩 페이지app/[customId]/page.tsx로 구현
/api/[...path]동일 출처 프록시 라우트브라우저 요청을 백엔드 게이트웨이로 전달

루트 라우트는 의도적으로 app/page.tsx에 둡니다. 그래야 커스텀 도메인이 모든 canonical 마케팅 페이지를 dynamic으로 만들지 않고도 /에서 테넌트 랜딩을 렌더링할 수 있습니다. Canonical 마케팅 하위 페이지는 app/(marketing) 아래에 남습니다.

/api/healthapp/api/health/route.ts에 별도로 있는 로컬 라우트입니다. 프론트엔드 liveness 용도로만 사용해야 하며, 백엔드 프록시는 검사하지 않습니다.

접근 제어

라우트 보호는 클라이언트 컴포넌트 곳곳에 흩어두지 않고 레이아웃에서 처리합니다.

온보딩

app/(onboarding)/layout.tsx는 다음을 수행합니다.

  • getServerUser()로 현재 사용자를 조회
  • 익명 사용자를 로그인 또는 세션 refresh로 리다이렉트
  • 학생을 /dashboard로 리다이렉트
  • 이미 온보딩을 마친 owner를 /admin으로 리다이렉트

관리자

app/admin/layout.tsx는 다음을 수행합니다.

  • 서버에서 현재 사용자를 확인
  • 로그인 후 복귀를 위해 요청된 관리자 경로를 보존
  • 학생을 /dashboard로 리다이렉트
  • 아직 온보딩하지 않은 owner를 /onboarding으로 리다이렉트

대시보드

app/dashboard/layout.tsx는 다음을 수행합니다.

  • 서버에서 현재 사용자를 확인
  • 로그인 후 복귀를 위해 요청된 대시보드 경로를 보존
  • 익명 사용자를 로그인 또는 세션 refresh로 리다이렉트
  • 학생이 아닌 사용자를 /admin으로 리다이렉트
  • 서버 세션 확인이 통과한 뒤에만 client DashboardShell을 렌더링

assignment 리디자인은 이 셸 아래에 학생 대시보드 페이지 두 개를 추가합니다.

  • 대상 과제 목록용 /dashboard/assignments
  • 상세, 제출, 즉시 결과 표시용 /dashboard/assignments/[id]

두 라우트 모두 이제 전용 /dashboard/assignments 메뉴 항목을 포함하는 StudentSidebar에서 접근할 수 있습니다.

학생 과제 라우트

라우트UI 엔트리포인트백엔드 계약비고
/dashboard/assignmentsapp/dashboard/assignments/page.tsx -> StudentAssignmentListPageGET /v1/assignments/me현재 학생에게 보이는 과제만 표시합니다. 페이지는 반환된 목록에서 요약 카운트를 계산하며 SSR prefetch는 하지 않습니다.
/dashboard/assignments/[id]app/dashboard/assignments/[id]/page.tsx -> StudentAssignmentDetailPageGET /v1/assignments/{id}/meassignment, canSubmit, 선택적 submission, EXAM_MANUAL용 선택적 연결 시험 메타데이터를 읽습니다.
/dashboard/assignments/[id] 제출 액션StudentAssignmentSubmissionFormPUT /v1/assignments/{id}/me/submission연결된 시험지에 대한 1-5 객관식 답안 선택 그리드를 렌더링한 뒤, 성공 시 목록과 상세 query를 모두 무효화합니다.

상세 라우트는 파라미터 전용입니다. 페이지 경계에서 notFound()를 호출하지 않습니다. 0 이하이거나 숫자가 아닌 ID는 클라이언트 라우트 계층에서 파싱되며, 이 경우 assignment query가 비활성화되어 GET /v1/assignments/{id}/me를 호출하는 대신 프론트엔드 오류 상태를 렌더링합니다.

학생 과제 UI 동작

  • useStudentAssignments()GET /v1/assignments/meStudentAssignment[]로 파싱하고, 이 라우트를 페이지네이션 피드가 아닌 평면 목록으로 취급합니다.
  • StudentAssignmentListPagesubmissionMode === 'EXAM_MANUAL'에서 "수동 과제" 카운트를 계산합니다.
  • useStudentAssignment()GET /v1/assignments/{id}/meStudentAssignmentDetail로 파싱합니다.
  • StudentAssignmentSubmissionForm은 렌더링된 각 문항에 1-5 답안이 있는지 검증한 뒤 학생 제출 mutation을 호출합니다.
  • StudentAssignmentResultCard는 채점된 제출이 있으면 점수, 합격 여부, 문항별 유형과 정오를 렌더링합니다. 정답 키 공개 여부만 showCorrectAnswers에 따릅니다.

즉 상세 페이지의 프론트엔드 라우팅 계약은 staff 제출 API가 아니라 assignment 서비스의 학생 전용 응답 형태와 결합되어 있습니다.

전환용 호환 라우트

app/auth/callback/page.tsx는 오래된 북마크나 외부 리다이렉트가 /auth/callback?callbackUrl=...를 계속 가리키더라도 곧바로 404로 떨어지지 않도록 남아 있습니다.

이 페이지는 OAuth 제공자 콜백이 아니며, 어떤 제공자 code나 token도 교환하지 않습니다. 이 라우트의 유일한 역할은 상대 callbackUrl을 정제한 뒤 비밀번호 로그인 진입점으로 브라우저를 리다이렉트하는 것입니다.

  • 누락되었거나 유효하지 않은 콜백 URL은 /login으로 이동합니다
  • 안전한 일반 콜백 URL은 /login?callbackUrl=...으로 이동합니다
  • 테넌트 콜백 URL은 /:customId?auth=login&callbackUrl=...으로 이동합니다

/auth/callback은 제거된 SSO 흐름을 위한 폐기 shim이지, 현재 활성 로그인 계약의 일부가 아닙니다.

테넌트 인지 라우팅

현재 공개 URL에는 테넌트를 식별하는 방식이 두 가지 있습니다.

  • https://lumie-edu.com/:customId 형태의 정식 테넌트 URL
  • https://academy.example/ 같은 호스트 기반 커스텀 도메인

정식 테넌트 URL은 테넌트 custom ID를 경로에 유지하며 app/[customId]/page.tsx에서 렌더링됩니다. 커스텀 도메인은 공개 URL에 custom ID 경로를 노출하지 않습니다. proxy.tsCUSTOM_DOMAIN_TENANT_MAP 또는 전환용 도메인 기반 조회 결과에서 신뢰된 테넌트 헤더를 주입하고, app/page.tsx/에서 테넌트 랜딩을 직접 렌더링합니다.

설정된 커스텀 도메인은 다음 환경 변수 맵 형태를 사용합니다. 소스 앵커: src/shared/lib/customDomain.ts#resolveConfiguredCustomDomainContextlumie-infra/applications/lumie/frontend/CUSTOM_DOMAIN_RUNBOOK.md#setup.

CUSTOM_DOMAIN_TENANT_MAP=academy.example=<SLUG>:<CUSTOM_ID>

<SLUG>는 API와 인증 고정에 사용하는 백엔드 테넌트 식별자입니다. <CUSTOM_ID>lumie-edu.com/:customId에서 쓰는 공개 정식 경로 별칭입니다. 둘은 다를 수 있습니다. 식별자가 갈라지는 버그를 막기 위해 app/page.tsx<CUSTOM_ID>로 공개 테넌트 데이터를 가져오고, 가져온 테넌트 slug가 신뢰된 <SLUG>와 같지 않으면 닫힌 상태로 실패합니다.

커스텀 도메인 라우팅은 호스트를 기준으로 동작합니다.

  • https://academy.example/는 테넌트 랜딩을 렌더링합니다
  • https://academy.example/?auth=login/?auth=register는 루트 URL에 인증 상태를 유지합니다
  • /login, /register, /signup은 루트 쿼리 형식으로 리다이렉트합니다
  • /admin, /dashboard, /auth/refresh, /api/*, /favicon.ico는 신뢰된 테넌트 헤더를 유지합니다. favicon은 테넌트 logo가 있으면 그 logo를 반환하고, 없으면 Lumie favicon으로 대체 처리합니다
  • 커스텀 도메인의 /:customId/:customId/loginCache-Control: no-store와 함께 404를 반환합니다
  • 커스텀 도메인의 관련 없는 정식 마케팅 경로는 404를 반환합니다
  • 설정되지 않은 커스텀 도메인은 부트스트랩 해석 경로 밖에서 503으로 닫힌 상태로 실패합니다

인증 경계의 리디렉션도 테넌트 컨텍스트를 유지합니다. buildTenantLoginUrl(...)는 다음 우선순위를 사용합니다.

  1. 검증된 테넌트 커스텀 도메인을 알고 있으면 https://{customDomain}/?auth=login
  2. 테넌트 custom ID만 알고 있으면 https://lumie-edu.com/{customId}?auth=login
  3. 테넌트 URL 정보를 전혀 알 수 없을 때만 https://lumie-edu.com/?auth=login

소스 앵커는 src/shared/lib/tenantRedirect.ts, src/shared/lib/sessionCache.ts, src/shared/api/base.ts입니다.

인증 폼은 pathname 파싱에만 의존하지 않습니다. app/[customId]/page.tsxapp/page.tsx의 커스텀 도메인 렌더링은 서버에서 공개 테넌트를 해석한 뒤 PublicTenantContextHydrator를 마운트해, 공유 인증 모달이 브라우저의 공개 테넌트 조회보다 먼저 검증된 tenantSlug를 읽을 수 있게 합니다. usePublicTenantAuthContext()는 서버에서 주입한 테넌트 컨텍스트를 우선 사용하고, 그다음 useTenantCustomIdFromPath()와 경로의 custom ID 또는 커스텀 도메인 호스트 기반 공개 테넌트 조회로 대체합니다. 이 hook은 활성 tenantSlug, tenantCustomId, 그리고 컨텍스트가 server, path, host 중 어디에서 왔는지를 함께 반환합니다.

이 공통 인증 컨텍스트는 세 가지 브라우저 진입 케이스를 같은 규칙으로 맞춥니다.

  • /:customId 아래의 브랜딩 랜딩 페이지는 서버에서 테넌트 컨텍스트를 해석하고 공유 인증 모달로 수화합니다
  • 커스텀 도메인 루트 페이지는 신뢰된 호스트 헤더에서 테넌트 컨텍스트를 해석하고 공유 인증 모달로 수화합니다
  • 일반 /login/signup 페이지는 브라우저가 테넌트별 경로나 호스트 위에 있지 않으면 테넌트 없는 상태를 유지합니다

테넌트 컨텍스트를 얻을 수 있을 때, 공유 인증 모달은 일반 /login이나 /signup 페이지에 학원 식별자를 하드코딩하지 않고도 학생 셀프 등록을 노출할 수 있습니다.

테넌트 범위 로그인은 tenantSlug가 해석될 때까지 프론트엔드에서 닫힌 상태로 실패합니다. 비밀번호 로그인 요청은 URL의 customId를 포함할 수 있지만, 인증된 세션 상태와 이후 API 호출은 공개 별칭이 아니라 백엔드가 발급한 tenantSlugtenantId를 신뢰합니다.

테넌트 쿼리가 아직 준비되지 않은 인증 경계에서 세션이 만료되면, sessionCache.getTenantRedirectContext()는 먼저 현재 테넌트 쿼리 데이터가 준비되어 있으면 그 값을 사용하고, 그다음 캐시된 /v1/me 사용자에서 백엔드가 검증한 tenantCustomIdtenantCustomDomain을 읽습니다. 두 캐시가 모두 없으면 현재 브라우저 호스트 또는 예약어가 아닌 첫 경로 segment를 대체 경로로 사용해 /:customId나 커스텀 도메인 호스트에서 발생한 cold 401이 루트 로그인 페이지로 떨어지는 것을 막습니다.

라우트 상태로서의 쿼리 파라미터

일부 UI 상태는 의도적으로 URL에 인코딩됩니다.

  • ?auth=login|register&callbackUrl=/target은 공유 인증 모달을 엽니다
  • ?auth=login&reason=session_replaced는 로그인을 열고 교체된 세션 안내를 한 번 표시한 뒤 URL에서 reason을 제거합니다
  • 학생 목록과 Q&A 같은 리스트 페이지는 필터, 검색, 정렬, 페이지 상태를 search param에 유지합니다
  • 학생 목록은 filter=active|inactive|all, class=all|unassigned|<id>를 사용하며, 파서는 이를 GET /v1/studentsisActive, classId 또는 hasActiveEnrollment=false로 변환합니다
  • 시험 상세 대시보드도 page, sort, dir과 함께 같은 filter, class 값을 사용하며, 이를 전체 통계, 학생별 성적, 반 비교, 문항 분석, 선지 분포 등 모든 시험 상세 통계 화면의 isActive, classId, hasActiveEnrollment=false로 변환합니다
  • 학습 리포트 대시보드는 선택한 클래스 필터를 ?classId=<id>에 유지하고, 전체 클래스 보기에서는 이 key를 제거합니다
  • parseStudentListParams()parseQnaListParams() 같은 헬퍼 파서는 라우트 코드와 쿼리 key 사이의 URL 파싱을 맞춰줍니다

이렇게 하면 리스트 뷰를 북마크할 수 있고, TanStack Query도 같은 라우트 상태에 대해 안정적인 key를 사용할 수 있습니다. 리포트 대시보드는 선택한 시험이 바뀔 때 classId도 지웁니다. 따라서 한 시험에서 고른 클래스가 다음 시험의 행을 숨기지 않습니다. 해당 대시보드의 리포트 생성 액션은 활성화된 모든 대시보드 필터가 적용된 뒤 현재 보이는 선택 행을 기준으로 동작합니다.

프록시 라우트 동작

app/api/[...path]/route.ts는 UI를 렌더링하지 않더라도 라우팅 표면의 일부입니다. 이 라우트는 다음을 수행합니다.

  • 요청을 NEXT_PUBLIC_API_BASE로 전달
  • origin 같은 브라우저 전용 또는 안전하지 않은 전달 헤더 제거
  • 브라우저 요청의 spoof 가능한 테넌트 및 user header 제거
  • configured 커스텀 도메인 host map에서, 또는 auth write 엔드포인트의 대체 처리 host resolution에서 X-Tenant-Slug 부착
  • localhost 프록시 모드에 맞게 Set-Cookie 헤더 재작성
  • Node fetch 압축 해제 후 오래된 압축 헤더 제거

소스 앵커: lumie-frontend/app/api/[...path]/route.ts#proxyRequest

const host = normalizeHost(request.headers.get('host'));
const targetUrl = `${getApiBase()}${url.pathname}${url.search}`;
const headers = new Headers(request.headers);
headers.delete('host');
headers.delete('x-tenant-slug');
headers.delete('x-lumie-custom-id');
headers.delete('x-tenant-id');
headers.delete('x-user-id');
headers.delete('x-user-role');
headers.delete('origin');

if (isResolutionEnabled() && isCustomDomainCandidate(host)) {
const configured = resolveConfiguredCustomDomainContext(host);
if (configured) {
headers.set('x-tenant-slug', configured.slug);
} else if (isAuthWriteEndpoint(url.pathname)) {
const tenant = await resolveCustomDomainTenant(host);
if (!tenant?.slug) return customDomainUnavailableResponse();
headers.set('x-tenant-slug', tenant.slug);
} else {
return customDomainUnavailableResponse();
}
}

같은 handler는 DomainSecure를 제거하고, SameSite=NoneSameSite=Lax로 낮춰 로컬 개발 중 http://localhost:3000에 인증 쿠키가 저장되도록 Set-Cookie를 다시 씁니다.

검증 가능한 프록시 요청

next devhttp://localhost:3000에서 실행 중이고 NEXT_PUBLIC_API_BASE가 도달 가능한 백엔드를 가리킬 때, 프론트엔드 리포지토리에서 다음을 실행합니다.

cd lumie-frontend
curl -i http://localhost:3000/api/v1/me

예상 성공 신호:

  • 요청은 로컬 app/api/health/route.ts가 아니라 app/api/[...path]/route.ts에서 처리됩니다
  • 인증 쿠키가 없으면 응답은 401 또는 403 같은 백엔드 인증 응답이어야 합니다
  • 유효한 lumie_access_token 쿠키가 있으면 같은 경로가 200을 반환해야 합니다
  • 두 경우 모두 프록시된 응답이 오면 프론트엔드 라우트가 존재하고, 브라우저가 보낸 spoof 가능 테넌트 header를 제거한 뒤, Next.js 404를 반환하는 대신 NEXT_PUBLIC_API_BASE로 전달했다는 뜻입니다

학생 과제 라우트 정적 연결 확인

cd /path/to/Lumie
rg -n "dashboard/assignments|useStudentAssignments|useStudentAssignment|useSubmitStudentAssignment" \
lumie-frontend/app/dashboard \
lumie-frontend/src/features/assignment-management \
lumie-frontend/src/entities/assignment/api/student-queries.ts \
lumie-frontend/src/widgets/student-sidebar/ui/StudentSidebar.tsx

예상 성공 신호:

  • app/dashboard/assignments/page.tsx에 대한 hit가 나타납니다
  • app/dashboard/assignments/[id]/page.tsx에 대한 hit가 나타납니다
  • 학생 쿼리 hook과 사이드바 내비게이션 항목에 대한 hit가 나타납니다

Auth-Boundary Redirect 정적 연결 확인

cd /path/to/Lumie
rg -n "buildTenantLoginUrl|getTenantRedirectContext|SESSION_REPLACED_BY_LOGIN_CODE|session_replaced" \
lumie-frontend/src/shared \
lumie-frontend/app/auth \
lumie-frontend/src/features/auth/logout

예상 성공 신호:

  • src/shared/lib/tenantRedirect.tssrc/shared/lib/sessionCache.ts에 hit가 나타납니다
  • src/shared/api/base.tsapp/auth/refresh/RefreshSession.tsx에 hit가 나타납니다
  • URL 기반 notice cleanup을 위해 src/shared/providers/AuthModalProvider.tsx에 hit가 나타납니다

관련 페이지