diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..7ef2e1a
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,201 @@
+# AGENTS.md
+
+This file provides guidance to Codex (Codex.ai/code) when working with code in this repository.
+
+---
+
+## 프로젝트 개요
+
+**라온누리 (Raonnuri)** - 초등학생 대상 창작 글쓰기 교육 플랫폼
+
+**Tech Stack**: Next.js 16, React 19, Chakra UI v3, Firebase Auth, TypeScript
+
+---
+
+## 개발 명령어
+
+```bash
+npm run dev # 개발 서버 (포트 3001, webpack 사용)
+npm run build # 프로덕션 빌드
+npm run lint # ESLint 실행
+npx tsc --noEmit # 타입 체크 (빌드 전 필수)
+```
+
+**주의**:
+- Dev server는 포트 3001 사용
+- React Compiler 활성화
+- 커밋 전 타입 체크 필수 (`npx tsc --noEmit`)
+
+---
+
+## 핵심 아키텍처
+
+### Manager Pattern (필수)
+
+**모든 데이터 작업은 Manager 사용 (서비스 직접 호출 금지)**
+
+```typescript
+import { teamManager, userManager } from "@/managers";
+
+// ✅ Good
+const teams = await teamManager.getMyTeams();
+const users = await userManager.getUsersByTeam(teamId);
+
+// ❌ Bad - 서비스 직접 호출 금지
+```
+
+**Available Managers**:
+- `teamManager` - Team CRUD, member management, security level
+- `userManager` - User CRUD
+- `draftManager` - localStorage + Realtime DB 하이브리드
+- `writingSessionManager` - Real-time monitoring
+- `writingManager`, `topicManager`, `feedManager`
+
+**상세**: `API_SPEC.md` 참조
+
+---
+
+### Data Model 핵심 원칙
+
+**Firebase Auth = Single Source of Truth** (이름, 이메일, 사진)
+
+- Firestore Users 컬렉션: `uid`, `createdAt`, `lastLoginAt`, `settings`만 저장
+- UI User 객체: Firebase Auth + Firestore 자동 결합
+- 팀별 닉네임: `team.members[uid].nickname` (User 아님)
+- 멤버 확인: `uid in team.members`
+
+**상세**: `DATA_MODELS.md` 참조
+
+---
+
+## 필수 개발 규칙
+
+### 다국어 지원 (i18n)
+
+**모든 새로운 UI 및 페이지는 다국어 지원이 필수입니다.**
+
+```typescript
+// ✅ Good
+import {useTranslations} from "next-intl";
+import {useRouter} from "@/i18n/routing";
+
+const t = useTranslations('newPage');
+return
{t('title')} ;
+
+// ❌ Bad
+return 새 페이지 ; // 하드코딩 금지!
+```
+
+**상세**: `I18N_GUIDE.md` 참조
+
+---
+
+### 스타일 가이드
+
+**버튼에는 항상 `colorPalette="brand"` 사용**:
+
+```tsx
+// ✅ Good
+클릭
+
+// ❌ Bad
+클릭 // 기본 gray 사용 금지
+```
+
+**Semantic 토큰 우선 사용** (숫자/하드코딩 금지):
+- `color="fg"` / `color="fg.muted"`
+- `bg="bg"` / `bg="brand.subtle"`
+- `borderColor="border.muted"`
+
+**Icon 규칙**: react-icons 필수 (이모티콘 금지)
+- ✅ `react-icons/lu` (Lucide) - 메인 아이콘 세트
+- ❌ 이모티콘 (🌍📝) - 사용 금지
+
+**상세**: `STYLE_GUIDE.md` 참조
+
+---
+
+### API 개발 규칙
+
+**RESTful 원칙**: HTTP Method로 동작 구분
+
+```
+POST /api/resource → 생성/추가
+DELETE /api/resource → 삭제/제거
+PUT /api/resource → 전체 수정
+GET /api/resource → 조회
+```
+
+**Firebase Admin SDK**: `adminFbClient` 싱글톤 사용
+
+```typescript
+// ✅ Good
+import {adminFbClient} from "@/lib/firebase-admin";
+const doc = await adminFbClient.collection('users').doc(uid).get();
+
+// ❌ Bad
+import {getFirestore} from "firebase-admin/firestore";
+const db = getFirestore(); // 초기화 문제 발생 가능
+```
+
+**API 응답**: 헬퍼 함수 필수
+
+```typescript
+import {successResponse, validationErrorResponse} from "@/lib/api-response";
+
+// ✅ Good
+return successResponse({ data });
+return validationErrorResponse("에러 메시지");
+
+// ❌ Bad
+return NextResponse.json({success: false, ...});
+```
+
+**상세**: `API_SPEC.md` 참조
+
+---
+
+### 보안
+
+**초대 링크 기반 팀 참여**: 디스코드 스타일 초대 시스템 사용
+- 모든 유저는 로그인 필수 (익명 인증 삭제됨)
+- 팀 참여는 초대 링크를 통해서만 가능
+- 닫힌 팀 → 초대 안 만들면 됨
+
+**XSS 방지**: 백엔드 자동 sanitize
+- `src/lib/server/writing.ts`에서 모든 HTML 자동 세탁
+- 프론트엔드 별도 처리 불필요
+
+**상세**: `SECURITY.md` 참조
+
+---
+
+## Documentation Requirements
+
+**모든 새 기능/페이지는 다음 3개 파일 업데이트 필수**:
+
+1. `PROJECT_STRUCTURE.md` - 페이지 구조, 컴포넌트 목록
+2. `ROADMAP.md` - 완료 작업, 예정 작업
+3. `TECH_STACK.md` - 아키텍처 패턴, 플로우 다이어그램
+
+---
+
+## 참조 문서
+
+### 개발 가이드
+- **`API_SPEC.md`** - API 명세서, RESTful 원칙, Firebase Admin SDK
+- **`STYLE_GUIDE.md`** - Color 사용법, Icon 규칙, Chakra UI 테마
+- **`FRONTEND_DESIGN_PATTERNS.md`** - 컴포넌트 디자인 철학, 인터랙션/시각/애니메이션 패턴
+- **`I18N_GUIDE.md`** - 다국어 지원 가이드 (필수)
+- **`DEVELOPMENT_GUIDE.md`** - AI Delta 전송, Draft 저장, Firebase Functions
+
+### 프로젝트 문서
+- **`PROJECT_STRUCTURE.md`** - 프로젝트 구조
+- **`TECH_STACK.md`** - 기술 스택, 아키텍처
+- **`DATA_MODELS.md`** - 데이터베이스 스키마
+- **`SECURITY.md`** - 보안 정책, 3단계 보안 레벨
+- **`ROADMAP.md`** - 개발 로드맵
+
+---
+
+© 2024 BlueNovaLab. All rights reserved.
\ No newline at end of file
diff --git a/PROJECT_STRUCTURE.md b/PROJECT_STRUCTURE.md
index 9da81f3..28c644e 100644
--- a/PROJECT_STRUCTURE.md
+++ b/PROJECT_STRUCTURE.md
@@ -1,10 +1,25 @@
# 라온누리 - 프로젝트 구조
-> 최종 업데이트: 2026-03-27 (학생/교사 로그인 분리)
+> 최종 업데이트: 2026-06-04 (스튜디오 플로우 UI 통합 리디자인)
초등학생을 위한 창작 글쓰기 교육 플랫폼
-**최신 업데이트** (2026-03-27):
+**최신 업데이트** (2026-06-02):
+- **스튜디오 6단계 선형 글쓰기 플로우** (`/write/studio`) - "그림으로 시작 → 글 완성"을 한 페이지에서 진행하는 신규 라우트
+ - **단일 페이지 상태머신**: `page.tsx` 오케스트레이터(useReducer)가 단일 진실 공급원(StudioFlowState)을 보유, 7개 스테이지 컴포넌트를 순차 렌더
+ - **6단계 흐름**: S0 안내(intro) → S1 업로드(upload) → S2 1차 작문(firstWriting) → S3 보상① 인터랙션(rewardInteraction) → S4 2차 작문(secondWriting) → S5 보상② 이펙트(rewardEffect) → S6 완료(complete)
+ - **S1 키워드 추출**: 종이 그림 촬영/업로드 → AI가 그림에서 키워드 5개 추출 (`POST /api/studio/analyze`)
+ - **S2 1차 작문**: 그림 + 키워드 5개 + 역할별 자유 3문장(상황/감정/이유, 한 문장씩 자유 작성) (학생 단독, AI 없음), 문장 구조는 플랫폼 비고정 — 선생님 직접 교육 + 역할별 예문·전구 안내로 지도(주제 연동 시 주제 데이터로 대체 예정), S2→S3 전환 시 draft Writing 생성(createWriting) + 이미지 업로드(uploadUserImage)
+ - **S3/S5 보상**: 공용 `RewardCanvasEditor`로 인터랙션(움직임) 1개 / 스프라이트 이펙트 1개 부여 (영역 1개 제한, `useDistortionEditor` 기반)
+ - **S4 글 다듬기**: AI 띄어쓰기 교정 + 의미 단위 낱말 분해 (`POST /api/studio/segment`) → 낱말 교체·자리 삽입 추천 (`POST /api/studio/suggest`), 낱말 칩 탭/+자리로 편집 (SentenceTokenEditor)
+ - **S6 완료**: 1회차 수업 종료 → draft를 발행(published)으로 마감 (`POST /api/studio/complete`)
+ - **공용 컴포넌트**: `StageStepper`(6단계 가로 진행 표시기, 점수/숫자 미표시), `RewardCanvasEditor`(인터랙션/이펙트 공용)
+ - **데이터**: writings 컬렉션에 `keywords`, `studioResult`(sentencesV1/V2, blanks, grantedInteraction/Effect, completedAt) 저장, 보상은 distortionAreas/spriteEffectAreas, status draft→published, rewardType `participation`
+ - **진입점**: `/write` 모드 선택 화면에 스튜디오 진입 카드 추가
+ - **다국어 지원**: `studio` 네임스페이스, `pageTitles.writeStudio` (ko/en/ja)
+ - **레거시 공존**: 기존 글쓰기 라우트(`/write/fill-in-blank`, `/write/image`, `/write/easy`)와 병행 운영, 추후 제거 예정
+
+**이전 업데이트** (2026-03-27):
- **학생/교사 역할 분리** - 로그인/가입 시 학생/교사 탭 선택, 역할별 홈 페이지 분리
- **역할 시스템**: `UserRole` (student/teacher), Firebase Auth Custom Claims, Firestore `role` 필드
- **교사 승인 워크플로우**: 가입 → 승인 대기 → 관리자 승인/거절 → 로그인 가능
@@ -546,7 +561,8 @@
| **교사 승인 대기** | `/[locale]/teacher/pending-approval` | 교사 승인 대기 화면 | 승인 대기/거절 상태, 상태 확인, 로그아웃 | ✅ 완료 |
| **내 글 모음** | `/[locale]/writings` | 🆕 **전체 글 목록 페이지** | 🆕 **사용자의 모든 글 표시 (Grid)** 🆕 **정렬 Select (최신순/오래된순)** 🆕 **WritingCard 컴포넌트 사용** 🆕 **Empty state 처리** 🆕 **전체 번역 완료** (ko/en/ja) | ✅ 완료 |
| **글 상세보기** | `/[locale]/writing/[writingId]` | 🆕 **Server Component 기반 상세 페이지** | 🆕 **SEO 최적화** (서버에서 HTML 생성) 🆕 **SNS 공유 미리보기** (카카오톡/페이스북) 🆕 **서버 데이터 로딩** (Firebase Admin SDK) 제목, 내용, 생성된 이미지 표시 주제 및 팀 정보 Badge 프롬프트 Collapsible 🆕 **CommentList** (Client Component) 🆕 **BackButton** 공통 컴포넌트 사용 | ✅ 완료 |
-| **글쓰기** | `/[locale]/write` | Tiptap 기반 순수 텍스트 에디터 + 주제 선택 | 주제 선택 (자유 주제/개인 주제/팀 주제) 🆕 **글 수정 기능 (URL params ?id=xxx)** 🆕 **수정 모드 배지 표시** 🆕 **주제 변경 경고** (작성 중 내용 초기화 알림, 임시 저장 안내) 제목 입력 (Editable), 순수 텍스트 에디터 (포맷팅 없음) 🆕 **다중 글조각 관리** (최대 10개), "저장된 글조각" 버튼 🆕 **강화된 자동 저장** (2초 debounce, 저장 상태 표시: 저장 중/저장됨) 🆕 **저장 플로우 개편** (저장 → 백그라운드 분석 → `/imageUpload` 리다이렉트) 🆕 **GenerateImageDialog 제거** (새 플로우로 대체) 템플릿 미리채우기 (제목/내용), Firestore 저장 비로그인도 접근 가능 (저장 시 로그인 유도) | ✅ 완료 |
+| **글쓰기** | `/[locale]/write` | Tiptap 기반 순수 텍스트 에디터 + 주제 선택 | 주제 선택 (자유 주제/개인 주제/팀 주제) 🆕 **글 수정 기능 (URL params ?id=xxx)** 🆕 **수정 모드 배지 표시** 🆕 **주제 변경 경고** (작성 중 내용 초기화 알림, 임시 저장 안내) 제목 입력 (Editable), 순수 텍스트 에디터 (포맷팅 없음) 🆕 **다중 글조각 관리** (최대 10개), "저장된 글조각" 버튼 🆕 **강화된 자동 저장** (2초 debounce, 저장 상태 표시: 저장 중/저장됨) 🆕 **저장 플로우 개편** (저장 → 백그라운드 분석 → `/imageUpload` 리다이렉트) 🆕 **GenerateImageDialog 제거** (새 플로우로 대체) 🆕 **스튜디오 진입 카드** (`/write/studio` 신규 플로우 진입) 템플릿 미리채우기 (제목/내용), Firestore 저장 비로그인도 접근 가능 (저장 시 로그인 유도) | ✅ 완료 |
+| **스튜디오 글쓰기** | `/[locale]/write/studio` | 🆕 **그림으로 시작하는 6단계 선형 글쓰기 플로우 (신규)** | 🆕 **단일 페이지 상태머신** (useReducer 오케스트레이터, StudioFlowState 단일 진실 공급원) 🆕 **6단계**: S0 안내 → S1 업로드(키워드 5개 추출) → S2 1차 작문(역할별 자유 3문장 + 예문·전구 안내, 학생 단독) → S3 보상① 인터랙션 → S4 글 다듬기(낱말 분해 + 교체·삽입 추천) → S5 보상② 이펙트 → S6 완료(발행) 🆕 **StageStepper** 진행 표시기 (점수/숫자 미표시) 🆕 **RewardCanvasEditor** 공용 (인터랙션/이펙트, 영역 1개 제한) 🆕 **AI 엔드포인트 4개**: analyze / segment / suggest / complete 🆕 **다국어 지원** (studio namespace, ko/en/ja) 레거시 라우트와 병행 운영 (추후 제거 예정) | ✅ 완료 |
| **이미지 업로드/선택** | `/[locale]/imageUpload` | 🆕 **이미지 소스 선택 페이지 (글 저장 후 자동 이동)** | 🆕 **2가지 선택지**: AI 생성 (장면 추출 + 선택 + 생성) / 직접 업로드 🆕 **드래그앤드롭 파일 업로드** (미리보기, 5MB 제한, JPEG/PNG/WebP) 🆕 **Canvas API 클라이언트 사이드 리사이즈** (1920x1080 최대, 85% 품질) 🆕 **Firebase Storage 업로드** (WritingManager.uploadUserImage) 🆕 **이미 이미지 있으면 자동으로 `/interaction` 리다이렉트** 🆕 **다국어 지원** (imageUpload namespace, ko/en/ja) | ✅ 완료 |
| **인터랙션 편집** | `/[locale]/interaction` | 🆕 **이미지 왜곡 편집 페이지 (이미지 생성/업로드 후 이동)** | 🆕 **7:3 그리드 레이아웃** (이미지 70%, 컨트롤러 30%) 🆕 **Sticky Header** (InteractionHeader, 스크롤 시 상단 고정) 🆕 **framer-motion 애니메이션** (모드 전환, 영역 선택 부드러운 전환) 🆕 **영역 목록 일반 모드 표시** (CustomAreaList, 모든 모드에서 접근 가능) 🆕 **에디터 버튼 우측 배치** (추가/삭제/숨기기, 가로 3개) 🆕 **컨트롤러 내부 스크롤** (커스텀 스크롤바, 높이 80dvh) 🆕 **반응형 이미지** (aspectRatio 유지, 찌그러짐 해결) 왜곡 영역 편집 (EditorCanvas, DistortionArea) 모션 프리셋 선택 (horizontal, vertical, rotate, pulse 등) 물리 설정 (stiffness, damping, mass) 에디터/인터랙션 모드 전환 (Switch) 저장 시 Writing.distortionAreas 업데이트 | ✅ 완료 |
| **공개 팀 목록** | `/[locale]/team/all` | 🆕 **공개 팀 둘러보기** | 🆕 **공개된 팀 목록 표시** (isPublic=true) 🆕 **TeamCard 그리드** (글래스모피즘) 🆕 **페이지네이션** (커서 기반) 🆕 **Navbar "공개 팀" 메뉴** | ✅ 완료 |
@@ -700,6 +716,7 @@
| **ColorMode** | `color-mode.tsx` | 다크모드 토글 | ✅ 완료 |
| **Toaster** | `toaster.tsx` | 토스트 알림 | ✅ 완료 |
| **Tooltip** | `tooltip.tsx` | 툴팁 | ✅ 완료 |
+| **StageStepper** | `StageStepper.tsx` | 🆕 **스튜디오 6단계 가로 진행 표시기** (현재/완료 단계 brand 강조, 점수·숫자 미표시, 모바일은 점만 표시) | ✅ 완료 |
---
@@ -729,6 +746,15 @@
| **VisibilitySelector** | `VisibilitySelector.tsx` | 🆕 **공개 범위 선택** (PUBLIC/TEAM/PRIVATE, RadioCard 기반) | ✅ 완료 |
| **VisibilityBadge** | `VisibilityBadge.tsx` | 🆕 **공개 범위 배지** (아이콘 + 라벨, 색상별 구분) | ✅ 완료 |
| **InteractiveImageViewer** | `InteractiveImageViewer.tsx` | 🆕 **인터랙티브 이미지 뷰어** (왜곡 효과, 애니메이션, 오디오 반응) | ✅ 완료 |
+| **RewardCanvasEditor** | `studio/RewardCanvasEditor.tsx` | 🆕 **스튜디오 보상 편집기** (인터랙션 S3 / 이펙트 S5 공용, `useDistortionEditor` 기반, 영역 1개 제한, onApplied 콜백) | ✅ 완료 |
+| **StudioCard** | `studio/StudioCard.tsx` | 🆕 **스튜디오 공용 콘텐츠 카드** (tone default/muted/brand, cascade index, 단계 전반 통일 카드) | ✅ 완료 |
+| **StudioStageHeader** | `studio/StudioStageHeader.tsx` | 🆕 **스튜디오 단계 헤더** (원형 아이콘 + 제목 + 부제, 전 단계 공용) | ✅ 완료 |
+| **RolePill** | `studio/RolePill.tsx` | 🆕 **역할 식별 Pill** (상황/마음/까닭 아이콘+라벨, S2·S4 공용, `studioRoleMeta.ts` 메타 기반) | ✅ 완료 |
+| **StudioImageCard** | `studio/StudioImageCard.tsx` | 🆕 **고정 비율 이미지 카드** (선택적 children, 예: 키워드 칩) | ✅ 완료 |
+| **RewardBanner** | `studio/RewardBanner.tsx` | 🆕 **보상 축하 배너** (S3/S5 보상 단계 공용) | ✅ 완료 |
+| **SentenceTokenEditor** | `studio/SentenceTokenEditor.tsx` | 🆕 **S4 낱말 칩 편집기** (낱말 탭→교체 Popover, +자리→삽입 Popover, 갱신 낱말 그라디언트, `sentenceTokens.ts` 조립/폴백 유틸) | ✅ 완료 |
+| **studioMotion** | `studio/studioMotion.ts` | 🆕 **스튜디오 공용 애니메이션** (studioFadeIn/Pop/Breathe/EmptyBreathe @keyframes + STUDIO_REDUCED_MOTION prefers-reduced-motion 게이트) | ✅ 완료 |
+| **studioRoleMeta** | `studio/studioRoleMeta.ts` | 🆕 **역할 메타 정의** (상황/마음/까닭 아이콘·라벨, RolePill 공용) | ✅ 완료 |
| **ImageDropzone** | `ImageDropzone.tsx` | 🆕 **범용 이미지 드롭존** (드래그앤드롭 업로드, 미리보기, 4:3 크롭 통합, 호버 오버레이, 삭제 버튼, AspectRatio 지원, 커스텀 라벨 — 글쓰기/팀 커버 이미지 공용) | ✅ 완료 |
| **ImageCropper** | `ImageCropper.tsx` | 🆕 **이미지 크롭 모달** (react-cropper 기반, 4:3 고정 비율, 회전/확대/축소, 최소 400x300) | ✅ 완료 |
| **CameraCaptureDialog** | `CameraCaptureDialog.tsx` | 🆕 **카메라 촬영 다이얼로그** (GlassDialog 기반, getUserMedia 카메라 스트림, 4:3 프레임 가이드 오버레이, 전/후면 카메라 전환, 촬영 후 ImageCropper 연동, 권한/미지원 에러 처리, 다국어 지원) | ✅ 완료 |
@@ -847,6 +873,31 @@
---
+### 📁 `src/app/[locale]/write/studio/` - 🆕 스튜디오 6단계 플로우
+
+| 파일 | 경로 | 설명 | 상태 |
+|------|------|------|------|
+| **StudioPage** | `page.tsx` | 🆕 **오케스트레이터** (useReducer 상태머신, StudioFlowState 단일 진실 공급원, goNext 부수효과 처리, AI 호출, draft 생성/발행) | ✅ 완료 |
+| **Flow 계약** | `_flow/types.ts` | 🆕 **StudioFlowState / StudioStageProps** (오케스트레이터↔스테이지 prop 시그니처), `deriveBlankValues` | ✅ 완료 |
+| **IntroStage** | `_stages/IntroStage.tsx` | 🆕 **S0 안내** (오프라인에서 종이에 그림 그리기 안내) | ✅ 완료 |
+| **UploadStage** | `_stages/UploadStage.tsx` | 🆕 **S1 업로드** (그림 촬영/업로드 → AI 키워드 5개 추출) | ✅ 완료 |
+| **FirstWritingStage** | `_stages/FirstWritingStage.tsx` | 🆕 **S2 1차 작문** (그림 + 키워드 5개 + 역할별 자유 3문장 + 전구 안내 + 예문, 학생 단독·AI 없음) | ✅ 완료 |
+| **RewardInteractionStage** | `_stages/RewardInteractionStage.tsx` | 🆕 **S3 보상①** (인터랙션/움직임 1개 부여, RewardCanvasEditor) | ✅ 완료 |
+| **SecondWritingStage** | `_stages/SecondWritingStage.tsx` | 🆕 **S4 글 다듬기** (낱말 분해 + 교체·삽입 추천, SentenceTokenEditor) | ✅ 완료 |
+| **RewardEffectStage** | `_stages/RewardEffectStage.tsx` | 🆕 **S5 보상②** (스프라이트 이펙트 1개 부여, RewardCanvasEditor) | ✅ 완료 |
+| **CompletionStage** | `_stages/CompletionStage.tsx` | 🆕 **S6 완료** (1회차 수업 종료, complete API 호출 → 발행) | ✅ 완료 |
+
+**주요 기능**:
+- ✅ **단일 페이지 선형 상태머신** (useReducer, 단계 전환 부수효과는 오케스트레이터 goNext에서 처리)
+- ✅ **역할별 자유 3문장**: 상황/감정/이유를 한 문장씩 자유 작성 (고정 빈칸 템플릿 제거, 선생님 직접 교육 + 예문·전구 안내로 지도)
+- ✅ **S2→S3 전환**: 모든 입력 채움 검증 → draft Writing 생성(createWriting) + 이미지 업로드(uploadUserImage), 1차 문장을 2차 작문 초기값으로 시드
+- ✅ **S3/S5 보상**: 공용 RewardCanvasEditor (영역 1개 제한), 적용 시 distortionAreas/spriteEffectAreas 저장 후 자동 전진
+- ✅ **AI 엔드포인트 4개**: `/api/studio/analyze`(키워드), `/api/studio/segment`(S4 분해), `/api/studio/suggest`(S4 교체·삽입 추천), `/api/studio/complete`(발행)
+- ✅ **데이터 저장**: writings.keywords + writings.studioResult (sentencesV1/V2, blanks, grantedInteraction/Effect, completedAt), status draft→published, rewardType `participation`
+- ✅ **다국어 지원** (studio namespace, pageTitles.writeStudio, ko/en/ja)
+
+---
+
### 📁 `src/extensions/` - Tiptap Extensions
| Extension | 파일명 | 설명 | 상태 |
@@ -1065,6 +1116,7 @@ firebase functions:log --only cleanupExpiredReservations
| **Pattern Analysis** | `patternAnalysisService.ts` | 🆕 **글 작성 패턴 분석 서비스** (10개 글 종합 분석, AI 평가) | ✅ 완료 |
| **Spelling Check** | `spellingService.ts` | **맞춤법 검사 서비스** (Gemini 기반, 초등학생 눈높이) | ✅ 완료 |
| **Writing Assistance** | `writingAssistanceService.ts` | 🆕 **AI 글쓰기 도우미 서비스** (4단계 힌트 생성, 주제 맥락 활용, 서버 캐싱) | ✅ 완료 |
+| **Studio Service** | `studioService.ts` | 🆕 **스튜디오 플로우 AI 서비스** (extractStudioKeywords: 그림→키워드 5개, segmentSentences: 띄어쓰기 교정+낱말 분해, suggestReplacements: 교체·삽입 추천, _ai 사용량 메타 전달) | ✅ 완료 |
| **Region Health** | `regionHealthManager.ts` | **Region 과부하 상태 추적** (자동 복구, 1분 TTL) | ✅ 완료 |
| ~~**Team Service**~~ | ~~`teamService.ts`~~ | ~~팀 CRUD~~ | ⚠️ Deprecated (TeamManager로 이동) |
| ~~**Student Service**~~ | ~~`studentService.ts`~~ | ~~학생 CRUD, PIN 해시/검증~~ | ⚠️ Deprecated (UserManager로 대체) |
@@ -1085,7 +1137,8 @@ firebase functions:log --only cleanupExpiredReservations
| **Plan 타입** | `plan.ts` | 🆕 **플랜 시스템 타입** (PlanType/BillingCycle/PlanSource/AIFeatureType Enum, UserPlan, Organization, AIUsage, PlanLimits, EffectivePlan, AIFeatureCheckResult) | ✅ 완료 |
| **Team 타입** | `team.ts` | 팀 데이터 모델 (members Map), 🆕 **AIAssistanceConfig** (AI 도우미 설정) | ✅ 완료 |
| **FirestoreUser 타입** | `firestoreUser.ts` | **FirestoreUser** (DB 저장용, 🆕 **plan/organizationId 필드 추가**, 🆕 **loginId/isSystemAccount/createdByTeacher 필드**), **User** (UI용) 분리 | ✅ 완료 |
-| **Writing 타입** | `writing.ts` | 글 데이터 모델, 🆕 **WritingAnalysis** (AI 분석 결과, contentHash 기반 재사용), **SpellingError** (맞춤법 오류), 🆕 **AIAssistanceRecord** (AI 도움 이력), 🆕 **GeneratedImage** (AI 생성 이미지) | ✅ 완료 |
+| **Writing 타입** | `writing.ts` | 글 데이터 모델, 🆕 **WritingAnalysis** (AI 분석 결과, contentHash 기반 재사용), **SpellingError** (맞춤법 오류), 🆕 **AIAssistanceRecord** (AI 도움 이력), 🆕 **GeneratedImage** (AI 생성 이미지), 🆕 **keywords?·studioResult?** (스튜디오 플로우 필드) | ✅ 완료 |
+| **Studio 타입** | `studio.ts` | 🆕 **스튜디오 6단계 플로우 타입** (StudioStage, StudioSentenceKey, StudioBlank, StudioScaffold, StudioToken, StudioResult, Analyze/Segment/Suggest/Complete Request·Response, STUDIO_STAGE_ORDER/SENTENCE_ORDER) | ✅ 완료 |
| **Scene 타입** | `scene.ts` | 🆕 **장면 데이터 모델** (Scene, SceneExtractionResponse) | ✅ 완료 |
| **Draft 타입** | `draft.ts` | 글조각 데이터 모델 (Draft, DraftListItem, **AnalysisHistoryItem**, **syncStatus**: 'local'\|'synced'\|'syncing') | ✅ 완료 |
| **WritingPattern 타입** | `writingPattern.ts` | **글 작성 패턴 분석** 데이터 모델 (WritingPatternAnalysis) | ✅ 완료 |
@@ -1146,6 +1199,9 @@ firebase functions:log --only cleanupExpiredReservations
| **Writing Assistance** | `writingAssistance.ts` | 🆕 **AI 글쓰기 도우미 프롬프트** (4단계 × 3개 언어, 주제 맥락 활용) | ✅ 완료 |
| **Scene Extraction** | `sceneExtraction.ts` | 🆕 **AI 장면 추출 프롬프트** (3~5개 장면 분리, Response Schema, ko/en/ja) | ✅ 완료 |
| **Prompt Optimization** | `promptOptimization.ts` | 🆕 **프롬프트 최적화 프롬프트** (원문 → 핵심 키워드 배열 추출, Imagen 최적화) | ✅ 완료 |
+| **Studio Templates** | `studio/templates.ts` | 🆕 **스튜디오 역할별 자유 슬롯** (상황/감정/이유 1슬롯씩, STUDIO_BLANK_IDS, getStudioBlanks, composeStudioSentences, studioBlankId) | ✅ 완료 |
+| **Studio Segmentation** | `studio/segmentation.ts` | 🆕 **S4 분해 프롬프트** (의미 단위 낱말 덩어리 + 띄어쓰기 교정, ko/en/ja) | ✅ 완료 |
+| **Studio Suggestion** | `studio/suggestion.ts` | 🆕 **S4 추천 프롬프트** (낱말 교체 + 자리 삽입 추천, ko/en/ja) | ✅ 완료 |
---
@@ -1157,6 +1213,10 @@ firebase functions:log --only cleanupExpiredReservations
| **패턴 분석** | `/api/analyze-pattern` | POST | **글 작성 패턴 분석** (3가지 타입, contentHash 기반 3단계 캐싱, 변경 감지) | ✅ 완료 |
| **맞춤법 검사** | `/api/spelling/check` | POST | **Gemini 기반 맞춤법 검사** (초등학생 눈높이) | ✅ 완료 |
| **AI 글쓰기 도우미** | `/api/writing-assistance` | POST | 🆕 **AI 힌트 생성** (4단계, 주제 맥락, 팀 설정 검증) | ✅ 완료 |
+| **스튜디오 그림 분석** | `/api/studio/analyze` | POST | 🆕 **S1 그림 키워드 추출** (analyzeImage 재사용, 키워드 5개 + 분석 결과, 플랜 검증) | ✅ 완료 |
+| **스튜디오 분해** | `/api/studio/segment` | POST | 🆕 **S4 띄어쓰기 교정 + 낱말 분해** (의미 단위 낱말 덩어리, 무결성 가드) | ✅ 완료 |
+| **스튜디오 추천** | `/api/studio/suggest` | POST | 🆕 **S4 교체·삽입 추천** (낱말 교체 + 자리 삽입, Response Schema) | ✅ 완료 |
+| **스튜디오 완료** | `/api/studio/complete` | POST | 🆕 **S6 발행** (draft→published, studioResult 저장, HTML sanitize, AI 호출 없음, 주제 사용량 증가) | ✅ 완료 |
| **글 생성** | `/api/writing` | POST | 🆕 **글 생성** (wordCount/charCount 자동 계산, 🆕 **analysis 저장**) | ✅ 완료 |
| **글 조회** | `/api/writing/[id]` | GET | 🆕 **글 조회** (작성자만 접근) | ✅ 완료 |
| **글 분석** | `/api/writing/[id]/analyze` | POST | 🆕 **글 분석 실행** (서버 데이터 기반, 결과 저장) | ✅ 완료 |
diff --git a/ROADMAP.md b/ROADMAP.md
index ded7d4e..6281171 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -1,6 +1,6 @@
# 라온누리 - 개발 로드맵
-> 최종 업데이트: 2026-03-27 (학생/교사 로그인 분리)
+> 최종 업데이트: 2026-06-04 (S2 첫 글쓰기 자유 작성 전환)
초등학생을 위한 창작 글쓰기 교육 플랫폼 개발 계획
@@ -167,6 +167,9 @@
| **학생 일괄 생성 (Bulk Student Creation)** | **CSV 기반 학생 계정 일괄 생성, 템플릿 ID/PW 시스템 ({teamCode}{number} 등), loginId 간편 로그인 (@ 없는 ID → 시스템 이메일 변환), BulkMemberCreator 4단계 UI (입력→미리보기→생성중→결과), 로그인 카드 인쇄 기능, POST /api/team/[teamId]/bulk-create-members (소유자 전용), POST /api/auth/resolve-login-id, 서버 레이어 bulk-member.ts, FirestoreUser loginId/isSystemAccount/createdByTeacher 필드 추가, authStore loginId 로그인 지원, LoginForm 이메일/loginId 겸용, 다국어 지원 (ko/en/ja)** | **2026-03-19** |
| **학생/교사 로그인 분리** | **UserRole (student/teacher) 타입, Custom Claims 기반 역할 관리, LoginDialog 학생/교사 탭 UI, 학생/교사 별도 SignupForm, 교사 승인 워크플로우 (가입→대기→관리자 승인/거절), withTeacherAuth/withAdminAuth 서버 래퍼, 역할별 홈 페이지 분리 (/student/home, /teacher/home), useRequireAuth requiredRole 옵션, 관리자 교사 승인 UI (/admin/teacher-approvals), TeacherApprovalManager 싱글톤, 마이그레이션 스크립트 (기존 유저 → student)** | **2026-03-27** |
+| **스튜디오 6단계 선형 글쓰기 플로우** | **"그림으로 시작 → 글 완성" 신규 라우트 /write/studio (기존 fill-in-blank/image/easy 라우트와 병행 운영, 추후 제거 예정), 단일 페이지 상태머신 (page.tsx 오케스트레이터 useReducer, StudioFlowState 단일 진실 공급원, _flow/types.ts에 StudioStageProps 계약 정의), 7개 스테이지 컴포넌트 (_stages/Intro·Upload·FirstWriting·RewardInteraction·SecondWriting·RewardEffect·CompletionStage), StageStepper 진행 표시기 (점수·숫자 미표시, 참여 기반), 6단계: S0 안내(종이 그림)→S1 업로드(AI 키워드 5개 추출)→S2 1차 작문(3문장 빈칸: 상황 2칸/감정/이유, 학생 단독 AI 없음)→S3 보상① 인터랙션→S4 2차 작문(AI 추천 표현 종류별)→S5 보상② 이펙트→S6 완료(발행), S2→S3 전환 시 draft Writing 생성(createWriting)+이미지 업로드(uploadUserImage), 공용 RewardCanvasEditor (인터랙션/이펙트 공용, 영역 1개 제한, useDistortionEditor 기반), AI 엔드포인트 3개 (POST /api/studio/analyze·recommend-expressions·complete), studioService.ts (extractStudioKeywords·recommendExpressions), 프롬프트 studio/templates.ts·expressionRecommendation.ts, 타입 studio.ts (StudioStage/SentenceKey/Blank/Result 등), writing.ts에 keywords?·studioResult? 추가, writings 컬렉션에 keywords·studioResult(sentencesV1/V2·blanks·grantedInteraction/Effect·completedAt) 저장, 보상은 distortionAreas/spriteEffectAreas, status draft→published, rewardType participation, /write 진입 카드 추가, 다국어 지원 (studio namespace, pageTitles.writeStudio, ko/en/ja)** | **2026-06-02** |
+| **스튜디오 플로우 UI 통합 리디자인** | **공용 프리미티브 + 단계별 일관 레이아웃, S2 빈칸 입력 버그 수정 (src/components/writing/studio/에 표현 전용 공용 프리미티브 정리: StudioCard·StudioStageHeader·RolePill+studioRoleMeta·FillBlankSentence·StudioImageCard·RewardBanner·ExpressionChip·studioMotion, 전 단계가 하나의 카드/헤더/애니메이션 시스템 공유, FillBlankSentence 고정 폭 빈칸 입력 + 빈칸별 힌트로 입력 늘어남 버그 수정, studio namespace i18n 키 추가 roles.{situation,emotion,reason}·firstWriting.blankStub·rewardInteraction.tip·rewardEffect.tip·reward.{controlsTitle,dragHint,applyButton}·secondWriting.contextTitle, ko/en/ja)** | **2026-06-04** |
+| **S2 첫 글쓰기 자유 작성 전환** | **고정 빈칸 템플릿("나는 ___ 때 ___ 일이 있었습니다" 등) 제거 → 선생님 직접 교육 방식. 역할(상황/감정/이유)별 자유 Textarea 1문장 + 전구 안내(guides) + 예문 2개(examples)를 FirstWritingStage가 직접 렌더, FillBlankSentence 컴포넌트 삭제, templates.ts 토큰 템플릿 제거하고 역할당 1슬롯 모델로 단순화 (STUDIO_BLANK_IDS 3개·getStudioBlanks·composeStudioSentences(values)·studioBlankId), StudioTemplateToken/StudioSentenceTemplate 타입 제거, 다운스트림(sentencesV1/V2·S4 분해) 불변, 예문/안내는 현재 i18n 하드코딩(주제 연동 시 주제 데이터로 변수화 예정), firstWriting i18n 재구성 freePlaceholder·examplesLabel·guides.{situation,emotion,reason}·examples.{role}.{0,1} (ko/en/ja). 부수: TECH_STACK 스튜디오 섹션을 이미 반영된 S4 segment/suggest 파이프라인 기준으로 정정** | **2026-06-04** |
### 🚧 진행 중
diff --git a/TECH_STACK.md b/TECH_STACK.md
index 2d7dc7c..57138ae 100644
--- a/TECH_STACK.md
+++ b/TECH_STACK.md
@@ -1,6 +1,6 @@
# 라온누리 - 기술 스택 및 개발 환경
-> 최종 업데이트: 2025-12-23 (이미지 4:3 비율 표준화)
+> 최종 업데이트: 2026-06-04 (스튜디오 플로우 UI 통합 리디자인)
---
@@ -2638,6 +2638,156 @@ interface BulkCreateResult {
---
+### 27. 스튜디오 6단계 선형 글쓰기 플로우 (Studio Flow)
+
+#### 핵심 개념
+
+**목적**: "그림으로 시작 → 글 완성"을 하나의 페이지에서 진행하는 1회차 수업형 선형 플로우.
+기존 글쓰기 라우트(`/write/fill-in-blank`, `/write/image`, `/write/easy`)와 **병행 운영**하는 신규 라우트(`/write/studio`)이며, 레거시 라우트는 추후 제거 예정이다.
+
+**설계 원칙**:
+- **점수/제한 없음**: 참여 기반 플로우 (StageStepper에 숫자 미표시, `rewardType: 'participation'`)
+- **AI는 아동 행동 이후에만**: S1 키워드 추출은 업로드 후, S4 추천 표현은 학생 1차 작문 후 실행
+- **단일 진실 공급원**: 오케스트레이터가 전역 상태(StudioFlowState)를 소유, 스테이지는 props만 받는다
+
+#### 단일 페이지 상태머신 아키텍처
+
+```
+┌──────────────────────────────────────────────────────────┐
+│ 오케스트레이터 src/app/[locale]/write/studio/page.tsx │
+│ - useReducer(flowReducer, StudioFlowState) ← 단일 진실 │
+│ - goNext(): 현재 단계별 부수효과 실행 후 advance() │
+│ - AI 호출 / draft 생성 / 보상 저장 / 발행 모두 여기서 처리 │
+│ - StageStepper(현재 단계) + AnimatePresence(스테이지 전환) │
+└──────────────────────────────────────────────────────────┘
+ │ Pick 으로 필요한 props만 전달
+ ▼
+┌──────────────────────────────────────────────────────────┐
+│ 스테이지 컴포넌트 src/app/[locale]/write/studio/_stages/ │
+│ IntroStage · UploadStage · FirstWritingStage · │
+│ RewardInteractionStage · SecondWritingStage · │
+│ RewardEffectStage · CompletionStage │
+│ (상태/부수효과 없음 — 입력 수집 + 콜백 호출만) │
+└──────────────────────────────────────────────────────────┘
+ │ 보상 단계(S3/S5)는 공용 편집기 사용
+ ▼
+┌──────────────────────────────────────────────────────────┐
+│ 공용 컴포넌트 │
+│ src/components/ui/StageStepper.tsx (6단계 진행 표시기) │
+│ src/components/writing/studio/RewardCanvasEditor.tsx │
+│ - mode: "interaction" | "effect" 로 S3/S5 공용 │
+│ - useDistortionEditor 기반, 영역 1개 제한 (AREA_CAP=1) │
+└──────────────────────────────────────────────────────────┘
+```
+
+**계약 파일**: `src/app/[locale]/write/studio/_flow/types.ts` — `StudioFlowState`(전역 상태) / `StudioStageProps`(스테이지 prop 시그니처) / `deriveBlankValues()` 헬퍼.
+
+#### S0 → S6 단계 흐름
+
+```
+S0 intro 오프라인에서 종이에 그림 그리기 안내 (앱 외부 활동)
+ ↓ goNext()
+S1 upload 그림 촬영/업로드 → AI 키워드 5개 추출
+ ↓ runAnalyze() → POST /api/studio/analyze
+S2 firstWriting 그림 + 키워드 5개 + 역할별 자유 3문장 (학생 단독, AI 없음)
+ · situation: 상황 — 언제/어디서 무슨 일이 있었는지 (자유 1문장)
+ · emotion: 감정 — 그때 어떤 마음이었는지 (자유 1문장)
+ · reason: 이유 — 왜 그런 마음이 들었는지 (자유 1문장)
+ · 문장 구조를 플랫폼이 고정하지 않음(선생님 직접 교육). 역할별 예문 + 전구 안내로만 지도. 주제 연동 시 예문/안내는 주제 데이터로 대체 예정(현재 i18n 하드코딩)
+ ↓ createDraft(): 입력 검증 → writingManager.createWriting(status:'draft')
+ ↓ + uploadUserImage() + 1차 문장을 2차 작문 초기값으로 시드
+S3 rewardInteraction 인터랙션(움직임) 1개 부여 → 적용 (RewardCanvasEditor, 영역 1개)
+ ↓ onInteractionApplied() → updateDistortionAreas()
+S4 secondWriting 3문장 다듬기 — AI 띄어쓰기 교정 + 낱말 분해 → 낱말 교체·자리 삽입 추천 (낱말 칩 편집)
+ ↓ 진입 시 fetchSegmentation() → POST /api/studio/segment (분해 후) fetchSuggestions() → POST /api/studio/suggest
+S5 rewardEffect 스프라이트 이펙트 1개 부여 → 적용 (RewardCanvasEditor, 영역 1개)
+ ↓ onEffectApplied() → updateDistortionAreas()
+S6 complete 1회차 수업 종료 → onComplete() → POST /api/studio/complete (발행)
+```
+
+#### AI 엔드포인트 4개
+
+| API | 경로 | AI | 역할 |
+|-----|------|----|------|
+| **분석** | `POST /api/studio/analyze` | ✅ | 그림 분석(analyzeImage 재사용) → 키워드 5개 + ImageAnalysisResult |
+| **분해** | `POST /api/studio/segment` | ✅ | S4: 3문장 → 띄어쓰기 교정 + 의미 단위 낱말 분해 (낱말 텍스트 그대로, 글자 변조 금지 가드) |
+| **추천** | `POST /api/studio/suggest` | ✅ | S4: 분해된 낱말 → 낱말 교체 추천 + 자리 삽입 추천 (분해와 분리된 별도 호출) |
+| **완료** | `POST /api/studio/complete` | ❌ | draft→published 발행, studioResult 저장, HTML sanitize |
+
+**서비스 레이어**: `src/services/studioService.ts`
+- `extractStudioKeywords(imageBase64, mimeType, locale)` — imageAnalysisService.analyzeImage 재사용, suggestedKeywords→(부족 시)objects 순으로 정확히 5개 확정 (패딩 없음)
+- `segmentSentences(sentences, locale)` — AI가 의미 단위 낱말 덩어리로 반환 → 결정적 분해/조립, `stripSpaces` 무결성 가드 통과 시 채택, 실패 시 공백 분리 폴백
+- `suggestReplacements(sentences, keywords, locale)` — generateContent + Response Schema, 문장별 `{replacements, insertions}`(교체·삽입) 클램프/정제, 실패 시 빈 추천 폴백
+- 사용량 메타데이터(`_ai`)는 라우트로 그대로 전달 → 라우트가 logAIUsage 기록
+
+**프롬프트**: `src/prompts/studio/templates.ts`(역할별 자유 슬롯 — STUDIO_BLANK_IDS/getStudioBlanks/composeStudioSentences/studioBlankId), `src/prompts/studio/segmentation.ts`·`suggestion.ts`(ko/en/ja)
+
+#### 데이터 / 영속화 모델
+
+draft를 먼저 만들고(S2→S3) 단계별로 갱신한 뒤 S6에서 발행하는 점진적 저장 모델.
+
+```typescript
+// src/types/writing.ts (스튜디오 모드에서만 사용)
+interface Writing {
+ // ...기존 필드
+ keywords?: string[]; // 🆕 그림에서 추출한 키워드 5개
+ studioResult?: StudioResult; // 🆕 스튜디오 플로우 결과
+}
+
+// src/types/studio.ts
+interface StudioResult {
+ keywords: string[];
+ sentencesV1: Record; // 1차 작문 (학생 단독)
+ sentencesV2: Record; // 2차 작문 (AI 도움, 최종 본문)
+ blanks: StudioBlank[];
+ grantedInteraction: boolean; // S3 보상 적용 여부
+ grantedEffect: boolean; // S5 보상 적용 여부
+ completedAt: string; // ISO 8601
+}
+```
+
+**저장 위치별 정리**:
+- **writings 컬렉션**: `keywords`, `studioResult`(sentencesV1/V2·blanks·grantedInteraction/Effect·completedAt)
+- **보상**: 인터랙션/이펙트는 `distortionAreas` / `spriteEffectAreas` (S3/S5에서 클라이언트가 저장, complete API는 건드리지 않음)
+- **상태 전이**: `status` draft → published (최초 발행 시 주제 usageCount 1회 증가)
+- **보상 분류**: `rewardType: 'participation'`
+- **하드닝**: complete API에서 본문 HTML sanitize + studioResult 자유 입력값은 태그 제거 후 평문 저장
+
+#### 진입점 및 i18n
+
+- **진입 카드**: `/write` 모드 선택 화면 상단에 스튜디오 진입 카드 추가 (`router.push("/write/studio")`)
+- **다국어**: `studio` 네임스페이스(stepper/actions/error/단계별 키), `pageTitles.writeStudio` (ko/en/ja)
+- **접근 제어**: `useRequireAiAccess()` + `useAiIpCheck()` (AI 사용 가능 검증)
+
+#### 공용 프리미티브 / 통합 비주얼 언어 (2026-06-04)
+
+전 단계가 **하나의 카드/헤더/애니메이션 시스템**을 공유하도록 `src/components/writing/studio/`에 표현 전용(presentational) 공용 프리미티브를 정리했다. 스테이지는 레이아웃 코드를 직접 들지 않고 이 프리미티브만 조합한다.
+
+- **`StudioCard`** — 단계 공용 콘텐츠 카드 (tone default/muted/brand, cascade index 진입 애니메이션)
+- **`StudioStageHeader`** — 원형 아이콘 + 제목 + 부제 헤더 (전 단계 통일)
+- **`RolePill` + `studioRoleMeta`** — 상황/마음/까닭 역할 식별(아이콘+라벨), S2·S4 공용
+- **`StudioImageCard`** — 고정 비율 이미지 카드 (선택적 children, 예: 키워드 칩)
+- **`RewardBanner`** — S3/S5 보상 축하 배너 공용
+- **`SentenceTokenEditor` + `sentenceTokens`** — S4 낱말 칩 편집기 (낱말 탭→교체 Popover, +자리→삽입 Popover, 갱신 낱말 그라디언트 표시) + 토큰 조립/폴백 유틸
+- **`studioMotion`** — 공용 `@keyframes`(studioFadeIn/Pop/Breathe/EmptyBreathe) + `STUDIO_REDUCED_MOTION`(prefers-reduced-motion 게이트)
+- **S2 자유 작성**: 고정 빈칸 템플릿(FillBlankSentence) 제거 → FirstWritingStage가 역할별 자유 Textarea + 전구 안내 + 예문을 직접 렌더
+- **i18n 추가**: `studio` 네임스페이스에 `roles.{situation,emotion,reason}`, `firstWriting.{freePlaceholder,examplesLabel,guides.*,examples.*}`, `rewardInteraction.tip`, `rewardEffect.tip`, `reward.{controlsTitle,dragHint,applyButton}`, `secondWriting.*`(낱말 편집 키) (ko/en/ja)
+
+#### 참고 파일
+
+- `src/app/[locale]/write/studio/page.tsx` - 오케스트레이터 (useReducer 상태머신)
+- `src/app/[locale]/write/studio/_flow/types.ts` - StudioFlowState / StudioStageProps
+- `src/app/[locale]/write/studio/_stages/*.tsx` - 7개 스테이지 컴포넌트
+- `src/components/ui/StageStepper.tsx` - 6단계 진행 표시기
+- `src/components/writing/studio/RewardCanvasEditor.tsx` - 인터랙션/이펙트 공용 편집기
+- `src/components/writing/studio/{StudioCard,StudioStageHeader,RolePill,StudioImageCard,RewardBanner,SentenceTokenEditor}.tsx` + `{sentenceTokens,studioMotion,studioRoleMeta}.ts` - 공용 프리미티브 (통합 비주얼 언어)
+- `src/services/studioService.ts` - extractStudioKeywords / segmentSentences / suggestReplacements
+- `src/app/api/studio/{analyze,segment,suggest,complete}/route.ts` - AI 엔드포인트 4개
+- `src/prompts/studio/{templates.ts,segmentation.ts,suggestion.ts}` - 프롬프트
+- `src/types/studio.ts` - 플로우 타입, `src/types/writing.ts` - keywords?/studioResult?
+
+---
+
## 참고 문서
- [PROJECT_STRUCTURE.md](./PROJECT_STRUCTURE.md) - 프로젝트 구조