diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..4dc96fd8 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,327 @@ +# 문서 인덱스 + +이 디렉토리는 AI 에이전트 및 개발자가 프로젝트를 이해하고 작업하는 데 필요한 구조화된 문서를 포함합니다. + +## 문서 간 의존 관계 요약 + +``` +[핵심 구조] +function-index.json → 기능 중심 데이터베이스 (기능명으로 관련 코드 검색) +project-structure.md → 파일 중심 인덱스 (파일 경로로 책임 확인) +architecture-guidelines.md → 원칙 중심 문서 (어떻게 코드를 작성할지) + +[보조 문서] +test-strategy.md → 테스트 작성 방법론 +tech-stack.md → 사용 기술 상세 설명 +prd-v2.md → function-index.json의 사람 친화적 버전 + +[의존 흐름] +1. 기능 작업 시: function-index.json → project-structure.md → 실제 코드 +2. 새 파일 생성 시: architecture-guidelines.md → project-structure.md +3. 테스트 작성 시: test-strategy.md → function-index.json (기존 패턴 참조) +``` + +--- + +## 문서 분류 태그 + +각 문서는 주 대상 사용자에 따라 태그로 분류됩니다: + +- **[AI]**: AI 에이전트가 파싱하여 사용하기 최적화된 문서 (구조화된 데이터) +- **[HUMAN]**: 사람이 읽기 위한 문서 (상세 설명 및 맥락 포함) +- **[AI/HUMAN]**: AI와 사람 모두 활용 가능한 문서 (규칙 및 가이드라인) +- **[ARCHIVE]**: 참고용 아카이브 문서 + +--- + +## 문서 목록 및 역할 + +### 1. `function-index.json` [AI] ⭐ + +**용도**: 기능별 코드 매핑 - AI 에이전트가 특정 기능을 수정/확장할 때 참조 + +**내용**: + +- 7개 기능 (일정 CRUD, 캘린더 뷰, 검색, 충돌 감지, 알림, 공휴일, 반복 일정) +- 각 기능별 관련 파일, API 엔드포인트, 내부 의존성, 테스트 파일, 구현 상태 + +**형식**: JSON (프로그래밍 방식으로 파싱 가능) + +**활용 시나리오**: + +- "일정 CRUD 기능을 수정해줘" → `function-index.json`에서 "일정 CRUD" 검색 → 관련 파일 목록 확인 +- "알림 시스템 테스트 추가해줘" → 기존 테스트 파일 패턴 확인 +- "검색 기능이 어떤 API를 사용하는지 확인" → api 필드 확인 + +**JSON 스키마**: + +```typescript +{ + "features": [ + { + "name": string, // 기능명 (예: "일정 CRUD") + "purpose": string, // 기능 목적 한 줄 설명 + "files": [ // 이 기능의 핵심 구현 파일들 + { + "path": string, // 파일 경로 (예: "src/hooks/useEventOperations.ts") + "role": string // 이 파일이 기능에서 하는 역할 + } + ], + "api": [ // 관련 API 엔드포인트 (없으면 빈 배열) + { + "method": "GET" | "POST" | "PUT" | "DELETE", + "endpoint": string, // API 경로 (예: "/api/events") + "description": string // API 역할 설명 + } + ], + "internalDependencies": [ // src/ 내부의 공용 의존 모듈들 + { + "path": string, // 의존 모듈 경로 + "description": string // 왜 이 모듈에 의존하는지 설명 + } + ], + "tests": [ // 관련 테스트 파일들 (없으면 빈 배열) + { + "path": string, // 테스트 파일 경로 + "scope": string // 테스트 범위 설명 + } + ], + "status": "implemented" | "planned" // 구현 상태 + } + ] +} +``` + +--- + +### 2. `project-structure.md` [AI] ⭐ + +**용도**: 파일 트리 및 각 파일의 책임 + +**내용**: + +- src/ 디렉토리의 전체 구조 +- 각 파일의 한 줄 책임 설명 +- 폴더별 역할 구분 (apis, hooks, utils, **tests**, **mocks**) + +**형식**: Markdown + +**활용 시나리오**: + +- "프로젝트 구조를 보여줘" → 전체 파일 트리 확인 +- "날짜 관련 유틸리티 파일이 어디 있어?" → utils/dateUtils.ts 찾기 +- "테스트 파일은 어디에 있어?" → **tests** 디렉토리 확인 + +--- + +### 3. `architecture-guidelines.md` [AI/HUMAN] + +**용도**: 아키텍처 철학 및 개발 가이드라인 + +**내용**: + +- 아키텍처 레이어 (프레젠테이션, 상태 관리, 유틸리티, API, 타입, 테스트) +- 데이터 흐름 +- 설계 원칙 (관심사 분리, 단일 책임, 재사용성, 타입 안정성, 테스트 가능성) +- 명명 규칙 +- 코딩 컨벤션 + +**형식**: Markdown + +**활용 시나리오**: + +- "새로운 훅을 만들 때 어떤 규칙을 따라야 해?" → 명명 규칙 확인 +- "이 프로젝트의 설계 원칙은 뭐야?" → 설계 원칙 섹션 확인 +- "코딩 컨벤션은?" → 코딩 컨벤션 섹션 확인 + +--- + +### 4. `test-strategy.md` [AI/HUMAN] + +**용도**: 테스트 전략 및 작성 가이드 + +**내용**: + +- 테스트 피라미드 (단위/훅/통합 테스트) +- 테스트 범위 및 커버리지 목표 +- 테스트 난이도 분류 +- 테스트 도구 (Vitest, Testing Library, MSW) +- 테스트 작성 패턴 및 베스트 프랙티스 + +**형식**: Markdown + +**활용 시나리오**: + +- "테스트를 어떻게 작성해야 해?" → 테스트 작성 가이드 확인 +- "테스트 파일명은 어떻게 지어?" → 파일 명명 규칙 확인 +- "API 모킹은 어떻게 해?" → MSW 사용법 확인 + +--- + +### 5. `tech-stack.md` [HUMAN] + +**용도**: 사용 기술 스택 상세 정보 + +**내용**: + +- 프론트엔드 프레임워크 (React, TypeScript) +- UI 라이브러리 (Material-UI) +- 상태 관리 (React Hooks) +- 빌드 도구 (Vite) +- 테스트 도구 (Vitest, Testing Library, MSW) +- 의존성 목록 + +**형식**: Markdown + +**활용 시나리오**: + +- "이 프로젝트는 어떤 라이브러리를 사용해?" → 전체 기술 스택 확인 +- "Material-UI를 왜 선택했어?" → 사용 이유 확인 +- "새로운 의존성을 추가해도 돼?" → 현재 스택과의 호환성 검토 + +--- + +### 6. `prd-v2.md` [HUMAN] + +**용도**: 기능별 PRD 인덱스 (사람이 읽기 좋은 Markdown 버전) + +**내용**: + +- function-index.json과 동일한 내용을 Markdown 형식으로 작성 +- 각 기능의 목적, 관련 코드, API, 의존성, 테스트, 구현 상태 +- 프로젝트 구조 개요 + +**형식**: Markdown + +**활용 시나리오**: + +- 사람이 읽기 편한 형태로 기능 전체 개요 파악 +- function-index.json의 사람 친화적 버전 + +**참고**: AI 에이전트는 `function-index.json` 사용 권장 (파싱 용이) + +--- + +### 7. `prd-v1.md` [ARCHIVE] + +**용도**: 초기 기능 명세서 (아카이브) + +**내용**: + +- 프로젝트 초기 작성된 상세 기능 명세서 +- 개요, 핵심 기능, 데이터 모델, API 명세, 컴포넌트 구조, 기술 스택 등 + +**형식**: Markdown + +**활용 시나리오**: + +- 프로젝트 초기 기획 의도 확인 +- 상세한 기능 설명 참조 + +**참고**: 구조화된 정보는 function-index.json 및 architecture-guidelines.md 참조 권장 + +--- + +### 8. `agents/agent-constraints.md` [AI] ⭐ + +**용도**: AI 에이전트별 권한 및 제약사항 정의 + +**내용**: + +- 4가지 에이전트 역할 (테스트/구현/리뷰/리팩토링) +- 각 에이전트별 Input/Output 스키마 +- 수정 가능/금지 파일 목록 +- 필수 업데이트 규칙 및 체크리스트 +- 에이전트 간 협업 프로세스 + +**형식**: Markdown + +**활용 시나리오**: + +- "테스트 코드 작성할 때 어떤 파일 수정 가능해?" → Agent-Test 섹션 확인 +- "새 기능 구현 시 어떤 문서 업데이트 필요해?" → Agent-Implementation 섹션 확인 +- "리팩토링 시 지켜야 할 규칙은?" → Agent-Refactoring 섹션 확인 +- "코드리뷰 시 자동 거부 조건은?" → Agent-Review 섹션 확인 + +--- + +## AI 에이전트 사용 가이드 + +### 시나리오별 참조 문서 + +| 목적 | 참조 문서 | 순서 | +| ------------------------------ | ------------------------------------------------------------- | ------------- | +| 특정 기능 수정/확장 | `function-index.json` → `project-structure.md` | 1순위 | +| 파일 위치 찾기 | `project-structure.md` | 1순위 | +| 새 파일/함수 생성 시 명명 규칙 | `architecture-guidelines.md` | 1순위 | +| 테스트 작성 | `test-strategy.md` → `function-index.json` (기존 테스트 패턴) | 1순위 → 2순위 | +| 코딩 스타일 확인 | `architecture-guidelines.md` | 1순위 | +| 아키텍처 이해 | `architecture-guidelines.md` → `project-structure.md` | 1순위 → 2순위 | +| 기술 스택 확인 | `tech-stack.md` | 1순위 | +| 상세 기능 설명 | `prd-v2.md` 또는 `function-index.json` | 1순위 | + +### 권장 워크플로우 + +1. **초기 프로젝트 이해** + + ``` + README.md (현재 파일) + → architecture-guidelines.md (아키텍처 개요) + → project-structure.md (파일 구조) + → function-index.json (기능별 코드 매핑) + ``` + +2. **특정 기능 작업** + + ``` + function-index.json (기능 검색) + → 관련 파일 코드 읽기 + → 수정/확장 작업 + → architecture-guidelines.md (명명 규칙/컨벤션 확인) + ``` + +3. **새 기능 추가** + ``` + architecture-guidelines.md (설계 원칙/컨벤션) + → project-structure.md (파일 위치 결정) + → 코드 작성 + → function-index.json 업데이트 + ``` + +--- + +## 문서 유지보수 규칙 + +### 코드 변경 시 업데이트 필요 + +- 새 파일 추가 → `project-structure.md` 업데이트 +- 새 기능 추가 → `function-index.json` 및 `prd-v2.md` 업데이트 +- 아키텍처 변경 → `architecture-guidelines.md` 업데이트 + +### 문서 간 일관성 유지 + +- `function-index.json`과 `prd-v2.md`는 내용이 동일해야 함 (형식만 다름) +- `project-structure.md`의 파일 목록은 실제 코드베이스와 일치해야 함 +- `architecture-guidelines.md`의 규칙은 실제 코드에 반영되어야 함 + +--- + +## 문서 우선순위 + +### AI 에이전트용 (파싱 우선) + +1. `agents/agent-constraints.md` - **에이전트별 권한 및 제약사항** (필수) +2. `function-index.json` - 기능별 코드 매핑 +3. `project-structure.md` - 파일 구조 +4. `architecture-guidelines.md` - 아키텍처 및 컨벤션 +5. `test-strategy.md` - 테스트 전략 +6. `tech-stack.md` - 기술 스택 정보 + +### 사람용 (가독성 우선) + +1. `prd-v2.md` - 기능별 명세서 +2. `architecture-guidelines.md` - 아키텍처 가이드 +3. `test-strategy.md` - 테스트 가이드 +4. `tech-stack.md` - 기술 스택 설명 +5. `project-structure.md` - 파일 구조 +6. `prd-v1.md` - 초기 기획서 (참고용) diff --git a/docs/agents/agent-constraints.md b/docs/agents/agent-constraints.md new file mode 100644 index 00000000..4e64af9a --- /dev/null +++ b/docs/agents/agent-constraints.md @@ -0,0 +1,790 @@ +--- +**문서 유형**: [AI] +**목적**: AI 에이전트별 권한 및 제약사항 정의 +**주요 내용**: 역할별 수정 가능/금지 파일, Input/Output 스키마, 필수 업데이트 규칙 +**관련 문서**: [function-index.json](../function-index.json), [architecture-guidelines.md](../architecture-guidelines.md) +**최종 수정일**: 2025-10-30 +--- + +# AI 에이전트 제약사항 및 권한 + +## 에이전트 역할 정의 + +### 1. 테스트코드 에이전트 (Agent-Test) + +**책임**: 테스트 코드 작성 및 커버리지 관리 + +### 2. 기능 구현 에이전트 (Agent-Implementation) + +**책임**: 새로운 기능 구현 및 기존 기능 확장 + +### 3. 코드리뷰 에이전트 (Agent-Review) + +**책임**: 코드 품질 검증 및 규칙 준수 확인 + +### 4. 리팩토링 에이전트 (Agent-Refactoring) + +**책임**: 코드 구조 개선 및 최적화 + +--- + +## 공통 제약사항 + +### 절대 수정 금지 파일 + +``` +- src/setupTests.ts # 테스트 환경 설정 (모든 에이전트) +- src/vite-env.d.ts # Vite 타입 정의 (모든 에이전트) +- docs/README.md # 문서 인덱스는 수동 관리 +- docs/prd-v1.md # 아카이브 문서 +``` + +### 필수 업데이트 규칙 + +#### 새 파일 추가 시 + +1. `docs/project-structure.md`에 파일 추가 및 책임 설명 +2. `docs/function-index.json`의 해당 기능 `files` 배열에 추가 + +#### 새 기능 추가 시 + +1. `docs/function-index.json`에 새 feature 객체 추가 +2. 관련 API가 있다면 `api` 배열 작성 +3. 테스트 파일 `tests` 배열에 등록 + +#### 파일 이동/삭제 시 + +1. `docs/project-structure.md` 업데이트 +2. `docs/function-index.json`의 모든 경로 업데이트 +3. import 경로 일괄 변경 + +--- + +## 1. 테스트코드 에이전트 (Agent-Test) + +### Input Schema + +```typescript +{ + featureName: string; // 기능명 (예: "일정 CRUD") + testType: "unit" | "hook" | "integration"; + targetFile: string; // 테스트 대상 파일 + testScenarios: string[]; // 테스트할 시나리오 목록 +} +``` + +### Output Schema + +```typescript +{ + testFilePath: string; // 생성된 테스트 파일 경로 + testCode: string; // 테스트 코드 + coverage: { + statements: number; + branches: number; + functions: number; + lines: number; + }; + updatedDocs: string[]; // 업데이트한 문서 목록 +} +``` + +### 수정 권한 + +#### ✅ 수정 가능 + +``` +src/__tests__/** # 모든 테스트 파일 +src/__mocks__/response/** # 테스트 데이터 추가 +``` + +#### ⚠️ 조건부 수정 + +``` +src/__mocks__/handlers.ts # 새 API 핸들러 추가만 가능 (기존 수정 금지) +src/__mocks__/handlersUtils.ts # 헬퍼 함수 추가만 가능 +``` + +#### ❌ 수정 금지 + +``` +src/setupTests.ts # 테스트 환경 설정 +src/**/*.ts (테스트 파일 제외) # 실제 구현 코드 +``` + +### 필수 준수 사항 + +1. **파일 명명 규칙** + + - `{난이도}.{대상}.spec.{ts|tsx}` + - 난이도: `easy` (단순) | `medium` (복잡) + - 예: `easy.dateUtils.spec.ts`, `medium.integration.spec.tsx` + +2. **테스트 위치** + + - 단위 테스트: `src/__tests__/unit/` + - 훅 테스트: `src/__tests__/hooks/` + - 통합 테스트: `src/__tests__/` + +3. **필수 업데이트** + - `docs/function-index.json`의 해당 기능 `tests` 배열에 추가: + ```json + { + "path": "src/__tests__/unit/easy.newUtil.spec.ts", + "scope": "newUtil 함수 단위 테스트" + } + ``` + +### 체크리스트 + +**작업 전** + +- [ ] `docs/test-strategy.md`의 테스트 작성 패턴 확인 +- [ ] `docs/function-index.json`에서 기존 테스트 패턴 참조 +- [ ] 테스트할 코드의 책임 범위 확인 + +**작업 후** + +- [ ] 모든 테스트 통과 확인 +- [ ] `docs/function-index.json` 업데이트 +- [ ] 커버리지 목표 달성 확인 (유틸: 90%+, 훅: 80%+) + +--- + +## 2. 기능 구현 에이전트 (Agent-Implementation) + +### Input Schema + +```typescript +{ + featureName: string; // 기능명 + featureType: "hook" | "util" | "api" | "component"; + requirements: string; // 요구사항 (자연어) + relatedFeatures: string[]; // 의존하는 다른 기능 + apiEndpoints?: { // 필요한 API (선택) + method: string; + endpoint: string; + description: string; + }[]; +} +``` + +### Output Schema + +```typescript +{ + createdFiles: string[]; // 생성된 파일 목록 + modifiedFiles: string[]; // 수정된 파일 목록 + typesAdded: string; // types.ts에 추가한 타입 + impactAnalysis: { + affectedFeatures: string[]; // 영향받는 기능 + breakingChanges: boolean; // 하위 호환성 깨짐 여부 + }; + updatedDocs: string[]; // 업데이트한 문서 목록 +} +``` + +### 수정 권한 + +#### ✅ 수정 가능 + +``` +src/hooks/** # 커스텀 훅 +src/utils/** # 유틸리티 함수 +src/apis/** # API 함수 +src/App.tsx # 메인 컴포넌트 +src/types.ts # 타입 정의 (추가만) +``` + +#### ⚠️ 조건부 수정 + +``` +src/types.ts # 기존 타입 수정 시 하위 호환성 필수 +src/main.tsx # 전역 설정 변경 시만 +``` + +#### ❌ 수정 금지 + +``` +src/__tests__/** # 테스트는 Agent-Test 담당 +src/__mocks__/** # 목 데이터는 Agent-Test 담당 +``` + +### 파일 생성 규칙 + +#### hooks/ 디렉토리 + +```typescript +// 명명: use + PascalCase +// 예: useNewFeature.ts + +export const useNewFeature = () => { + // 1. 다른 훅 import 가능 + // 2. 컴포넌트 import 금지 + // 3. 부수 효과는 useEffect 내부에서만 + + return { + /* 훅 반환값 */ + }; +}; +``` + +#### utils/ 디렉토리 + +```typescript +// 명명: camelCase +// 예: newHelper.ts + +// ✅ 순수 함수만 +export function newHelper(input: string): string { + // 부수 효과 금지 + // API 호출 금지 + // 전역 상태 변경 금지 + return result; +} + +// ❌ 금지 패턴 +export function badHelper() { + fetch('/api/data'); // API 호출 금지 + window.location.href = '/'; // 부수 효과 금지 +} +``` + +#### apis/ 디렉토리 + +```typescript +// 명명: fetch + PascalCase +// 예: fetchNewData.ts + +export async function fetchNewData(): Promise { + // 반환 타입 명시 필수 + const response = await fetch('/api/new-data'); + return response.json(); +} +``` + +### 필수 준수 사항 + +1. **명명 규칙** (`docs/architecture-guidelines.md` 참조) + + - 파일명: camelCase (utils), PascalCase (components) + - 함수명: camelCase, 동사로 시작 + - 타입명: PascalCase + - 상수명: UPPER_SNAKE_CASE + +2. **타입 안정성** + + - `any` 타입 사용 금지 + - 모든 함수 반환 타입 명시 + - Strict mode 준수 + +3. **설계 원칙** (`docs/architecture-guidelines.md` 참조) + + - 단일 책임 원칙 + - 순수 함수 우선 (utils/) + - 관심사의 분리 + +4. **필수 업데이트** + - `docs/project-structure.md`: 새 파일 추가 + - `docs/function-index.json`: 새 기능 또는 files 배열 업데이트 + - 타입 변경 시: 영향받는 모든 기능 확인 + +### 영향 범위 분석 절차 + +새 파일 생성 시: + +1. `docs/function-index.json`에서 관련 기능 찾기 +2. `internalDependencies`에 추가할지 결정 +3. 여러 기능에서 사용될 가능성 평가 + +기존 파일 수정 시: + +1. `docs/function-index.json`에서 해당 파일을 사용하는 모든 기능 검색 +2. 각 기능의 영향 범위 확인 +3. 하위 호환성 검토 + +### 체크리스트 + +**작업 전** + +- [ ] `docs/function-index.json`에서 기능 구조 확인 +- [ ] `docs/architecture-guidelines.md`에서 규칙 확인 +- [ ] 의존하는 기능의 API 확인 + +**작업 후** + +- [ ] 린트 에러 없음 +- [ ] 타입 에러 없음 +- [ ] `docs/project-structure.md` 업데이트 +- [ ] `docs/function-index.json` 업데이트 +- [ ] 영향받는 기능 목록 작성 + +--- + +## 3. 코드리뷰 에이전트 (Agent-Review) + +### Input Schema + +```typescript +{ + changedFiles: string[]; // 변경된 파일 목록 + diff: string; // 변경 내용 + changeReason: string; // 변경 이유 + author: "Agent-Implementation" | "Agent-Test" | "Agent-Refactoring"; +} +``` + +### Output Schema + +```typescript +{ + approved: boolean; // 승인 여부 + violations: { + file: string; + rule: string; // 위반한 규칙 + violation: string; // 위반 내용 + suggestion: string; // 수정 제안 + severity: "error" | "warning" | "info"; + }[]; + impactAnalysis: { + affectedFiles: string[]; // 영향받는 파일 + affectedFeatures: string[]; // 영향받는 기능 + breakingChange: boolean; // 하위 호환성 + }; + docsUpdated: boolean; // 문서 업데이트 여부 +} +``` + +### 리뷰 권한 + +#### ✅ 검토 대상 + +``` +src/**/*.{ts,tsx} # 모든 소스 코드 +docs/function-index.json # 기능 인덱스 +docs/project-structure.md # 프로젝트 구조 +``` + +#### 수정 불가 + +- 리뷰 에이전트는 코드 수정 권한 없음 +- 오직 승인/거부 및 피드백만 제공 + +### 자동 거부 조건 (Error) + +```typescript +const autoReject = [ + 'any 타입 사용', + 'utils/ 디렉토리에 부수 효과 있는 함수', + '테스트 없이 새 public 함수 추가', + 'function-index.json 미업데이트 (새 기능 추가 시)', + 'project-structure.md 미업데이트 (새 파일 추가 시)', + '린트 에러 존재', + '타입 에러 존재', +]; +``` + +### 경고 조건 (Warning) + +```typescript +const warnings = [ + '100줄 이상의 컴포넌트/함수', + '5개 이상의 함수 파라미터', + '3단계 이상 중첩된 조건문', + '순환 의존성 감지', + '주석 없는 복잡한 로직', + 'TODO/FIXME 주석 존재', +]; +``` + +### 리뷰 체크리스트 + +#### 1. 명명 규칙 (`docs/architecture-guidelines.md`) + +- [ ] 파일명이 규칙에 맞는가? +- [ ] 변수/함수명이 camelCase인가? +- [ ] 타입명이 PascalCase인가? +- [ ] boolean 변수가 is/has prefix를 사용하는가? + +#### 2. 타입 안정성 + +- [ ] any 타입 사용 여부 +- [ ] 모든 함수에 반환 타입 명시 +- [ ] 암묵적 타입 추론이 명확한가? + +#### 3. 설계 원칙 + +- [ ] 단일 책임 원칙 준수 +- [ ] utils/는 순수 함수인가? +- [ ] 관심사가 적절히 분리되었는가? + +#### 4. 테스트 + +- [ ] 새 함수에 대한 테스트가 있는가? +- [ ] 기존 테스트가 여전히 통과하는가? + +#### 5. 문서 + +- [ ] `project-structure.md` 업데이트 (새 파일) +- [ ] `function-index.json` 업데이트 (새 기능/파일) +- [ ] 복잡한 로직에 주석이 있는가? + +#### 6. 영향 범위 + +- [ ] 공용 모듈 변경인가? +- [ ] 타입 변경이 다른 파일에 영향을 주는가? +- [ ] API 변경이 있는가? +- [ ] 하위 호환성이 유지되는가? + +### 영향 범위 분석 방법 + +```typescript +// 1. function-index.json에서 영향받는 기능 찾기 +function findAffectedFeatures(changedFile: string): string[] { + const features = readFunctionIndex(); + return features + .filter( + (f) => + f.files.some((file) => file.path === changedFile) || + f.internalDependencies.some((dep) => dep.path === changedFile) + ) + .map((f) => f.name); +} + +// 2. 각 기능의 모든 관련 파일 확인 +function findAffectedFiles(featureNames: string[]): string[] { + const features = readFunctionIndex(); + return features + .filter((f) => featureNames.includes(f.name)) + .flatMap((f) => f.files.map((file) => file.path)); +} +``` + +### 리뷰 프로세스 + +``` +1. 변경 파일 목록 확인 + ↓ +2. 각 파일에 대해 자동 거부 조건 검사 + ↓ +3. 경고 조건 검사 + ↓ +4. function-index.json에서 영향받는 기능 찾기 + ↓ +5. 문서 업데이트 여부 확인 + ↓ +6. 승인/거부 결정 및 피드백 생성 +``` + +--- + +## 4. 리팩토링 에이전트 (Agent-Refactoring) + +### Input Schema + +```typescript +{ + targetType: 'file' | 'function' | 'feature'; + targetPath: string; // 대상 경로 + refactoringType: 'rename' | 'move' | 'extract' | 'inline' | 'optimize'; + reason: 'performance' | 'readability' | 'maintainability'; + keepCompatibility: boolean; // 하위 호환성 유지 여부 +} +``` + +### Output Schema + +```typescript +{ + modifiedFiles: string[]; // 수정된 파일 + movedCode: { + from: string; + to: string; + }[]; + typeChanges: { + before: string; + after: string; + }[]; + impactAnalysis: { + affectedFeatures: string[]; // 영향받는 기능 + affectedTests: string[]; // 영향받는 테스트 + breakingChange: boolean; // 하위 호환성 + }; + migrationGuide?: string; // 마이그레이션 가이드 (breaking change 시) + updatedDocs: string[]; // 업데이트한 문서 +} +``` + +### 수정 권한 + +#### ✅ 수정 가능 + +``` +src/hooks/** # 내부 구현 리팩토링 +src/utils/** # 내부 구현 리팩토링 +src/apis/** # 내부 구현 리팩토링 +src/App.tsx # 컴포넌트 구조 개선 +``` + +#### ⚠️ 조건부 수정 + +``` +src/types.ts # public 타입 변경 시 하위 호환성 필수 +export된 함수 시그니처 # 기존 사용처 모두 업데이트 필요 +``` + +#### ❌ 수정 금지 + +``` +public API 시그니처 (하위 호환성 깨는 변경) +테스트 결과를 변경시키는 리팩토링 +``` + +### 절대 불변 규칙 + +#### 1. Public API 하위 호환성 + +```typescript +// ❌ 금지: 기존 함수 시그니처 변경 +// Before +export function getData(id: string): Data; + +// After (Breaking Change!) +export function getData(id: number): Data; + +// ✅ 허용: 오버로드 추가 +export function getData(id: string): Data; +export function getData(id: number): Data; +export function getData(id: string | number): Data { + // ... +} +``` + +#### 2. Export된 타입 변경 + +```typescript +// ❌ 금지: 기존 속성 제거/이름 변경 +export interface Event { + id: string; + title: string; // 이 필드 제거 금지 +} + +// ✅ 허용: 새 속성 추가 (optional) +export interface Event { + id: string; + title: string; + subtitle?: string; // optional 추가는 OK +} +``` + +#### 3. 테스트 결과 + +- 리팩토링 전후 모든 테스트가 동일하게 통과해야 함 +- 테스트 실패 시 리팩토링 롤백 + +### 리팩토링 전 필수 체크리스트 + +```typescript +// 1. 영향 범위 분석 +const impactAnalysis = { + // function-index.json에서 찾기 + affectedFeatures: findFeaturesUsingFile(targetFile), + + // grep으로 실제 import 문 찾기 + realDependencies: grepImports(targetFile), + + // 테스트 파일 의존성 + affectedTests: findTestsFor(targetFile), +}; + +// 2. 하위 호환성 체크 +const compatibilityCheck = { + isPublicAPI: isExportedFunction(targetFunction), + isUsedByMultipleFeatures: impactAnalysis.affectedFeatures.length > 1, + hasExternalDependents: checkExternalUsage(targetFile), +}; + +// 3. 테스트 커버리지 확인 +const testCoverage = getTestCoverage(targetFile); +if (testCoverage < 80) { + throw new Error('리팩토링 전 테스트 커버리지 80% 이상 필요'); +} +``` + +### 리팩토링 유형별 규칙 + +#### 1. 파일 이동 (move) + +```typescript +// 필수 업데이트 +const updates = [ + 'docs/project-structure.md', // 파일 경로 변경 + 'docs/function-index.json', // 모든 경로 업데이트 + '모든 import 문', // 일괄 변경 + '관련 테스트의 import 경로', +]; +``` + +#### 2. 함수 추출 (extract) + +```typescript +// 기존 함수에서 로직 분리 +// ✅ 허용: private 헬퍼 함수 추출 +function complexFunction() { + const result = helperFunction(); // 추출된 함수 + // ... +} + +function helperFunction() { + // 새로 추출된 함수 (export 안 함) + // ... +} +``` + +#### 3. 함수 병합 (inline) + +```typescript +// 작은 함수를 호출 지점에 병합 +// ✅ 허용: 한 곳에서만 사용되는 함수 +// ❌ 금지: 여러 곳에서 사용되는 함수 +``` + +#### 4. 이름 변경 (rename) + +```typescript +// ✅ 허용: 내부 변수/함수 +// ⚠️ 주의: export된 함수 (모든 사용처 변경 필요) +// ❌ 금지: public API 함수 (하위 호환성) +``` + +### 리팩토링 프로세스 + +``` +1. 리팩토링 대상 분석 + ↓ +2. function-index.json에서 영향 범위 확인 + ↓ +3. 테스트 커버리지 확인 (80% 이상) + ↓ +4. 모든 기존 테스트 실행 (Before) + ↓ +5. 리팩토링 실행 + ↓ +6. 모든 테스트 실행 (After) - 동일한 결과 확인 + ↓ +7. 영향받는 파일들 업데이트 + ↓ +8. 문서 업데이트 + ↓ +9. 린트/타입 체크 + ↓ +10. Agent-Review에게 제출 +``` + +### 필수 업데이트 문서 + +#### 파일 이동 시 + +``` +- docs/project-structure.md +- docs/function-index.json (모든 경로) +``` + +#### 공용 모듈 변경 시 + +``` +- docs/function-index.json의 internalDependencies +- 영향받는 모든 기능의 files 배열 +``` + +#### Breaking Change 시 + +``` +- CHANGELOG.md에 마이그레이션 가이드 작성 +- 영향받는 기능 목록 문서화 +``` + +### 체크리스트 + +**리팩토링 전** + +- [ ] 테스트 커버리지 80% 이상 +- [ ] 모든 테스트 통과 확인 +- [ ] 영향 범위 분석 완료 +- [ ] 하위 호환성 체크 완료 + +**리팩토링 중** + +- [ ] 단계별 커밋 +- [ ] 테스트 결과 모니터링 + +**리팩토링 후** + +- [ ] 모든 테스트 통과 (Before와 동일) +- [ ] 린트/타입 에러 없음 +- [ ] import 경로 모두 업데이트 +- [ ] 문서 모두 업데이트 +- [ ] Agent-Review 승인 획득 + +--- + +## 문서 업데이트 우선순위 + +### Priority 1 (필수) + +``` +docs/function-index.json # 모든 에이전트 +docs/project-structure.md # 파일 변경 시 +``` + +### Priority 2 (권장) + +``` +docs/architecture-guidelines.md # 규칙 변경 시 +docs/test-strategy.md # 테스트 패턴 변경 시 +``` + +### Priority 3 (선택) + +``` +docs/tech-stack.md # 새 의존성 추가 시 +docs/prd-v2.md # 기능 설명 보완 시 +``` + +--- + +## 에이전트 간 협업 프로세스 + +``` +[Agent-Implementation] + ↓ 구현 완료 +[Agent-Test] + ↓ 테스트 추가 +[Agent-Review] + ↓ 승인/거부 +[Agent-Refactoring] (필요 시) + ↓ 최적화 +[Agent-Review] + ↓ 최종 승인 +[Deploy] +``` + +--- + +## 충돌 해결 규칙 + +### 동일 파일 수정 시 + +1. function-index.json: 마지막 에이전트가 병합 +2. 실제 코드: Agent-Review가 판단 +3. 문서: 각 에이전트가 자신의 섹션만 수정 + +### 우선순위 + +``` +1. Agent-Review (최종 결정권) +2. Agent-Implementation (기능 변경) +3. Agent-Refactoring (구조 변경) +4. Agent-Test (테스트 추가) +``` + diff --git a/docs/architecture-guidelines.md b/docs/architecture-guidelines.md new file mode 100644 index 00000000..cd754b9c --- /dev/null +++ b/docs/architecture-guidelines.md @@ -0,0 +1,158 @@ +--- +**문서 유형**: [AI/HUMAN] +**목적**: 아키텍처 철학 및 개발 가이드라인 +**주요 내용**: 레이어 구조, 설계 원칙, 명명 규칙, 코딩 컨벤션 +**관련 문서**: [test-strategy.md](./test-strategy.md), [tech-stack.md](./tech-stack.md) +**최종 수정일**: 2025-10-29 +--- + +# 아키텍처 가이드라인 + +## 아키텍처 레이어 + +### 1. 프레젠테이션 레이어 (Presentation Layer) + +- **역할**: UI 렌더링 및 사용자 인터랙션 처리 +- **특징**: React 함수형 컴포넌트로 구성, Material-UI 사용 +- **구성**: 일정 입력 폼, 캘린더 그리드(월간/주간), 일정 목록, 다이얼로그, 알림 패널 + +### 2. 상태 관리 레이어 (State Management Layer) + +- **역할**: 비즈니스 로직 및 애플리케이션 상태 관리 +- **특징**: 커스텀 훅으로 관심사 분리, React Hooks(useState, useEffect, useMemo) 활용 +- **구성**: 캘린더 뷰 관리, 일정 CRUD, 폼 상태, 검색/필터링, 알림 시스템 + +### 3. 유틸리티 레이어 (Utility Layer) + +- **역할**: 순수 함수로 구성된 재사용 가능한 공통 로직 +- **특징**: 부수 효과 없음, 테스트 용이성 높음 +- **구성**: 날짜 계산, 시간 유효성 검사, 일정 검색/필터링, 중복 감지, 알림 메시지 생성 + +### 4. API 레이어 (API Layer) + +- **역할**: 외부 데이터 소스와의 통신 +- **특징**: REST API 호출, 공휴일 데이터 제공 +- **구성**: 일정 CRUD API, 공휴일 데이터 조회 + +### 5. 타입 정의 레이어 (Type Definition Layer) + +- **역할**: 애플리케이션 전역 타입 시스템 정의 +- **특징**: TypeScript 타입 안전성 보장 +- **구성**: Event, EventForm, RepeatInfo, RepeatType 등 + +### 6. 테스트 레이어 (Test Layer) + +- **역할**: 코드 품질 보장 및 회귀 방지 +- **특징**: 단위/통합 테스트로 구성, MSW로 API 모킹 +- **구성**: 유틸리티 단위 테스트, 훅 테스트, 통합 테스트 + +## 데이터 흐름 + +``` +사용자 인터랙션 + ↓ +프레젠테이션 레이어 (컴포넌트) + ↓ +상태 관리 레이어 (커스텀 훅) + ↓ +유틸리티 레이어 (순수 함수) + ↓ +API 레이어 (fetch 호출) + ↓ +상태 업데이트 (useState) + ↓ +UI 리렌더링 (React) +``` + +## 설계 원칙 + +### 1. 관심사의 분리 (Separation of Concerns) + +- UI, 비즈니스 로직, 유틸리티를 명확히 분리 +- 각 레이어는 독립적으로 개발 및 테스트 가능 +- 컴포넌트는 UI에만 집중, 로직은 훅으로 분리 + +### 2. 단일 책임 원칙 (Single Responsibility Principle) + +- 각 파일과 함수는 하나의 명확한 책임만 가짐 +- 유틸리티 함수는 순수 함수로 작성 +- 훅은 특정 도메인 로직만 담당 + +### 3. 재사용성 (Reusability) + +- 커스텀 훅으로 로직 재사용 +- 유틸리티 함수로 공통 로직 추출 +- 타입 정의를 통한 인터페이스 통일 + +### 4. 타입 안정성 (Type Safety) + +- TypeScript로 모든 코드 작성 +- 명시적 타입 정의로 런타임 에러 방지 +- any 타입 사용 금지 + +### 5. 테스트 가능성 (Testability) + +- 순수 함수 우선 설계 +- 의존성 주입으로 테스트 용이성 확보 +- 단위 테스트와 통합 테스트 조합 + +> **참고**: 상세한 테스트 전략은 [test-strategy.md](./test-strategy.md) 참조 + +## 명명 규칙 + +### 파일명 + +- **컴포넌트**: PascalCase (예: App.tsx) +- **훅**: camelCase with `use` prefix (예: useCalendarView.ts) +- **유틸리티**: camelCase (예: dateUtils.ts) +- **타입**: camelCase (예: types.ts) +- **테스트**: 난이도 prefix + 대상 + `.spec.ts/tsx` (예: easy.dateUtils.spec.ts) + +### 변수/함수명 + +- **변수**: camelCase (예: currentDate, searchTerm) +- **함수**: camelCase, 동사로 시작 (예: getWeekDates, formatMonth) +- **상수**: UPPER_SNAKE_CASE (예: HOLIDAY_RECORD) +- **타입/인터페이스**: PascalCase (예: Event, EventForm) +- **boolean 변수**: is/has prefix (예: isRepeating, hasError) + +### 훅 명명 규칙 + +- 항상 `use`로 시작 +- 훅의 목적을 명확히 표현 (예: useEventOperations, useNotifications) + +> **참고**: 기술 스택 상세 정보는 [tech-stack.md](./tech-stack.md) 참조 + +## 코딩 컨벤션 + +### TypeScript + +- Strict mode 활성화 +- 명시적 타입 정의 우선 +- any 타입 사용 금지 +- 인터페이스보다 타입 별칭 선호 (일관성 있게 사용) + +### React + +- 함수형 컴포넌트 사용 +- Hooks 사용 권장 +- Props drilling 최소화 +- 컴포넌트 분리를 통한 재사용성 확보 + +### 스타일링 + +- Material-UI의 `sx` prop 사용 +- 인라인 스타일링 선호 +- 반응형 디자인 고려 + +### 에러 처리 + +- API 호출은 try-catch로 래핑 +- 에러 발생 시 사용자에게 알림 표시 (notistack) +- 콘솔 에러 로깅 + +### 접근성 + +- aria-label 속성 사용 +- 시맨틱 HTML 사용 +- 키보드 네비게이션 지원 diff --git a/docs/function-index.json b/docs/function-index.json new file mode 100644 index 00000000..266cc989 --- /dev/null +++ b/docs/function-index.json @@ -0,0 +1,262 @@ +{ + "_meta": { + "documentType": "AI", + "purpose": "기능별 코드 매핑 데이터베이스", + "description": "각 기능의 관련 파일, API, 의존성, 테스트를 구조화하여 제공. AI 에이전트가 특정 기능 수정/확장 시 필수 참조.", + "relatedDocuments": ["project-structure.md", "test-strategy.md"], + "lastUpdated": "2025-10-29" + }, + "features": [ + { + "name": "일정 CRUD", + "purpose": "사용자가 일정을 생성, 조회, 수정, 삭제할 수 있게 한다.", + "files": [ + { + "path": "src/hooks/useEventOperations.ts", + "role": "일정 목록 로드 및 생성/수정/삭제 API 호출" + }, + { + "path": "src/hooks/useEventForm.ts", + "role": "일정 폼 상태 관리 및 편집 모드 전환" + }, + { + "path": "src/App.tsx", + "role": "일정 폼 UI 렌더링 및 저장 이벤트 핸들링" + }, + { + "path": "src/types.ts", + "role": "Event, EventForm 타입 정의" + } + ], + "api": [ + { "method": "GET", "endpoint": "/api/events", "description": "일정 목록 조회" }, + { "method": "POST", "endpoint": "/api/events", "description": "일정 생성" }, + { "method": "PUT", "endpoint": "/api/events/:id", "description": "일정 수정" }, + { "method": "DELETE", "endpoint": "/api/events/:id", "description": "일정 삭제" } + ], + "internalDependencies": [ + { + "path": "src/utils/timeValidation.ts", + "description": "폼 입력 시 시작/종료 시간 유효성 검사" + }, + { + "path": "src/utils/eventOverlap.ts", + "description": "일정 저장 전 기존 일정과의 시간 충돌 여부 확인" + } + ], + "tests": [ + { + "path": "src/__tests__/hooks/medium.useEventOperations.spec.ts", + "scope": "일정 CRUD API 호출 및 상태 관리 통합 테스트" + }, + { + "path": "src/__tests__/medium.integration.spec.tsx", + "scope": "일정 추가/수정/삭제 E2E 통합 테스트" + }, + { + "path": "src/__tests__/unit/easy.timeValidation.spec.ts", + "scope": "시간 유효성 검사 로직 단위 테스트" + } + ], + "status": "implemented" + }, + { + "name": "캘린더 뷰 (월간/주간)", + "purpose": "사용자가 월간 또는 주간 단위로 일정을 시각적으로 확인하고 네비게이션할 수 있게 한다.", + "files": [ + { + "path": "src/hooks/useCalendarView.ts", + "role": "뷰 모드 상태 관리(월/주) 및 날짜 네비게이션 로직" + }, + { + "path": "src/App.tsx", + "role": "renderWeekView, renderMonthView 함수로 캘린더 그리드 렌더링" + }, + { + "path": "src/utils/dateUtils.ts", + "role": "주/월 날짜 배열 계산 및 포맷팅" + } + ], + "api": [], + "internalDependencies": [ + { + "path": "src/utils/dateUtils.ts", + "description": "주간/월간 날짜 범위 계산 및 포맷팅" + }, + { + "path": "src/apis/fetchHolidays.ts", + "description": "월간 뷰에서 표시할 공휴일 데이터 조회" + } + ], + "tests": [ + { + "path": "src/__tests__/hooks/easy.useCalendarView.spec.ts", + "scope": "캘린더 뷰 상태 및 네비게이션 로직 단위 테스트" + }, + { + "path": "src/__tests__/unit/easy.dateUtils.spec.ts", + "scope": "날짜 계산 및 포맷팅 함수 단위 테스트" + } + ], + "status": "implemented" + }, + { + "name": "일정 검색", + "purpose": "사용자가 제목, 설명, 위치를 기반으로 일정을 실시간 검색하고 필터링할 수 있게 한다.", + "files": [ + { + "path": "src/hooks/useSearch.ts", + "role": "검색어 상태 관리 및 필터링된 일정 목록 계산" + }, + { + "path": "src/utils/eventUtils.ts", + "role": "텍스트 검색 및 날짜 범위 필터링 로직" + }, + { + "path": "src/App.tsx", + "role": "검색 입력창 렌더링 및 검색 결과 표시" + } + ], + "api": [], + "internalDependencies": [ + { + "path": "src/utils/eventUtils.ts", + "description": "텍스트 검색 및 뷰에 따른 날짜 범위 필터링" + }, + { + "path": "src/utils/dateUtils.ts", + "description": "주간/월간 날짜 범위 계산" + } + ], + "tests": [ + { + "path": "src/__tests__/hooks/easy.useSearch.spec.ts", + "scope": "검색 훅 로직 단위 테스트" + }, + { + "path": "src/__tests__/unit/easy.eventUtils.spec.ts", + "scope": "검색 및 필터링 함수 단위 테스트" + } + ], + "status": "implemented" + }, + { + "name": "일정 충돌 감지", + "purpose": "동일 날짜에 시간이 겹치는 일정이 있을 경우 사용자에게 경고하여 스케줄 충돌을 방지한다.", + "files": [ + { + "path": "src/utils/eventOverlap.ts", + "role": "일정 시간 중복 감지 로직 (start1 < end2 && start2 < end1)" + }, + { + "path": "src/App.tsx", + "role": "중복 경고 다이얼로그 표시 및 사용자 확인 처리" + } + ], + "api": [], + "internalDependencies": [ + { + "path": "src/utils/eventOverlap.ts", + "description": "두 일정의 시간 범위 중복 여부 계산" + } + ], + "tests": [ + { + "path": "src/__tests__/unit/easy.eventOverlap.spec.ts", + "scope": "일정 중복 감지 알고리즘 단위 테스트" + } + ], + "status": "implemented" + }, + { + "name": "알림 시스템", + "purpose": "일정 시작 전 설정된 시간(1분/10분/1시간/2시간/1일 전)에 사용자에게 알림을 표시한다.", + "files": [ + { + "path": "src/hooks/useNotifications.ts", + "role": "1초마다 upcoming 일정 체크 및 알림 상태 관리" + }, + { + "path": "src/utils/notificationUtils.ts", + "role": "알림 대상 일정 필터링 및 메시지 생성" + }, + { + "path": "src/App.tsx", + "role": "알림 패널 렌더링 및 알림된 일정 강조 표시" + } + ], + "api": [], + "internalDependencies": [ + { + "path": "src/utils/notificationUtils.ts", + "description": "현재 시간 기준 알림 시간 도달 여부 계산 및 메시지 포맷팅" + } + ], + "tests": [ + { + "path": "src/__tests__/hooks/medium.useNotifications.spec.ts", + "scope": "알림 트리거 및 상태 관리 통합 테스트" + }, + { + "path": "src/__tests__/unit/easy.notificationUtils.spec.ts", + "scope": "알림 유틸리티 함수 단위 테스트" + } + ], + "status": "implemented" + }, + { + "name": "공휴일 표시", + "purpose": "월간 뷰에서 한국 공휴일을 빨간색으로 표시하여 사용자가 휴일을 쉽게 인지할 수 있게 한다.", + "files": [ + { + "path": "src/apis/fetchHolidays.ts", + "role": "2025년 한국 공휴일 데이터 반환" + }, + { + "path": "src/hooks/useCalendarView.ts", + "role": "현재 날짜에 따라 공휴일 데이터 조회" + }, + { + "path": "src/App.tsx", + "role": "renderMonthView에서 공휴일 표시" + } + ], + "api": [], + "internalDependencies": [ + { + "path": "src/apis/fetchHolidays.ts", + "description": "하드코딩된 공휴일 데이터 조회" + } + ], + "tests": [ + { + "path": "src/__tests__/unit/easy.fetchHolidays.spec.ts", + "scope": "공휴일 조회 함수 단위 테스트" + } + ], + "status": "implemented" + }, + { + "name": "반복 일정", + "purpose": "일정을 매일/주간/월간/연간 반복 등록할 수 있게 한다.", + "files": [ + { + "path": "src/types.ts", + "role": "RepeatInfo, RepeatType 타입 정의 (반복 구조 계획)" + }, + { + "path": "src/hooks/useEventForm.ts", + "role": "반복 관련 상태 필드 선언 (미사용)" + }, + { + "path": "src/App.tsx", + "role": "반복 설정 UI 주석 처리됨" + } + ], + "api": [], + "internalDependencies": [], + "tests": [], + "status": "planned" + } + ] +} diff --git a/docs/prd-v1.md b/docs/prd-v1.md new file mode 100644 index 00000000..e936d78f --- /dev/null +++ b/docs/prd-v1.md @@ -0,0 +1,791 @@ +# 일정 관리 캘린더 애플리케이션 PRD (Product Requirements Document) + +## 목차 + +- [개요](#개요) +- [프로젝트 구조](#프로젝트-구조) +- [핵심 기능](#핵심-기능) +- [데이터 모델](#데이터-모델) +- [API 명세](#api-명세) +- [컴포넌트 구조](#컴포넌트-구조) +- [기술 스택](#기술-스택) + +--- + +## 개요 + +일정 관리 캘린더 애플리케이션은 사용자가 일정을 등록, 수정, 삭제하고 월간/주간 뷰로 확인할 수 있는 웹 애플리케이션입니다. 일정 검색, 중복 확인, 알림 기능을 제공하여 효율적인 일정 관리를 지원합니다. + +### 주요 특징 + +- 월간/주간 캘린더 뷰 제공 +- 일정 CRUD (생성, 조회, 수정, 삭제) +- 실시간 일정 검색 +- 일정 시간 중복 감지 및 경고 +- 일정 시작 전 알림 기능 +- 한국 공휴일 표시 +- 반응형 UI (Material-UI) + +--- + +## 프로젝트 구조 + +``` +src/ +├── apis/ +│ └── fetchHolidays.ts # 공휴일 데이터 조회 API +├── hooks/ +│ ├── useCalendarView.ts # 캘린더 뷰 상태 관리 (월/주 전환, 날짜 네비게이션) +│ ├── useEventForm.ts # 일정 폼 상태 관리 (입력값, 유효성 검사) +│ ├── useEventOperations.ts # 일정 CRUD 작업 (생성, 조회, 수정, 삭제) +│ ├── useNotifications.ts # 알림 시스템 (일정 시작 전 알림) +│ └── useSearch.ts # 일정 검색 및 필터링 +├── utils/ +│ ├── dateUtils.ts # 날짜 관련 유틸리티 (월/주 계산, 포맷팅) +│ ├── eventUtils.ts # 일정 필터링 및 검색 유틸리티 +│ ├── eventOverlap.ts # 일정 중복 감지 로직 +│ ├── notificationUtils.ts # 알림 메시지 생성 및 upcoming 이벤트 필터 +│ └── timeValidation.ts # 시간 유효성 검사 +├── __tests__/ +│ ├── hooks/ # 커스텀 훅 테스트 +│ ├── unit/ # 유틸리티 함수 단위 테스트 +│ └── medium.integration.spec.tsx # 통합 테스트 +├── __mocks__/ +│ ├── handlers.ts # MSW 핸들러 (API 모킹) +│ ├── handlersUtils.ts # 핸들러 유틸리티 +│ └── response/ # 목 데이터 +├── App.tsx # 메인 애플리케이션 컴포넌트 +├── types.ts # TypeScript 타입 정의 +└── main.tsx # 앱 진입점 + +``` + +### 폴더별 역할 + +| 폴더/파일 | 책임 | 주요 파일 | +| ------------------ | ------------------------------------- | ------------------- | +| **apis/** | 외부 API 통신 및 데이터 조회 | `fetchHolidays.ts` | +| **hooks/** | 비즈니스 로직 및 상태 관리 | 5개의 커스텀 훅 | +| **utils/** | 순수 함수 유틸리티 (날짜, 검색, 검증) | 5개의 유틸리티 모듈 | +| \***\*tests**/\*\* | 테스트 코드 (단위/통합 테스트) | 12개의 테스트 파일 | +| \***\*mocks**/\*\* | API 모킹 및 테스트 데이터 | MSW 핸들러 | + +--- + +## 핵심 기능 + +### 1. 일정 관리 (CRUD) + +#### 1.1 일정 생성 + +- **기능**: 새로운 일정 추가 +- **입력 필드**: + - 제목 (필수) + - 날짜 (필수) + - 시작 시간 (필수) + - 종료 시간 (필수) + - 설명 (선택) + - 위치 (선택) + - 카테고리 (업무/개인/가족/기타) + - 반복 설정 (선택, 8주차 과제) + - 알림 시간 (1분/10분/1시간/2시간/1일 전) +- **유효성 검사**: + - 필수 필드 검증 + - 시작 시간 < 종료 시간 검증 + - 기존 일정과 시간 중복 검사 +- **관련 파일**: `hooks/useEventOperations.ts`, `hooks/useEventForm.ts`, `utils/timeValidation.ts`, `utils/eventOverlap.ts` + +#### 1.2 일정 조회 + +- **기능**: 등록된 일정 목록 표시 +- **뷰 모드**: + - 월간 뷰: 한 달 전체 일정 + - 주간 뷰: 해당 주(일~토) 일정 +- **데이터 표시**: + - 캘린더 그리드에 일정 표시 + - 우측 패널에 상세 목록 + - 알림 설정된 일정 강조 표시 +- **관련 파일**: `hooks/useCalendarView.ts`, `App.tsx`, `utils/dateUtils.ts` + +#### 1.3 일정 수정 + +- **기능**: 기존 일정 수정 +- **동작**: + - 일정 클릭 시 폼에 데이터 로드 + - 수정 후 저장 + - 중복 검사 재실행 +- **관련 파일**: `hooks/useEventForm.ts`, `hooks/useEventOperations.ts` + +#### 1.4 일정 삭제 + +- **기능**: 일정 삭제 +- **동작**: 삭제 버튼 클릭 시 즉시 삭제 +- **관련 파일**: `hooks/useEventOperations.ts` + +--- + +### 2. 캘린더 뷰 + +#### 2.1 월간 뷰 + +- **표시 내용**: + - 현재 월의 모든 날짜 (7x5 또는 7x6 그리드) + - 각 날짜별 일정 목록 + - 공휴일 표시 (빨간색) +- **네비게이션**: 이전/다음 월 이동 +- **관련 파일**: `App.tsx` (renderMonthView), `utils/dateUtils.ts` + +#### 2.2 주간 뷰 + +- **표시 내용**: + - 현재 주의 7일 (일~토) + - 각 요일별 일정 목록 +- **네비게이션**: 이전/다음 주 이동 +- **관련 파일**: `App.tsx` (renderWeekView), `utils/dateUtils.ts` + +--- + +### 3. 일정 검색 및 필터링 + +#### 3.1 검색 기능 + +- **검색 대상**: 제목, 설명, 위치 +- **검색 방식**: 실시간 텍스트 검색 (대소문자 무시) +- **결과 표시**: 현재 뷰(월/주)에 해당하는 일정만 필터링 +- **관련 파일**: `hooks/useSearch.ts`, `utils/eventUtils.ts` + +#### 3.2 날짜 범위 필터링 + +- **자동 필터링**: 현재 선택된 뷰(월/주)에 따라 자동으로 날짜 범위 필터링 +- **관련 파일**: `utils/eventUtils.ts` + +--- + +### 4. 일정 충돌 감지 + +#### 4.1 중복 확인 로직 + +- **검사 시점**: 일정 저장 시 +- **검사 조건**: 동일 날짜에 시간 범위가 겹치는 일정 +- **알고리즘**: `start1 < end2 && start2 < end1` +- **관련 파일**: `utils/eventOverlap.ts` + +#### 4.2 중복 경고 + +- **UI**: 다이얼로그 표시 +- **내용**: 겹치는 일정 목록 표시 +- **선택**: 계속 진행 / 취소 +- **관련 파일**: `App.tsx` (Dialog 컴포넌트) + +--- + +### 5. 알림 시스템 + +#### 5.1 알림 설정 + +- **옵션**: + - 1분 전 + - 10분 전 (기본값) + - 1시간 전 + - 2시간 전 + - 1일 전 +- **관련 파일**: `hooks/useEventForm.ts` + +#### 5.2 알림 트리거 + +- **동작**: + - 1초마다 현재 시간과 일정 시작 시간 비교 + - 설정된 알림 시간에 도달하면 알림 표시 + - 이미 알림된 일정은 재알림 방지 +- **표시 위치**: 우측 상단 고정 위치 +- **관련 파일**: `hooks/useNotifications.ts`, `utils/notificationUtils.ts` + +#### 5.3 알림 표시 + +- **UI**: Material-UI Alert 컴포넌트 +- **내용**: `{알림시간}분 후 {제목} 일정이 시작됩니다.` +- **알림된 일정 강조**: 빨간색 배경, 굵은 글씨, 알림 아이콘 +- **관련 파일**: `App.tsx`, `utils/notificationUtils.ts` + +--- + +### 6. 공휴일 표시 + +- **데이터 소스**: 하드코딩된 2025년 한국 공휴일 +- **표시**: 월간 뷰에서 빨간색으로 공휴일 이름 표시 +- **관련 파일**: `apis/fetchHolidays.ts` + +--- + +## 데이터 모델 + +### TypeScript 타입 정의 (`types.ts`) + +#### RepeatInfo + +```typescript +export type RepeatType = 'none' | 'daily' | 'weekly' | 'monthly' | 'yearly'; + +export interface RepeatInfo { + type: RepeatType; // 반복 유형 + interval: number; // 반복 간격 + endDate?: string; // 반복 종료일 (선택) +} +``` + +#### EventForm + +```typescript +export interface EventForm { + title: string; // 일정 제목 (필수) + date: string; // 날짜 (YYYY-MM-DD) + startTime: string; // 시작 시간 (HH:mm) + endTime: string; // 종료 시간 (HH:mm) + description: string; // 설명 + location: string; // 위치 + category: string; // 카테고리 (업무/개인/가족/기타) + repeat: RepeatInfo; // 반복 정보 + notificationTime: number; // 알림 시간 (분 단위) +} +``` + +#### Event + +```typescript +export interface Event extends EventForm { + id: string; // 고유 식별자 +} +``` + +--- + +## API 명세 + +### 기본 정보 + +- **Base URL**: `/api` +- **Content-Type**: `application/json` + +### Endpoints + +#### 1. 일정 목록 조회 + +``` +GET /api/events +``` + +**Response**: + +```json +{ + "events": [ + { + "id": "1", + "title": "팀 회의", + "date": "2025-01-15", + "startTime": "10:00", + "endTime": "11:00", + "description": "주간 팀 미팅", + "location": "회의실 A", + "category": "업무", + "repeat": { + "type": "none", + "interval": 1 + }, + "notificationTime": 10 + } + ] +} +``` + +#### 2. 일정 생성 + +``` +POST /api/events +``` + +**Request Body**: + +```json +{ + "title": "팀 회의", + "date": "2025-01-15", + "startTime": "10:00", + "endTime": "11:00", + "description": "주간 팀 미팅", + "location": "회의실 A", + "category": "업무", + "repeat": { + "type": "none", + "interval": 1 + }, + "notificationTime": 10 +} +``` + +**Response**: 생성된 Event 객체 + +#### 3. 일정 수정 + +``` +PUT /api/events/:id +``` + +**Request Body**: Event 객체 (id 포함) +**Response**: 수정된 Event 객체 + +#### 4. 일정 삭제 + +``` +DELETE /api/events/:id +``` + +**Response**: 성공 메시지 + +--- + +## 컴포넌트 구조 + +### App.tsx - 메인 컴포넌트 + +#### 레이아웃 구조 + +``` +┌─────────────────────────────────────────────────────────────┐ +│ 일정 관리 애플리케이션 │ +├──────────────┬──────────────────────┬───────────────────────┤ +│ 일정 폼 │ 캘린더 뷰 │ 일정 목록 │ +│ (20%) │ (50%) │ (30%) │ +│ │ │ │ +│ - 제목 │ ┌─ 뷰 선택 ───────┐ │ - 검색창 │ +│ - 날짜 │ │ ← Week/Month → │ │ - 일정 카드 │ +│ - 시작시간 │ └─────────────────┘ │ (스크롤) │ +│ - 종료시간 │ │ │ +│ - 설명 │ [캘린더 그리드] │ │ +│ - 위치 │ │ │ +│ - 카테고리 │ │ │ +│ - 반복 │ │ │ +│ - 알림 │ │ │ +│ │ │ │ +│ [일정 추가] │ │ │ +└──────────────┴──────────────────────┴───────────────────────┘ +``` + +#### 주요 하위 컴포넌트 + +1. **일정 입력 폼 (좌측 패널)** + + - FormControl 컴포넌트들로 구성 + - 실시간 유효성 검사 + - 수정 모드 지원 + +2. **캘린더 뷰 (중앙 패널)** + + - `renderWeekView()`: 주간 테이블 뷰 + - `renderMonthView()`: 월간 테이블 뷰 + - 네비게이션 버튼 (이전/다음) + - 뷰 타입 선택 드롭다운 + +3. **일정 목록 (우측 패널)** + + - 검색 입력창 + - 일정 카드 목록 (스크롤 가능) + - 수정/삭제 버튼 + +4. **다이얼로그** + + - 일정 중복 경고 다이얼로그 + +5. **알림 패널 (우측 상단 고정)** + - Alert 컴포넌트 스택 + +--- + +## 커스텀 훅 상세 + +### 1. useCalendarView + +**역할**: 캘린더 뷰 상태 및 네비게이션 관리 + +**상태**: + +- `view`: 'week' | 'month' +- `currentDate`: Date +- `holidays`: { [key: string]: string } + +**함수**: + +- `setView(view)`: 뷰 모드 변경 +- `navigate(direction)`: 이전/다음 월 또는 주로 이동 + +**의존성**: `apis/fetchHolidays.ts` + +--- + +### 2. useEventForm + +**역할**: 일정 입력 폼 상태 관리 + +**상태**: 모든 폼 필드 (title, date, startTime, endTime, ...) + +- 시간 에러 상태 (startTimeError, endTimeError) +- 편집 중인 일정 (editingEvent) + +**함수**: + +- `handleStartTimeChange()`: 시작 시간 변경 및 유효성 검사 +- `handleEndTimeChange()`: 종료 시간 변경 및 유효성 검사 +- `resetForm()`: 폼 초기화 +- `editEvent(event)`: 편집 모드로 전환 + +**의존성**: `utils/timeValidation.ts` + +--- + +### 3. useEventOperations + +**역할**: 일정 CRUD 작업 + +**상태**: + +- `events`: Event[] + +**함수**: + +- `fetchEvents()`: 일정 목록 조회 +- `saveEvent(eventData)`: 일정 생성/수정 +- `deleteEvent(id)`: 일정 삭제 + +**API 호출**: + +- GET /api/events +- POST /api/events +- PUT /api/events/:id +- DELETE /api/events/:id + +**의존성**: `notistack` (알림 표시) + +--- + +### 4. useNotifications + +**역할**: 알림 시스템 관리 + +**상태**: + +- `notifications`: { id, message }[] +- `notifiedEvents`: string[] (이미 알림된 일정 ID 목록) + +**함수**: + +- `checkUpcomingEvents()`: 1초마다 실행, upcoming 일정 확인 +- `removeNotification(index)`: 알림 제거 + +**의존성**: `utils/notificationUtils.ts` + +--- + +### 5. useSearch + +**역할**: 일정 검색 및 필터링 + +**상태**: + +- `searchTerm`: string +- `filteredEvents`: Event[] (useMemo로 최적화) + +**함수**: + +- `setSearchTerm(term)`: 검색어 업데이트 + +**의존성**: `utils/eventUtils.ts` + +--- + +## 유틸리티 함수 상세 + +### 1. dateUtils.ts + +**주요 함수**: + +- `getDaysInMonth(year, month)`: 월의 일수 반환 +- `getWeekDates(date)`: 해당 주의 모든 날짜 배열 반환 +- `getWeeksAtMonth(date)`: 월간 뷰 주 배열 생성 (7x5/6 그리드) +- `getEventsForDay(events, date)`: 특정 날짜의 일정 필터링 +- `formatWeek(date)`: "YYYY년 M월 N주" 형식 +- `formatMonth(date)`: "YYYY년 M월" 형식 +- `formatDate(date, day?)`: "YYYY-MM-DD" 형식 +- `isDateInRange(date, start, end)`: 날짜 범위 확인 +- `fillZero(value, size)`: 숫자 0 패딩 + +--- + +### 2. eventUtils.ts + +**주요 함수**: + +- `getFilteredEvents(events, searchTerm, currentDate, view)`: 검색 + 날짜 범위 필터링 +- `searchEvents(events, term)`: 제목/설명/위치 검색 +- `filterEventsByDateRangeAtWeek(events, date)`: 주간 범위 필터링 +- `filterEventsByDateRangeAtMonth(events, date)`: 월간 범위 필터링 + +--- + +### 3. eventOverlap.ts + +**주요 함수**: + +- `parseDateTime(date, time)`: 날짜+시간 문자열을 Date 객체로 변환 +- `convertEventToDateRange(event)`: 일정을 시작/종료 Date 객체로 변환 +- `isOverlapping(event1, event2)`: 두 일정의 시간 중복 여부 확인 +- `findOverlappingEvents(newEvent, events)`: 겹치는 일정 목록 반환 + +--- + +### 4. notificationUtils.ts + +**주요 함수**: + +- `getUpcomingEvents(events, now, notifiedEvents)`: 알림 대상 일정 필터링 + - 조건: 시작 시간까지 남은 시간 ≤ 알림 시간 && 아직 알림 안됨 +- `createNotificationMessage(event)`: 알림 메시지 생성 + +--- + +### 5. timeValidation.ts + +**주요 함수**: + +- `getTimeErrorMessage(start, end)`: 시작/종료 시간 유효성 검사 + - 반환: `{ startTimeError: string | null, endTimeError: string | null }` + +--- + +## 기술 스택 + +### Frontend Framework + +- **React** (v18+): UI 라이브러리 +- **TypeScript**: 타입 안전성 + +### UI Components + +- **Material-UI (MUI)**: 디자인 시스템 + - Table, Dialog, Alert, TextField, Select, Button 등 + +### State Management + +- **React Hooks**: 상태 관리 + - useState, useEffect, useMemo + - Custom Hooks (5개) + +### Notifications + +- **notistack**: 토스트 알림 라이브러리 + +### Testing + +- **Vitest**: 테스트 프레임워크 +- **Testing Library**: React 컴포넌트 테스트 +- **MSW (Mock Service Worker)**: API 모킹 + +### Build Tool + +- **Vite**: 빌드 도구 + +--- + +## 주요 비즈니스 로직 + +### 1. 일정 중복 검사 알고리즘 + +```typescript +// utils/eventOverlap.ts +function isOverlapping(event1, event2) { + const { start: start1, end: end1 } = convertEventToDateRange(event1); + const { start: start2, end: end2 } = convertEventToDateRange(event2); + + // 두 구간이 겹치는 조건: start1 < end2 && start2 < end1 + return start1 < end2 && start2 < end1; +} +``` + +### 2. 알림 대상 일정 필터링 + +```typescript +// utils/notificationUtils.ts +function getUpcomingEvents(events, now, notifiedEvents) { + return events.filter((event) => { + const eventStart = new Date(`${event.date}T${event.startTime}`); + const timeDiff = (eventStart.getTime() - now.getTime()) / 분; + + // 조건: 0 < 남은시간 ≤ 알림시간 && 아직 알림안됨 + return timeDiff > 0 && timeDiff <= event.notificationTime && !notifiedEvents.includes(event.id); + }); +} +``` + +### 3. 검색 및 필터링 + +```typescript +// utils/eventUtils.ts +function getFilteredEvents(events, searchTerm, currentDate, view) { + // 1단계: 텍스트 검색 + const searchedEvents = searchEvents(events, searchTerm); + + // 2단계: 날짜 범위 필터링 + if (view === 'week') { + return filterEventsByDateRangeAtWeek(searchedEvents, currentDate); + } + if (view === 'month') { + return filterEventsByDateRangeAtMonth(searchedEvents, currentDate); + } + + return searchedEvents; +} +``` + +--- + +## 테스트 전략 + +### 테스트 카테고리 + +1. **Unit Tests** (`src/__tests__/unit/`) + + - 유틸리티 함수 테스트 + - 순수 함수 로직 검증 + +2. **Hook Tests** (`src/__tests__/hooks/`) + + - 커스텀 훅 동작 테스트 + - 상태 변경 및 부수 효과 검증 + +3. **Integration Tests** (`src/__tests__/medium.integration.spec.tsx`) + - 컴포넌트 통합 테스트 + - 사용자 시나리오 테스트 + +### 테스트 난이도 구분 + +- **easy**: 기본 기능 테스트 +- **medium**: 복잡한 로직 및 통합 테스트 + +--- + +## 향후 확장 가능성 + +### 현재 미구현 기능 + +1. **반복 일정** (8주차 과제) + - 일간/주간/월간/연간 반복 + - 반복 종료일 설정 + +### 제안 기능 + +1. **드래그 앤 드롭**: 일정 시간 변경 +2. **일정 카테고리별 색상**: 시각적 구분 +3. **월간 뷰에서 더보기**: 하루에 많은 일정이 있을 때 +4. **엑스포트**: iCal, Google Calendar 연동 +5. **다크 모드**: 테마 지원 +6. **모바일 최적화**: 반응형 개선 + +--- + +## 파일별 주요 책임 요약 + +| 파일 경로 | 주요 책임 | 의존성 | +| ----------------------------- | ----------------------------- | ------------------------- | +| `App.tsx` | 메인 UI 렌더링, 이벤트 핸들링 | 모든 커스텀 훅, MUI | +| `types.ts` | 타입 정의 | 없음 | +| `hooks/useCalendarView.ts` | 캘린더 뷰 상태 | `apis/fetchHolidays` | +| `hooks/useEventForm.ts` | 폼 상태 관리 | `utils/timeValidation` | +| `hooks/useEventOperations.ts` | CRUD 작업 | `notistack` | +| `hooks/useNotifications.ts` | 알림 시스템 | `utils/notificationUtils` | +| `hooks/useSearch.ts` | 검색 기능 | `utils/eventUtils` | +| `utils/dateUtils.ts` | 날짜 계산 | 없음 | +| `utils/eventUtils.ts` | 일정 필터링 | `utils/dateUtils` | +| `utils/eventOverlap.ts` | 중복 검사 | 없음 | +| `utils/notificationUtils.ts` | 알림 로직 | 없음 | +| `utils/timeValidation.ts` | 시간 검증 | 없음 | +| `apis/fetchHolidays.ts` | 공휴일 데이터 | 없음 | + +--- + +## 성능 최적화 + +### 1. useMemo 사용 + +- `useSearch.ts`에서 filteredEvents 계산 메모이제이션 + +### 2. 불필요한 리렌더링 방지 + +- 커스텀 훅으로 관심사 분리 +- 상태 관리 최적화 + +### 3. 알림 체크 최적화 + +- 1초 간격 체크 (setInterval) +- 이미 알림된 일정 제외 (notifiedEvents 배열) + +--- + +## 에러 처리 + +### 1. API 에러 + +- try-catch로 모든 API 호출 래핑 +- 에러 발생 시 notistack으로 사용자에게 알림 +- 콘솔에 에러 로깅 + +### 2. 유효성 검사 에러 + +- 필수 필드 누락: "필수 정보를 모두 입력해주세요." +- 시간 검증 실패: "시간 설정을 확인해주세요." +- 실시간 툴팁으로 에러 메시지 표시 + +### 3. 일정 중복 경고 + +- 다이얼로그로 사용자 확인 요청 +- 계속 진행 or 취소 선택 가능 + +--- + +## 접근성 (Accessibility) + +- `aria-label` 속성 사용 +- `aria-labelledby` 속성 사용 +- 키보드 네비게이션 지원 (Material-UI 기본 지원) +- 시맨틱 HTML (FormControl, FormLabel) + +--- + +## 개발 가이드 + +### 새로운 기능 추가 시 고려사항 + +1. **타입 정의**: `types.ts`에 필요한 타입 추가 +2. **유틸리티 함수**: 순수 함수는 `utils/` 디렉토리에 추가 +3. **API 통신**: `hooks/useEventOperations.ts` 또는 별도 API 파일 사용 +4. **상태 관리**: 커스텀 훅으로 분리 +5. **테스트 작성**: 단위/통합 테스트 필수 + +### 코드 스타일 + +- TypeScript strict mode +- ESLint 규칙 준수 +- 함수형 컴포넌트 및 Hooks 사용 +- 한글 주석 및 변수명 허용 (UI 텍스트) + +--- + +## 버전 히스토리 + +- **v1.0**: 초기 버전 (일정 CRUD, 검색, 알림, 중복 검사) +- **v2.0** (예정): 반복 일정 기능 추가 + +--- + +## 문의 및 기여 + +- 이슈 및 버그 리포트: GitHub Issues +- 기능 제안: Pull Request diff --git a/docs/prd-v2.md b/docs/prd-v2.md new file mode 100644 index 00000000..7a31c3e7 --- /dev/null +++ b/docs/prd-v2.md @@ -0,0 +1,192 @@ +--- +**문서 유형**: [HUMAN] +**목적**: 기능별 PRD 인덱스 (function-index.json의 사람 친화적 버전) +**주요 내용**: 각 기능의 목적, 관련 코드, API, 의존성, 테스트, 구현 상태 +**관련 문서**: [function-index.json](./function-index.json), [project-structure.md](./project-structure.md) +**최종 수정일**: 2025-10-29 +--- + +# 일정 관리 캘린더 애플리케이션 - 기능별 PRD 인덱스 + +## 프로젝트 구조 개요 + +상세한 파일 트리 및 각 파일의 책임은 [project-structure.md](./project-structure.md)를 참조하세요. + +## 기능명: 일정 CRUD + +**목적**: 사용자가 일정을 생성, 조회, 수정, 삭제할 수 있도록 하여 개인/업무 일정을 관리할 수 있게 한다. + +**관련 코드**: + +- `src/hooks/useEventOperations.ts` (일정 생성/수정/삭제 API 호출 및 상태 관리) +- `src/hooks/useEventForm.ts` (일정 입력 폼 상태 관리 및 편집 모드 전환) +- `src/App.tsx` (일정 폼 UI 렌더링 및 이벤트 핸들링) +- `src/types.ts` (Event, EventForm 타입 정의) + +**관련 API**: + +- GET /api/events (일정 목록 조회) +- POST /api/events (일정 생성) +- PUT /api/events/:id (일정 수정) +- DELETE /api/events/:id (일정 삭제) + +**내부 의존 모듈**: + +- `src/utils/timeValidation.ts` (시작/종료 시간 유효성 검사) +- `src/utils/eventOverlap.ts` (일정 중복 검사 로직) + +**테스트 파일**: + +- `src/__tests__/hooks/medium.useEventOperations.spec.ts` (일정 CRUD 훅 테스트) +- `src/__tests__/medium.integration.spec.tsx` (일정 추가/수정/삭제 통합 테스트) + +**구현 상태**: 구현됨 + +--- + +## 기능명: 캘린더 뷰 (월간/주간) + +**목적**: 사용자가 월간 또는 주간 단위로 일정을 시각적으로 확인하고 네비게이션할 수 있도록 한다. + +**관련 코드**: + +- `src/hooks/useCalendarView.ts` (뷰 모드 상태 관리 및 날짜 네비게이션 로직) +- `src/App.tsx` (renderWeekView, renderMonthView 함수로 캘린더 그리드 렌더링) +- `src/utils/dateUtils.ts` (주/월 계산, 날짜 포맷팅, 주별 날짜 배열 생성) + +**관련 API**: 없음 + +**내부 의존 모듈**: + +- `src/utils/dateUtils.ts` (날짜 계산 및 포맷팅 유틸리티) +- `src/apis/fetchHolidays.ts` (공휴일 데이터 조회) + +**테스트 파일**: + +- `src/__tests__/hooks/easy.useCalendarView.spec.ts` (캘린더 뷰 훅 단위 테스트) +- `src/__tests__/unit/easy.dateUtils.spec.ts` (날짜 유틸리티 함수 단위 테스트) + +**구현 상태**: 구현됨 + +--- + +## 기능명: 일정 검색 + +**목적**: 사용자가 제목, 설명, 위치를 기반으로 일정을 실시간 검색하고 필터링할 수 있게 한다. + +**관련 코드**: + +- `src/hooks/useSearch.ts` (검색어 상태 관리 및 필터링된 일정 목록 계산) +- `src/utils/eventUtils.ts` (검색 로직 및 날짜 범위 필터링) +- `src/App.tsx` (검색 입력창 렌더링 및 검색 결과 표시) + +**관련 API**: 없음 + +**내부 의존 모듈**: + +- `src/utils/eventUtils.ts` (텍스트 검색 및 날짜 범위 필터링 로직) +- `src/utils/dateUtils.ts` (주/월 날짜 범위 계산) + +**테스트 파일**: + +- `src/__tests__/hooks/easy.useSearch.spec.ts` (검색 훅 단위 테스트) +- `src/__tests__/unit/easy.eventUtils.spec.ts` (검색 유틸리티 함수 단위 테스트) + +**구현 상태**: 구현됨 + +--- + +## 기능명: 일정 충돌 감지 + +**목적**: 동일 날짜에 시간이 겹치는 일정이 있을 경우 사용자에게 경고하여 스케줄 충돌을 방지한다. + +**관련 코드**: + +- `src/utils/eventOverlap.ts` (일정 시간 중복 감지 로직) +- `src/App.tsx` (중복 경고 다이얼로그 표시 및 처리) + +**관련 API**: 없음 + +**내부 의존 모듈**: + +- `src/utils/eventOverlap.ts` (중복 검사 알고리즘: start1 < end2 && start2 < end1) + +**테스트 파일**: + +- `src/__tests__/unit/easy.eventOverlap.spec.ts` (중복 감지 로직 단위 테스트) + +**구현 상태**: 구현됨 + +--- + +## 기능명: 알림 시스템 + +**목적**: 일정 시작 전 설정된 시간(1분/10분/1시간/2시간/1일 전)에 사용자에게 알림을 표시하여 일정을 놓치지 않도록 한다. + +**관련 코드**: + +- `src/hooks/useNotifications.ts` (1초마다 upcoming 일정 체크 및 알림 상태 관리) +- `src/utils/notificationUtils.ts` (알림 대상 일정 필터링 및 메시지 생성) +- `src/App.tsx` (알림 패널 렌더링 및 알림된 일정 강조 표시) + +**관련 API**: 없음 + +**내부 의존 모듈**: + +- `src/utils/notificationUtils.ts` (알림 시간 계산 및 메시지 포맷팅) + +**테스트 파일**: + +- `src/__tests__/hooks/medium.useNotifications.spec.ts` (알림 훅 단위 테스트) +- `src/__tests__/unit/easy.notificationUtils.spec.ts` (알림 유틸리티 함수 단위 테스트) + +**구현 상태**: 구현됨 + +--- + +## 기능명: 공휴일 표시 + +**목적**: 월간 뷰에서 한국 공휴일을 빨간색으로 표시하여 사용자가 휴일을 쉽게 인지할 수 있도록 한다. + +**관련 코드**: + +- `src/apis/fetchHolidays.ts` (2025년 한국 공휴일 데이터 반환) +- `src/hooks/useCalendarView.ts` (현재 날짜에 따라 공휴일 데이터 조회) +- `src/App.tsx` (renderMonthView에서 공휴일 표시) + +**관련 API**: 없음 + +**내부 의존 모듈**: + +- `src/apis/fetchHolidays.ts` (하드코딩된 공휴일 데이터) + +**테스트 파일**: + +- `src/__tests__/unit/easy.fetchHolidays.spec.ts` (공휴일 조회 함수 단위 테스트) + +**구현 상태**: 구현됨 + +--- + +## 기능명: 반복 일정 + +**목적**: 일간/주간/월간/연간 단위로 반복되는 일정을 설정하여 반복 입력 없이 주기적인 일정을 관리할 수 있도록 한다. + +**관련 코드**: + +- `src/types.ts` (RepeatInfo, RepeatType 타입 정의됨) +- `src/hooks/useEventForm.ts` (반복 관련 상태 필드 존재) +- `src/App.tsx` (반복 설정 UI는 주석 처리됨) + +**관련 API**: + +- POST /api/events (반복 정보를 포함한 일정 생성 가능하나 로직 미구현) +- PUT /api/events/:id (반복 정보를 포함한 일정 수정 가능하나 로직 미구현) + +**내부 의존 모듈**: 없음 + +**테스트 파일**: 없음 + +**구현 상태**: 미구현(예정) + +--- diff --git a/docs/project-structure.md b/docs/project-structure.md new file mode 100644 index 00000000..f5b6ddb1 --- /dev/null +++ b/docs/project-structure.md @@ -0,0 +1,55 @@ +--- +**문서 유형**: [AI] +**목적**: 파일 트리 및 각 파일의 책임 매핑 +**주요 내용**: src/ 디렉토리 구조와 각 파일의 한 줄 책임 설명 +**관련 문서**: [function-index.json](./function-index.json) +**최종 수정일**: 2025-10-29 +--- + +# 프로젝트 구조 + +## src/ 디렉토리 트리 + +``` +src/ +├── apis/ +│ └── fetchHolidays.ts # 공휴일 데이터 조회 +├── hooks/ +│ ├── useCalendarView.ts # 캘린더 뷰 상태 관리 (월/주 전환, 날짜 네비게이션) +│ ├── useEventForm.ts # 일정 폼 상태 관리 및 유효성 검사 +│ ├── useEventOperations.ts # 일정 CRUD API 호출 및 상태 관리 +│ ├── useNotifications.ts # 알림 시스템 상태 관리 및 주기적 체크 +│ └── useSearch.ts # 일정 검색 및 필터링 로직 +├── utils/ +│ ├── dateUtils.ts # 날짜 계산, 포맷팅, 주/월 범위 계산 +│ ├── eventOverlap.ts # 일정 시간 중복 감지 로직 +│ ├── eventUtils.ts # 일정 검색 및 날짜 범위 필터링 +│ ├── notificationUtils.ts # 알림 메시지 생성 및 대상 이벤트 필터링 +│ └── timeValidation.ts # 시작/종료 시간 유효성 검사 +├── __tests__/ +│ ├── hooks/ +│ │ ├── easy.useCalendarView.spec.ts # useCalendarView 훅 단위 테스트 +│ │ ├── easy.useSearch.spec.ts # useSearch 훅 단위 테스트 +│ │ ├── medium.useEventOperations.spec.ts # useEventOperations 훅 통합 테스트 +│ │ └── medium.useNotifications.spec.ts # useNotifications 훅 통합 테스트 +│ ├── unit/ +│ │ ├── easy.dateUtils.spec.ts # 날짜 유틸리티 함수 단위 테스트 +│ │ ├── easy.eventOverlap.spec.ts # 일정 중복 감지 로직 단위 테스트 +│ │ ├── easy.eventUtils.spec.ts # 일정 검색/필터링 함수 단위 테스트 +│ │ ├── easy.fetchHolidays.spec.ts # 공휴일 조회 함수 단위 테스트 +│ │ ├── easy.notificationUtils.spec.ts # 알림 유틸리티 함수 단위 테스트 +│ │ └── easy.timeValidation.spec.ts # 시간 유효성 검사 단위 테스트 +│ ├── medium.integration.spec.tsx # 일정 CRUD 통합 테스트 +│ └── utils.ts # 테스트 헬퍼 함수 +├── __mocks__/ +│ ├── handlers.ts # MSW API 모킹 핸들러 +│ ├── handlersUtils.ts # 핸들러 유틸리티 함수 +│ └── response/ +│ ├── events.json # 테스트용 이벤트 목 데이터 +│ └── realEvents.json # 실제 이벤트 목 데이터 +├── App.tsx # 메인 애플리케이션 컴포넌트 +├── main.tsx # 애플리케이션 진입점 +├── types.ts # TypeScript 타입 정의 (Event, EventForm, RepeatInfo 등) +├── setupTests.ts # 테스트 환경 설정 +└── vite-env.d.ts # Vite 환경 타입 정의 +``` diff --git a/docs/tech-stack.md b/docs/tech-stack.md new file mode 100644 index 00000000..1a014056 --- /dev/null +++ b/docs/tech-stack.md @@ -0,0 +1,381 @@ +--- +**문서 유형**: [HUMAN] +**목적**: 사용 기술 스택 상세 정보 +**주요 내용**: 프레임워크, 라이브러리, 도구, 의존성 목록 및 선택 이유 +**관련 문서**: [architecture-guidelines.md](./architecture-guidelines.md) +**최종 수정일**: 2025-10-29 +--- + +# 기술 스택 + +## 프론트엔드 프레임워크 + +### React + +**버전**: v18+ + +**역할**: UI 라이브러리 + +**사용 이유**: + +- 컴포넌트 기반 아키텍처 +- 가상 DOM으로 효율적인 렌더링 +- 풍부한 생태계 + +**핵심 기능 사용**: + +- 함수형 컴포넌트 +- Hooks (useState, useEffect, useMemo, useCallback) +- 커스텀 훅 + +--- + +### TypeScript + +**역할**: 타입 시스템 및 정적 분석 + +**사용 이유**: + +- 컴파일 타임 타입 검사 +- IDE 자동완성 지원 +- 리팩토링 안정성 + +**설정**: + +- Strict mode 활성화 +- 명시적 타입 정의 우선 +- any 타입 사용 금지 + +--- + +## UI 라이브러리 + +### Material-UI (MUI) + +**버전**: v5+ + +**역할**: 디자인 시스템 및 컴포넌트 라이브러리 + +**사용 이유**: + +- Google Material Design 기반 +- 즉시 사용 가능한 컴포넌트 +- 접근성 내장 +- 반응형 디자인 지원 + +**사용 컴포넌트**: + +- Layout: Box, Stack, Grid +- Form: TextField, Select, Checkbox, Button +- Display: Table, Dialog, Alert, Typography +- Navigation: IconButton +- Feedback: Tooltip + +**스타일링 방법**: + +- `sx` prop 사용 (인라인 스타일링) +- Theme 커스터마이징 가능 + +--- + +### MUI Icons + +**역할**: 아이콘 세트 + +**사용 아이콘**: + +- Notifications: 알림 표시 +- ChevronLeft/ChevronRight: 네비게이션 +- Edit: 일정 수정 +- Delete: 일정 삭제 +- Close: 닫기 + +--- + +## 상태 관리 + +### React Hooks + +**역할**: 상태 관리 및 부수 효과 처리 + +**사용 Hooks**: + +- `useState`: 로컬 상태 관리 +- `useEffect`: 부수 효과 (API 호출, 이벤트 리스너, 타이머) +- `useMemo`: 계산 비용이 큰 값 메모이제이션 +- `useCallback`: 함수 메모이제이션 (최적화) + +**커스텀 훅**: + +- `useCalendarView`: 캘린더 뷰 상태 +- `useEventForm`: 폼 상태 +- `useEventOperations`: 일정 CRUD +- `useNotifications`: 알림 시스템 +- `useSearch`: 검색 및 필터링 + +**전역 상태 관리**: + +- 현재 사용하지 않음 (Context API, Redux 등 미사용) +- 커스텀 훅으로 충분히 관리 가능한 규모 + +--- + +## 알림 시스템 + +### notistack + +**역할**: 토스트 알림 라이브러리 + +**사용 이유**: + +- MUI와 완벽 호환 +- 다중 알림 스택 관리 +- 커스터마이징 가능 + +**사용 API**: + +- `enqueueSnackbar`: 알림 표시 +- `variant`: success, error, info, warning + +**사용 위치**: + +- API 성공/실패 알림 +- 폼 유효성 검사 에러 +- 일정 추가/수정/삭제 완료 메시지 + +--- + +## 빌드 도구 + +### Vite + +**역할**: 빌드 도구 및 개발 서버 + +**사용 이유**: + +- 빠른 개발 서버 시작 +- HMR (Hot Module Replacement) +- ES Module 네이티브 지원 +- 최적화된 프로덕션 빌드 + +**설정 파일**: `vite.config.ts` + +--- + +## 테스트 도구 + +### Vitest + +**역할**: 테스트 프레임워크 + +**사용 이유**: + +- Vite 기반으로 빠른 실행 +- Jest 호환 API +- ES Module 지원 + +**사용 API**: + +- `describe`, `it`, `expect` +- `beforeEach`, `afterEach` +- `vi.fn()`: 모킹 + +--- + +### Testing Library + +**패키지**: `@testing-library/react`, `@testing-library/user-event` + +**역할**: React 컴포넌트 테스트 유틸리티 + +**사용 이유**: + +- 사용자 관점 테스트 +- 접근성 중심 쿼리 +- React 베스트 프랙티스 강제 + +**사용 API**: + +- `render`: 컴포넌트 렌더링 +- `renderHook`: 커스텀 훅 테스트 +- `screen`: 쿼리 접근 +- `fireEvent`: 이벤트 트리거 +- `waitFor`: 비동기 대기 +- `act`: 상태 업데이트 래핑 + +--- + +### MSW (Mock Service Worker) + +**버전**: v2+ + +**역할**: API 모킹 + +**사용 이유**: + +- 네트워크 레벨 모킹 +- 실제 fetch 호출 인터셉트 +- 브라우저/Node 환경 모두 지원 + +**설정**: + +- `src/__mocks__/handlers.ts`: API 핸들러 정의 +- `src/setupTests.ts`: MSW 서버 설정 + +**모킹 API**: + +- GET /api/events +- POST /api/events +- PUT /api/events/:id +- DELETE /api/events/:id + +--- + +## 코드 품질 + +### ESLint + +**역할**: 정적 분석 및 코드 스타일 검사 + +**설정 파일**: `eslint.config.js` + +**사용 이유**: + +- 코드 일관성 유지 +- 잠재적 버그 사전 발견 +- 베스트 프랙티스 강제 + +--- + +### TypeScript Strict Mode + +**역할**: 엄격한 타입 검사 + +**활성화된 옵션**: + +- `noImplicitAny`: 암묵적 any 금지 +- `strictNullChecks`: null/undefined 체크 +- `strictFunctionTypes`: 함수 타입 엄격 검사 +- `noImplicitThis`: this 타입 명시 강제 + +--- + +## 패키지 매니저 + +### pnpm + +**역할**: 의존성 관리 + +**사용 이유**: + +- 디스크 공간 효율적 +- 빠른 설치 속도 +- 엄격한 의존성 관리 (Phantom dependencies 방지) + +**주요 명령어**: + +- `pnpm install`: 의존성 설치 +- `pnpm dev`: 개발 서버 실행 +- `pnpm build`: 프로덕션 빌드 +- `pnpm test`: 테스트 실행 + +--- + +## 의존성 목록 + +### 프로덕션 의존성 (dependencies) + +```json +{ + "react": "^18.x", + "react-dom": "^18.x", + "@mui/material": "^5.x", + "@mui/icons-material": "^5.x", + "@emotion/react": "^11.x", + "@emotion/styled": "^11.x", + "notistack": "^3.x" +} +``` + +### 개발 의존성 (devDependencies) + +```json +{ + "vite": "^5.x", + "typescript": "^5.x", + "vitest": "^1.x", + "@testing-library/react": "^14.x", + "@testing-library/user-event": "^14.x", + "msw": "^2.x", + "eslint": "^8.x", + "@typescript-eslint/parser": "^6.x", + "@typescript-eslint/eslint-plugin": "^6.x" +} +``` + +--- + +## 브라우저 지원 + +### 타겟 브라우저 + +- Chrome (최신 2개 버전) +- Firefox (최신 2개 버전) +- Safari (최신 2개 버전) +- Edge (최신 2개 버전) + +### 최소 요구사항 + +- ES2020 지원 +- ES Module 지원 +- Service Worker 지원 (MSW) + +--- + +## 개발 서버 + +### Vite Dev Server + +**포트**: 기본 5173 + +**특징**: + +- HMR (Hot Module Replacement) +- ES Module 네이티브 지원 +- 빠른 시작 시간 + +### API Mock Server + +**파일**: `server.js` + +**역할**: 로컬 개발용 API 모킹 서버 + +**포트**: /api 경로로 프록시 + +--- + +## 향후 도입 검토 기술 + +### 상태 관리 + +- Zustand / Jotai (전역 상태 필요 시) + +### 라우팅 + +- React Router (다중 페이지 전환 시) + +### 폼 관리 + +- React Hook Form (복잡한 폼 검증 시) + +### 날짜 라이브러리 + +- date-fns / dayjs (현재는 네이티브 Date 사용) + +### 스타일링 + +- CSS-in-JS 대안 (성능 최적화 필요 시) + +### API 클라이언트 + +- Axios / TanStack Query (복잡한 API 관리 시) diff --git a/docs/test-strategy.md b/docs/test-strategy.md new file mode 100644 index 00000000..a459b808 --- /dev/null +++ b/docs/test-strategy.md @@ -0,0 +1,329 @@ +--- +**문서 유형**: [AI/HUMAN] +**목적**: 테스트 전략 및 작성 가이드 +**주요 내용**: 테스트 피라미드, 테스트 도구, 작성 패턴, 베스트 프랙티스 +**관련 문서**: [function-index.json](./function-index.json), [architecture-guidelines.md](./architecture-guidelines.md) +**최종 수정일**: 2025-10-29 +--- + +# 테스트 전략 + +## 테스트 피라미드 + +### 1. 단위 테스트 (Unit Tests) + +**목적**: 유틸리티 함수 및 개별 로직 검증 + +**위치**: `src/__tests__/unit/` + +**특징**: + +- 순수 함수 테스트 +- 빠른 실행 속도 +- 높은 커버리지 + +**예시**: + +- `easy.dateUtils.spec.ts` - 날짜 계산 함수 +- `easy.eventOverlap.spec.ts` - 일정 중복 감지 로직 +- `easy.timeValidation.spec.ts` - 시간 유효성 검사 + +--- + +### 2. 훅 테스트 (Hook Tests) + +**목적**: 커스텀 훅의 상태 변경 및 부수 효과 검증 + +**위치**: `src/__tests__/hooks/` + +**특징**: + +- React Testing Library의 `renderHook` 사용 +- 상태 변화 추적 +- 비즈니스 로직 검증 + +**예시**: + +- `easy.useCalendarView.spec.ts` - 캘린더 뷰 상태 관리 +- `easy.useSearch.spec.ts` - 검색 로직 +- `medium.useEventOperations.spec.ts` - API 호출 및 상태 관리 +- `medium.useNotifications.spec.ts` - 알림 시스템 + +--- + +### 3. 통합 테스트 (Integration Tests) + +**목적**: 컴포넌트 간 상호작용 및 사용자 시나리오 검증 + +**위치**: `src/__tests__/` + +**특징**: + +- 실제 사용자 플로우 시뮬레이션 +- 여러 레이어 통합 검증 +- MSW로 API 모킹 + +**예시**: + +- `medium.integration.spec.tsx` - 일정 CRUD E2E 시나리오 + +--- + +## 테스트 범위 + +### 필수 테스트 + +- ✅ 모든 유틸리티 함수는 단위 테스트 필수 +- ✅ 비즈니스 로직을 포함한 커스텀 훅은 테스트 필수 +- ✅ API 호출은 MSW로 모킹하여 독립적 테스트 +- ✅ 핵심 사용자 시나리오는 통합 테스트 필수 + +### 선택 테스트 + +- 단순 UI 컴포넌트 (로직이 없는 경우) +- 외부 라이브러리 래핑 함수 (라이브러리 자체 테스트에 의존) + +--- + +## 테스트 난이도 분류 + +### easy + +**특징**: + +- 기본 기능 테스트 +- 순수 함수 테스트 +- 동기 처리 + +**예시**: + +- 날짜 포맷팅 함수 +- 검색 필터링 로직 +- 시간 유효성 검사 + +### medium + +**특징**: + +- 복잡한 로직 테스트 +- 통합 테스트 +- 비동기 처리 (API 호출, setTimeout 등) +- 상태 변화가 많은 로직 + +**예시**: + +- 일정 CRUD 통합 테스트 +- 알림 시스템 (setInterval 사용) +- API 호출을 포함한 훅 + +--- + +## 테스트 도구 + +### Vitest + +**역할**: 테스트 프레임워크 + +**특징**: + +- Vite 기반으로 빠른 실행 +- Jest와 호환되는 API +- ES Module 지원 + +### Testing Library + +**역할**: React 컴포넌트 테스트 유틸리티 + +**특징**: + +- 사용자 관점 테스트 +- `render`, `renderHook`, `screen`, `fireEvent`, `waitFor` 등 제공 +- 접근성 중심 쿼리 + +### MSW (Mock Service Worker) + +**역할**: API 모킹 + +**특징**: + +- 네트워크 레벨 모킹 +- 실제 fetch/axios 호출 인터셉트 +- 브라우저/Node 환경 모두 지원 + +**설정 위치**: `src/__mocks__/handlers.ts` + +--- + +## 테스트 작성 가이드 + +### 1. 파일 명명 + +``` +[난이도].[테스트대상].spec.[ts|tsx] +``` + +**예시**: + +- `easy.dateUtils.spec.ts` +- `medium.useEventOperations.spec.ts` +- `medium.integration.spec.tsx` + +### 2. 테스트 구조 + +```typescript +describe('모듈/함수명', () => { + describe('특정 기능/케이스', () => { + it('should 기대 동작', () => { + // Arrange (준비) + // Act (실행) + // Assert (검증) + }); + }); +}); +``` + +### 3. 훅 테스트 패턴 + +```typescript +import { renderHook } from '@testing-library/react'; + +it('should 훅 동작 설명', () => { + const { result } = renderHook(() => useCustomHook()); + + expect(result.current.state).toBe(expected); + + act(() => { + result.current.action(); + }); + + expect(result.current.state).toBe(newExpected); +}); +``` + +### 4. 통합 테스트 패턴 + +```typescript +import { render, screen, fireEvent, waitFor } from '@testing-library/react'; + +it('should 사용자 시나리오 설명', async () => { + render(); + + // 사용자 액션 시뮬레이션 + const input = screen.getByLabelText('제목'); + fireEvent.change(input, { target: { value: '회의' } }); + + const button = screen.getByText('일정 추가'); + fireEvent.click(button); + + // 결과 검증 + await waitFor(() => { + expect(screen.getByText('회의')).toBeInTheDocument(); + }); +}); +``` + +### 5. API 모킹 패턴 + +```typescript +// handlers.ts에 정의 +import { http, HttpResponse } from 'msw'; + +export const handlers = [ + http.get('/api/events', () => { + return HttpResponse.json({ events: mockEvents }); + }), + + http.post('/api/events', async ({ request }) => { + const newEvent = await request.json(); + return HttpResponse.json(newEvent, { status: 201 }); + }), +]; +``` + +--- + +## 테스트 실행 + +### 전체 테스트 실행 + +```bash +npm test +# 또는 +pnpm test +``` + +### 특정 파일만 실행 + +```bash +npm test -- dateUtils +``` + +### 커버리지 확인 + +```bash +npm test -- --coverage +``` + +### Watch 모드 + +```bash +npm test -- --watch +``` + +--- + +## 테스트 커버리지 목표 + +### 최소 커버리지 + +- **유틸리티 함수**: 90% 이상 +- **커스텀 훅**: 80% 이상 +- **통합 테스트**: 핵심 시나리오 100% + +### 우선순위 + +1. 비즈니스 로직 (일정 CRUD, 검색, 알림 등) +2. 데이터 변환 로직 (날짜 계산, 포맷팅 등) +3. 유효성 검사 로직 +4. 에러 처리 + +--- + +## 테스트 베스트 프랙티스 + +### ✅ DO + +- 테스트는 독립적으로 실행 가능해야 함 +- 테스트 이름은 기대 동작을 명확히 표현 +- Given-When-Then 패턴 사용 +- 에지 케이스 테스트 포함 +- API 호출은 반드시 모킹 + +### ❌ DON'T + +- 테스트 간 의존성 생성 금지 +- 실제 API 호출 금지 +- 구현 세부사항 테스트 금지 (내부 상태보다 결과 테스트) +- 테스트에서 복잡한 로직 작성 금지 +- 스냅샷 테스트 남용 금지 + +--- + +## 테스트 유지보수 + +### 코드 변경 시 + +- 관련 테스트 함께 업데이트 +- 실패하는 테스트는 즉시 수정 +- 테스트가 없는 버그는 테스트 추가 후 수정 + +### 리팩토링 시 + +- 테스트가 여전히 통과하는지 확인 +- 테스트 코드도 함께 리팩토링 +- 불필요한 테스트 제거 + +### 새 기능 추가 시 + +- TDD 방식 권장 (테스트 먼저 작성) +- 최소 단위 테스트 + 통합 테스트 필수