본문으로 건너뛰기

프론트엔드 개요

Lumie의 프론트엔드는 공개 사이트, 인증 플로우, 테넌트 온보딩, staff 관리자 워크스페이스, 학생 대시보드를 제공하는 Next.js 16 App Router 애플리케이션입니다. 라우팅은 app/에 있고, 제품 로직은 src/에 있으며, 브라우저 요청은 브라우저에서 백엔드를 직접 호출하지 않고 프론트엔드 자체의 /api 프록시를 거칩니다.

이 리포지토리가 담당하는 것

  • 공개 마케팅 페이지와 학원 랜딩 페이지
  • 로그인, OWNER 회원가입, 학생 self-등록, 세션 refresh 플로우
  • 회원가입 후 OWNER 온보딩
  • /admin 아래의 관리자용 학원 운영 페이지
  • 관리자 OMR 채점, 성적 관리 테이블, 결과 수정 액션
  • 과제 목록 및 제출 흐름을 포함한 /dashboard 아래의 학생용 페이지
  • 프론트엔드 측 프록시, 인증 쿠키 처리, 테넌트 헤더 전달

런타임 형태

로컬 개발에서는 프론트엔드가 http://localhost:3000에서 실행되고, 백엔드와 상태 저장 서비스는 dev 클러스터에서 실행됩니다. 브라우저 코드는 /api/v1/...를 호출하고, app/api/[...path]/route.ts가 그 요청을 NEXT_PUBLIC_API_BASE로 전달하며, localhost 쿠키를 위해 응답 헤더를 다시 쓰고, 커스텀 도메인 해석이 활성화되어 있으면 테넌트 컨텍스트를 붙입니다.

app/layout.tsx의 루트 레이아웃은 다음을 연결합니다.

  • TanStack Query용 QueryProvider
  • AuthModalUrlSync와 공유 인증 모달
  • 전역 Toaster
  • 로컬 Noto Sans KR 폰트와 문서 셸

주요 구현 규칙

영역현재 접근 방식
라우팅라우트 group과 중첩 레이아웃을 사용하는 Next.js App Router
애플리케이션 구조src/ 아래의 Feature-Sliced Design
서버 상태TanStack Query
클라이언트 UI 상태Zustand와 로컬 컴포넌트 상태
Zod 검증을 결합한 React Hook Form
API 클라이언트공유 fetch 레이어와 orval 생성 hook/쿼리 헬퍼
E2E 테스트Playwright
단위 테스트jsdom 환경의 Vitest

코드 맵

경로책임
app/라우트, 레이아웃, 로딩 상태, 에러 바운더리, 라우트 핸들러
src/shared/API 기본 요소, 설정, 범용 UI, 제공자, 유틸리티
src/entities/도메인 모델, 생성된 API hook, 엔티티 수준 헬퍼
src/features/사용자 액션과 기능별 UI 또는 상태
src/widgets/헤더, 사이드바, 인증 모달 같은 조합된 화면과 셸
components/ui/관례상 리포지토리 루트에 유지되는 포크된 shadcn 기본 요소

소스 경로

주장소스 경로
동일 출처 /api 프록시와 쿠키 재작성lumie-frontend/app/api/[...path]/route.ts
브라우저 API base는 /apilumie-frontend/src/shared/config/env.ts
루트 provider와 전역 셸lumie-frontend/app/layout.tsx
TanStack Query 제공자lumie-frontend/src/shared/providers/QueryProvider.tsx
Feature-Sliced Design aliaslumie-frontend/tsconfig.json
학생 과제 라우트lumie-frontend/app/dashboard/assignments/page.tsx, lumie-frontend/app/dashboard/assignments/[id]/page.tsx
학생 과제 API hooklumie-frontend/src/entities/assignment/api/student-queries.ts
학생 과제 기능 UIlumie-frontend/src/features/assignment-management/list-student-assignments/, lumie-frontend/src/features/assignment-management/view-student-assignment/
OMR 결과 전화번호 수정 dialoglumie-frontend/src/entities/exam/ui/ExamResultPhoneEditDialog.tsx
OMR 완료 모달의 전화번호 수정 진입점lumie-frontend/src/features/grade-omr/track-omr-grading/ui/OmrResultPreview.tsx
학생별 성적 테이블의 학생 등록 진입점lumie-frontend/src/features/grade-management/view-grade-detail/ui/StudentGradeTable.tsx

관리자 OMR 결과 수정

OMR 인식이 전화번호를 잘못 읽으면 교직원은 OMR 완료 모달에서 전화번호를 수정할 수 있습니다. 공유 dialog는 React Hook Form과 Zod로 전화번호를 검증한 뒤 시험 결과 전화번호 수정 mutation을 호출합니다. 수정된 번호가 활성 등록 학생과 일치하면 백엔드 응답은 해당 결과를 등록 상태로 반환하고, 프론트엔드는 수정 영향이 있는 시험 결과, 학생별 성적, 학생 결과, 통계, OMR job 캐시를 무효화합니다.

성적 테이블은 미등록 결과 row에만 학생 등록을 노출합니다. 교직원이 해당 row에서 학생을 등록하면서 OMR에서 가져온 전화번호를 수정하면, 프론트엔드는 제출된 전화번호로 결과를 다시 연결합니다. 삭제 이력 row는 성적 테이블에서 상세 열기 대상에서 제외되며, 백엔드 전화번호 수정 endpoint도 삭제 이력 row를 거부합니다.

검증

cd lumie-frontend
rg -n "API_URL: '/api'|app/api/\\[\\.\\.\\.path\\]|QueryProvider|@/shared" \
app src tsconfig.json
rg -n "dashboard/assignments|useStudentAssignments|useSubmitStudentAssignment" \
app/dashboard src/entities/assignment src/features/assignment-management src/widgets/student-sidebar
rg -n "ExamResultPhoneEditDialog|useUpdateExamResultPhone|RegisterStudentModal" \
src/entities/exam src/entities/student src/features/grade-omr src/features/grade-management
npm run lint

성공 기준은 grep이 프록시, 루트 제공자, FSD alias 경계, 학생 과제 라우트, 쿼리 hook, 사이드바 진입점, OMR 결과 수정 진입점을 찾아내고, npm run lint가 오류 없이 완료되는 것입니다.

관련 페이지