2025-11-21 06:35:24 +00:00

234 lines
6.8 KiB
Markdown

# 라온누리 (Raonnuri)
초등학생을 위한 창의적 글쓰기 교육 플랫폼
> 최종 업데이트: 2025-11-07
## 프로젝트 소개
라온누리는 초등학생들이 재미있게 글쓰기를 배울 수 있는 한국어 교육 플랫폼입니다.
### 주요 특징
- **팀 코드 시스템**: 초등 저학년도 쉽게 로그인 ("춤추는 파란 사자")
- **개인 맞춤 주제**: 자유 주제, 그룹 주제, 개인 주제 지원
- **글쓰기 에디터**: 초등학생 친화적인 순수 텍스트 에디터
- 🔜 **레벨업 시스템**: 경험치와 스티커 보상 (예정)
- 🔜 **학습 커리큘럼**: 체계적인 레슨 시스템 (예정)
## 기술 스택
- **Framework**: Next.js 16 (App Router) with React 19
- **언어**: TypeScript
- **UI Library**: Chakra UI v3
- **인증**: Firebase Authentication
- Email/Password, Google OAuth (정식 계정)
- Anonymous Auth (학생 팀 코드 로그인)
- **데이터베이스**: Firestore
- **상태 관리**: Zustand
- **비즈니스 로직**: Manager 패턴 (API 호출 + 클라이언트 캐싱)
- **스타일링**: Chakra UI + Emotion
- **애니메이션**: Framer Motion
- 🔜 **캐싱**: Redis (예정)
## 시작하기
### 필수 요구사항
- Node.js 18.17 이상
- npm, yarn, pnpm, 또는 bun
### 설치
```bash
npm install
```
### 개발 서버 실행
```bash
npm run dev
```
개발 서버는 [http://localhost:3001](http://localhost:3001)에서 실행됩니다.
> **참고**: 이 프로젝트는 React Compiler를 사용하므로 webpack 모드로 실행됩니다 (Turbopack 아님).
### 기타 명령어
```bash
npm run build # 프로덕션 빌드
npm start # 프로덕션 서버 실행 (포트 3001)
npm run lint # ESLint 실행
```
## 프로젝트 구조
```
src/
├── app/ # Next.js App Router
│ ├── layout.tsx # 루트 레이아웃
│ ├── page.tsx # 랜딩 페이지
│ ├── home/ # 유저 대시보드
│ ├── write/ # 글쓰기 페이지
│ └── team/ # 팀 관련 페이지 (목록, 생성, 상세, 관리)
├── components/
│ ├── auth/ # 인증 (로그인, 회원가입, 학생 로그인)
│ ├── writing/ # 글쓰기 에디터, 주제 선택
│ ├── navigation/ # 네비게이션 바
│ └── ui/ # Chakra UI 기본 컴포넌트
├── managers/ # ✅ 비즈니스 로직 (API + 캐싱)
│ ├── ManagerBase.ts # 공통 기능 (authenticatedFetch, caching)
│ ├── TeamManager.ts # 팀 관련 API 호출
│ ├── StudentManager.ts # 학생 관련 API 호출
│ ├── WritingManager.ts # 글쓰기 API 호출
│ └── TopicManager.ts # 주제 API 호출
├── types/ # TypeScript 타입
│ ├── team.ts, student.ts, writing.ts, topic.ts
│ └── api/ # API Request/Response 타입
├── config/ # Firebase 설정
├── services/ # Firebase Auth, Firestore
├── store/ # Zustand (인증 상태)
└── theme/ # Chakra UI 커스텀 테마
```
## 주요 기능
### ✅ 인증 시스템
**정식 계정** (학부모/고학년):
- 이메일/비밀번호 로그인 및 회원가입
- Google OAuth 소셜 로그인
- 비밀번호 강도 체크 + HIBP API 유출 확인
**학생 로그인** (초등 저학년):
- 팀 코드 기반 로그인 ("춤추는 파란 사자")
- Anonymous Auth 사용
- 이름만 입력 또는 이름 + PIN
- 정식 계정 연결 가능 (선택적)
### ✅ 팀 관리 시스템
- 팀 생성 (누구나 가능)
- 한글 팀 코드 자동 생성 (10만 가지 조합)
- 보안 모드 3종: simple, normal, open
- 팀원 관리 (이름 수정, 강퇴)
- 멤버 페이지 (팀 정보 및 멤버 목록)
### ✅ 글쓰기 기능
- Tiptap 순수 텍스트 에디터 (포맷팅 없음)
- 주제 선택 (자유/그룹/개인)
- 개인 주제 생성 (템플릿 지원)
- 실시간 글자수/단어수 카운터
- LocalStorage 자동 저장
### ✅ UI/UX
- 다크 모드 지원
- 반응형 디자인 (모바일 우선)
- Chakra UI v3 커스텀 테마
- Framer Motion 애니메이션
- 초등학생 친화적 디자인
### ✅ 아키텍처
- Manager 패턴 (비즈니스 로직 레이어)
- API 추상화 (HTTP 호출)
- 클라이언트 사이드 캐싱 (TTL 기반)
- 타입 안전성 (완전한 타입 정의)
- 35개 API 엔드포인트 준비 완료
## 개발자 가이드
상세한 개발 가이드는 다음 문서를 참고하세요:
- [CLAUDE.md](./CLAUDE.md) - Claude Code 개발 가이드
- [API_SPEC.md](./API_SPEC.md) - API 명세서
- [TECH_STACK.md](./TECH_STACK.md) - 기술 스택 상세
- [PROJECT_STRUCTURE.md](./PROJECT_STRUCTURE.md) - 프로젝트 구조 상세
- [DATA_MODELS.md](./DATA_MODELS.md) - 데이터 모델
### Manager 패턴 사용
**❌ 서비스 직접 사용 금지**:
```typescript
// Bad - deprecated
import { getTeamsByOwner } from "@/services/teamService";
```
**✅ Manager 사용**:
```typescript
// Good
import { teamManager, studentManager } from "@/managers";
// 팀 목록 (1분 캐싱)
const teams = await teamManager.getMyTeams();
// 학생 목록 (30초 캐싱)
const students = await studentManager.getStudentsByTeam(teamId);
// 팀 생성 (캐시 자동 무효화)
const teamId = await teamManager.createTeam({
name: "우리반",
code: "춤추는파란사자",
securityMode: "simple",
requirePin: false,
allowAnonymousJoin: true
});
```
### 보호된 페이지 만들기
```tsx
"use client";
import { useAuthStore } from "@/store/authStore";
import { useRouter } from "next/navigation";
import { useEffect } from "react";
export default function ProtectedPage() {
const { isAuthenticated, isLoading } = useAuthStore();
const router = useRouter();
useEffect(() => {
if (!isLoading && !isAuthenticated) {
router.push("/");
}
}, [isAuthenticated, isLoading, router]);
if (isLoading) return <div>로딩 ...</div>;
if (!isAuthenticated) return null;
return <div>보호된 콘텐츠</div>;
}
```
## 환경 변수
Firebase 설정을 위해 `.env.local` 파일을 생성하세요:
```bash
# Firebase 설정 (필수)
NEXT_PUBLIC_FIREBASE_API_KEY=your_api_key
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your_auth_domain
NEXT_PUBLIC_FIREBASE_PROJECT_ID=your_project_id
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=your_storage_bucket
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=your_sender_id
NEXT_PUBLIC_FIREBASE_APP_ID=your_app_id
# 사이트 URL (프로덕션)
NEXT_PUBLIC_URL=https://raonnuri.life
# API Base URL (선택적, 기본값: /api)
NEXT_PUBLIC_API_URL=/api
```
## 라이선스
MIT License
## 기여하기
기여는 언제나 환영합니다! Pull Request를 보내주세요.
---
**라온누리** - 즐거운 글쓰기, 밝은 배움터