diff --git a/PROJECT_STRUCTURE.md b/PROJECT_STRUCTURE.md
index 50404d4..3c6f256 100644
--- a/PROJECT_STRUCTURE.md
+++ b/PROJECT_STRUCTURE.md
@@ -526,7 +526,7 @@
| **글 상세보기** | `/[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]/imageUpload` | 🆕 **이미지 소스 선택 페이지 (글 저장 후 자동 이동)** | 🆕 **2가지 선택지**: AI 생성 (장면 추출 + 선택 + 생성) / 직접 업로드
🆕 **드래그앤드롭 파일 업로드** (미리보기, 5MB 제한, JPEG/PNG/WebP)
🆕 **Canvas API 클라이언트 사이드 리사이즈** (1920x1080 최대, 85% 품질)
🆕 **Firebase Storage 업로드** (WritingManager.uploadUserImage)
🆕 **이미 이미지 있으면 자동으로 `/interaction` 리다이렉트**
🆕 **다국어 지원** (imageUpload namespace, ko/en/ja) | ✅ 완료 |
-| **인터랙션 편집** | `/[locale]/interaction` | 🆕 **이미지 왜곡 편집 페이지 (이미지 생성/업로드 후 이동)** | 🆕 **이미지 없으면 `/imageUpload` 자동 리다이렉트**
왜곡 영역 편집 (EditorCanvas, DistortionArea)
모션 프리셋 선택 (horizontal, vertical, rotate, pulse 등)
물리 설정 (stiffness, damping, mass)
에디터/인터랙션 모드 전환 (Switch)
저장 시 Writing.distortionAreas 업데이트 | ✅ 완료 |
+| **인터랙션 편집** | `/[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]/test` | 팀 코드 시스템 테스트 페이지 | 팀 코드 생성/검증 테스트
팀/학생 생성 테스트
학생 로그인 테스트
authStore 상태 확인 | 🔜 예정 |
| **공개 팀 목록** | `/[locale]/team/all` | 🆕 **공개 팀 둘러보기** | 🆕 **공개된 팀 목록 표시** (isPublic=true)
🆕 **TeamCard 그리드** (글래스모피즘)
🆕 **페이지네이션** (커서 기반)
🆕 **Navbar "공개 팀" 메뉴** | ✅ 완료 |
| **내 팀 목록** | `/[locale]/team` | 내가 만든/참여한 팀 목록 (정식 계정 전용) | 팀 카드 그리드, 팀 정보 (코드, 멤버 수, 보안 설정)
"새 팀 만들기" 버튼 | ✅ 완료 |
@@ -770,10 +770,19 @@
| 컴포넌트 | 파일명 | 설명 | 상태 |
|---------|--------|------|------|
+| **InteractionHeader** | `InteractionHeader.tsx` | 🆕 **인터랙션 페이지 Sticky Header** (IntersectionObserver + Sentinel 패턴, glassmorphism, 반응형 제목/버튼) | ✅ 완료 |
| **AnalysisNeededBanner** | `AnalysisNeededBanner.tsx` | 분석 필요 알림 배너 (AI 분석 요청 유도) | ✅ 완료 |
| **AreaUnlockBadge** | `AreaUnlockBadge.tsx` | 영역 잠금 해제 배지 (점수 달성 시 표시) | ✅ 완료 |
| **ImprovementHint** | `ImprovementHint.tsx` | 개선 힌트 표시 (점수가 낮을 때 조언 제공) | ✅ 완료 |
| **ScoreBadge** | `ScoreBadge.tsx` | 점수 배지 (오감/감정/대화/의성어 점수 표시) | ✅ 완료 |
+| **EditorModeSwitch** | `EditorModeSwitch.tsx` | 기본/고급 모드 전환 스위치 | ✅ 완료 |
+| **SimpleMotionSelector** | `SimpleMotionSelector.tsx` | 간소화된 모션 선택기 (기본 모드용) | ✅ 완료 |
+| **SimpleEasingSelector** | `SimpleEasingSelector.tsx` | 간소화된 이징 선택기 | ✅ 완료 |
+| **SimpleSpeedSelector** | `SimpleSpeedSelector.tsx` | 간소화된 속도 선택기 | ✅ 완료 |
+| **SimpleStrengthSelector** | `SimpleStrengthSelector.tsx` | 간소화된 강도 선택기 | ✅ 완료 |
+| **PhysicsPresetSelector** | `PhysicsPresetSelector.tsx` | 물리 프리셋 선택기 | ✅ 완료 |
+| **CustomAreaList** | `CustomAreaList.tsx` | 🆕 **왜곡 영역 목록 (일반/고급 모드 공통 표시)** | ✅ 완료 |
+| **CustomParameterPanel** | `CustomParameterPanel.tsx` | 커스텀 파라미터 패널 (고급 모드 전용) | ✅ 완료 |
---
diff --git a/ROADMAP.md b/ROADMAP.md
index 39fb726..474e5ca 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -1,6 +1,6 @@
# 라온누리 - 개발 로드맵
-> 최종 업데이트: 2025-12-23 (이미지 4:3 비율 표준화)
+> 최종 업데이트: 2025-12-24 (인터랙션 페이지 UX 개선)
초등학생을 위한 창작 글쓰기 교육 플랫폼 개발 계획
@@ -160,6 +160,7 @@
| **글 상세 페이지 Sticky Header** | **WritingDetailHeader.tsx 컴포넌트 추가, 스크롤 시 상단에 고정되는 헤더 기능, 글 제목/작성자 정보/이미지 포함 여부 표시, WritingOwnerActions 컴포넌트 재활용, 기존 헤더 관련 코드 제거 및 구조 변경** | **2025-12-19** |
| **AI 이미지 생성 에러 처리 개선** | **에러 코드별 토스트 메시지 처리 로직 개선, plan_not_supported/limit_exceeded/ai_disabled 등 에러 코드 메시지 추가, 에러 발생 시 'selecting' 단계로 되돌아가는 로직 유지, 다국어 지원 (ko/en/ja)** | **2025-12-19** |
| **의존성 업데이트** | **@ark-ui/react 및 @zag-js 패키지 버전 업데이트 (v1.29.1 → v1.31.1)** | **2025-12-19** |
+| **인터랙션 페이지 UX 대폭 개선** | **7:3 그리드 레이아웃 (이미지 70%, 컨트롤러 30%), 한 화면에서 이미지 보면서 편집 가능, 컨트롤러 내부 스크롤 (커스텀 스크롤바), InteractionHeader 컴포넌트 (IntersectionObserver + Sentinel 패턴, sticky header, glassmorphism 효과, 제목 크기 동적 변경 2xl→xl, 버튼 텍스트 숨김), framer-motion 애니메이션 (AnimatePresence, MotionBox/MotionVStack, 모드 전환/영역 선택 부드러운 전환, 0.2~0.3초 ease curve), 영역 목록을 일반 모드에서도 표시 (CustomAreaList, 고급 모드에서만 CustomParameterPanel), 에디터 버튼 우측 패널 상단 이동 (추가/삭제/숨기기, 가로 배치 flex:1), Container maxW 확장 (1400px→95vw), 이미지 반응형 수정 (InteractiveImageViewer width:100%, VStack maxH 제거, aspectRatio 충돌 해결), 높이 제한 80dvh (우측만 스크롤), 타입 체크 통과** | **2025-12-24** |
### 🚧 진행 중
diff --git a/TECH_STACK.md b/TECH_STACK.md
index b276284..108f7fc 100644
--- a/TECH_STACK.md
+++ b/TECH_STACK.md
@@ -1,6 +1,6 @@
# 라온누리 - 기술 스택 및 개발 환경
-> 최종 업데이트: 2025-12-19 (Curriculum Fork Model + 의존성 업데이트)
+> 최종 업데이트: 2025-12-23 (이미지 4:3 비율 표준화)
---
@@ -27,6 +27,13 @@
| **Tiptap** | v3.9.1 | 리치 텍스트 에디터 |
| **next-intl** | v4.5.2 | 🆕 **다국어 지원 (i18n)** |
+### Image Processing
+
+| 기술 | 버전 | 용도 |
+|-----|------|------|
+| **react-cropper** | ^2.3.3 | 🆕 **이미지 크롭 React 래퍼** (4:3 비율 크롭) |
+| **cropperjs** | ^1.6.1 | 🆕 **이미지 크롭 라이브러리** (회전, 확대/축소, 리셋) |
+
### Backend & Database
| 기술 | 버전 | 용도 |
@@ -2546,6 +2553,257 @@ src/hooks/useShakeAnimation.ts (+45줄) - Shake 애니메이션 훅
---
+### 25. 인터랙션 페이지 UX 패턴 (Sticky Header + 7:3 그리드 + 애니메이션)
+
+#### 핵심 개념
+
+**목적**: 이미지를 보면서 실시간으로 인터랙션을 편집할 수 있는 최적화된 레이아웃
+
+#### Sticky Header 패턴 (IntersectionObserver + Sentinel)
+
+**기술**: `WritingDetailHeader.tsx`와 동일한 패턴 재사용
+
+**구조**:
+```tsx
+// InteractionHeader.tsx
+<>
+ {/* Sentinel - 스크롤 감지용 */}
+
+
+ {/* Sticky Header */}
+
+
+
+ {/* 왼쪽: 뒤로가기 + 제목 */}
+
+
+
+ {title}
+
+
+
+ {/* 오른쪽: 배지 + 모드 전환 + 이미지 변경 */}
+
+
+
+
+
+
+
+
+
+>
+```
+
+**IntersectionObserver 로직**:
+```typescript
+const [isSticky, setIsSticky] = useState(false);
+const sentinelRef = useRef(null);
+
+useEffect(() => {
+ const sentinel = sentinelRef.current;
+ if (!sentinel) return;
+
+ const observer = new IntersectionObserver(
+ ([entry]) => {
+ setIsSticky(!entry.isIntersecting); // sentinel이 안 보이면 sticky
+ },
+ { threshold: 0 }
+ );
+
+ observer.observe(sentinel);
+ return () => observer.disconnect();
+}, []);
+```
+
+**glassmorphism 효과**:
+- 반투명 배경 (`bg/80`)
+- 블러 효과 (`blur(12px)`)
+- 부드러운 전환 (0.2s ease)
+
+#### 7:3 그리드 레이아웃
+
+**구조**:
+```tsx
+
+ {/* 왼쪽: 이미지 영역 */}
+
+
+
+
+ {/* 오른쪽: 컨트롤러 영역 (스크롤 가능) */}
+
+
+ {/* 모드 전환 스위치 */}
+ {/* 에디터 버튼 (추가/삭제/숨기기) */}
+ {/* 영역 목록 (일반/고급 모드 공통) */}
+ {/* 파라미터 패널 (고급 모드 전용) */}
+ {/* 선택된 영역 설정 */}
+
+
+
+```
+
+**주요 특징**:
+- ✅ **한 화면 편집**: 이미지 보면서 인터랙션 수정 (스크롤 불필요)
+- ✅ **독립 스크롤**: 컨트롤러만 내부 스크롤 (80dvh 제한)
+- ✅ **반응형 이미지**: `width="100%"` + `aspectRatio` 유지
+- ✅ **Container 확장**: `maxW="95vw"` (화면 최대 활용)
+
+#### framer-motion 애니메이션 패턴
+
+**MotionBox 생성**:
+```typescript
+import {motion, AnimatePresence} from "framer-motion";
+
+const MotionBox = motion.create(Box);
+const MotionVStack = motion.create(VStack);
+```
+
+**AnimatePresence 활용**:
+```tsx
+{/* 고급 모드 에디터 컨트롤 패널 */}
+
+ {showEditor && isAdvanced && (
+
+ {/* 영역 목록 + 파라미터 패널 */}
+
+ )}
+
+
+{/* 선택된 영역 설정 */}
+
+ {selectedArea && (
+
+ {/* 모션/이징/속도/강도 선택기 */}
+
+ )}
+
+
+{/* 조건부 UI (모션 있을 때만 표시) */}
+
+ {selectedArea.movement.preset !== 'none' && (
+
+
+
+ )}
+
+```
+
+**애니메이션 특징**:
+- ✅ **Easing Curve**: `[0.22, 1, 0.36, 1]` (자연스러운 감속)
+- ✅ **Duration**: 0.2~0.3초 (빠르면서도 부드러운)
+- ✅ **mode="wait"**: 퇴장 완료 후 등장 시작
+- ✅ **key 전략**: 고정 key로 영역 변경 시 재마운트 방지
+
+#### 반응형 이미지 처리 (aspectRatio 충돌 해결)
+
+**문제**: VStack `maxH` + Box `aspectRatio` 충돌 → 이미지 찌그러짐
+
+**해결**:
+```tsx
+{/* VStack에서 maxH 제거 */}
+
+ {/* aspectRatio가 자유롭게 작동 */}
+
+```
+
+**InteractiveImageViewer 개선**:
+```tsx
+// 에디터 모드
+
+
+
+```
+
+**라이브러리 동작**:
+- EditorCanvas: `width: 100%, height: 100%` (부모 크기 따름)
+- ImageDistortion: `width: 100%, height: 100%` (부모 크기 따름)
+- ResizeObserver로 실제 렌더링 크기 측정
+
+#### z-index 계층 구조
+
+```
+Navbar (z-index: 1000)
+ └─ Sticky Headers (z-index: 100)
+ ├─ WritingDetailHeader
+ └─ InteractionHeader
+ └─ 하단 저장 버튼 바 (z-index: 10)
+```
+
+#### 주요 컴포넌트
+
+| 컴포넌트 | 파일 | 역할 |
+|---------|------|------|
+| **InteractionHeader** | `src/components/interaction/InteractionHeader.tsx` | Sticky header (제목, 배지, 모드 전환, 이미지 변경) |
+| **CustomAreaList** | `src/components/interaction/CustomAreaList.tsx` | 왜곡 영역 목록 (일반/고급 모드 공통) |
+| **CustomParameterPanel** | `src/components/interaction/CustomParameterPanel.tsx` | 파라미터 패널 (고급 모드 전용) |
+
+#### 성능 최적화
+
+- ✅ **IntersectionObserver**: scroll 이벤트 대비 성능 우수
+- ✅ **ResizeObserver**: Canvas 크기 동적 조정
+- ✅ **AnimatePresence**: DOM 제거 시에도 애니메이션
+- ✅ **key 전략**: 불필요한 재마운트 방지
+
+---
+
## 참고 문서
- [PROJECT_STRUCTURE.md](./PROJECT_STRUCTURE.md) - 프로젝트 구조