Files

13 KiB

관리자 라우트 지연 로딩 PRD

문서 정보

항목 내용
문서 상태 구현 완료
작성일 2026-08-06
최종 수정일 2026-08-06
대상 제품 AI 캐릭터 관리자 웹
작성자·결정권자 Codex 작성, 사용자 결정
관련 API Contract 불필요 — API와 payload 변경 없음
관련 구현 계획 plan-task.md
관련 review Phase 1 관리자 라우트 지연 로딩 리뷰

요구사항 상태

상태 의미 구현 처리
확정 제품·기술 결정이 완료된 구현 기준 plan-task.md의 Task와 완료 증거로 추적
미결 추가 결정 필요 구현 전 결정
외부 의존 프론트엔드 밖의 제공 필요 제공 전 관련 구현 중단
권고 확정 전 추천안 수용 기준으로 사용하지 않음
제외 이번 범위에서 구현하지 않음 포함 조건을 Decision Log에 기록

문서 우선순위와 갱신 순서

  1. 초기 bundle과 라우트 로딩 결정은 이 PRD가 소유한다.
  2. API 변경이 없으므로 별도 API Contract를 만들지 않는다.
  3. 구현 순서와 완료 증거는 plan-task.md가 소유한다.
  4. 결정이 바뀌면 Decision Log → 요구사항 → 계획 순서로 갱신한다.

1. Overview

보호된 관리자 페이지를 React.lazy() 기반 동적 import로 분리한다. 최초 접속에는 현재 라우트에 필요한 코드만 내려받고, 다른 페이지 코드는 해당 라우트에 처음 진입할 때 로드한다. 기능·API·권한·데이터 흐름은 유지한다.

2. Problem Statement

현재 protected-admin-shell.tsx는 14개 보호 페이지를 정적으로 import한다.

  • production build가 310개 module을 하나의 598.78kB minified JS chunk로 출력한다.
  • Vite 8.1.5 기본 기준 500kB를 넘어 build마다 chunk size warning이 발생한다.
  • gzip 전송량은 158.94kB지만 browser가 최초 접속에 전체 chunk를 다운로드·파싱·실행한다.
  • 이미지 cropper처럼 현재 라우트에서 사용하지 않는 기능도 초기 module graph에 포함된다.

문제를 해결했다는 판단은 production build가 보호 페이지를 여러 chunk로 분리하고 모든 JS chunk가 500,000 bytes 이하이며, 기존 사용자 흐름이 그대로 통과할 때로 한다. 구현 완료 build는 37개 JS chunk, 최대 JS 315.09kB, chunk size warning 0건이다.

3. Goals

3.1 제품 목표

  • 최초 접속에서 현재 관리자 화면에 필요하지 않은 페이지 코드를 지연 로드한다.
  • Vite의 500kB 초과 chunk warning을 실제 code splitting으로 제거한다.
  • 직접 URL, 내부 이동, 뒤로 가기와 권한 검사를 기존과 동일하게 유지한다.

3.2 UX 목표

  • 첫 화면의 다운로드·파싱·실행 부담을 줄인다.
  • 미로드 라우트 최초 진입에는 명확한 loading 상태를 표시한다.
  • loading 중 keyboard focus, 관리자 shell과 현재 URL을 유지한다.

4. Non-Goals

  • chunkSizeWarningLimit 상향으로 경고만 숨기기
  • manualChunks 또는 vendor chunk 설정 추가
  • react-advanced-cropper, zod, React Query 교체·제거
  • router library, bundle 분석 library 또는 새 runtime dependency 추가
  • API, 인증·권한, route path, page props와 상태 관리 변경
  • 서버 rendering, prefetch, service worker cache 또는 offline 지원 추가

Non-Goal을 변경하려면 Decision Log와 plan-task.md를 먼저 갱신한다.

5. Target Users and Permissions

사용자 목표 주요 작업 사용 환경
ADMIN 관리자 화면에 빠르게 진입 캐릭터·오디오·시리즈·커뮤니티·FanTalk 관리 desktop, tablet, mobile
인증되지 않은 사용자 보호 코드 노출 없이 로그인 로그인, 인증 후 관리자 진입 desktop, tablet, mobile
  • 기존 ADMIN probe, 401 session 제거와 403 접근 거부 정책을 유지한다.
  • lazy page loading은 권한 검사 성공 뒤에만 보호 UI를 표시한다.

