248 lines
7.4 KiB
Markdown
248 lines
7.4 KiB
Markdown
# 라온누리 (Raonnuri)
|
|
|
|
초등학생을 위한 창의적 글쓰기 교육 플랫폼
|
|
|
|
## 프로젝트 소개
|
|
|
|
라온누리는 초등학생들이 재미있게 글쓰기를 배울 수 있는 한국어 교육 플랫폼입니다.
|
|
|
|
### 주요 특징
|
|
- **팀 코드 시스템**: 초등 저학년도 쉽게 로그인 ("춤추는 파란 사자")
|
|
- **개인 맞춤 주제**: 자유 주제, 그룹 주제, 개인 주제 지원
|
|
- **글쓰기 에디터**: 초등학생 친화적인 순수 텍스트 에디터
|
|
- 🔜 **레벨업 시스템**: 경험치와 스티커 보상 (예정)
|
|
- 🔜 **학습 커리큘럼**: 체계적인 레슨 시스템 (예정)
|
|
|
|
## 기술 스택
|
|
|
|
- **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 호출
|
|
│ ├── 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 유출 확인
|
|
|
|
**학생 로그인** (초등 저학년):
|
|
- 팀 코드 기반 로그인 ("춤추는 파란 사자")
|
|
- Anonymous Auth 사용
|
|
- 이름만 입력 또는 이름 + PIN
|
|
- 정식 계정 연결 가능 (선택적)
|
|
|
|
### ✅ 팀 관리 시스템
|
|
|
|
- 팀 생성 (누구나 가능)
|
|
- 한글 팀 코드 자동 생성 (10만 가지 조합)
|
|
- 보안 모드 3종: simple, normal, open
|
|
- 팀원 관리 (이름 수정, 강퇴)
|
|
- 멤버 페이지 (팀 정보 및 멤버 목록)
|
|
|
|
### ✅ 글쓰기 기능
|
|
|
|
- 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 <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를 보내주세요.
|
|
|
|
---
|
|
|
|
**라온누리** - 즐거운 글쓰기, 밝은 배움터 |