# 라온누리 (Raonnuri) 초등학생을 위한 창의적 글쓰기 교육 플랫폼 ## 프로젝트 소개 라온누리는 초등학생들이 재미있게 글쓰기를 배울 수 있는 한국어 교육 플랫폼입니다. ### 주요 특징 - **초대 링크 시스템**: 디스코드 스타일 초대 링크로 팀 참여 - **개인 맞춤 주제**: 자유 주제, 그룹 주제, 개인 주제 지원 - **글쓰기 에디터**: 초등학생 친화적인 순수 텍스트 에디터 - 🔜 **레벨업 시스템**: 경험치와 스티커 보상 (예정) - 🔜 **학습 커리큘럼**: 체계적인 레슨 시스템 (예정) ## 기술 스택 - **Framework**: Next.js 16 (App Router) with React 19 - **언어**: TypeScript - **UI Library**: Chakra UI v3 - **인증**: Firebase Authentication - Email/Password, Google OAuth - **데이터베이스**: 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 호출 │ ├── WritingManager.ts # 글쓰기 API 호출 │ └── TopicManager.ts # 주제 API 호출 ├── types/ # TypeScript 타입 │ ├── team.ts, writing.ts, topic.ts │ └── api/ # API Request/Response 타입 ├── config/ # Firebase 설정 ├── services/ # Firebase Auth, Firestore ├── store/ # Zustand (인증 상태) └── theme/ # Chakra UI 커스텀 테마 ``` ## 주요 기능 ### ✅ 인증 시스템 **정식 계정** (학부모/고학년): - 이메일/비밀번호 로그인 및 회원가입 - Google OAuth 소셜 로그인 - 비밀번호 강도 체크 + HIBP API 유출 확인 ### ✅ 팀 관리 시스템 - 팀 생성 (누구나 가능) - 초대 링크 생성 및 관리 (만료 시간, 최대 사용 횟수 설정) - 팀원 관리 (이름 수정, 강퇴) - 멤버 페이지 (팀 정보 및 멤버 목록) ### ✅ 글쓰기 기능 - Tiptap 순수 텍스트 에디터 (포맷팅 없음) - 주제 선택 (자유/그룹/개인) - 개인 주제 생성 (템플릿 지원) - 실시간 글자수/단어수 카운터 - LocalStorage 자동 저장 ### ✅ 댓글 및 피드백 시스템 - 계층형 댓글 구조 (대댓글 지원) - 칭찬 및 격려 중심의 반응(Reaction) 시스템 - 작성자, 글 주인, 선생님(팀 소유자) 권한 관리 - 실시간 업데이트 및 알림 ### ✅ 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 명세서 (RESTful 원칙, Firebase Admin SDK) - [STYLE_GUIDE.md](./STYLE_GUIDE.md) - 스타일 가이드 (Color, Icon 규칙) - [I18N_GUIDE.md](./I18N_GUIDE.md) - 다국어 지원 가이드 (필수) - [DEVELOPMENT_GUIDE.md](./DEVELOPMENT_GUIDE.md) - 구현 세부사항 ### 프로젝트 문서 - [PROJECT_STRUCTURE.md](./PROJECT_STRUCTURE.md) - 프로젝트 구조 - [TECH_STACK.md](./TECH_STACK.md) - 기술 스택 - [DATA_MODELS.md](./DATA_MODELS.md) - 데이터 모델 - [SECURITY.md](./SECURITY.md) - 보안 정책 - [ROADMAP.md](./ROADMAP.md) - 개발 로드맵 - [CHANGELOG.md](./CHANGELOG.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
로딩 중...
; if (!isAuthenticated) return null; return
보호된 콘텐츠
; } ``` ## 환경 변수 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를 보내주세요. --- **라온누리** - 즐거운 글쓰기, 밝은 배움터