6. 핵심 사용자 흐름

  1. 사용자가 로그인 또는 보호된 직접 URL로 접속한다.
  2. 기존 인증·ADMIN probe가 완료된다.
  3. 현재 라우트 page chunk가 없으면 관리자 shell 안에 loading 상태를 표시한다.
  4. chunk가 로드되면 기존 page를 같은 props와 URL로 표시한다.
  5. 다른 메뉴에 처음 진입하면 해당 page chunk만 추가로 받고, 이후 browser cache를 재사용한다.
  6. 내부 이동·뒤로 가기·새로고침과 mutation 흐름은 기존과 동일하게 동작한다.

7. 정보 구조와 라우팅

/login                               # eager 유지
/access-denied                       # eager 유지
/ai-characters                       # protected page lazy
/ai-characters/new                   # protected page lazy
/ai-characters/:characterId/**       # protected page lazy
  • App, 인증 provider와 ProtectedAdminShell은 application shell로 유지한다.
  • ProtectedAdminShell이 현재 판정하는 모든 보호 page component만 lazy boundary로 이동한다.
  • route path parser와 URL 상태는 변경하지 않는다.

8. 기능 요구사항

8.1 Code splitting

ID 상태 요구사항 수용 기준 계약/Goal 연결
ARL-001 확정 ProtectedAdminShell의 보호 page 정적 import를 React.lazy() 동적 import로 전환한다. 14개 page component가 현재 route에서 render될 때 해당 module을 import한다. contract 불필요, P1-T1
ARL-002 확정 named export를 유지하며 page component의 public props를 변경하지 않는다. page export·호출부 type과 기존 test가 변경 없이 통과한다. contract 불필요, P1-T1
ARL-003 확정 보호 page 영역을 Suspense로 감싸 loading 상태를 표시한다. 미로드 page 진입 시 화면을 불러오는 중 status가 관리자 shell 안에 표시된다. contract 불필요, P1-T1
ARL-004 확정 production build의 모든 minified JS chunk를 500,000 bytes 이하로 유지한다. production graph test가 JS chunk 2개 이상과 최대 chunk <=500,000 bytes를 확인하고 Vite 경고가 없다. contract 불필요, P1-T1, P1-GATE

8.2 기능 보존

ID 상태 요구사항 수용 기준 계약/Goal 연결
ARL-005 확정 로그인, ADMIN probe, 401·403와 malformed route 처리를 유지한다. 기존 App auth·protected 오류 test가 모두 통과한다. 기존 인증 계약 유지, P1-GATE
ARL-006 확정 직접 URL, 내부 이동, 뒤로 가기와 route별 page props를 유지한다. 기존 App route test와 mock Chromium E2E가 모두 통과한다. 기존 route contract 유지, P1-GATE
ARL-007 확정 각 page의 조회·생성·수정·삭제, upload와 댓글 동작을 변경하지 않는다. 전체 unit과 mock Chromium E2E에서 신규 실패가 0건이다. 기존 domain 계약 유지, P1-GATE
ARL-008 확정 mock module은 production bundle에서 계속 제외한다. 기존 production-graph.test.ts의 mock 제외 assertion이 통과한다. 기존 production boundary 유지, P1-T1

9. 반응형 기능 범위

기능 Desktop Tablet Mobile 비고
보호 page lazy loading 지원 지원 지원 동일 route boundary
loading 상태 지원 지원 지원 관리자 main 안에 표시
직접 URL·뒤로 가기 유지 유지 유지 URL 변경 없음
  • 320px와 200% zoom에서 loading 상태와 page가 수평 overflow를 만들지 않아야 한다.
  • 기존 모바일 조회·수정 capability 정책은 변경하지 않는다.

10. UI/UX Expectations

10.1 디자인과 component 원칙

  • 기존 PageState를 loading fallback으로 재사용한다.
  • 관리자 shell, navigation, header와 success notification은 page chunk loading 중 유지한다.
  • 새 spinner, skeleton, animation 또는 styling을 추가하지 않는다.

10.2 화면 상태

  • lazy page가 준비되지 않았을 때 화면을 불러오는 중을 표시한다.
  • page가 준비되면 같은 main 영역에서 기존 page로 교체한다.
  • 기존 API loading·empty·error·success 상태는 page 내부 책임으로 유지한다.

10.3 접근성

  • fallback은 기존 PageState의 semantic status를 사용한다.
  • keyboard focus 순서, skip link와 route 전환 focus 정책을 변경하지 않는다.
  • 200% zoom과 axe critical·serious 0건을 유지한다.

11. API 계약

11.1 공통 규칙

  • lazy loading은 module 전달 방식만 변경한다.
  • endpoint, method, payload, response, 오류와 pagination 계약을 변경하지 않는다.

11.2 Endpoint 추적

요구사항 Method Path 계약 상태 API Contract 소유 Goal
ARL-001~008 해당 없음 해당 없음 변경 불필요 기존 domain 계약 유지 P1-T1, P1-GATE

11.3 외부 제공 대기 계약

없음.

12. 보안과 데이터 취급

  • 인증 token 저장·전달, 401 clear와 403 route 정책을 변경하지 않는다.
  • 보호 page chunk는 기존과 같은 정적 asset이므로 권한 경계를 대체하지 않는다.
  • log, analytics와 외부 전송을 추가하지 않는다.
  • production mock 제외 경계를 유지한다.

13. 성능과 품질 요구사항

  • 기준 build: Vite 8.1.5, 단일 JS 598.78kB, gzip 158.94kB, 310 modules.
  • 완료 build: JS chunk 2개 이상, 각 minified JS <=500,000 bytes, chunk size warning 0건.
  • chunkSizeWarningLimit 기본값 500을 변경하지 않는다.
  • 새 dependency와 custom chunk configuration을 추가하지 않는다.
  • production graph test, App unit, 전체 unit, mock Chromium E2E, typecheck, lint와 production build를 Gate로 사용한다.

14. 성공 기준

14.1 기능 수용 기준

  • 모든 보호 page가 직접 URL과 내부 이동에서 기존 기능을 제공한다. (ARL-001~003, ARL-005~007)
  • 인증·권한·API request와 page props가 변경되지 않는다. (ARL-002, ARL-005~008)

14.2 UI/UX 수용 기준

  • 미로드 route에 기존 PageState loading 상태가 표시된다.
  • 320px·200% zoom·keyboard 흐름과 axe critical·serious 0건을 유지한다.
  • 첫 route 이후 다른 route 최초 진입만 추가 chunk loading을 수행한다.

14.3 성능·추적성 완료 기준

  • production build에 500kB 초과 chunk warning이 없다. (ARL-004)
  • 모든 JS chunk가 500,000 bytes 이하임을 자동 test로 검증한다.
  • ARL-001~008P1-T1 또는 P1-GATE 완료 증거로 연결된다.
  • API Contract가 불필요함을 기록했다.

15. Open Questions

없음. route-level React.lazy()를 선택했고 경고 임계값 상향과 수동 vendor 분리는 제외했다.

16. 요구사항 추적표

요구사항 범위 API Contract 계획 Phase Goal 자동 검증 수동 검증
ARL-001~004, ARL-008 불필요 1 P1-T1 production graph, App focused unit, production build Network의 route chunk loading
ARL-005~007 기존 계약 유지 1 P1-GATE 전체 unit, mock Chromium E2E, typecheck, lint 직접 URL·내부 이동·뒤로 가기·320px·200% zoom
ARL-006~007 CJK zoom 회귀 기존 계약 유지 1 P1-R1 CJK E2E, ResourcePagination unit, mock mobile Chrome E2E 320px·200% zoom 한국어 줄바꿈

17. Decision Log

날짜 ID 상태 결정 근거 영향 요구사항·계약·Goal
2026-08-06 ARL-DEC-001 확정 보호된 관리자 page를 route-level React.lazy()로 분리한다. 단일 chunk의 원인이 모든 보호 page 정적 import이며 실제 초기 loading 비용도 줄일 수 있다. ARL-001~008, P1-T1, P1-GATE
2026-08-06 ARL-DEC-002 확정 chunkSizeWarningLimit 상향과 manualChunks는 적용하지 않는다. 경고만 숨기거나 초기 총량을 유지하는 방식 대신 실제 지연 loading을 선택한다. ARL-004, Non-Goals
2026-08-06 ARL-DEC-003 확정 기존 PageState만 fallback으로 재사용하고 새 loading component를 만들지 않는다. 현재 디자인·접근성 관례를 유지하는 최소 구현이다. ARL-003, P1-T1
2026-08-06 ARL-DEC-004 확정 공통 ResourcePagination의 mobile movement controls는 동일 폭 2열 대신 1열 stacked 배치로 대체한다. 320px·200% zoom에서 한국어 버튼 텍스트가 음절 단위 세로 열로 분리되는 것을 막고, desktop/tablet 배치는 기존 sm:flex로 유지한다. ARL-006~007, P1-R1, P1-GATE