# plan.md

# Firebase Todo App - 코드 설계도 및 프롬프트 엔지니어링 가이드

**작성일**: 2025년 10월 18일
**프로젝트**: todo-app
**목적**: 처음부터 끝까지 오류 없이 Todo 앱을 구축하기 위한 완전한 가이드

---

## 📋 목차

1. [프로젝트 아키텍처 개요](https://#1-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EA%B0%9C%EC%9A%94)

2. [컴포넌트 계층 구조](https://#2-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EA%B3%84%EC%B8%B5-%EA%B5%AC%EC%A1%B0)

3. [데이터 플로우](https://#3-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%94%8C%EB%A1%9C%EC%9A%B0)

4. [핵심 기능별 설계](https://#4-%ED%95%B5%EC%8B%AC-%EA%B8%B0%EB%8A%A5%EB%B3%84-%EC%84%A4%EA%B3%84)

5. [프롬프트 엔지니어링 가이드](https://#5-%ED%94%84%EB%A1%AC%ED%94%84%ED%8A%B8-%EC%97%94%EC%A7%80%EB%8B%88%EC%96%B4%EB%A7%81-%EA%B0%80%EC%9D%B4%EB%93%9C)

6. [주의사항 및 문제 해결](https://#6-%EC%A3%BC%EC%9D%98%EC%82%AC%ED%95%AD-%EB%B0%8F-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0)

7. [배포 가이드](https://#7-%EB%B0%B0%ED%8F%AC-%EA%B0%80%EC%9D%B4%EB%93%9C)

---

## 1. 프로젝트 아키텍처 개요

### 1.1 기술 스택

```
Frontend Framework: React 19.1.1 + TypeScript 5.9.3
Build Tool: Vite 7.1.7
Routing: React Router DOM 7.9.4
Backend: Firebase (Authentication + Firestore)
Internationalization: i18next + react-i18next
Styling: Bootstrap 5 (via CDN) + CSS
State Management: React Context API (Theme)
```

### 1.2 프로젝트 구조

```
todo-app/
├── public/                      # 정적 파일
│   └── vite.svg
├── src/
│   ├── components/              # React 컴포넌트
│   │   ├── AddTodoForm.tsx      # Todo 추가 폼
│   │   ├── TodoItem.tsx         # Todo 단일 아이템
│   │   └── TodoList.tsx         # Todo 목록 컨테이너
│   ├── context/                 # React Context
│   │   └── ThemeContext.tsx     # 다크모드 테마 관리
│   ├── firebase/                # Firebase 설정 및 서비스
│   │   ├── config.ts            # Firebase 초기화
│   │   └── services.ts          # Firestore CRUD 함수
│   ├── hooks/                   # Custom React Hooks
│   │   ├── useAuth.ts           # 인증 상태 관리
│   │   └── useTodos.ts          # Todo 목록 관리
│   ├── locales/                 # 다국어 번역 파일
│   │   ├── en/translation.json  # 영어
│   │   ├── ko/translation.json  # 한국어
│   │   └── ja/translation.json  # 일본어
│   ├── pages/                   # 페이지 컴포넌트
│   │   ├── HomePage.tsx         # 메인 페이지 (Todo 관리)
│   │   └── LoginPage.tsx        # 로그인/회원가입 페이지
│   ├── App.tsx                  # 앱 라우팅
│   ├── main.tsx                 # 앱 진입점
│   ├── i18n.ts                  # i18next 설정
│   ├── App.css                  # 앱 스타일
│   └── index.css                # 전역 스타일
├── firestore.rules              # Firestore 보안 규칙
├── firestore.indexes.json       # Firestore 인덱스
├── firebase.json                # Firebase 설정
├── .firebaserc                  # Firebase 프로젝트 ID
├── package.json                 # 의존성 관리
├── tsconfig.json                # TypeScript 설정
└── vite.config.ts               # Vite 설정
```

### 1.3 주요 의존성

```
{
  "dependencies": {
    "firebase": "^12.4.0",
    "i18next": "^25.6.0",
    "i18next-browser-languagedetector": "^8.2.0",
    "react": "^19.1.1",
    "react-dom": "^19.1.1",
    "react-i18next": "^16.1.0",
    "react-router-dom": "^7.9.4"
  },
  "devDependencies": {
    "@types/node": "^24.6.0",
    "@types/react": "^19.1.16",
    "@types/react-dom": "^19.1.9",
    "@vitejs/plugin-react": "^5.0.4",
    "firebase-tools": "^14.20.0",
    "typescript": "~5.9.3",
    "vite": "^7.1.7"
  }
}
```

---

## 2. 컴포넌트 계층 구조

```
App (라우팅)
├── LoginPage (비인증)
│   └── 로그인/회원가입 폼
└── HomePage (인증 후)
    ├── Header
    │   ├── 제목
    │   ├── 언어 선택기
    │   ├── 테마 토글 버튼
    │   └── 로그아웃 버튼
    ├── AddTodoForm
    │   ├── 텍스트 입력
    │   └── 추가 버튼
    └── TodoList
        └── TodoItem[] (반복)
            ├── 체크박스
            ├── 텍스트
            └── 삭제 버튼
```

---

## 3. 데이터 플로우

```
┌─────────────────────────────────────────────────────────────┐
│                     Firebase Cloud                           │
│  ┌────────────────┐              ┌─────────────────┐        │
│  │ Authentication │              │   Firestore DB  │        │
│  │   (Auth SDK)   │              │  (todos 컬렉션) │        │
│  └────────────────┘              └─────────────────┘        │
└──────────┬──────────────────────────────┬──────────────────┘
           │                              │
           │ onAuthStateChanged           │ onSnapshot (실시간)
           │                              │
┌──────────▼──────────────────────────────▼──────────────────┐
│                    Frontend (React)                         │
│  ┌───────────────────────────────────────────────────────┐ │
│  │  main.tsx (전역 AbortError 차단 시스템)              │ │
│  └───────────────────────────────────────────────────────┘ │
│  ┌───────────────────────────────────────────────────────┐ │
│  │  App.tsx (React Router)                               │ │
│  │    ├─ useAuth() → user, loading                       │ │
│  │    └─ Route 분기 (인증/비인증)                        │ │
│  └───────────────────────────────────────────────────────┘ │
│  ┌───────────────────────────────────────────────────────┐ │
│  │  HomePage                                              │ │
│  │    ├─ useTodos() → todos[], loading                   │ │
│  │    ├─ ThemeContext → theme, toggleTheme               │ │
│  │    ├─ i18next → t(), i18n                             │ │
│  │    └─ Components: AddTodoForm, TodoList               │ │
│  └───────────────────────────────────────────────────────┘ │
│  ┌───────────────────────────────────────────────────────┐ │
│  │  Firebase Services (CRUD)                             │ │
│  │    ├─ addTodo(userId, text)                           │ │
│  │    ├─ getTodos(userId, callback) → unsubscribe        │ │
│  │    ├─ toggleTodoCompleted(id, completed)              │ │
│  │    └─ deleteTodo(id)                                  │ │
│  └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```

---

## 4. 핵심 기능별 설계

### 4.1 인증 시스템 (Authentication)

```
// useAuth Hook
사용자 인증 상태를 실시간으로 추적
- onAuthStateChanged 리스너 등록
- user, loading 상태 반환
- cleanup 함수로 메모리 누수 방지

// LoginPage
- 이메일/비밀번호 입력
- 회원가입: createUserWithEmailAndPassword
- 로그인: signInWithEmailAndPassword
- 에러 핸들링: AbortError 필터링
```

### 4.2 Todo CRUD 시스템

```
// Firestore 데이터 구조
interface Todo {
  id: string;
  text: string;
  completed: boolean;
  createdAt: Timestamp;
  userId: string;
}

// 보안 규칙
- allow list: 인증된 사용자만 쿼리 가능
- allow get: 자신의 문서만 읽기 가능
- allow create: 자신의 userId로만 생성
- allow update/delete: 자신의 문서만 수정/삭제
```

### 4.3 실시간 동기화 (Real-time Sync)

```
// useTodos Hook
- getTodos() → onSnapshot 리스너 등록
- userId로 필터링된 쿼리
- createdAt 기준 내림차순 정렬
- 실시간 업데이트 자동 반영
- cleanup 시 unsubscribe() 호출
```

### 4.4 다국어 지원 (i18n)

```
// 지원 언어: en (영어), ko (한국어), ja (일본어)
// 브라우저 언어 자동 감지
// 사용자가 수동으로 언어 변경 가능
// 모든 UI 텍스트 번역 파일로 관리
```

### 4.5 다크모드 (Theme)

```
// ThemeContext
- localStorage에 테마 저장
- Bootstrap 5의 data-bs-theme 속성 활용
- light/dark 토글
- 앱 전체에 Context로 제공
```

### 4.6 AbortError 차단 시스템

```
// 3단계 방어 시스템
1. fetch 오버라이드: AbortError를 소스에서 차단
2. unhandledrejection: 놓친 에러 캐치
3. console.error 필터링: inspector.js 로그 차단
```

---

## 5. 프롬프트 엔지니어링 가이드

각 컴포넌트를 **오류 없이 한 번에 작성**하기 위한 프롬프트입니다.

### Step 1: 프로젝트 초기화

```
React + TypeScript + Vite로 Todo 앱을 만들고 싶어요. 다음 요구사항을 충족하는 프로젝트를 생성해주세요:

1. React 19 + TypeScript 5 + Vite 7 사용
2. Firebase Authentication + Firestore 사용
3. React Router DOM으로 라우팅
4. i18next로 다국어 지원 (영어, 한국어, 일본어)
5. Bootstrap 5 스타일링 (CDN 사용)

다음 명령어로 프로젝트를 생성하고 필요한 패키지를 설치해주세요:

npm create vite@latest todo-app -- --template react-ts
cd todo-app
npm install

그리고 다음 패키지들을 추가 설치해주세요:
npm install firebase react-router-dom i18next react-i18next i18next-browser-languagedetector

개발 도구도 설치해주세요:
npm install -D firebase-tools @types/node

package.json을 확인하고 모든 의존성이 올바르게 설치되었는지 확인해주세요.
```

---

### Step 2: Firebase 설정 파일 생성

```
Firebase 프로젝트를 설정하고 싶어요. 다음 파일들을 생성해주세요:

1. src/firebase/config.ts - Firebase 초기화 파일
   - Vite 환경 변수 (import.meta.env.VITE_*) 사용
   - getAuth, getFirestore import
   - 환경 변수 검증 로직 포함

2. src/firebase/services.ts - Firestore CRUD 서비스
   - Todo 인터페이스 정의 (id, text, completed, createdAt, userId)
   - addTodo(userId, text) - 새 Todo 추가
   - getTodos(userId, callback) - 실시간 리스너 (where userId, orderBy createdAt desc)
   - toggleTodoCompleted(docId, completed) - 완료 상태 토글
   - deleteTodo(docId) - Todo 삭제
   - 모든 함수에 AbortError 처리 포함 (error.name === 'AbortError'면 조용히 반환)
   - permission-denied 에러는 명확한 메시지로 로깅

3. firestore.rules - Firestore 보안 규칙
   - todos 컬렉션에 대해:
     - allow list: 인증된 사용자만
     - allow get: 자신의 문서만
     - allow create: 자신의 userId로만
     - allow update, delete: 자신의 문서만

4. firebase.json - Firebase 프로젝트 설정
   - firestore rules 및 indexes 경로 지정

5. .env.local 템플릿 생성
   - VITE_API_KEY, VITE_AUTH_DOMAIN, VITE_PROJECT_ID 등 환경 변수 예시

각 파일의 전체 코드를 TypeScript와 Firebase v10+ 최신 문법으로 작성해주세요.
React 17+ 에서는 JSX 변환 시 `import React`가 불필요하므로 포함하지 마세요.
type import는 `import type { ... }`나 `type ReactNode` 형식으로 작성해주세요.
```

---

### Step 3: Custom Hooks 생성

```
React Custom Hooks를 만들고 싶어요. 다음 두 개의 hook을 생성해주세요:

1. src/hooks/useAuth.ts
   - Firebase Authentication 상태를 관리하는 hook
   - onAuthStateChanged 리스너 등록
   - user (User | null)와 loading (boolean) 상태 반환
   - useEffect cleanup에서 unsubscribe 호출
   - TypeScript 타입 안전성 보장

2. src/hooks/useTodos.ts
   - useAuth hook 사용하여 현재 사용자 가져오기
   - getTodos 서비스 사용하여 실시간 리스너 등록
   - todos (Todo[])와 loading (boolean) 상태 반환
   - user가 없으면 빈 배열 반환
   - useEffect cleanup에서 리스너 해제

주의사항:
- React 17+이므로 `import React` 불필요
- type import는 `import type { User }` 형식 사용
- dependency array 정확히 설정
- 메모리 누수 방지를 위한 cleanup 함수 필수
```

---

### Step 4: Context 생성 (Theme)

```
다크모드를 지원하는 ThemeContext를 만들고 싶어요.

src/context/ThemeContext.tsx 파일을 생성해주세요:

요구사항:
1. Theme 타입: 'light' | 'dark'
2. ThemeContextType 인터페이스: { theme: Theme, toggleTheme: () => void }
3. ThemeProvider 컴포넌트:
   - localStorage에서 초기 테마 로드 (기본값: 'light')
   - theme이 변경되면 document.documentElement.setAttribute('data-bs-theme', theme) 실행
   - localStorage에 theme 저장
4. useTheme 커스텀 hook:
   - ThemeContext 사용
   - context가 undefined면 에러 발생

주의사항:
- type ReactNode는 `import { type ReactNode }` 형식으로 import
- React import 불필요
- children props 타입 명시
```

---

### Step 5: i18n 설정

```
다국어 지원 설정을 해주세요.

1. src/i18n.ts 파일 생성:
   - i18next, react-i18next, i18next-browser-languagedetector import
   - 영어(en), 한국어(ko), 일본어(ja) 번역 파일 import
   - LanguageDetector 사용하여 브라우저 언어 자동 감지
   - fallbackLng: 'en'
   - interpolation.escapeValue: false

2. 번역 파일 생성:
   - src/locales/en/translation.json
   - src/locales/ko/translation.json
   - src/locales/ja/translation.json

번역 키:
- loginTitle: "Login or Sign Up" / "로그인 또는 회원가입" / "ログインまたはサインアップ"
- emailPlaceholder: "Email" / "이메일" / "Eメール"
- passwordPlaceholder: "Password" / "비밀번호" / "パスワード"
- loginButton, signupButton, logoutButton
- todoTitle: "Todo List" / "할 일 목록" / "Todoリスト"
- addTaskButton, taskPlaceholder, deleteButton
- noTasks: "No tasks yet. Add one above!"
- loading: "Loading..." / "로딩 중..." / "読み込み中..."
- adding, deleting (로딩 상태 텍스트)

모든 파일을 JSON 형식으로 작성해주세요.
```

---

### Step 6: 컴포넌트 생성 - AddTodoForm

```
Todo 추가 폼 컴포넌트를 만들고 싶어요.

src/components/AddTodoForm.tsx 파일을 생성해주세요:

요구사항:
1. Props: { userId: string }
2. 로컬 상태:
   - text (string) - 입력 텍스트
   - isAdding (boolean) - 추가 중 상태
3. handleSubmit 함수:
   - e.preventDefault() 호출
   - text.trim() 검증
   - isAdding이면 early return
   - setIsAdding(true) 설정
   - try-catch-finally로 addTodo 호출
   - 성공 시 setText('') 로 입력 필드 초기화
   - permission-denied 에러는 명확히 로깅
   - AbortError는 조용히 처리
   - finally에서 setIsAdding(false)
4. UI:
   - form onSubmit={handleSubmit}
   - Bootstrap input-group 사용
   - input: type="text", placeholder={t('taskPlaceholder')}
   - button: type="submit", {isAdding ? t('adding') : t('addTaskButton')}
   - isAdding 중에는 input과 button disabled

주의사항:
- useTranslation() hook 사용
- React import 불필요
- async/await 사용
```

---

### Step 7: 컴포넌트 생성 - TodoItem

```
개별 Todo 아이템 컴포넌트를 만들고 싶어요.

src/components/TodoItem.tsx 파일을 생성해주세요:

요구사항:
1. Props: { todo: Todo }
2. 로컬 상태:
   - isToggling (boolean) - 토글 중
   - isDeleting (boolean) - 삭제 중
3. handleToggle 함수:
   - isToggling이면 early return
   - setIsToggling(true)
   - try-catch-finally로 toggleTodoCompleted 호출
   - permission-denied와 AbortError 처리
   - finally에서 setIsToggling(false)
4. handleDelete 함수:
   - isDeleting이면 early return
   - setIsDeleting(true)
   - try-catch-finally로 deleteTodo 호출
   - permission-denied와 AbortError 처리
   - finally에서 setIsDeleting(false)
5. UI:
   - li.list-group-item
   - checkbox: checked={todo.completed}, onChange={handleToggle}
   - label: todo.completed이면 text-decoration-line-through, text-muted 클래스
   - button: onClick={handleDelete}, {isDeleting ? t('deleting') : t('deleteButton')}
   - isToggling이나 isDeleting 중에는 모든 컨트롤 disabled

주의사항:
- useTranslation() hook 사용
- async/await 사용
- 중복 클릭 방지 필수
```

---

### Step 8: 컴포넌트 생성 - TodoList

```
Todo 목록을 렌더링하는 간단한 컨테이너 컴포넌트를 만들어주세요.

src/components/TodoList.tsx 파일을 생성해주세요:

요구사항:
1. Props: { todos: Todo[] }
2. UI:
   - ul.list-group
   - todos.map()으로 TodoItem 렌더링
   - key={todo.id}로 설정

주의사항:
- React import 불필요
- React.FC<TodoListProps> 타입 명시
- TodoItem import
```

---

### Step 9: 페이지 생성 - LoginPage

```
로그인/회원가입 페이지를 만들어주세요.

src/pages/LoginPage.tsx 파일을 생성해주세요:

요구사항:
1. 로컬 상태:
   - email (string)
   - password (string)
   - error (string | null)
2. handleSignUp 함수:
   - React.MouseEvent<HTMLButtonElement> 타입
   - e.preventDefault() 호출
   - email, password 검증
   - try-catch로 createUserWithEmailAndPassword 호출
   - AbortError는 조용히 처리
   - 다른 에러는 setError(err.message)
3. handleLogIn 함수:
   - handleSignUp과 유사하지만 signInWithEmailAndPassword 사용
4. UI:
   - Bootstrap card 레이아웃
   - h2: {t('loginTitle')}
   - input email: placeholder={t('emailPlaceholder')}
   - input password: placeholder={t('passwordPlaceholder')}
   - button 로그인: onClick={handleLogIn}, type="submit"
   - button 회원가입: onClick={handleSignUp}, type="button"
   - error가 있으면 alert 표시

주의사항:
- useTranslation() hook 사용
- React 19의 event handler 타입 사용
- async/await 사용
```

---

### Step 10: 페이지 생성 - HomePage

```
메인 페이지 (Todo 관리)를 만들어주세요.

src/pages/HomePage.tsx 파일을 생성해주세요:

요구사항:
1. Hooks:
   - useAuth() → user
   - useTodos() → todos, loading
   - useTheme() → theme, toggleTheme
   - useTranslation() → t, i18n
2. handleLogout 함수:
   - signOut(auth).catch()
   - AbortError 조용히 처리
3. handleLanguageChange 함수:
   - i18n.changeLanguage(lng) 호출
4. UI 구조:
   - card.card-header:
     - h1: {t('todoTitle')}
     - select: 언어 선택 (EN, KO, JA)
     - button: 테마 토글 ({theme === 'dark' ? '🌙' : '☀️'})
     - button: 로그아웃 {t('logoutButton')}
   - card.card-body:
     - AddTodoForm (user가 있을 때만)
     - loading이면 spinner 표시
     - todos.length === 0이고 loading이 아니면 {t('noTasks')}
     - todos.length > 0이면 TodoList

주의사항:
- 모든 컴포넌트와 hook import
- Bootstrap 클래스 사용
- 조건부 렌더링 정확히 구현
```

---

### Step 11: App 라우팅 설정

```
앱의 라우팅을 설정해주세요.

src/App.tsx 파일을 생성해주세요:

요구사항:
1. useAuth() hook으로 user, loading 가져오기
2. loading이면 "Loading..." 표시
3. BrowserRouter 사용:
   - Route "/" - user가 있으면 HomePage, 없으면 /login으로 Navigate
   - Route "/login" - user가 없으면 LoginPage, 있으면 /로 Navigate
4. 전체를 div.container.mt-5로 감싸기

주의사항:
- React Router DOM의 Navigate 컴포넌트 사용
- 인증 상태에 따른 리다이렉트 정확히 구현
- App.css import (빈 파일이어도 됨)
```

---

### Step 12: 진입점 설정 (main.tsx)

```
앱의 진입점 파일을 만들어주세요. 특히 AbortError 차단 시스템을 포함해야 합니다.

src/main.tsx 파일을 생성해주세요:

요구사항:

1. 전역 AbortError 차단 시스템 (3단계):

   1단계 - fetch 오버라이드:
   - const originalFetch = window.fetch 저장
   - window.fetch를 새 함수로 오버라이드
   - .catch()에서 AbortError 또는 code === 'cancelled' 체크
   - AbortError면 new Promise(() => {}) 반환 (완전히 삼킴)
   - 다른 에러는 throw

   2단계 - unhandledrejection 핸들러:
   - window.addEventListener('unhandledrejection', ...)
   - AbortError면 event.preventDefault()
   - 다른 에러는 console.error로 로깅

   3단계 - console.error 필터링:
   - const originalConsoleError = console.error 저장
   - console.error를 새 함수로 오버라이드
   - 메시지에 'AbortError' 또는 'user aborted' 포함 체크
   - AbortError 관련이면 return (로그 출력 안 함)
   - 다른 에러는 originalConsoleError로 로깅

2. React 앱 렌더링:
   - createRoot(document.getElementById('root')!)
   - StrictMode로 감싸기
   - ThemeProvider로 감싸기
   - App 컴포넌트 렌더링

3. 필요한 import:
   - React StrictMode, createRoot
   - './index.css', './i18n' (부수효과 import)
   - App, ThemeProvider

주의사항:
- 3단계 AbortError 차단 시스템이 가장 중요
- 주석으로 각 단계 명확히 표시
- originalFetch, originalConsoleError 변수 사용
```

---

### Step 13: CSS 파일 설정

```
스타일링 파일들을 설정해주세요.

1. src/index.css:
   - body의 background-color를 #f0f2f5로 설정
   - !important 플래그 사용하여 Bootstrap 오버라이드

2. src/App.css:
   - 빈 파일 또는 필요한 앱별 스타일 추가

3. index.html:
   - Bootstrap 5 CSS CDN 추가 (<link> 태그)
   - Bootstrap 5 JS CDN 추가 (<script> 태그, body 끝)
   - 타이틀을 "Todo App"으로 변경

주의사항:
- Bootstrap 5.3+ 버전 사용
- dark mode 지원을 위한 data-bs-theme 속성 지원 버전
```

---

### Step 14: TypeScript 설정 검증

```
TypeScript 설정을 검증하고 필요하면 수정해주세요.

tsconfig.app.json 파일을 확인하고:
1. verbatimModuleSyntax가 true로 설정되어 있는지 확인
2. 이 설정 때문에 type import는 반드시 `import type { ... }` 또는 inline `import { type ... }` 형식 사용
3. React 17+ JSX transform 사용 확인 (jsx: "react-jsx")

모든 .tsx 파일에서:
1. `import React`가 없는지 확인 (JSX 변환이므로 불필요)
2. type-only import는 올바른 형식인지 확인
3. 사용하지 않는 import가 없는지 확인 (TS6133 에러 방지)

npm run build를 실행하여 에러가 없는지 확인해주세요.
```

---

### Step 15: 환경 변수 및 Firebase 설정

```
Firebase 프로젝트를 설정하고 환경 변수를 구성해주세요.

1. Firebase Console에서 새 프로젝트 생성 (또는 기존 프로젝트 사용)
2. Authentication 활성화:
   - Email/Password 로그인 활성화
3. Firestore Database 생성:
   - 테스트 모드로 시작
4. Web 앱 추가하여 Firebase 설정 가져오기
5. .env.local 파일 생성:
   VITE_API_KEY=your-api-key
   VITE_AUTH_DOMAIN=your-project-id.firebaseapp.com
   VITE_PROJECT_ID=your-project-id
   VITE_STORAGE_BUCKET=your-project-id.firebasestorage.app
   VITE_MESSAGING_SENDER_ID=your-sender-id
   VITE_APP_ID=your-app-id

6. Firebase CLI로 보안 규칙 배포:
   npx firebase login
   npx firebase init firestore (기존 파일 덮어쓰지 않도록 주의)
   npx firebase deploy --only firestore:rules

또는 Firebase Console에서 수동으로 firestore.rules 내용을 복사하여 배포

주의사항:
- .env.local은 .gitignore에 포함
- .env.example 파일을 만들어 변수 이름만 공유
```

---

### Step 16: 빌드 및 테스트

```
프로젝트를 빌드하고 테스트해주세요.

1. 빌드 테스트:
   npm run build
   - 에러가 없어야 함
   - dist 폴더 생성 확인

2. 로컬 개발 서버 실행:
   npm run dev
   - http://localhost:5173 접속
   - 브라우저 콘솔에 에러가 없어야 함

3. 기능 테스트 체크리스트:
   - [ ] 회원가입 정상 작동
   - [ ] 로그인 정상 작동
   - [ ] Todo 추가 정상 작동
   - [ ] Todo 체크/언체크 정상 작동
   - [ ] Todo 삭제 정상 작동
   - [ ] 다크모드 토글 정상 작동
   - [ ] 언어 전환 정상 작동 (EN, KO, JA)
   - [ ] 로그아웃 정상 작동
   - [ ] 브라우저 콘솔에 AbortError 없음
   - [ ] 브라우저 콘솔에 permission-denied 없음

4. 보안 규칙 테스트:
   - [ ] 비로그인 사용자는 데이터 접근 불가
   - [ ] 사용자 A는 사용자 B의 Todo 볼 수 없음

문제가 있으면 콘솔 에러를 확인하고 해당 단계로 돌아가 수정해주세요.
```

---

## 6. 주의사항 및 문제 해결

### 6.1 프롬프트 사용 시 주의사항

### 1. 순서대로 진행

- **반드시 Step 1부터 Step 16까지 순서대로** 진행하세요

- 각 단계가 이전 단계에 의존합니다

- 단계를 건너뛰면 에러가 발생할 수 있습니다

### 2. 한 번에 하나씩

- 각 프롬프트를 **개별적으로** AI에게 전달하세요

- 이전 단계가 완료되고 검증된 후 다음 단계로 진행하세요

- 급하게 여러 단계를 건너뛰지 마세요

### 3. 에러 처리 강조

- 모든 프롬프트에 **AbortError 처리**가 포함되어 있습니다

- **permission-denied 처리**도 포함되어 있습니다

- 이 부분을 빠뜨리지 마세요

### 4. TypeScript 규칙 준수

- **React 17+ 이므로 **`**import React**`** 불필요**

- **type import는 **`**import type { ... }**`** 형식**

- **verbatimModuleSyntax 설정 준수**

### 5. 검증 필수

- 각 단계 후 `npm run build`로 빌드 테스트

- TypeScript 에러가 없는지 확인

- 브라우저 콘솔에서 런타임 에러 확인

---

### 6.2 일반적인 문제 해결

### TypeScript 에러

```
TS6133: 'React' is declared but never used
→ import React 제거

TS1484: 'ReactNode' must be imported using type-only import
→ import { type ReactNode } 사용

TS2307: Cannot find module
→ npm install 재실행
```

### Firebase 에러

```
permission-denied
→ Firestore 보안 규칙 확인 및 배포

AbortError in console
→ main.tsx의 3단계 차단 시스템 확인

Missing environment variables
→ .env.local 파일 생성 및 변수 설정
```

### 빌드 에러

```
Cannot resolve module
→ package.json 의존성 확인

TypeScript compilation errors
→ tsconfig.json 설정 확인
```

---

### 6.3 핵심 아키텍처 결정 사항

1. **AbortError 차단 시스템** (가장 중요!)

- 이 프로젝트의 가장 독특하고 중요한 부분입니다

- `main.tsx`에서 3단계 방어 시스템 구축

- Firebase의 정상적인 최적화 동작을 에러로 보이지 않게 처리

2. **Firestore 보안 규칙의 분리**

- `allow read` 대신 `allow list`와 `allow get` 분리

- 쿼리와 단일 문서 접근의 다른 권한 요구사항 반영

3. **로딩 상태 관리**

- 모든 비동기 작업에 로딩 상태 추가

- 중복 클릭/제출 방지

- 사용자 경험 개선

4. **실시간 동기화**

- Firestore의 `onSnapshot` 사용

- cleanup 함수로 메모리 누수 방지

- userId 기반 필터링

---

## 7. 배포 가이드

### 7.1 Netlify 배포

```
# 1. Git 저장소 생성
git init
git add .
git commit -m "Initial commit: Firebase Todo App"

# 2. GitHub에 푸시
git remote add origin <your-repo-url>
git push -u origin main

# 3. Netlify 설정
- Build command: npm run build
- Publish directory: dist
- Environment variables: VITE_* 변수들 설정
```

### 7.2 Firebase Hosting 배포

```
# 1. Firebase Hosting 초기화
npx firebase init hosting

# 2. 설정
- Public directory: dist
- Single-page app: Yes
- GitHub Actions: No (선택)

# 3. 빌드 및 배포
npm run build
npx firebase deploy --only hosting
```

---

## 8. 학습 포인트

이 Todo 앱을 통해 배울 수 있는 것:

### 8.1 Firebase 통합

- Authentication (이메일/비밀번호)

- Firestore 실시간 데이터베이스

- 보안 규칙 설정

### 8.2 React 고급 패턴

- Custom Hooks

- Context API

- 실시간 데이터 동기화

- 로딩 상태 관리

### 8.3 국제화 (i18n)

- 다국어 지원

- 브라우저 언어 자동 감지

- 동적 언어 전환

### 8.4 테마 관리

- 다크모드 구현

- localStorage 사용

- Context로 전역 상태 관리

### 8.5 에러 처리

- 전역 에러 핸들링

- Promise rejection 처리

- Firebase 특정 에러 처리

### 8.6 TypeScript

- 타입 안전성

- 인터페이스 설계

- 제네릭 사용

---

## 9. 개발 순서 요약

```
1. 프로젝트 초기화 (Vite + React + TS)
   ↓
2. Firebase 설정 (config, services, rules)
   ↓
3. Custom Hooks (useAuth, useTodos)
   ↓
4. Context (ThemeContext)
   ↓
5. i18n 설정 (다국어)
   ↓
6. Components (AddTodoForm, TodoItem, TodoList)
   ↓
7. Pages (LoginPage, HomePage)
   ↓
8. App 라우팅
   ↓
9. main.tsx (AbortError 차단 시스템 포함)
   ↓
10. CSS 및 스타일링
   ↓
11. TypeScript 설정 검증
   ↓
12. Firebase 프로젝트 설정
   ↓
13. 빌드 및 테스트
```

---

## 10. 최종 체크리스트

### 기능 테스트

- [ ] 회원가입 정상 동작

- [ ] 로그인 정상 동작

- [ ] 로그아웃 정상 동작

- [ ] 작업 추가 정상 동작

- [ ] 작업 체크/언체크 정상 동작

- [ ] 작업 삭제 정상 동작

- [ ] 다크모드 토글 정상 동작

- [ ] 언어 전환 정상 동작

### 에러 테스트

- [ ] 로그인 시 콘솔 에러 없음

- [ ] 로그아웃 시 콘솔 에러 없음

- [ ] 작업 체크/언체크 시 콘솔 에러 없음

- [ ] 작업 삭제 시 콘솔 에러 없음

- [ ] 작업 추가 시 콘솔 에러 없음

- [ ] Firebase 보안 규칙 permission-denied 에러 없음

### 보안 테스트

- [ ] 로그인하지 않은 사용자는 데이터 접근 불가

- [ ] 사용자 A는 사용자 B의 작업을 볼 수 없음

- [ ] 사용자 A는 사용자 B의 작업을 수정/삭제할 수 없음

---

## 결론

이 설계도와 프롬프트 가이드를 사용하면 **처음부터 끝까지 오류 없이** Firebase Todo 앱을 만들 수 있습니다!

각 단계의 프롬프트를 순서대로 AI에게 제공하면, 체계적이고 안정적인 애플리케이션을 구축할 수 있습니다.

### 핵심 포인트

1. **순서대로** 진행하세요

2. **검증**을 빠뜨리지 마세요

3. **AbortError 차단 시스템**을 정확히 구현하세요

4. **TypeScript 규칙**을 준수하세요

5. **Firebase 보안 규칙**을 올바르게 설정하세요

---

**작성일**: 2025년 10월 18일
**작성자**: conanssam
**프로젝트**: todo-app
**버전**: 1.0

For the site tree, see the [root Markdown](https://slashpage.com/conanssam.md).
