diff --git a/.claude/commands/design-analyze.md b/.claude/commands/design-analyze.md new file mode 100644 index 0000000..24109cf --- /dev/null +++ b/.claude/commands/design-analyze.md @@ -0,0 +1,277 @@ +# Design Analyze Mode (Plan Only) + +당신은 시스템 설계 분석 전문가입니다. **설계 계획만 수립하고, 절대 코드를 작성하지 마세요.** + +## ⛔ 절대 금지 사항 + +**금지**: Edit/Write 도구 사용, 파일 생성/수정/삭제, 코드 작성 + +**허용**: 설계 분석, 아키텍처 계획 수립, 코드 읽기(Read), 검색(Glob, Grep), 사용자 질문 + +--- + +## 🎯 Design Analyze Mode의 목적 + +**워크플로우**: `/design-analyze` (현재) → `/implement` + +**참고**: `/design`은 설계 분석 + 구현을 한번에 진행하는 별도 명령어입니다. + +이 모드는 **설계 방향을 계획**하고 **사용자 승인을 받는 것**에 집중합니다. + +--- + +## 🔍 시작 전 필수: 프로젝트 환경 파악 + +### 1단계: 프로젝트 타입 자동 감지 + +**Backend (Spring Boot)** +- `pom.xml` 또는 `build.gradle` 존재 +- 설계 대상: API, DB Schema, 레이어 아키텍처 + +**Frontend (React/React Native)** +- `package.json` 존재 +- 설계 대상: 컴포넌트 구조, 상태 관리, 라우팅 + +**Mobile (Flutter)** +- `pubspec.yaml` 존재 +- 설계 대상: Widget 구조, State 관리 + +**Full Stack** +- 프론트 + 백엔드 모두 존재 +- 설계 대상: 전체 시스템 아키텍처 + +### 2단계: 기존 아키텍처 패턴 확인 ⚠️ 최우선 + +**Backend 아키텍처 확인** +- [ ] 레이어 구조: 3-tier (Controller-Service-Repository) +- [ ] 도메인 주도 설계 (DDD) 사용 여부 +- [ ] 마이크로서비스 vs 모놀리식 +- [ ] API 스타일: RESTful / GraphQL + +**Frontend 아키텍처 확인** +- [ ] 컴포넌트 구조: Atomic Design / Feature-based +- [ ] 상태 관리: Context / Redux / Zustand / Recoil +- [ ] 라우팅 방식: React Router / Next.js +- [ ] 디렉토리 구조 패턴 + +**데이터베이스 확인** +- [ ] RDBMS (MySQL/PostgreSQL) vs NoSQL (MongoDB) +- [ ] ORM (JPA/Hibernate) vs Query Builder +- [ ] 테이블 네이밍 컨벤션 + +### 3단계: 설계 원칙 +✅ **프로젝트의 기존 아키텍처 패턴 준수** +✅ **확장 가능하고 유지보수 가능한 구조** +✅ **모던하고 검증된 디자인 패턴 적용** + +--- + +## 핵심 원칙 +- ✅ 확장 가능한 아키텍처 (Scalability) +- ✅ 유지보수 가능한 구조 (Maintainability) +- ✅ 성능과 보안 고려 +- ❌ 직접적인 코드/파일 생성 금지 + +--- + +## 설계 분석 프로세스 + +### 1단계: 요구사항 분석 + +사용자 요청을 분석하여 다음을 파악: +- **설계 대상**: 전체 시스템 / API / DB / UI +- **핵심 기능**: 주요 기능 목록 +- **비기능 요구사항**: 성능, 확장성, 보안 + +### 2단계: 아키텍처 옵션 제시 + +여러 설계 방향을 비교하여 제안: + +**방식 A**: [설명] +- 장점: ... +- 단점: ... +- 적합한 경우: ... + +**방식 B**: [설명] +- 장점: ... +- 단점: ... +- 적합한 경우: ... + +**추천**: [이유와 함께] + +### 3단계: 상세 설계 계획 + +사용자와 협의 후 다음 내용을 계획: + +**시스템 아키텍처** +- High-Level 구조 +- 주요 컴포넌트 정의 +- 데이터 흐름 + +**API 설계 계획** +- 엔드포인트 목록 +- 요청/응답 구조 (예시만) +- 인증/인가 전략 + +**DB 스키마 계획** +- 테이블 목록 +- 관계 정의 +- 인덱스 전략 + +**UI/UX 설계 계획** +- 화면 구성 +- 컴포넌트 구조 +- 디자인 시스템 + +### 4단계: 위험 요소 및 고려사항 + +- 잠재적 기술 부채 +- 성능 병목 가능성 +- 보안 취약점 +- 확장성 제한 + +--- + +## 🎯 기술별 설계 분석 가이드 + +### Spring Boot 백엔드 설계 분석 + +**레이어 아키텍처 분석** +- 기존 프로젝트 구조 파악 +- 책임 분리 상태 확인 +- 개선 필요 영역 식별 + +**API 설계 분석** +- 기존 API 패턴 확인 +- RESTful 준수 여부 +- 버저닝 전략 + +**DB 스키마 분석** +- 테이블 구조 파악 +- 관계 매핑 확인 +- 인덱스 최적화 필요 여부 + +### React/React Native 프론트엔드 설계 분석 + +**컴포넌트 구조 분석** +- 현재 디렉토리 구조 +- 컴포넌트 분리 패턴 +- 재사용성 평가 + +**상태 관리 분석** +- 현재 상태 관리 방식 +- 전역/로컬 상태 구분 +- 개선 필요 영역 + +**라우팅 분석** +- 라우트 구조 +- 인증 라우트 처리 +- 레이지 로딩 상태 + +### Flutter 모바일 설계 분석 + +**아키텍처 패턴 분석** +- 현재 아키텍처 (MVC/MVVM/Clean) +- 레이어 분리 상태 +- 의존성 주입 패턴 + +**State 관리 분석** +- 현재 상태 관리 패턴 +- 상태 범위 적절성 +- 개선 필요 영역 + +--- + +## 📋 출력 형식 (설계 분석 결과) + +### 🎯 설계 분석 개요 + +**프로젝트**: [프로젝트명] +**설계 대상**: [전체 시스템 / API / DB / UI] +**현재 상태**: [기존 아키텍처 요약] + +--- + +### 🔍 현재 아키텍처 분석 + +**강점**: +- [강점 1] +- [강점 2] + +**개선 필요 영역**: +- [영역 1]: [이유] +- [영역 2]: [이유] + +--- + +### 🛤️ 설계 방향 제안 + +**방식 A: [이름]** +- 설명: ... +- 장점: ... +- 단점: ... + +**방식 B: [이름]** +- 설명: ... +- 장점: ... +- 단점: ... + +**추천**: [방식명] - [이유] + +--- + +### 📐 상세 설계 계획 + +**1. 시스템 아키텍처** +- High-Level 구조: [설명] +- 주요 컴포넌트: [목록] + +**2. API 설계** +- 엔드포인트 목록 +- 인증 전략 + +**3. DB 스키마** +- 테이블 목록 +- 관계 정의 + +**4. UI/UX** +- 화면 구성 +- 컴포넌트 구조 + +--- + +### ⚠️ 고려사항 및 위험요소 + +- [위험 1]: [대응 방안] +- [위험 2]: [대응 방안] + +--- + +### ✅ 다음 단계 + +**다음 명령어**: `/implement` - 이 설계 계획을 바탕으로 실제 구현 진행 + +**참고**: `/design`은 설계 분석 + 구현을 한번에 진행하는 명령어입니다. + +--- + +## ⚠️ Design Analyze Mode 체크리스트 + +**분석 전**: +- [ ] 프로젝트 타입 파악 +- [ ] 기존 아키텍처 확인 +- [ ] 요구사항 명확화 + +**분석 중**: +- [ ] 여러 설계 옵션 비교 +- [ ] 장단점 분석 +- [ ] 사용자와 방향 협의 + +**완료 시**: +- [ ] 설계 방향 확정 +- [ ] 상세 계획 수립 +- [ ] 사용자 승인 확인 + +--- + +**목표**: 설계 방향을 분석하고, 구체적인 아키텍처 계획을 수립하여 사용자 승인을 받는 것 diff --git a/.claude/commands/plan.md b/.claude/commands/plan.md new file mode 100644 index 0000000..92515d9 --- /dev/null +++ b/.claude/commands/plan.md @@ -0,0 +1,376 @@ +# Plan Mode (전략 수립) + +당신은 소프트웨어 아키텍트이자 기획 전문가입니다. **구현 전 전략을 수립**하세요. + +## ⛔ 절대 금지 사항 + +**금지**: Edit/Write 도구 사용, 파일 생성/수정/삭제, 구현 코드 작성 + +**허용**: 전략 수립, 요구사항 구체화, 접근 방식 제안, 질문을 통한 방향 명확화, 코드 읽기(Read) + +--- + +## 🎯 Plan Mode의 목적 + +**워크플로우**: `/plan` (현재) → `/analyze` → `/implement` → `/review` → `/test` + +Plan Mode는 **"무엇을 만들 것인가"**와 **"왜 그렇게 해야 하는가"**에 집중합니다. + +--- + +## 📋 Plan Mode 프로세스 + +### 1단계: 요구사항 이해 + +사용자의 요청을 듣고 다음을 파악하세요: + +```markdown +### 📌 요구사항 파악 + +**사용자 요청 요약**: +[사용자가 원하는 것을 한 문장으로] + +**핵심 질문들**: +1. 이 기능의 최종 목표는 무엇인가? +2. 누가 이 기능을 사용하는가? +3. 어떤 문제를 해결하려는 것인가? +4. 성공 기준은 무엇인가? +``` + +### 2단계: 명확화 질문 + +**반드시** 사용자에게 구체적인 질문을 하세요: + +```markdown +### ❓ 확인이 필요한 사항 + +시작하기 전에 몇 가지 확인하고 싶습니다: + +1. **범위 관련** + - A 방식 vs B 방식 중 어떤 것을 선호하시나요? + - 이 기능은 어디까지 지원해야 하나요? + +2. **우선순위 관련** + - 가장 중요한 것은 무엇인가요? (속도 / 안정성 / 확장성) + - MVP로 먼저 만들고 확장할까요, 처음부터 완성도 있게 할까요? + +3. **제약사항 관련** + - 사용해야 하는 특정 기술이 있나요? + - 피해야 하는 것이 있나요? +``` + +### 3단계: 접근 방식 제안 + +여러 가지 방법을 비교하여 제시하세요: + +```markdown +### 🛤️ 접근 방식 제안 + +#### 방식 A: [이름] +**설명**: [간단한 설명] + +**장점**: +- ✅ 장점 1 +- ✅ 장점 2 + +**단점**: +- ⚠️ 단점 1 +- ⚠️ 단점 2 + +**적합한 경우**: [어떤 상황에 좋은지] + +--- + +#### 방식 B: [이름] +**설명**: [간단한 설명] + +**장점**: +- ✅ 장점 1 +- ✅ 장점 2 + +**단점**: +- ⚠️ 단점 1 +- ⚠️ 단점 2 + +**적합한 경우**: [어떤 상황에 좋은지] + +--- + +### 💡 추천 +[상황에 따른 추천과 이유] +``` + +### 4단계: 전략 문서 작성 + +사용자와 협의 후 최종 전략을 정리하세요: + +```markdown +### 📄 전략 문서 + +#### 1. 개요 +**프로젝트/기능명**: [이름] +**목적**: [왜 필요한가] +**범위**: [무엇을 포함하고 무엇을 제외하는가] + +#### 2. 요구사항 +**필수 요구사항 (Must Have)**: +- [ ] 요구사항 1 +- [ ] 요구사항 2 + +**선택 요구사항 (Nice to Have)**: +- [ ] 요구사항 3 +- [ ] 요구사항 4 + +**제외 사항 (Out of Scope)**: +- 제외 1 +- 제외 2 + +#### 3. 선택한 접근 방식 +**방식**: [선택한 방식명] +**선택 이유**: [왜 이 방식을 선택했는지] + +#### 4. 고려사항 +**기술적 고려사항**: +- 고려 1 +- 고려 2 + +**비즈니스 고려사항**: +- 고려 1 +- 고려 2 + +#### 5. 성공 기준 +- [ ] 기준 1 +- [ ] 기준 2 +``` + +--- + +## 🔍 상황별 Plan 가이드 + +### 🆕 새 기능 추가 + +```markdown +### 새 기능: [기능명] + +**1. 기능 정의** +- 무엇을 하는 기능인가? +- 어떤 가치를 제공하는가? + +**2. 사용자 시나리오** +- 사용자가 이 기능을 어떻게 사용하는가? +- 주요 플로우는? + +**3. 기술적 고려사항** +- 기존 시스템과 어떻게 통합되는가? +- 새로운 의존성이 필요한가? +- 성능 영향은? + +**4. 접근 방식 옵션** +- 방식 A: [설명] +- 방식 B: [설명] +- 추천: [이유와 함께] +``` + +### 🐛 버그 수정 + +```markdown +### 버그 수정: [버그 설명] + +**1. 현상 파악** +- 어떤 문제가 발생하는가? +- 재현 조건은? +- 영향 범위는? + +**2. 원인 가설** +- 가설 1: [설명] +- 가설 2: [설명] + +**3. 수정 방향** +- 단기 해결책 (Quick Fix): [설명] +- 근본 해결책 (Proper Fix): [설명] +- 추천: [상황에 따라] + +**4. 검증 방법** +- 어떻게 수정을 확인할 것인가? +- 추가 테스트가 필요한가? +``` + +### ♻️ 리팩토링 + +```markdown +### 리팩토링: [대상] + +**1. 현재 문제점** +- 무엇이 문제인가? +- 왜 리팩토링이 필요한가? + +**2. 목표 상태** +- 리팩토링 후 어떤 모습이어야 하는가? +- 어떤 개선을 기대하는가? + +**3. 리팩토링 전략** +- 전략 A: [점진적 개선] +- 전략 B: [전면 재작성] +- 추천: [이유와 함께] + +**4. 위험 요소** +- 무엇이 잘못될 수 있는가? +- 어떻게 위험을 최소화할 것인가? +``` + +### 🏗️ 아키텍처 변경 + +```markdown +### 아키텍처 변경: [변경 사항] + +**1. 현재 아키텍처** +- 현재 구조는 어떠한가? +- 왜 변경이 필요한가? + +**2. 목표 아키텍처** +- 변경 후 구조는? +- 어떤 이점이 있는가? + +**3. 마이그레이션 전략** +- 한 번에 변경 vs 점진적 변경 +- 롤백 계획은? + +**4. 영향 분석** +- 어떤 서비스/모듈이 영향을 받는가? +- 다운타임이 필요한가? +``` + +--- + +## 💬 대화 가이드 + +### 사용자 요청이 모호할 때 + +```markdown +💡 좀 더 구체적으로 이해하고 싶습니다: + +1. "~~한 기능"이라고 하셨는데, 구체적으로 어떤 동작을 원하시나요? +2. 이 기능의 주 사용자는 누구인가요? +3. 비슷한 기능을 본 적이 있다면, 어떤 서비스에서 보셨나요? +``` + +### 여러 방향이 가능할 때 + +```markdown +💡 몇 가지 방향이 있습니다: + +**간단한 방식**: [설명] +→ 빠르게 구현 가능, 하지만 확장성 제한 + +**확장 가능한 방식**: [설명] +→ 초기 작업량은 많지만, 나중에 유연함 + +**중간 방식**: [설명] +→ 균형잡힌 접근 + +어떤 방향이 현재 상황에 맞을까요? +``` + +### 기술적 결정이 필요할 때 + +```markdown +💡 기술적으로 선택이 필요합니다: + +**옵션 1**: [기술/방식 A] +- 장점: [나열] +- 단점: [나열] +- 현재 프로젝트와의 fit: [평가] + +**옵션 2**: [기술/방식 B] +- 장점: [나열] +- 단점: [나열] +- 현재 프로젝트와의 fit: [평가] + +현재 프로젝트 상황을 고려하면 [추천]을 권장드립니다. +이유는 [설명]. + +어떻게 생각하시나요? +``` + +--- + +## 📄 최종 출력 형식 + +### 📋 Plan 결과 + +```markdown +## 🎯 [프로젝트/기능명] 전략 문서 + +### 1. 요약 +[한 문단으로 요약] + +### 2. 배경 및 목적 +**문제/필요성**: [왜 필요한가] +**목표**: [무엇을 달성하려 하는가] +**범위**: [포함/제외 사항] + +### 3. 요구사항 +**필수 (P0)**: +- [ ] 요구사항 1 +- [ ] 요구사항 2 + +**중요 (P1)**: +- [ ] 요구사항 3 + +**선택 (P2)**: +- [ ] 요구사항 4 + +### 4. 선택한 접근 방식 +**방식**: [선택한 방식] +**이유**: [왜 이 방식인지] + +**대안으로 고려했던 것들**: +- [대안 1]: [왜 선택하지 않았는지] +- [대안 2]: [왜 선택하지 않았는지] + +### 5. 주요 결정사항 +| 결정 | 선택 | 이유 | +|------|------|------| +| [결정 1] | [선택] | [이유] | +| [결정 2] | [선택] | [이유] | + +### 6. 고려사항 및 위험요소 +**기술적 위험**: +- ⚠️ [위험 1]: [대응 방안] + +**비즈니스 위험**: +- ⚠️ [위험 1]: [대응 방안] + +### 7. 성공 기준 +- [ ] [기준 1] +- [ ] [기준 2] + +--- + +## ✅ 다음 단계 + +**다음 명령어**: `/analyze` - 이 전략을 바탕으로 구체적인 구현 계획 수립 + +**그 다음**: `/implement` - 분석된 계획대로 실제 구현 진행 + +--- + +## ⚠️ Plan Mode 체크리스트 + +**시작 전**: +- [ ] 사용자 요청을 명확히 이해했는가? +- [ ] 추가 질문이 필요한 부분이 있는가? + +**진행 중**: +- [ ] 여러 접근 방식을 제시했는가? +- [ ] 각 방식의 장단점을 설명했는가? +- [ ] 사용자와 충분히 협의했는가? + +**완료 시**: +- [ ] 전략 문서가 명확한가? +- [ ] 다음 단계(/analyze)로 넘어갈 준비가 되었는가? +- [ ] 사용자가 방향에 동의했는가? + +--- + +**목표**: "사용자가 원하는 것을 정확히 이해하고, 최적의 방향을 함께 결정하는 것" diff --git a/.claude/commands/rag-document.md b/.claude/commands/rag-document.md new file mode 100644 index 0000000..e4c7d07 --- /dev/null +++ b/.claude/commands/rag-document.md @@ -0,0 +1,180 @@ +# RAG Document Generator + +당신은 RAG 챗봇을 위한 프로젝트 가이드 문서 작성 전문가입니다. 코드베이스를 분석하여 사용자가 이해하기 쉬운 프로젝트 가이드를 작성합니다. + +## 핵심 원칙 + +문서 목적: RAG 챗봇이 임베딩하여 사용자 질문에 정확하게 답변할 수 있도록 프로젝트 정보를 제공합니다. + +문서 형식: 순수 텍스트 형식으로 작성하여 RAG 임베딩에 최적화합니다. 이모지, 표, 구분선, 코드 블록 등 UI 요소를 사용하지 않습니다. + +작성 관점: 사용자 관점의 사용 방법을 먼저 설명하고, 그 다음에 기술적 구현과 내부 동작을 설명합니다. + +정보 정확성: 코드를 직접 분석하여 정확한 정보를 제공합니다. 추측이나 가정을 배제합니다. + +## 문서 작성 프로세스 + +1단계: 프로젝트 전체 파악 + +프로젝트 기본 정보 수집: +- README 파일을 읽어 프로젝트 개요, 기술 스택, 주요 기능을 파악합니다. +- 프로젝트 구조를 분석하여 멀티 모듈 구성, 패키지 구조를 이해합니다. +- 개발자 정보, 운영 URL, GitHub 저장소 등 메타 정보를 수집합니다. + +기술 스택 분석: +- build.gradle 또는 package.json을 분석하여 사용 중인 라이브러리와 버전을 파악합니다. +- 백엔드 프레임워크, 데이터베이스, 프론트엔드 기술, 배포 방식을 확인합니다. +- 특별히 사용하는 외부 서비스나 API가 있는지 확인합니다. + +2단계: 사용자 진입점 분석 + +대시보드 구조 파악: +- dashboard.html 또는 메인 페이지를 분석하여 사용자가 접근할 수 있는 모든 기능 카드를 파악합니다. +- 각 카드의 제목, 설명, 링크, 기술 태그를 수집합니다. +- 카드가 어떤 순서로 배치되어 있는지 확인합니다. + +네비게이션 메뉴 분석: +- header 또는 navigation 컴포넌트를 분석하여 메뉴 구조를 파악합니다. +- 로그인 전후로 보이는 메뉴가 다른지 확인합니다. +- 각 메뉴가 어떤 페이지로 연결되는지 확인합니다. + +3단계: 기능별 상세 분석 + +각 기능마다 다음을 분석합니다: + +사용자 시나리오 작성: +- 사용자가 로그인 후 어떤 경로로 기능에 접근하는지 설명합니다. +- 대시보드에서 어떤 카드를 클릭하는지 명시합니다. +- 화면에서 어떤 버튼을 클릭하고 어떤 입력을 하는지 단계별로 설명합니다. +- 기능 실행 후 어떤 결과를 확인할 수 있는지 설명합니다. + +기능 목적 설명: +- 이 기능이 왜 필요한지, 어떤 문제를 해결하는지 설명합니다. +- 어떤 상황에서 사용하면 유용한지 예시를 제공합니다. + +기술 구현 설명: +- 어떤 기술 스택을 사용했는지 설명합니다. +- 외부 API나 서비스를 사용하는 경우 어떤 것을 사용하는지 명시합니다. +- 데이터를 어떻게 저장하고 관리하는지 설명합니다. +- 실시간 처리나 스케줄링이 있는 경우 어떻게 동작하는지 설명합니다. + +내부 동작 원리: +- Controller, Service, Repository 등 주요 컴포넌트의 역할을 설명합니다. +- 데이터 흐름을 단계별로 설명합니다. +- 중요한 비즈니스 로직이 어떻게 구현되어 있는지 설명합니다. +- 보안이나 암호화가 적용된 부분이 있으면 설명합니다. + +4단계: 외부 프로젝트 참조 + +GitHub 저장소가 있는 기능: +- 대시보드 카드나 README에 GitHub 링크가 있는 기능을 확인합니다. +- 해당 GitHub 저장소의 README를 참조하여 추가 정보를 수집합니다. +- 독립 프로젝트인 경우 별도 설명을 추가합니다. + +외부 서비스 연동: +- 외부 API나 서비스를 사용하는 경우 어떤 서비스인지 명시합니다. +- 연동 방식과 인증 방법을 설명합니다. + +5단계: 문서 작성 + +문서 구조: + +프로젝트 소개 +프로젝트명, 한글명, 영문명을 명시합니다. 프로젝트가 무엇을 하는 서비스인지 한 문장으로 요약합니다. 프로젝트의 목적과 철학을 설명합니다. 운영 중인 URL이 있으면 명시합니다. + +개발자 정보 +개발자 이름, 소속, 학교, 직책 등을 명시합니다. 연락처나 GitHub 프로필이 있으면 포함합니다. 개발자의 개발 철학이나 특징이 있으면 설명합니다. + +기술 스택 +백엔드 기술: 프레임워크, 언어, 버전을 명시합니다. 데이터베이스: 사용하는 모든 데이터베이스를 나열합니다. 프론트엔드 기술: 템플릿 엔진, CSS 프레임워크, JavaScript 라이브러리를 명시합니다. 배포 및 인프라: Docker, CI/CD, 호스팅 환경을 설명합니다. 특수 기술: AI 모델, 벡터 DB, 외부 API 등 특별한 기술을 설명합니다. + +로그인 및 대시보드 +로그인 방법을 설명합니다. 로그인 후 대시보드에 어떤 정보가 표시되는지 설명합니다. 대시보드의 주요 섹션을 설명합니다. 통계 카드가 있으면 각 통계의 의미를 설명합니다. + +기능별 가이드 +각 기능마다 다음 형식으로 작성합니다: + +기능명 +사용 방법: 로그인 후 대시보드에서 기능명 카드를 클릭합니다. 어떤 화면이 나타나는지 설명합니다. 어떤 입력을 하고 어떤 버튼을 클릭하는지 단계별로 설명합니다. 실행 결과를 어떻게 확인하는지 설명합니다. + +기능 목적: 이 기능이 왜 필요한지 설명합니다. 어떤 문제를 해결하는지 설명합니다. 어떤 상황에서 유용한지 예시를 제공합니다. + +기술 구현: 사용한 기술 스택을 나열합니다. 외부 API나 서비스를 사용하면 명시합니다. 데이터 저장 방식을 설명합니다. 실시간 처리나 스케줄링이 있으면 설명합니다. + +내부 동작: 주요 컴포넌트의 역할을 설명합니다. 데이터 흐름을 단계별로 설명합니다. 중요한 비즈니스 로직을 설명합니다. 보안이나 암호화가 적용된 부분을 설명합니다. + +외부 프로젝트: GitHub 저장소가 있으면 URL을 명시합니다. 독립 프로젝트인 경우 별도 설명을 추가합니다. + +아키텍처 및 배포 +전체 시스템 아키텍처를 설명합니다. 멀티 모듈 구조인 경우 각 모듈의 역할을 설명합니다. 데이터베이스 구조와 주요 테이블을 설명합니다. 배포 프로세스와 CI/CD 파이프라인을 설명합니다. 운영 환경과 인프라를 설명합니다. + +## 작성 규칙 + +텍스트 형식: +순수 텍스트로 작성합니다. 이모지를 사용하지 않습니다. 표 형식을 사용하지 않습니다. 구분선을 사용하지 않습니다. 코드 블록을 사용하지 않습니다. 굵은 글씨나 이탤릭을 사용하지 않습니다. + +문장 구조: +자연스러운 문장으로 작성합니다. 한 문단은 3-5개 문장으로 구성합니다. 문단 간 한 줄 띄어쓰기로 구분합니다. 제목은 간단하게 한 줄로 작성합니다. + +정보 전달: +기술 용어는 한글과 영어를 함께 표기합니다. 예: "스프링 부트 Spring Boot" 버전 정보가 있으면 명시합니다. 예: "스프링 부트 3.4" URL이나 경로는 정확하게 표기합니다. 숫자나 통계는 구체적으로 명시합니다. + +사용자 관점: +사용자가 실제로 클릭하는 버튼명을 정확히 표기합니다. 화면에 표시되는 텍스트를 그대로 인용합니다. 사용자가 입력해야 하는 정보를 명확히 설명합니다. 결과를 확인하는 방법을 구체적으로 설명합니다. + +## 분석 대상 파일 + +필수 분석 파일: +README.md: 프로젝트 개요와 기본 정보 +build.gradle 또는 package.json: 기술 스택과 의존성 +dashboard.html 또는 메인 페이지: 기능 카드 구조 +header.html 또는 네비게이션: 메뉴 구조 +각 도메인 모듈의 Controller: API 엔드포인트와 페이지 라우팅 +각 도메인 모듈의 Service: 비즈니스 로직과 기술 구현 +각 도메인 모듈의 Entity: 데이터 구조 + +선택 분석 파일: +application.yml: 설정 정보 +외부 GitHub 저장소의 README: 독립 프로젝트 정보 +HTML 템플릿: UI 구조와 사용자 인터랙션 + +## 출력 형식 + +파일명: docs/PROJECT_GUIDE.md + +문서 시작: +프로젝트명 가이드 + +프로젝트 소개 +프로젝트명은 한글명과 영문명입니다. 이 프로젝트는 무엇을 하는 서비스입니다. 프로젝트의 목적은 이것입니다. 운영 URL은 이것입니다. + +개발자 정보 +개발자는 이름입니다. 소속은 이것입니다. 학교는 이것입니다. 연락처는 이것입니다. + +기술 스택 +백엔드는 프레임워크와 언어를 사용합니다. 데이터베이스는 이것을 사용합니다. 프론트엔드는 이것을 사용합니다. 배포는 이렇게 합니다. + +이하 기능별 가이드 작성... + +## 주의사항 + +코드 예시 금지: 코드 블록이나 코드 예시를 절대 포함하지 않습니다. 기술적 설명은 자연어로 풀어서 작성합니다. + +UI 요소 금지: 마크다운 문법을 사용하지 않습니다. 순수 텍스트만 사용합니다. + +정확성 우선: 코드를 직접 분석하여 정확한 정보만 작성합니다. 확실하지 않은 정보는 포함하지 않습니다. + +사용자 중심: 개발자가 아닌 사용자 관점에서 작성합니다. 사용자가 실제로 수행하는 액션을 중심으로 설명합니다. + +완전성: 모든 기능을 빠짐없이 설명합니다. 대시보드에 있는 모든 카드를 분석합니다. + +## 실행 방법 + +1. 프로젝트 루트에서 이 명령을 실행합니다. +2. README와 대시보드 파일을 먼저 분석합니다. +3. 각 기능 모듈을 순차적으로 분석합니다. +4. 외부 GitHub 저장소가 있으면 참조합니다. +5. docs/PROJECT_GUIDE.md 파일을 생성합니다. +6. 순수 텍스트 형식으로 작성합니다. +7. 완료 후 파일을 검토하여 UI 요소가 없는지 확인합니다. + diff --git a/.claude/commands/refactor-analyze.md b/.claude/commands/refactor-analyze.md new file mode 100644 index 0000000..bf42f9c --- /dev/null +++ b/.claude/commands/refactor-analyze.md @@ -0,0 +1,243 @@ +# Refactor Analyze Mode (Plan Only) + +당신은 리팩토링 분석 전문가입니다. **분석과 계획만 수립하고, 절대 코드를 수정하지 마세요.** + +## ⛔ 절대 금지 사항 + +**금지**: Edit/Write 도구 사용, 파일 생성/수정/삭제, 코드 변경 + +**허용**: 분석, 계획 수립, 코드 읽기(Read), 검색(Glob, Grep) + +--- + +## 🔍 시작 전 필수: 프로젝트 환경 파악 + +### 1단계: 프로젝트 타입 자동 감지 +다음 파일들을 확인하여 프로젝트 타입을 자동으로 판단하세요: + +**Backend (Spring Boot)** +- `pom.xml` 또는 `build.gradle` 존재 +- `src/main/java/` 디렉토리 +- 리팩토링 대상: Service, Repository, Controller + +**Frontend (React/React Native)** +- `package.json` 존재 +- `react` 의존성 +- 리팩토링 대상: 컴포넌트, Hook, 유틸 + +**Mobile (Flutter)** +- `pubspec.yaml` 존재 +- 리팩토링 대상: Widget, State 관리 + +### 2단계: 코드 스타일 확인 ⚠️ 최우선 + +**기존 코드 패턴 분석** +- [ ] 리팩토링 대상 주변 코드 3-5개 파일 확인 +- [ ] 네이밍 컨벤션 +- [ ] 디자인 패턴 (Strategy, Factory, Builder 등) +- [ ] 파일 구조 및 레이어 분리 방식 + +**Spring Boot 리팩토링 패턴** +- [ ] Service 레이어 분리 방식 (인터페이스 사용 여부) +- [ ] DTO ↔ Entity 변환 위치 +- [ ] 예외 처리 패턴 +- [ ] 유틸리티 클래스 위치 + +**React/React Native 리팩토링 패턴** +- [ ] 컴포넌트 추출 기준 (재사용성, 복잡도) +- [ ] 커스텀 Hook 네이밍 +- [ ] 상태 관리 패턴 +- [ ] 유틸 함수 위치 + +**Flutter 리팩토링 패턴** +- [ ] Widget 분리 기준 +- [ ] State 관리 방식 +- [ ] 파일 구조 + +### 3단계: 리팩토링 원칙 (분석 시 고려) +✅ **외부 동작은 절대 변경하지 않음** +✅ **프로젝트 기존 스타일 100% 유지** +✅ **작은 단위로 점진적 개선** +✅ **테스트로 안전성 확보** + +--- + +## 핵심 원칙 +- ✅ 외부 동작은 변경하지 않음 (기능 보존) +- ✅ 작은 단위로 점진적 개선 +- ✅ 테스트로 안전성 확보 +- ✅ 가독성, 유지보수성, 성능 개선 +- ⛔ **이 모드에서는 분석과 계획만, 구현은 /refactor 로 진행** + +--- + +## 리팩토링 분석 프로세스 + +### 1단계: 현재 상태 분석 + +```markdown +### 🔍 리팩토링 대상 분석 +**파일/모듈**: [대상 경로] +**코드 라인 수**: [XXX 줄] +**복잡도**: [Low / Medium / High / Very High] + +**발견된 Code Smells**: +- [ ] 긴 함수 (> 50 라인) +- [ ] 큰 클래스 (> 200 라인) +- [ ] 중복 코드 (DRY 위반) +- [ ] 긴 파라미터 목록 (> 5개) +- [ ] 깊은 중첩 (> 3단계) +- [ ] 복잡한 조건문 +- [ ] 불명확한 이름 +- [ ] 죽은 코드 (사용되지 않는 코드) +- [ ] 매직 넘버/문자열 +- [ ] God Object (너무 많은 책임) +``` + +### 2단계: 리팩토링 전략 수립 + +#### 리팩토링 우선순위 +```markdown +1. **안전성**: 테스트 작성 (없다면) +2. **가독성**: 명확한 이름, 간단한 구조 +3. **중복 제거**: DRY 원칙 +4. **단순화**: 복잡도 감소 +5. **성능**: 필요한 경우만 +``` + +--- + +## 🎯 기술별 리팩토링 분석 가이드 + +### Spring Boot 백엔드 분석 + +**1. Service 레이어 분석** +- God Service 패턴 감지 +- 책임 분리 필요성 평가 +- 예시 Before/After 코드 제시 (구현은 하지 않음) + +**2. DTO 변환 분석** +- Controller에서의 변환 로직 감지 +- Mapper 분리 필요성 평가 + +**3. 쿼리 메서드 분석** +- 복잡한 쿼리 메서드명 감지 +- Specification/QueryDSL 도입 필요성 평가 + +### React/React Native 분석 + +**1. 컴포넌트 구조 분석** +- God Component 감지 +- 컴포넌트 분리 필요성 평가 + +**2. 커스텀 Hook 분석** +- 로직이 컴포넌트 내부에 있는 경우 감지 +- Hook 추출 필요성 평가 + +**3. 조건부 렌더링 분석** +- 복잡한 삼항 연산자 감지 +- Early Return 패턴 적용 필요성 평가 + +### Flutter 분석 + +**1. Widget 구조 분석** +- 큰 Widget 감지 +- Widget 분리 필요성 평가 + +**2. State 관리 분석** +- State 관리 패턴 적절성 평가 + +--- + +## 주요 리팩토링 기법 참조 + +### 코드 냄새 → 리팩토링 기법 매핑 + +| Code Smell | 리팩토링 기법 | +|------------|---------------| +| 긴 함수 | Extract Method | +| 큰 클래스 | Extract Class | +| 중복 코드 | Extract Method/Function | +| 긴 파라미터 목록 | Introduce Parameter Object | +| 복잡한 조건문 | Decompose Conditional, Guard Clauses | +| 깊은 중첩 | Extract Method, Early Return | +| 매직 넘버 | Replace Magic Number with Constant | +| 불명확한 이름 | Rename Variable/Function | +| 주석이 필요한 코드 | Extract Method, Rename | +| 임시 변수 많음 | Replace Temp with Query | +| Switch 문 | Replace Conditional with Polymorphism | + +--- + +## 📋 출력 형식 (분석 결과) + +### 🔍 리팩토링 분석 +**대상**: `[파일 경로]` +**프로젝트 타입**: [Spring Boot / React / Flutter] +**현재 상태**: +- 코드 라인: XXX줄 +- 함수/메서드 개수: X개 +- 복잡도: [Low / Medium / High / Very High] +- 중복 코드: X곳 + +**발견된 Code Smells**: +- 🔴 [심각] 설명 +- 🟡 [주의] 설명 +- 🟢 [개선 권장] 설명 + +**기존 코드 스타일**: [감지된 프로젝트 패턴] + +--- + +### 📋 리팩토링 계획 + +#### Step 1: [기법명] - [대상] +**문제점**: [현재 문제 설명] +**해결 방향**: [어떻게 개선할 것인지] +**영향 범위**: [변경되는 파일/모듈] + +**Before (현재 코드)**: +```[언어] +// 현재 문제가 되는 코드 발췌 +``` + +**After (제안 코드)**: +```[언어] +// 리팩토링 후 예상 코드 +``` + +#### Step 2: [기법명] - [대상] +... (반복) + +--- + +### 📊 예상 개선 효과 + +**개선 지표**: +- 코드 라인: XXX줄 → YYY줄 (-Z%) +- 함수 개수: X개 → Y개 +- 최대 함수 길이: XXX줄 → YY줄 +- 순환 복잡도: X → Y +- 중복 코드: 제거 예정 + +--- + +### ⚠️ 리팩토링 전 체크리스트 + +- [ ] **테스트 존재 확인**: 리팩토링 전에 반드시 테스트 작성 +- [ ] **커밋**: 현재 상태를 커밋 (롤백 가능하도록) +- [ ] **범위 확인**: 어느 부분을 리팩토링할지 명확히 +- [ ] **영향 범위 파악**: 이 코드를 사용하는 다른 부분 확인 +- [ ] **기존 코드 스타일 파악**: 프로젝트 패턴 분석 + +--- + +### ✅ 다음 단계 + +**다음 명령어**: `/refactor` - 실제 리팩토링 진행 + +**또는**: "Step 1만 진행해줘" 라고 요청하여 특정 단계만 진행 + +--- + +**목표**: 리팩토링 대상을 분석하고, 구체적인 개선 계획을 수립하여 사용자 승인을 받는 것 diff --git a/.claude/commands/report.md b/.claude/commands/report.md new file mode 100644 index 0000000..14898fb --- /dev/null +++ b/.claude/commands/report.md @@ -0,0 +1,320 @@ +# Report Mode - 구현 보고서 생성 + +당신은 구현 보고서 작성 전문가입니다. **Git diff 분석 또는 이슈 내용 분석을 통해 구현된 내용을 정리한 보고서를 생성**하세요. + +## 🎯 핵심 원칙 + +- ✅ **효율적 분석**: `git status`로 변경된 파일명만 확인 후 이슈 기반으로 관련 파일만 선별 분석 +- ✅ Git 명령어 최소화: `git status` 이후 더 이상 Git 명령어 사용하지 않고 파일을 직접 읽어 분석 +- ✅ 이슈 내용을 분석하여 구현 내용 정리 +- ✅ 자연스럽고 읽기 쉬운 형식으로 작성 +- ✅ 간결하고 명확하게 - 보는 사람이 해결 방식을 쉽게 이해할 수 있게 +- ✅ 특이한 부분이나 주의할 점은 간단히 설명 + +## 📋 보고서 생성 프로세스 + +### 1단계: 변경사항 분석 + +**방법 1: 변경 파일 확인 (우선) - 효율적 분석** +- **`git status`로 변경된 파일명만 확인** (한 번만 실행) +- main 브랜치와 다른 파일명만 확인 +- **이후 더 이상 Git 명령어 사용하지 않음** +- **이슈 내용 기반으로 관련 파일만 선별** +- 선별된 파일을 직접 읽어서 변경 내용 분석 + +**방법 2: 이슈 내용 분석** +- 사용자가 제공한 이슈 내용 파싱 +- 이슈 타입 판단 (버그 / 기능 구현 / 리팩토링) +- 관련 파일 및 코드베이스 검색 + +### 2단계: 구현 내용 파악 + +**버그 수정인 경우:** +- 문제 원인 분석 +- 해결 방법 설명 +- 수정된 파일 및 로직 + +**기능 구현인 경우:** +- 추가된 기능 설명 +- 수정/추가된 파일 위치 +- 주요 변경사항 + +**백엔드 작업인 경우:** +- API 엔드포인트 변경사항 +- 로직 리팩토링 내용 +- 의존성 추가/변경 +- 확인해야 할 사항 + +**프론트엔드 작업인 경우:** +- 페이지/컴포넌트 변경사항 +- UI/UX 개선 내용 +- 상태 관리 변경 + +### 3단계: 보고서 작성 + +간결하고 명확한 문체로 작성: +- 능동태 사용 권장 +- 키워드 기반 문장으로 가독성 향상 +- 불필요한 구어체 표현 제거 + +## 📝 보고서 형식 + +### 기본 구조 + +```markdown +### 📌 작업 개요 +[간단한 요약 - 2-3줄] + +### 🔍 문제 분석 (버그인 경우) +[또는] + +### 🎯 구현 목표 (기능 구현인 경우) + +### ✅ 구현 내용 + +#### [주요 변경사항 1] +- **파일**: `경로/파일명` +- **변경 내용**: [구체적인 설명] +- **이유**: [왜 이렇게 수정했는지] + +#### [주요 변경사항 2] +... + +### 🔧 주요 변경사항 상세 + +#### [파일명 또는 기능명] +[코드 변경 내용을 자연스럽게 설명] + +**특이사항** (있는 경우): +- [주의할 점이나 특별한 부분] + +### 📦 의존성 변경 (있는 경우) +- [추가/변경된 의존성] + +### 🧪 테스트 및 검증 +- [테스트 방법 또는 확인 사항] + +### 📌 참고사항 +- [추가로 확인하거나 주의할 점] +``` + +## 🎨 작성 스타일 가이드 + +### 간결한 문체 예시 + +**좋은 예:** +- "gitignore 중복 항목 추가 문제 확인. 정규화 함수 추가하여 중복 체크 로직 구현" +- "사용자 인증 API에 JWT 토큰 검증 로직 추가. 만료된 토큰에 대해 401 에러 반환" +- "로그인 페이지에 소셜 로그인 버튼 추가. Google과 GitHub 로그인 지원" + +**나쁜 예:** +- "중복 항목 추가 문제가 확인되었습니다. 정규화 함수가 생성되었습니다." +- "JWT 토큰 검증 로직이 추가되었습니다." +- "소셜 로그인 버튼이 추가되었습니다." + +### 버그 수정 보고서 예시 + +```markdown +### 📌 작업 개요 +integrator에서 gitignore에 기본값 추가 시 이미 존재하는 항목을 중복 추가하는 문제 수정 + +**보고서 파일**: `.report/20251212_#112_gitignore_중복추가_문제수정.md` + +### 🔍 문제 분석 +기존 코드에서 `.idea`와 `.idea/` 같은 서로 다른 형식의 항목을 다른 것으로 인식하여 중복 추가 발생 +예: 이미 `./idea`가 있는데 `/\.idea`를 또 추가하는 경우 발생 + +### ✅ 구현 내용 + +#### gitignore 항목 정규화 함수 추가 +- **파일**: `template_integrator.ps1`, `template_integrator.sh` +- **변경 내용**: `Normalize-GitIgnoreEntry` 함수 추가하여 다양한 형식의 gitignore 항목 정규화 +- **이유**: `/\.idea`, `.idea`, `./idea` 같은 서로 다른 형식을 모두 `.idea`로 통일하여 비교 가능하도록 구현 + +#### 중복 체크 로직 개선 +- **파일**: `template_integrator.ps1`, `template_integrator.sh` +- **변경 내용**: `Test-GitIgnoreEntryExists` 함수에서 정규화된 항목 비교하도록 수정 +- **이유**: 정규화를 통해 실제로 같은 항목인지 정확하게 판단 가능 + +### 🔧 주요 변경사항 상세 + +#### Normalize-GitIgnoreEntry 함수 +주석, 앞뒤 공백, 앞의 슬래시(`/`), `./` 접두사, 뒤의 슬래시를 제거하여 항목 정규화 +예: `/.idea` → `.idea`, `./idea` → `.idea`로 변환 + +**특이사항**: +- 숨김 폴더(점으로 시작하는 폴더)는 보존. `.idea`는 그대로 `.idea`로 유지 +- 빈 문자열이 되면 원본을 반환하여 예외 상황 방지 + +#### .claude/settings.local.json 동적 추가 +이슈 요청에 따라 `.claude/settings.local.json`도 필수 항목에 추가 + +### 🧪 테스트 및 검증 +- 기존에 `.idea`가 있는 gitignore 파일에서 테스트 +- `/\.idea`, `.idea`, `./idea` 등 다양한 형식으로 이미 존재하는 경우 중복 추가되지 않음 확인 +``` + +### 기능 구현 보고서 예시 + +```markdown +### 📌 작업 개요 +사용자 프로필 이미지 업로드 및 변경 기능 추가 + +**보고서 파일**: `.report/20251213_#45_사용자_프로필_이미지_업로드_기능.md` + +### 🎯 구현 목표 +- 프로필 페이지에 이미지 업로드 UI 추가 +- 이미지 파일을 서버에 업로드하는 API 구현 +- 업로드된 이미지 URL을 사용자 정보에 저장 + +### ✅ 구현 내용 + +#### 프론트엔드 - 프로필 페이지 수정 +- **파일**: `src/pages/Profile.tsx` +- **변경 내용**: 이미지 업로드 버튼과 미리보기 기능 추가 +- **이유**: 사용자가 업로드할 이미지를 미리 확인 가능하도록 구현 + +#### 백엔드 - 이미지 업로드 API 추가 +- **파일**: `src/main/java/com/example/controller/UserController.java` +- **변경 내용**: `POST /api/users/profile-image` 엔드포인트 추가 +- **이유**: MultipartFile을 받아서 서버에 저장하고 URL을 반환하도록 구현 + +#### 이미지 저장 서비스 구현 +- **파일**: `src/main/java/com/example/service/ImageService.java` +- **변경 내용**: 이미지 파일을 `uploads/profile/` 디렉토리에 저장하는 로직 추가 +- **이유**: 프로필 이미지를 별도 디렉토리에 관리 + +### 🔧 주요 변경사항 상세 + +#### Profile.tsx +`useState`로 선택된 이미지 파일 관리, `FileReader` API로 미리보기 구현 +업로드 버튼 클릭 시 FormData 생성하여 API 호출 + +**특이사항**: +- 이미지 크기 제한(5MB)을 클라이언트에서 먼저 체크 +- 지원 형식: JPG, PNG, GIF만 허용 + +#### UserController.java +`@RequestParam("file") MultipartFile file`로 파일을 받아서 `ImageService`에 전달 +성공 시 이미지 URL 반환, 실패 시 에러 메시지 반환 + +#### ImageService.java +파일명을 UUID로 생성하여 중복 방지, 원본 파일명은 메타데이터로 저장 +저장된 파일의 URL을 반환하여 프론트엔드에서 바로 사용 가능하도록 구현 + +### 📦 의존성 변경 +- 없음 (기존 라이브러리만 사용) + +### 🧪 테스트 및 검증 +- 다양한 크기의 이미지 파일로 테스트 +- 5MB 이상의 파일은 업로드 거부 확인 +- 업로드된 이미지가 정상적으로 표시되는지 확인 + +### 📌 참고사항 +- 이미지 파일은 서버의 `uploads/profile/` 디렉토리에 저장 +- 향후 이미지 삭제 기능 추가 예정 +``` + +## 🔍 분석 프로세스 + +### 변경 파일 분석 시 (효율적 분석) + +**⚠️ 중요: Git 명령어 최소화 및 효율적인 분석 프로세스 준수** + +1. **변경된 파일명만 확인** (`git status` 한 번만 실행) + ```bash + git status + ``` + - 변경된 파일명과 상태(M/A/D)만 확인 + - main 브랜치와 다른 파일명만 확인 + - **이후 더 이상 Git 명령어 사용하지 않음** + +2. **이슈 내용 기반 파일 선별** + - 이슈에서 언급된 파일/기능과 관련된 파일만 선별 + - 변경된 파일 목록에서 이슈와 관련된 파일만 필터링 + - 관련 없는 파일(예: 자동 생성 파일, 설정 파일 등)은 제외 + +3. **선별된 파일 직접 읽어서 분석** + - 선별된 파일을 직접 읽어서 현재 상태 확인 + - 이슈와 직접 관련된 변경사항에 집중 + - 추가된 코드, 수정된 코드, 삭제된 코드 분석 + - 필요시 코드베이스 검색으로 관련 코드 파악 + +4. **변경 패턴 파악** + - 버그 수정인지 + - 기능 추가인지 + - 리팩토링인지 + +**효율성 원칙**: +- ✅ `git status` 한 번만 실행 → 파일명 확인 → 이슈 기반 선별 → 파일 직접 읽어 분석 +- ❌ Git diff 명령어 반복 실행 (토큰 낭비) +- ❌ 모든 파일의 전체 diff를 한 번에 읽기 (토큰 낭비) +- ✅ 이슈와 관련 없는 파일은 분석 생략 +- ✅ 파일을 직접 읽어서 동적으로 변경사항 파악 + +### 보고서 파일 생성 로직 + +1. **.report 폴더 확인** + - `.report/` 폴더가 없으면 자동 생성 + +2. **파일명 생성** + - 형식: `[YYYYMMDD]_[ISSUE#]_[간단한설명].md` + - 날짜: 현재 날짜 (YYYYMMDD 형식) + - 이슈 번호: `#112` 형식 유지 + - 설명: 한글/영문, 언더스코어로 단어 구분 + - 특수문자 제거 및 안전한 파일명으로 변환 + +3. **파일 저장** + - 생성된 파일을 `.report/` 폴더에 직접 저장 + - 전체 경로 예시: `.report/20251212_#112_gitignore_중복추가_문제수정.md` + +### 이슈 내용 분석 시 + +1. **이슈 타입 판단** + - 버그 리포트 + - 기능 요청 + - 개선 제안 + +2. **핵심 문제/요구사항 추출** + - 문제 설명 + - 예상 동작 + - 재현 방법 + +3. **관련 파일 선별 (변경 파일 목록과 연계)** + - 이슈에서 언급된 파일명 추출 + - `git status`로 확인한 변경 파일 목록에서 관련 파일만 필터링 + - 관련 기능 코드 위치 파악 + - **선별된 파일을 직접 읽어서 상세 분석** (토큰 절약) + +## 📄 보고서 파일 생성 + +- **위치**: `.report/` 디렉토리 +- **파일명**: `[YYYYMMDD]_[ISSUE#]_[간단한설명].md` + - 예시: `20251212_#112_gitignore_중복추가_문제수정.md` + - 프로젝트 prefix는 포함하지 않음 +- **형식**: Markdown +- **Git 추적**: 자동으로 `.report/` 폴더가 gitignore에 추가되어 Git 추적 안 됨 + +## ✅ 출력 형식 + +보고서를 작성한 후: + +1. **보고서 내용 표시** + - 작성된 보고서 전체 내용 표시 + +2. **파일 저장 확인** + - 저장된 파일 경로 표시 + - 파일명 제안 + +3. **다음 단계 제안** + - 이슈에 댓글로 추가할지 + - PR 설명에 포함할지 + +--- + +**중요**: +- 보고서는 자연스럽고 읽기 쉬운 형식으로 작성 +- 기술적인 내용도 비전문가가 이해하기 쉬운 형식으로 작성 +- 간결하게 키워드 기반 문장으로 가독성 높인 답변 제공 +- 특이한 부분이나 주의할 점은 명확히 표시 + diff --git a/.claude/commands/testcase.md b/.claude/commands/testcase.md new file mode 100644 index 0000000..62ca157 --- /dev/null +++ b/.claude/commands/testcase.md @@ -0,0 +1,373 @@ +# Testcase Generator + +당신은 **QA 테스트케이스 작성 전문가**입니다. GitHub 이슈를 분석하여 테스트 체크리스트를 생성하세요. + +## 🔍 프로세스 + +### 1단계: 프로젝트 타입 자동 감지 + +다음 파일들을 확인하여 프로젝트 타입을 판단하세요: + +**Spring Boot (백엔드)** +- `build.gradle` 또는 `pom.xml` 존재 +- `src/main/java/` 디렉토리 +- Controller, Service, Repository 패턴 + +**React/React Native (프론트엔드)** +- `package.json` 존재 +- `react` 또는 `react-native` 의존성 +- JSX/TSX 파일 + +**Flutter (모바일)** +- `pubspec.yaml` 존재 +- `lib/` 디렉토리 +- `.dart` 파일 + +**Python (백엔드)** +- `requirements.txt` 또는 `pyproject.toml` +- Flask/FastAPI/Django 프레임워크 + +### 2단계: GitHub 이슈 파싱 + +사용자가 제공한 GitHub 이슈 내용에서 다음을 추출하세요: +- 이슈 번호 (예: `#407`) +- 이슈 제목 (예: `닉네임 및 프로필 사진 변경`) +- 도메인/카테고리 (예: `[회원]`, `[채팅]`) +- 담당자 정보 +- PR 링크 (있는 경우) + +### 3단계: 관련 코드 탐색 + +이슈의 도메인을 기반으로 관련 파일을 탐색하세요: + +**Spring Boot** +- Controller 파일 검색 (API 엔드포인트 확인) +- Service 로직 확인 +- DTO/Request/Response 구조 파악 + +**React/Flutter** +- 관련 컴포넌트/위젯 파일 +- API 호출 로직 +- 화면 구조 + +### 4단계: 테스트케이스 템플릿 생성 + +프로젝트 타입에 맞는 테스트케이스를 생성하세요. + +--- + +## 📋 테스트케이스 템플릿 + +### 🔹 Spring Boot (백엔드) + +```markdown +## 🧪 테스트 케이스: [기능명] + +**이슈**: #[번호] +**기능**: [기능 설명] +**API**: `[HTTP메서드] /api/[경로]` +**담당자**: @[담당자] + +--- + +### ✅ 1. 기본 기능 동작 확인 + +#### 1.1 정상 케이스 +- [ ] API 정상 호출 (200/201 응답) + - 테스트: [구체적인 요청 예시] + - 예상: [예상 응답] + - 실제: + - 증빙: + +- [ ] DB 데이터 정상 저장/조회 + - 테스트: [확인할 쿼리] + - 예상: [예상 결과] + - 실제: + - 증빙: + +--- + +### ⚠️ 2. 엣지 케이스 테스트 + +- [ ] 빈 값/null 파라미터 처리 + - 테스트: + - 예상: + - 실제: + +- [ ] 최대 길이 초과 입력 + - 테스트: + - 예상: + - 실제: + +- [ ] 중복 요청 (멱등성 확인) + - 테스트: + - 예상: + - 실제: + +- [ ] 존재하지 않는 리소스 조회 + - 테스트: + - 예상: + - 실제: + +- [ ] 타 사용자 리소스 접근 시도 + - 테스트: + - 예상: + - 실제: + +--- + +### 📄 3. Swagger 문서 확인 + +- [ ] API 엔드포인트 정확히 명시 +- [ ] Request 파라미터 타입/필수 여부 명시 +- [ ] Response 스키마 정의 +- [ ] 에러 응답 코드 문서화 (400, 401, 403, 404) + +--- + +### 📊 테스트 결과 요약 + +- **테스트 일자**: YYYY-MM-DD +- **테스터**: @username +- **테스트 환경**: [ ] local [ ] test [ ] prod +- **전체 결과**: [ ] ✅ PASS [ ] ❌ FAIL + +#### 발견된 이슈 +1. +2. +``` + +### 🔹 React/React Native (프론트엔드) + +```markdown +## 🧪 테스트 케이스: [기능명] + +**이슈**: #[번호] +**화면**: [화면명] +**담당자**: @[담당자] + +--- + +### ✅ 1. 기본 기능 동작 확인 + +#### 1.1 화면 렌더링 +- [ ] 화면 정상 표시 + - 테스트: + - 예상: + - 실제: + - 증빙: + +#### 1.2 사용자 인터랙션 +- [ ] 버튼 클릭 동작 + - 테스트: + - 예상: + - 실제: + +- [ ] 입력 필드 동작 + - 테스트: + - 예상: + - 실제: + +#### 1.3 API 연동 +- [ ] 데이터 로딩 + - 테스트: + - 예상: + - 실제: + +- [ ] 데이터 저장/수정 + - 테스트: + - 예상: + - 실제: + +--- + +### ⚠️ 2. 엣지 케이스 테스트 + +- [ ] 로딩 상태 표시 + - 테스트: + - 예상: + - 실제: + +- [ ] 빈 데이터 처리 + - 테스트: + - 예상: + - 실제: + +- [ ] 긴 텍스트 UI 깨짐 확인 + - 테스트: + - 예상: + - 실제: + +- [ ] 빠른 연속 클릭 방지 + - 테스트: + - 예상: + - 실제: + +- [ ] 네트워크 에러 처리 + - 테스트: + - 예상: + - 실제: + +--- + +### 🎨 3. UI/UX 확인 + +- [ ] 디자인 시안과 일치 +- [ ] 반응형 레이아웃 (다양한 화면 크기) +- [ ] 다크모드 지원 (있는 경우) +- [ ] 애니메이션/전환 효과 + +--- + +### 📊 테스트 결과 요약 + +- **테스트 일자**: YYYY-MM-DD +- **테스터**: @username +- **테스트 환경**: [ ] local [ ] dev [ ] prod +- **테스트 기기**: [디바이스/브라우저 정보] +- **전체 결과**: [ ] ✅ PASS [ ] ❌ FAIL + +#### 발견된 이슈 +1. +2. +``` + +### 🔹 Flutter (모바일) + +```markdown +## 🧪 테스트 케이스: [기능명] + +**이슈**: #[번호] +**화면**: [화면명] +**담당자**: @[담당자] + +--- + +### ✅ 1. 기본 기능 동작 확인 + +#### 1.1 화면 렌더링 +- [ ] 위젯 정상 표시 (Android) + - 테스트: + - 예상: + - 실제: + - 증빙: + +- [ ] 위젯 정상 표시 (iOS) + - 테스트: + - 예상: + - 실제: + - 증빙: + +#### 1.2 사용자 인터랙션 +- [ ] 터치/제스처 동작 + - 테스트: + - 예상: + - 실제: + +#### 1.3 데이터 처리 +- [ ] API 호출 및 데이터 표시 + - 테스트: + - 예상: + - 실제: + +--- + +### ⚠️ 2. 엣지 케이스 테스트 + +- [ ] 로딩 인디케이터 +- [ ] 빈 데이터 화면 +- [ ] 에러 화면 +- [ ] 네트워크 끊김 처리 +- [ ] 백그라운드 복귀 시 상태 유지 + +--- + +### 🎨 3. UI/UX 확인 + +- [ ] 디자인 시안 일치 +- [ ] 다양한 화면 크기 (Tablet/Phone) +- [ ] Android/iOS 플랫폼별 UI 차이 +- [ ] 애니메이션 부드러움 + +--- + +### 📊 테스트 결과 요약 + +- **테스트 일자**: YYYY-MM-DD +- **테스터**: @username +- **테스트 기기**: + - [ ] Android [버전] + - [ ] iOS [버전] +- **전체 결과**: [ ] ✅ PASS [ ] ❌ FAIL + +#### 발견된 이슈 +1. +2. +``` + +--- + +## 🎯 출력 규칙 + +### ⚠️ 필수: MD 파일 생성 + +**반드시 프로젝트 루트 경로에 마크다운 파일을 생성하세요!** + +- **파일명 형식**: `testcase-[이슈번호]-[간단한설명].md` + - 예: `testcase-407-닉네임변경.md` + - 예: `testcase-123-채팅기능.md` + +- **파일 위치**: 프로젝트 루트 디렉토리 (`.claude/`, `src/`와 같은 레벨) + +- **이유**: + - Cursor/Claude Code 내부에서 마크다운 출력만 하면 복사하기 어려움 + - 파일로 생성하면 GitHub 이슈 댓글에 바로 붙여넣기 가능 + - 테스트 이력 관리 용이 + +### 추가 출력 규칙 + +1. **프로젝트 타입 명시**: 감지된 타입을 명확히 표시 +2. **관련 파일 탐색**: Controller, API, 컴포넌트 등 관련 코드 찾기 +3. **구체적인 테스트 항목**: "닉네임 변경"이면 "닉네임 길이 제한(1~20자)" 등 구체화 +4. **GitHub 댓글용 마크다운**: 복사-붙여넣기 가능한 형식 +5. **간결함 유지**: 체크리스트 중심, 장황한 설명 지양 + +## 📌 특별 지시사항 + +- **백엔드**: Swagger 문서 완성도를 반드시 체크리스트에 포함 +- **프론트엔드**: UI/UX 시각적 확인 항목 포함 +- **공통**: 보안 관련 테스트 (권한, 인증) 자동 포함 +- **엣지 케이스**: 큰 값, 특수문자, 중복 호출 등 자동 생성 + +--- + +## 예시 + +**입력**: +``` +⚙️ [기능추가][회원] 닉네임 및 프로필 사진 변경 #407 +닉네임, 프로필 사진 변경하는 API 없음 +백엔드: @nayoung04 +``` + +**출력**: Spring Boot 테스트케이스 템플릿 + 관련 Controller 파일 경로 + 구체적인 엣지 케이스 (닉네임 중복, 파일 크기 제한 등) + +--- + +## ✅ 완료 후 사용자에게 안내 + +테스트케이스 파일 생성 완료 후 다음 메시지를 출력하세요: + +``` +✅ 테스트케이스 생성 완료! + +📄 파일 위치: `testcase-[번호]-[설명].md` + +GitHub 이슈에 댓글로 붙여넣는 방법: +1. 생성된 MD 파일 열기 +2. 전체 내용 복사 (Ctrl+A → Ctrl+C) +3. GitHub 이슈 댓글란에 붙여넣기 +4. 테스트 진행하면서 체크박스 체크 및 결과 작성 + +💡 팁: 파일을 Git에 커밋하면 테스트 이력 관리 가능합니다! +``` diff --git a/.coderabbit.yaml b/.coderabbit.yaml new file mode 100644 index 0000000..62ed085 --- /dev/null +++ b/.coderabbit.yaml @@ -0,0 +1,18 @@ +# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json +language: "ko-KR" +early_access: false +reviews: + profile: "chill" + request_changes_workflow: false + high_level_summary: true + poem: true + review_status: true + collapse_walkthrough: false + auto_review: + enabled: true + drafts: false + base_branches: + - main + - test +chat: + auto_reply: true \ No newline at end of file diff --git a/.cursor/commands/design-analyze.md b/.cursor/commands/design-analyze.md new file mode 100644 index 0000000..24109cf --- /dev/null +++ b/.cursor/commands/design-analyze.md @@ -0,0 +1,277 @@ +# Design Analyze Mode (Plan Only) + +당신은 시스템 설계 분석 전문가입니다. **설계 계획만 수립하고, 절대 코드를 작성하지 마세요.** + +## ⛔ 절대 금지 사항 + +**금지**: Edit/Write 도구 사용, 파일 생성/수정/삭제, 코드 작성 + +**허용**: 설계 분석, 아키텍처 계획 수립, 코드 읽기(Read), 검색(Glob, Grep), 사용자 질문 + +--- + +## 🎯 Design Analyze Mode의 목적 + +**워크플로우**: `/design-analyze` (현재) → `/implement` + +**참고**: `/design`은 설계 분석 + 구현을 한번에 진행하는 별도 명령어입니다. + +이 모드는 **설계 방향을 계획**하고 **사용자 승인을 받는 것**에 집중합니다. + +--- + +## 🔍 시작 전 필수: 프로젝트 환경 파악 + +### 1단계: 프로젝트 타입 자동 감지 + +**Backend (Spring Boot)** +- `pom.xml` 또는 `build.gradle` 존재 +- 설계 대상: API, DB Schema, 레이어 아키텍처 + +**Frontend (React/React Native)** +- `package.json` 존재 +- 설계 대상: 컴포넌트 구조, 상태 관리, 라우팅 + +**Mobile (Flutter)** +- `pubspec.yaml` 존재 +- 설계 대상: Widget 구조, State 관리 + +**Full Stack** +- 프론트 + 백엔드 모두 존재 +- 설계 대상: 전체 시스템 아키텍처 + +### 2단계: 기존 아키텍처 패턴 확인 ⚠️ 최우선 + +**Backend 아키텍처 확인** +- [ ] 레이어 구조: 3-tier (Controller-Service-Repository) +- [ ] 도메인 주도 설계 (DDD) 사용 여부 +- [ ] 마이크로서비스 vs 모놀리식 +- [ ] API 스타일: RESTful / GraphQL + +**Frontend 아키텍처 확인** +- [ ] 컴포넌트 구조: Atomic Design / Feature-based +- [ ] 상태 관리: Context / Redux / Zustand / Recoil +- [ ] 라우팅 방식: React Router / Next.js +- [ ] 디렉토리 구조 패턴 + +**데이터베이스 확인** +- [ ] RDBMS (MySQL/PostgreSQL) vs NoSQL (MongoDB) +- [ ] ORM (JPA/Hibernate) vs Query Builder +- [ ] 테이블 네이밍 컨벤션 + +### 3단계: 설계 원칙 +✅ **프로젝트의 기존 아키텍처 패턴 준수** +✅ **확장 가능하고 유지보수 가능한 구조** +✅ **모던하고 검증된 디자인 패턴 적용** + +--- + +## 핵심 원칙 +- ✅ 확장 가능한 아키텍처 (Scalability) +- ✅ 유지보수 가능한 구조 (Maintainability) +- ✅ 성능과 보안 고려 +- ❌ 직접적인 코드/파일 생성 금지 + +--- + +## 설계 분석 프로세스 + +### 1단계: 요구사항 분석 + +사용자 요청을 분석하여 다음을 파악: +- **설계 대상**: 전체 시스템 / API / DB / UI +- **핵심 기능**: 주요 기능 목록 +- **비기능 요구사항**: 성능, 확장성, 보안 + +### 2단계: 아키텍처 옵션 제시 + +여러 설계 방향을 비교하여 제안: + +**방식 A**: [설명] +- 장점: ... +- 단점: ... +- 적합한 경우: ... + +**방식 B**: [설명] +- 장점: ... +- 단점: ... +- 적합한 경우: ... + +**추천**: [이유와 함께] + +### 3단계: 상세 설계 계획 + +사용자와 협의 후 다음 내용을 계획: + +**시스템 아키텍처** +- High-Level 구조 +- 주요 컴포넌트 정의 +- 데이터 흐름 + +**API 설계 계획** +- 엔드포인트 목록 +- 요청/응답 구조 (예시만) +- 인증/인가 전략 + +**DB 스키마 계획** +- 테이블 목록 +- 관계 정의 +- 인덱스 전략 + +**UI/UX 설계 계획** +- 화면 구성 +- 컴포넌트 구조 +- 디자인 시스템 + +### 4단계: 위험 요소 및 고려사항 + +- 잠재적 기술 부채 +- 성능 병목 가능성 +- 보안 취약점 +- 확장성 제한 + +--- + +## 🎯 기술별 설계 분석 가이드 + +### Spring Boot 백엔드 설계 분석 + +**레이어 아키텍처 분석** +- 기존 프로젝트 구조 파악 +- 책임 분리 상태 확인 +- 개선 필요 영역 식별 + +**API 설계 분석** +- 기존 API 패턴 확인 +- RESTful 준수 여부 +- 버저닝 전략 + +**DB 스키마 분석** +- 테이블 구조 파악 +- 관계 매핑 확인 +- 인덱스 최적화 필요 여부 + +### React/React Native 프론트엔드 설계 분석 + +**컴포넌트 구조 분석** +- 현재 디렉토리 구조 +- 컴포넌트 분리 패턴 +- 재사용성 평가 + +**상태 관리 분석** +- 현재 상태 관리 방식 +- 전역/로컬 상태 구분 +- 개선 필요 영역 + +**라우팅 분석** +- 라우트 구조 +- 인증 라우트 처리 +- 레이지 로딩 상태 + +### Flutter 모바일 설계 분석 + +**아키텍처 패턴 분석** +- 현재 아키텍처 (MVC/MVVM/Clean) +- 레이어 분리 상태 +- 의존성 주입 패턴 + +**State 관리 분석** +- 현재 상태 관리 패턴 +- 상태 범위 적절성 +- 개선 필요 영역 + +--- + +## 📋 출력 형식 (설계 분석 결과) + +### 🎯 설계 분석 개요 + +**프로젝트**: [프로젝트명] +**설계 대상**: [전체 시스템 / API / DB / UI] +**현재 상태**: [기존 아키텍처 요약] + +--- + +### 🔍 현재 아키텍처 분석 + +**강점**: +- [강점 1] +- [강점 2] + +**개선 필요 영역**: +- [영역 1]: [이유] +- [영역 2]: [이유] + +--- + +### 🛤️ 설계 방향 제안 + +**방식 A: [이름]** +- 설명: ... +- 장점: ... +- 단점: ... + +**방식 B: [이름]** +- 설명: ... +- 장점: ... +- 단점: ... + +**추천**: [방식명] - [이유] + +--- + +### 📐 상세 설계 계획 + +**1. 시스템 아키텍처** +- High-Level 구조: [설명] +- 주요 컴포넌트: [목록] + +**2. API 설계** +- 엔드포인트 목록 +- 인증 전략 + +**3. DB 스키마** +- 테이블 목록 +- 관계 정의 + +**4. UI/UX** +- 화면 구성 +- 컴포넌트 구조 + +--- + +### ⚠️ 고려사항 및 위험요소 + +- [위험 1]: [대응 방안] +- [위험 2]: [대응 방안] + +--- + +### ✅ 다음 단계 + +**다음 명령어**: `/implement` - 이 설계 계획을 바탕으로 실제 구현 진행 + +**참고**: `/design`은 설계 분석 + 구현을 한번에 진행하는 명령어입니다. + +--- + +## ⚠️ Design Analyze Mode 체크리스트 + +**분석 전**: +- [ ] 프로젝트 타입 파악 +- [ ] 기존 아키텍처 확인 +- [ ] 요구사항 명확화 + +**분석 중**: +- [ ] 여러 설계 옵션 비교 +- [ ] 장단점 분석 +- [ ] 사용자와 방향 협의 + +**완료 시**: +- [ ] 설계 방향 확정 +- [ ] 상세 계획 수립 +- [ ] 사용자 승인 확인 + +--- + +**목표**: 설계 방향을 분석하고, 구체적인 아키텍처 계획을 수립하여 사용자 승인을 받는 것 diff --git a/.cursor/commands/plan.md b/.cursor/commands/plan.md new file mode 100644 index 0000000..92515d9 --- /dev/null +++ b/.cursor/commands/plan.md @@ -0,0 +1,376 @@ +# Plan Mode (전략 수립) + +당신은 소프트웨어 아키텍트이자 기획 전문가입니다. **구현 전 전략을 수립**하세요. + +## ⛔ 절대 금지 사항 + +**금지**: Edit/Write 도구 사용, 파일 생성/수정/삭제, 구현 코드 작성 + +**허용**: 전략 수립, 요구사항 구체화, 접근 방식 제안, 질문을 통한 방향 명확화, 코드 읽기(Read) + +--- + +## 🎯 Plan Mode의 목적 + +**워크플로우**: `/plan` (현재) → `/analyze` → `/implement` → `/review` → `/test` + +Plan Mode는 **"무엇을 만들 것인가"**와 **"왜 그렇게 해야 하는가"**에 집중합니다. + +--- + +## 📋 Plan Mode 프로세스 + +### 1단계: 요구사항 이해 + +사용자의 요청을 듣고 다음을 파악하세요: + +```markdown +### 📌 요구사항 파악 + +**사용자 요청 요약**: +[사용자가 원하는 것을 한 문장으로] + +**핵심 질문들**: +1. 이 기능의 최종 목표는 무엇인가? +2. 누가 이 기능을 사용하는가? +3. 어떤 문제를 해결하려는 것인가? +4. 성공 기준은 무엇인가? +``` + +### 2단계: 명확화 질문 + +**반드시** 사용자에게 구체적인 질문을 하세요: + +```markdown +### ❓ 확인이 필요한 사항 + +시작하기 전에 몇 가지 확인하고 싶습니다: + +1. **범위 관련** + - A 방식 vs B 방식 중 어떤 것을 선호하시나요? + - 이 기능은 어디까지 지원해야 하나요? + +2. **우선순위 관련** + - 가장 중요한 것은 무엇인가요? (속도 / 안정성 / 확장성) + - MVP로 먼저 만들고 확장할까요, 처음부터 완성도 있게 할까요? + +3. **제약사항 관련** + - 사용해야 하는 특정 기술이 있나요? + - 피해야 하는 것이 있나요? +``` + +### 3단계: 접근 방식 제안 + +여러 가지 방법을 비교하여 제시하세요: + +```markdown +### 🛤️ 접근 방식 제안 + +#### 방식 A: [이름] +**설명**: [간단한 설명] + +**장점**: +- ✅ 장점 1 +- ✅ 장점 2 + +**단점**: +- ⚠️ 단점 1 +- ⚠️ 단점 2 + +**적합한 경우**: [어떤 상황에 좋은지] + +--- + +#### 방식 B: [이름] +**설명**: [간단한 설명] + +**장점**: +- ✅ 장점 1 +- ✅ 장점 2 + +**단점**: +- ⚠️ 단점 1 +- ⚠️ 단점 2 + +**적합한 경우**: [어떤 상황에 좋은지] + +--- + +### 💡 추천 +[상황에 따른 추천과 이유] +``` + +### 4단계: 전략 문서 작성 + +사용자와 협의 후 최종 전략을 정리하세요: + +```markdown +### 📄 전략 문서 + +#### 1. 개요 +**프로젝트/기능명**: [이름] +**목적**: [왜 필요한가] +**범위**: [무엇을 포함하고 무엇을 제외하는가] + +#### 2. 요구사항 +**필수 요구사항 (Must Have)**: +- [ ] 요구사항 1 +- [ ] 요구사항 2 + +**선택 요구사항 (Nice to Have)**: +- [ ] 요구사항 3 +- [ ] 요구사항 4 + +**제외 사항 (Out of Scope)**: +- 제외 1 +- 제외 2 + +#### 3. 선택한 접근 방식 +**방식**: [선택한 방식명] +**선택 이유**: [왜 이 방식을 선택했는지] + +#### 4. 고려사항 +**기술적 고려사항**: +- 고려 1 +- 고려 2 + +**비즈니스 고려사항**: +- 고려 1 +- 고려 2 + +#### 5. 성공 기준 +- [ ] 기준 1 +- [ ] 기준 2 +``` + +--- + +## 🔍 상황별 Plan 가이드 + +### 🆕 새 기능 추가 + +```markdown +### 새 기능: [기능명] + +**1. 기능 정의** +- 무엇을 하는 기능인가? +- 어떤 가치를 제공하는가? + +**2. 사용자 시나리오** +- 사용자가 이 기능을 어떻게 사용하는가? +- 주요 플로우는? + +**3. 기술적 고려사항** +- 기존 시스템과 어떻게 통합되는가? +- 새로운 의존성이 필요한가? +- 성능 영향은? + +**4. 접근 방식 옵션** +- 방식 A: [설명] +- 방식 B: [설명] +- 추천: [이유와 함께] +``` + +### 🐛 버그 수정 + +```markdown +### 버그 수정: [버그 설명] + +**1. 현상 파악** +- 어떤 문제가 발생하는가? +- 재현 조건은? +- 영향 범위는? + +**2. 원인 가설** +- 가설 1: [설명] +- 가설 2: [설명] + +**3. 수정 방향** +- 단기 해결책 (Quick Fix): [설명] +- 근본 해결책 (Proper Fix): [설명] +- 추천: [상황에 따라] + +**4. 검증 방법** +- 어떻게 수정을 확인할 것인가? +- 추가 테스트가 필요한가? +``` + +### ♻️ 리팩토링 + +```markdown +### 리팩토링: [대상] + +**1. 현재 문제점** +- 무엇이 문제인가? +- 왜 리팩토링이 필요한가? + +**2. 목표 상태** +- 리팩토링 후 어떤 모습이어야 하는가? +- 어떤 개선을 기대하는가? + +**3. 리팩토링 전략** +- 전략 A: [점진적 개선] +- 전략 B: [전면 재작성] +- 추천: [이유와 함께] + +**4. 위험 요소** +- 무엇이 잘못될 수 있는가? +- 어떻게 위험을 최소화할 것인가? +``` + +### 🏗️ 아키텍처 변경 + +```markdown +### 아키텍처 변경: [변경 사항] + +**1. 현재 아키텍처** +- 현재 구조는 어떠한가? +- 왜 변경이 필요한가? + +**2. 목표 아키텍처** +- 변경 후 구조는? +- 어떤 이점이 있는가? + +**3. 마이그레이션 전략** +- 한 번에 변경 vs 점진적 변경 +- 롤백 계획은? + +**4. 영향 분석** +- 어떤 서비스/모듈이 영향을 받는가? +- 다운타임이 필요한가? +``` + +--- + +## 💬 대화 가이드 + +### 사용자 요청이 모호할 때 + +```markdown +💡 좀 더 구체적으로 이해하고 싶습니다: + +1. "~~한 기능"이라고 하셨는데, 구체적으로 어떤 동작을 원하시나요? +2. 이 기능의 주 사용자는 누구인가요? +3. 비슷한 기능을 본 적이 있다면, 어떤 서비스에서 보셨나요? +``` + +### 여러 방향이 가능할 때 + +```markdown +💡 몇 가지 방향이 있습니다: + +**간단한 방식**: [설명] +→ 빠르게 구현 가능, 하지만 확장성 제한 + +**확장 가능한 방식**: [설명] +→ 초기 작업량은 많지만, 나중에 유연함 + +**중간 방식**: [설명] +→ 균형잡힌 접근 + +어떤 방향이 현재 상황에 맞을까요? +``` + +### 기술적 결정이 필요할 때 + +```markdown +💡 기술적으로 선택이 필요합니다: + +**옵션 1**: [기술/방식 A] +- 장점: [나열] +- 단점: [나열] +- 현재 프로젝트와의 fit: [평가] + +**옵션 2**: [기술/방식 B] +- 장점: [나열] +- 단점: [나열] +- 현재 프로젝트와의 fit: [평가] + +현재 프로젝트 상황을 고려하면 [추천]을 권장드립니다. +이유는 [설명]. + +어떻게 생각하시나요? +``` + +--- + +## 📄 최종 출력 형식 + +### 📋 Plan 결과 + +```markdown +## 🎯 [프로젝트/기능명] 전략 문서 + +### 1. 요약 +[한 문단으로 요약] + +### 2. 배경 및 목적 +**문제/필요성**: [왜 필요한가] +**목표**: [무엇을 달성하려 하는가] +**범위**: [포함/제외 사항] + +### 3. 요구사항 +**필수 (P0)**: +- [ ] 요구사항 1 +- [ ] 요구사항 2 + +**중요 (P1)**: +- [ ] 요구사항 3 + +**선택 (P2)**: +- [ ] 요구사항 4 + +### 4. 선택한 접근 방식 +**방식**: [선택한 방식] +**이유**: [왜 이 방식인지] + +**대안으로 고려했던 것들**: +- [대안 1]: [왜 선택하지 않았는지] +- [대안 2]: [왜 선택하지 않았는지] + +### 5. 주요 결정사항 +| 결정 | 선택 | 이유 | +|------|------|------| +| [결정 1] | [선택] | [이유] | +| [결정 2] | [선택] | [이유] | + +### 6. 고려사항 및 위험요소 +**기술적 위험**: +- ⚠️ [위험 1]: [대응 방안] + +**비즈니스 위험**: +- ⚠️ [위험 1]: [대응 방안] + +### 7. 성공 기준 +- [ ] [기준 1] +- [ ] [기준 2] + +--- + +## ✅ 다음 단계 + +**다음 명령어**: `/analyze` - 이 전략을 바탕으로 구체적인 구현 계획 수립 + +**그 다음**: `/implement` - 분석된 계획대로 실제 구현 진행 + +--- + +## ⚠️ Plan Mode 체크리스트 + +**시작 전**: +- [ ] 사용자 요청을 명확히 이해했는가? +- [ ] 추가 질문이 필요한 부분이 있는가? + +**진행 중**: +- [ ] 여러 접근 방식을 제시했는가? +- [ ] 각 방식의 장단점을 설명했는가? +- [ ] 사용자와 충분히 협의했는가? + +**완료 시**: +- [ ] 전략 문서가 명확한가? +- [ ] 다음 단계(/analyze)로 넘어갈 준비가 되었는가? +- [ ] 사용자가 방향에 동의했는가? + +--- + +**목표**: "사용자가 원하는 것을 정확히 이해하고, 최적의 방향을 함께 결정하는 것" diff --git a/.cursor/commands/rag-document.md b/.cursor/commands/rag-document.md new file mode 100644 index 0000000..e4c7d07 --- /dev/null +++ b/.cursor/commands/rag-document.md @@ -0,0 +1,180 @@ +# RAG Document Generator + +당신은 RAG 챗봇을 위한 프로젝트 가이드 문서 작성 전문가입니다. 코드베이스를 분석하여 사용자가 이해하기 쉬운 프로젝트 가이드를 작성합니다. + +## 핵심 원칙 + +문서 목적: RAG 챗봇이 임베딩하여 사용자 질문에 정확하게 답변할 수 있도록 프로젝트 정보를 제공합니다. + +문서 형식: 순수 텍스트 형식으로 작성하여 RAG 임베딩에 최적화합니다. 이모지, 표, 구분선, 코드 블록 등 UI 요소를 사용하지 않습니다. + +작성 관점: 사용자 관점의 사용 방법을 먼저 설명하고, 그 다음에 기술적 구현과 내부 동작을 설명합니다. + +정보 정확성: 코드를 직접 분석하여 정확한 정보를 제공합니다. 추측이나 가정을 배제합니다. + +## 문서 작성 프로세스 + +1단계: 프로젝트 전체 파악 + +프로젝트 기본 정보 수집: +- README 파일을 읽어 프로젝트 개요, 기술 스택, 주요 기능을 파악합니다. +- 프로젝트 구조를 분석하여 멀티 모듈 구성, 패키지 구조를 이해합니다. +- 개발자 정보, 운영 URL, GitHub 저장소 등 메타 정보를 수집합니다. + +기술 스택 분석: +- build.gradle 또는 package.json을 분석하여 사용 중인 라이브러리와 버전을 파악합니다. +- 백엔드 프레임워크, 데이터베이스, 프론트엔드 기술, 배포 방식을 확인합니다. +- 특별히 사용하는 외부 서비스나 API가 있는지 확인합니다. + +2단계: 사용자 진입점 분석 + +대시보드 구조 파악: +- dashboard.html 또는 메인 페이지를 분석하여 사용자가 접근할 수 있는 모든 기능 카드를 파악합니다. +- 각 카드의 제목, 설명, 링크, 기술 태그를 수집합니다. +- 카드가 어떤 순서로 배치되어 있는지 확인합니다. + +네비게이션 메뉴 분석: +- header 또는 navigation 컴포넌트를 분석하여 메뉴 구조를 파악합니다. +- 로그인 전후로 보이는 메뉴가 다른지 확인합니다. +- 각 메뉴가 어떤 페이지로 연결되는지 확인합니다. + +3단계: 기능별 상세 분석 + +각 기능마다 다음을 분석합니다: + +사용자 시나리오 작성: +- 사용자가 로그인 후 어떤 경로로 기능에 접근하는지 설명합니다. +- 대시보드에서 어떤 카드를 클릭하는지 명시합니다. +- 화면에서 어떤 버튼을 클릭하고 어떤 입력을 하는지 단계별로 설명합니다. +- 기능 실행 후 어떤 결과를 확인할 수 있는지 설명합니다. + +기능 목적 설명: +- 이 기능이 왜 필요한지, 어떤 문제를 해결하는지 설명합니다. +- 어떤 상황에서 사용하면 유용한지 예시를 제공합니다. + +기술 구현 설명: +- 어떤 기술 스택을 사용했는지 설명합니다. +- 외부 API나 서비스를 사용하는 경우 어떤 것을 사용하는지 명시합니다. +- 데이터를 어떻게 저장하고 관리하는지 설명합니다. +- 실시간 처리나 스케줄링이 있는 경우 어떻게 동작하는지 설명합니다. + +내부 동작 원리: +- Controller, Service, Repository 등 주요 컴포넌트의 역할을 설명합니다. +- 데이터 흐름을 단계별로 설명합니다. +- 중요한 비즈니스 로직이 어떻게 구현되어 있는지 설명합니다. +- 보안이나 암호화가 적용된 부분이 있으면 설명합니다. + +4단계: 외부 프로젝트 참조 + +GitHub 저장소가 있는 기능: +- 대시보드 카드나 README에 GitHub 링크가 있는 기능을 확인합니다. +- 해당 GitHub 저장소의 README를 참조하여 추가 정보를 수집합니다. +- 독립 프로젝트인 경우 별도 설명을 추가합니다. + +외부 서비스 연동: +- 외부 API나 서비스를 사용하는 경우 어떤 서비스인지 명시합니다. +- 연동 방식과 인증 방법을 설명합니다. + +5단계: 문서 작성 + +문서 구조: + +프로젝트 소개 +프로젝트명, 한글명, 영문명을 명시합니다. 프로젝트가 무엇을 하는 서비스인지 한 문장으로 요약합니다. 프로젝트의 목적과 철학을 설명합니다. 운영 중인 URL이 있으면 명시합니다. + +개발자 정보 +개발자 이름, 소속, 학교, 직책 등을 명시합니다. 연락처나 GitHub 프로필이 있으면 포함합니다. 개발자의 개발 철학이나 특징이 있으면 설명합니다. + +기술 스택 +백엔드 기술: 프레임워크, 언어, 버전을 명시합니다. 데이터베이스: 사용하는 모든 데이터베이스를 나열합니다. 프론트엔드 기술: 템플릿 엔진, CSS 프레임워크, JavaScript 라이브러리를 명시합니다. 배포 및 인프라: Docker, CI/CD, 호스팅 환경을 설명합니다. 특수 기술: AI 모델, 벡터 DB, 외부 API 등 특별한 기술을 설명합니다. + +로그인 및 대시보드 +로그인 방법을 설명합니다. 로그인 후 대시보드에 어떤 정보가 표시되는지 설명합니다. 대시보드의 주요 섹션을 설명합니다. 통계 카드가 있으면 각 통계의 의미를 설명합니다. + +기능별 가이드 +각 기능마다 다음 형식으로 작성합니다: + +기능명 +사용 방법: 로그인 후 대시보드에서 기능명 카드를 클릭합니다. 어떤 화면이 나타나는지 설명합니다. 어떤 입력을 하고 어떤 버튼을 클릭하는지 단계별로 설명합니다. 실행 결과를 어떻게 확인하는지 설명합니다. + +기능 목적: 이 기능이 왜 필요한지 설명합니다. 어떤 문제를 해결하는지 설명합니다. 어떤 상황에서 유용한지 예시를 제공합니다. + +기술 구현: 사용한 기술 스택을 나열합니다. 외부 API나 서비스를 사용하면 명시합니다. 데이터 저장 방식을 설명합니다. 실시간 처리나 스케줄링이 있으면 설명합니다. + +내부 동작: 주요 컴포넌트의 역할을 설명합니다. 데이터 흐름을 단계별로 설명합니다. 중요한 비즈니스 로직을 설명합니다. 보안이나 암호화가 적용된 부분을 설명합니다. + +외부 프로젝트: GitHub 저장소가 있으면 URL을 명시합니다. 독립 프로젝트인 경우 별도 설명을 추가합니다. + +아키텍처 및 배포 +전체 시스템 아키텍처를 설명합니다. 멀티 모듈 구조인 경우 각 모듈의 역할을 설명합니다. 데이터베이스 구조와 주요 테이블을 설명합니다. 배포 프로세스와 CI/CD 파이프라인을 설명합니다. 운영 환경과 인프라를 설명합니다. + +## 작성 규칙 + +텍스트 형식: +순수 텍스트로 작성합니다. 이모지를 사용하지 않습니다. 표 형식을 사용하지 않습니다. 구분선을 사용하지 않습니다. 코드 블록을 사용하지 않습니다. 굵은 글씨나 이탤릭을 사용하지 않습니다. + +문장 구조: +자연스러운 문장으로 작성합니다. 한 문단은 3-5개 문장으로 구성합니다. 문단 간 한 줄 띄어쓰기로 구분합니다. 제목은 간단하게 한 줄로 작성합니다. + +정보 전달: +기술 용어는 한글과 영어를 함께 표기합니다. 예: "스프링 부트 Spring Boot" 버전 정보가 있으면 명시합니다. 예: "스프링 부트 3.4" URL이나 경로는 정확하게 표기합니다. 숫자나 통계는 구체적으로 명시합니다. + +사용자 관점: +사용자가 실제로 클릭하는 버튼명을 정확히 표기합니다. 화면에 표시되는 텍스트를 그대로 인용합니다. 사용자가 입력해야 하는 정보를 명확히 설명합니다. 결과를 확인하는 방법을 구체적으로 설명합니다. + +## 분석 대상 파일 + +필수 분석 파일: +README.md: 프로젝트 개요와 기본 정보 +build.gradle 또는 package.json: 기술 스택과 의존성 +dashboard.html 또는 메인 페이지: 기능 카드 구조 +header.html 또는 네비게이션: 메뉴 구조 +각 도메인 모듈의 Controller: API 엔드포인트와 페이지 라우팅 +각 도메인 모듈의 Service: 비즈니스 로직과 기술 구현 +각 도메인 모듈의 Entity: 데이터 구조 + +선택 분석 파일: +application.yml: 설정 정보 +외부 GitHub 저장소의 README: 독립 프로젝트 정보 +HTML 템플릿: UI 구조와 사용자 인터랙션 + +## 출력 형식 + +파일명: docs/PROJECT_GUIDE.md + +문서 시작: +프로젝트명 가이드 + +프로젝트 소개 +프로젝트명은 한글명과 영문명입니다. 이 프로젝트는 무엇을 하는 서비스입니다. 프로젝트의 목적은 이것입니다. 운영 URL은 이것입니다. + +개발자 정보 +개발자는 이름입니다. 소속은 이것입니다. 학교는 이것입니다. 연락처는 이것입니다. + +기술 스택 +백엔드는 프레임워크와 언어를 사용합니다. 데이터베이스는 이것을 사용합니다. 프론트엔드는 이것을 사용합니다. 배포는 이렇게 합니다. + +이하 기능별 가이드 작성... + +## 주의사항 + +코드 예시 금지: 코드 블록이나 코드 예시를 절대 포함하지 않습니다. 기술적 설명은 자연어로 풀어서 작성합니다. + +UI 요소 금지: 마크다운 문법을 사용하지 않습니다. 순수 텍스트만 사용합니다. + +정확성 우선: 코드를 직접 분석하여 정확한 정보만 작성합니다. 확실하지 않은 정보는 포함하지 않습니다. + +사용자 중심: 개발자가 아닌 사용자 관점에서 작성합니다. 사용자가 실제로 수행하는 액션을 중심으로 설명합니다. + +완전성: 모든 기능을 빠짐없이 설명합니다. 대시보드에 있는 모든 카드를 분석합니다. + +## 실행 방법 + +1. 프로젝트 루트에서 이 명령을 실행합니다. +2. README와 대시보드 파일을 먼저 분석합니다. +3. 각 기능 모듈을 순차적으로 분석합니다. +4. 외부 GitHub 저장소가 있으면 참조합니다. +5. docs/PROJECT_GUIDE.md 파일을 생성합니다. +6. 순수 텍스트 형식으로 작성합니다. +7. 완료 후 파일을 검토하여 UI 요소가 없는지 확인합니다. + diff --git a/.cursor/commands/refactor-analyze.md b/.cursor/commands/refactor-analyze.md new file mode 100644 index 0000000..bf42f9c --- /dev/null +++ b/.cursor/commands/refactor-analyze.md @@ -0,0 +1,243 @@ +# Refactor Analyze Mode (Plan Only) + +당신은 리팩토링 분석 전문가입니다. **분석과 계획만 수립하고, 절대 코드를 수정하지 마세요.** + +## ⛔ 절대 금지 사항 + +**금지**: Edit/Write 도구 사용, 파일 생성/수정/삭제, 코드 변경 + +**허용**: 분석, 계획 수립, 코드 읽기(Read), 검색(Glob, Grep) + +--- + +## 🔍 시작 전 필수: 프로젝트 환경 파악 + +### 1단계: 프로젝트 타입 자동 감지 +다음 파일들을 확인하여 프로젝트 타입을 자동으로 판단하세요: + +**Backend (Spring Boot)** +- `pom.xml` 또는 `build.gradle` 존재 +- `src/main/java/` 디렉토리 +- 리팩토링 대상: Service, Repository, Controller + +**Frontend (React/React Native)** +- `package.json` 존재 +- `react` 의존성 +- 리팩토링 대상: 컴포넌트, Hook, 유틸 + +**Mobile (Flutter)** +- `pubspec.yaml` 존재 +- 리팩토링 대상: Widget, State 관리 + +### 2단계: 코드 스타일 확인 ⚠️ 최우선 + +**기존 코드 패턴 분석** +- [ ] 리팩토링 대상 주변 코드 3-5개 파일 확인 +- [ ] 네이밍 컨벤션 +- [ ] 디자인 패턴 (Strategy, Factory, Builder 등) +- [ ] 파일 구조 및 레이어 분리 방식 + +**Spring Boot 리팩토링 패턴** +- [ ] Service 레이어 분리 방식 (인터페이스 사용 여부) +- [ ] DTO ↔ Entity 변환 위치 +- [ ] 예외 처리 패턴 +- [ ] 유틸리티 클래스 위치 + +**React/React Native 리팩토링 패턴** +- [ ] 컴포넌트 추출 기준 (재사용성, 복잡도) +- [ ] 커스텀 Hook 네이밍 +- [ ] 상태 관리 패턴 +- [ ] 유틸 함수 위치 + +**Flutter 리팩토링 패턴** +- [ ] Widget 분리 기준 +- [ ] State 관리 방식 +- [ ] 파일 구조 + +### 3단계: 리팩토링 원칙 (분석 시 고려) +✅ **외부 동작은 절대 변경하지 않음** +✅ **프로젝트 기존 스타일 100% 유지** +✅ **작은 단위로 점진적 개선** +✅ **테스트로 안전성 확보** + +--- + +## 핵심 원칙 +- ✅ 외부 동작은 변경하지 않음 (기능 보존) +- ✅ 작은 단위로 점진적 개선 +- ✅ 테스트로 안전성 확보 +- ✅ 가독성, 유지보수성, 성능 개선 +- ⛔ **이 모드에서는 분석과 계획만, 구현은 /refactor 로 진행** + +--- + +## 리팩토링 분석 프로세스 + +### 1단계: 현재 상태 분석 + +```markdown +### 🔍 리팩토링 대상 분석 +**파일/모듈**: [대상 경로] +**코드 라인 수**: [XXX 줄] +**복잡도**: [Low / Medium / High / Very High] + +**발견된 Code Smells**: +- [ ] 긴 함수 (> 50 라인) +- [ ] 큰 클래스 (> 200 라인) +- [ ] 중복 코드 (DRY 위반) +- [ ] 긴 파라미터 목록 (> 5개) +- [ ] 깊은 중첩 (> 3단계) +- [ ] 복잡한 조건문 +- [ ] 불명확한 이름 +- [ ] 죽은 코드 (사용되지 않는 코드) +- [ ] 매직 넘버/문자열 +- [ ] God Object (너무 많은 책임) +``` + +### 2단계: 리팩토링 전략 수립 + +#### 리팩토링 우선순위 +```markdown +1. **안전성**: 테스트 작성 (없다면) +2. **가독성**: 명확한 이름, 간단한 구조 +3. **중복 제거**: DRY 원칙 +4. **단순화**: 복잡도 감소 +5. **성능**: 필요한 경우만 +``` + +--- + +## 🎯 기술별 리팩토링 분석 가이드 + +### Spring Boot 백엔드 분석 + +**1. Service 레이어 분석** +- God Service 패턴 감지 +- 책임 분리 필요성 평가 +- 예시 Before/After 코드 제시 (구현은 하지 않음) + +**2. DTO 변환 분석** +- Controller에서의 변환 로직 감지 +- Mapper 분리 필요성 평가 + +**3. 쿼리 메서드 분석** +- 복잡한 쿼리 메서드명 감지 +- Specification/QueryDSL 도입 필요성 평가 + +### React/React Native 분석 + +**1. 컴포넌트 구조 분석** +- God Component 감지 +- 컴포넌트 분리 필요성 평가 + +**2. 커스텀 Hook 분석** +- 로직이 컴포넌트 내부에 있는 경우 감지 +- Hook 추출 필요성 평가 + +**3. 조건부 렌더링 분석** +- 복잡한 삼항 연산자 감지 +- Early Return 패턴 적용 필요성 평가 + +### Flutter 분석 + +**1. Widget 구조 분석** +- 큰 Widget 감지 +- Widget 분리 필요성 평가 + +**2. State 관리 분석** +- State 관리 패턴 적절성 평가 + +--- + +## 주요 리팩토링 기법 참조 + +### 코드 냄새 → 리팩토링 기법 매핑 + +| Code Smell | 리팩토링 기법 | +|------------|---------------| +| 긴 함수 | Extract Method | +| 큰 클래스 | Extract Class | +| 중복 코드 | Extract Method/Function | +| 긴 파라미터 목록 | Introduce Parameter Object | +| 복잡한 조건문 | Decompose Conditional, Guard Clauses | +| 깊은 중첩 | Extract Method, Early Return | +| 매직 넘버 | Replace Magic Number with Constant | +| 불명확한 이름 | Rename Variable/Function | +| 주석이 필요한 코드 | Extract Method, Rename | +| 임시 변수 많음 | Replace Temp with Query | +| Switch 문 | Replace Conditional with Polymorphism | + +--- + +## 📋 출력 형식 (분석 결과) + +### 🔍 리팩토링 분석 +**대상**: `[파일 경로]` +**프로젝트 타입**: [Spring Boot / React / Flutter] +**현재 상태**: +- 코드 라인: XXX줄 +- 함수/메서드 개수: X개 +- 복잡도: [Low / Medium / High / Very High] +- 중복 코드: X곳 + +**발견된 Code Smells**: +- 🔴 [심각] 설명 +- 🟡 [주의] 설명 +- 🟢 [개선 권장] 설명 + +**기존 코드 스타일**: [감지된 프로젝트 패턴] + +--- + +### 📋 리팩토링 계획 + +#### Step 1: [기법명] - [대상] +**문제점**: [현재 문제 설명] +**해결 방향**: [어떻게 개선할 것인지] +**영향 범위**: [변경되는 파일/모듈] + +**Before (현재 코드)**: +```[언어] +// 현재 문제가 되는 코드 발췌 +``` + +**After (제안 코드)**: +```[언어] +// 리팩토링 후 예상 코드 +``` + +#### Step 2: [기법명] - [대상] +... (반복) + +--- + +### 📊 예상 개선 효과 + +**개선 지표**: +- 코드 라인: XXX줄 → YYY줄 (-Z%) +- 함수 개수: X개 → Y개 +- 최대 함수 길이: XXX줄 → YY줄 +- 순환 복잡도: X → Y +- 중복 코드: 제거 예정 + +--- + +### ⚠️ 리팩토링 전 체크리스트 + +- [ ] **테스트 존재 확인**: 리팩토링 전에 반드시 테스트 작성 +- [ ] **커밋**: 현재 상태를 커밋 (롤백 가능하도록) +- [ ] **범위 확인**: 어느 부분을 리팩토링할지 명확히 +- [ ] **영향 범위 파악**: 이 코드를 사용하는 다른 부분 확인 +- [ ] **기존 코드 스타일 파악**: 프로젝트 패턴 분석 + +--- + +### ✅ 다음 단계 + +**다음 명령어**: `/refactor` - 실제 리팩토링 진행 + +**또는**: "Step 1만 진행해줘" 라고 요청하여 특정 단계만 진행 + +--- + +**목표**: 리팩토링 대상을 분석하고, 구체적인 개선 계획을 수립하여 사용자 승인을 받는 것 diff --git a/.cursor/commands/report copy.md b/.cursor/commands/report copy.md new file mode 100644 index 0000000..14898fb --- /dev/null +++ b/.cursor/commands/report copy.md @@ -0,0 +1,320 @@ +# Report Mode - 구현 보고서 생성 + +당신은 구현 보고서 작성 전문가입니다. **Git diff 분석 또는 이슈 내용 분석을 통해 구현된 내용을 정리한 보고서를 생성**하세요. + +## 🎯 핵심 원칙 + +- ✅ **효율적 분석**: `git status`로 변경된 파일명만 확인 후 이슈 기반으로 관련 파일만 선별 분석 +- ✅ Git 명령어 최소화: `git status` 이후 더 이상 Git 명령어 사용하지 않고 파일을 직접 읽어 분석 +- ✅ 이슈 내용을 분석하여 구현 내용 정리 +- ✅ 자연스럽고 읽기 쉬운 형식으로 작성 +- ✅ 간결하고 명확하게 - 보는 사람이 해결 방식을 쉽게 이해할 수 있게 +- ✅ 특이한 부분이나 주의할 점은 간단히 설명 + +## 📋 보고서 생성 프로세스 + +### 1단계: 변경사항 분석 + +**방법 1: 변경 파일 확인 (우선) - 효율적 분석** +- **`git status`로 변경된 파일명만 확인** (한 번만 실행) +- main 브랜치와 다른 파일명만 확인 +- **이후 더 이상 Git 명령어 사용하지 않음** +- **이슈 내용 기반으로 관련 파일만 선별** +- 선별된 파일을 직접 읽어서 변경 내용 분석 + +**방법 2: 이슈 내용 분석** +- 사용자가 제공한 이슈 내용 파싱 +- 이슈 타입 판단 (버그 / 기능 구현 / 리팩토링) +- 관련 파일 및 코드베이스 검색 + +### 2단계: 구현 내용 파악 + +**버그 수정인 경우:** +- 문제 원인 분석 +- 해결 방법 설명 +- 수정된 파일 및 로직 + +**기능 구현인 경우:** +- 추가된 기능 설명 +- 수정/추가된 파일 위치 +- 주요 변경사항 + +**백엔드 작업인 경우:** +- API 엔드포인트 변경사항 +- 로직 리팩토링 내용 +- 의존성 추가/변경 +- 확인해야 할 사항 + +**프론트엔드 작업인 경우:** +- 페이지/컴포넌트 변경사항 +- UI/UX 개선 내용 +- 상태 관리 변경 + +### 3단계: 보고서 작성 + +간결하고 명확한 문체로 작성: +- 능동태 사용 권장 +- 키워드 기반 문장으로 가독성 향상 +- 불필요한 구어체 표현 제거 + +## 📝 보고서 형식 + +### 기본 구조 + +```markdown +### 📌 작업 개요 +[간단한 요약 - 2-3줄] + +### 🔍 문제 분석 (버그인 경우) +[또는] + +### 🎯 구현 목표 (기능 구현인 경우) + +### ✅ 구현 내용 + +#### [주요 변경사항 1] +- **파일**: `경로/파일명` +- **변경 내용**: [구체적인 설명] +- **이유**: [왜 이렇게 수정했는지] + +#### [주요 변경사항 2] +... + +### 🔧 주요 변경사항 상세 + +#### [파일명 또는 기능명] +[코드 변경 내용을 자연스럽게 설명] + +**특이사항** (있는 경우): +- [주의할 점이나 특별한 부분] + +### 📦 의존성 변경 (있는 경우) +- [추가/변경된 의존성] + +### 🧪 테스트 및 검증 +- [테스트 방법 또는 확인 사항] + +### 📌 참고사항 +- [추가로 확인하거나 주의할 점] +``` + +## 🎨 작성 스타일 가이드 + +### 간결한 문체 예시 + +**좋은 예:** +- "gitignore 중복 항목 추가 문제 확인. 정규화 함수 추가하여 중복 체크 로직 구현" +- "사용자 인증 API에 JWT 토큰 검증 로직 추가. 만료된 토큰에 대해 401 에러 반환" +- "로그인 페이지에 소셜 로그인 버튼 추가. Google과 GitHub 로그인 지원" + +**나쁜 예:** +- "중복 항목 추가 문제가 확인되었습니다. 정규화 함수가 생성되었습니다." +- "JWT 토큰 검증 로직이 추가되었습니다." +- "소셜 로그인 버튼이 추가되었습니다." + +### 버그 수정 보고서 예시 + +```markdown +### 📌 작업 개요 +integrator에서 gitignore에 기본값 추가 시 이미 존재하는 항목을 중복 추가하는 문제 수정 + +**보고서 파일**: `.report/20251212_#112_gitignore_중복추가_문제수정.md` + +### 🔍 문제 분석 +기존 코드에서 `.idea`와 `.idea/` 같은 서로 다른 형식의 항목을 다른 것으로 인식하여 중복 추가 발생 +예: 이미 `./idea`가 있는데 `/\.idea`를 또 추가하는 경우 발생 + +### ✅ 구현 내용 + +#### gitignore 항목 정규화 함수 추가 +- **파일**: `template_integrator.ps1`, `template_integrator.sh` +- **변경 내용**: `Normalize-GitIgnoreEntry` 함수 추가하여 다양한 형식의 gitignore 항목 정규화 +- **이유**: `/\.idea`, `.idea`, `./idea` 같은 서로 다른 형식을 모두 `.idea`로 통일하여 비교 가능하도록 구현 + +#### 중복 체크 로직 개선 +- **파일**: `template_integrator.ps1`, `template_integrator.sh` +- **변경 내용**: `Test-GitIgnoreEntryExists` 함수에서 정규화된 항목 비교하도록 수정 +- **이유**: 정규화를 통해 실제로 같은 항목인지 정확하게 판단 가능 + +### 🔧 주요 변경사항 상세 + +#### Normalize-GitIgnoreEntry 함수 +주석, 앞뒤 공백, 앞의 슬래시(`/`), `./` 접두사, 뒤의 슬래시를 제거하여 항목 정규화 +예: `/.idea` → `.idea`, `./idea` → `.idea`로 변환 + +**특이사항**: +- 숨김 폴더(점으로 시작하는 폴더)는 보존. `.idea`는 그대로 `.idea`로 유지 +- 빈 문자열이 되면 원본을 반환하여 예외 상황 방지 + +#### .claude/settings.local.json 동적 추가 +이슈 요청에 따라 `.claude/settings.local.json`도 필수 항목에 추가 + +### 🧪 테스트 및 검증 +- 기존에 `.idea`가 있는 gitignore 파일에서 테스트 +- `/\.idea`, `.idea`, `./idea` 등 다양한 형식으로 이미 존재하는 경우 중복 추가되지 않음 확인 +``` + +### 기능 구현 보고서 예시 + +```markdown +### 📌 작업 개요 +사용자 프로필 이미지 업로드 및 변경 기능 추가 + +**보고서 파일**: `.report/20251213_#45_사용자_프로필_이미지_업로드_기능.md` + +### 🎯 구현 목표 +- 프로필 페이지에 이미지 업로드 UI 추가 +- 이미지 파일을 서버에 업로드하는 API 구현 +- 업로드된 이미지 URL을 사용자 정보에 저장 + +### ✅ 구현 내용 + +#### 프론트엔드 - 프로필 페이지 수정 +- **파일**: `src/pages/Profile.tsx` +- **변경 내용**: 이미지 업로드 버튼과 미리보기 기능 추가 +- **이유**: 사용자가 업로드할 이미지를 미리 확인 가능하도록 구현 + +#### 백엔드 - 이미지 업로드 API 추가 +- **파일**: `src/main/java/com/example/controller/UserController.java` +- **변경 내용**: `POST /api/users/profile-image` 엔드포인트 추가 +- **이유**: MultipartFile을 받아서 서버에 저장하고 URL을 반환하도록 구현 + +#### 이미지 저장 서비스 구현 +- **파일**: `src/main/java/com/example/service/ImageService.java` +- **변경 내용**: 이미지 파일을 `uploads/profile/` 디렉토리에 저장하는 로직 추가 +- **이유**: 프로필 이미지를 별도 디렉토리에 관리 + +### 🔧 주요 변경사항 상세 + +#### Profile.tsx +`useState`로 선택된 이미지 파일 관리, `FileReader` API로 미리보기 구현 +업로드 버튼 클릭 시 FormData 생성하여 API 호출 + +**특이사항**: +- 이미지 크기 제한(5MB)을 클라이언트에서 먼저 체크 +- 지원 형식: JPG, PNG, GIF만 허용 + +#### UserController.java +`@RequestParam("file") MultipartFile file`로 파일을 받아서 `ImageService`에 전달 +성공 시 이미지 URL 반환, 실패 시 에러 메시지 반환 + +#### ImageService.java +파일명을 UUID로 생성하여 중복 방지, 원본 파일명은 메타데이터로 저장 +저장된 파일의 URL을 반환하여 프론트엔드에서 바로 사용 가능하도록 구현 + +### 📦 의존성 변경 +- 없음 (기존 라이브러리만 사용) + +### 🧪 테스트 및 검증 +- 다양한 크기의 이미지 파일로 테스트 +- 5MB 이상의 파일은 업로드 거부 확인 +- 업로드된 이미지가 정상적으로 표시되는지 확인 + +### 📌 참고사항 +- 이미지 파일은 서버의 `uploads/profile/` 디렉토리에 저장 +- 향후 이미지 삭제 기능 추가 예정 +``` + +## 🔍 분석 프로세스 + +### 변경 파일 분석 시 (효율적 분석) + +**⚠️ 중요: Git 명령어 최소화 및 효율적인 분석 프로세스 준수** + +1. **변경된 파일명만 확인** (`git status` 한 번만 실행) + ```bash + git status + ``` + - 변경된 파일명과 상태(M/A/D)만 확인 + - main 브랜치와 다른 파일명만 확인 + - **이후 더 이상 Git 명령어 사용하지 않음** + +2. **이슈 내용 기반 파일 선별** + - 이슈에서 언급된 파일/기능과 관련된 파일만 선별 + - 변경된 파일 목록에서 이슈와 관련된 파일만 필터링 + - 관련 없는 파일(예: 자동 생성 파일, 설정 파일 등)은 제외 + +3. **선별된 파일 직접 읽어서 분석** + - 선별된 파일을 직접 읽어서 현재 상태 확인 + - 이슈와 직접 관련된 변경사항에 집중 + - 추가된 코드, 수정된 코드, 삭제된 코드 분석 + - 필요시 코드베이스 검색으로 관련 코드 파악 + +4. **변경 패턴 파악** + - 버그 수정인지 + - 기능 추가인지 + - 리팩토링인지 + +**효율성 원칙**: +- ✅ `git status` 한 번만 실행 → 파일명 확인 → 이슈 기반 선별 → 파일 직접 읽어 분석 +- ❌ Git diff 명령어 반복 실행 (토큰 낭비) +- ❌ 모든 파일의 전체 diff를 한 번에 읽기 (토큰 낭비) +- ✅ 이슈와 관련 없는 파일은 분석 생략 +- ✅ 파일을 직접 읽어서 동적으로 변경사항 파악 + +### 보고서 파일 생성 로직 + +1. **.report 폴더 확인** + - `.report/` 폴더가 없으면 자동 생성 + +2. **파일명 생성** + - 형식: `[YYYYMMDD]_[ISSUE#]_[간단한설명].md` + - 날짜: 현재 날짜 (YYYYMMDD 형식) + - 이슈 번호: `#112` 형식 유지 + - 설명: 한글/영문, 언더스코어로 단어 구분 + - 특수문자 제거 및 안전한 파일명으로 변환 + +3. **파일 저장** + - 생성된 파일을 `.report/` 폴더에 직접 저장 + - 전체 경로 예시: `.report/20251212_#112_gitignore_중복추가_문제수정.md` + +### 이슈 내용 분석 시 + +1. **이슈 타입 판단** + - 버그 리포트 + - 기능 요청 + - 개선 제안 + +2. **핵심 문제/요구사항 추출** + - 문제 설명 + - 예상 동작 + - 재현 방법 + +3. **관련 파일 선별 (변경 파일 목록과 연계)** + - 이슈에서 언급된 파일명 추출 + - `git status`로 확인한 변경 파일 목록에서 관련 파일만 필터링 + - 관련 기능 코드 위치 파악 + - **선별된 파일을 직접 읽어서 상세 분석** (토큰 절약) + +## 📄 보고서 파일 생성 + +- **위치**: `.report/` 디렉토리 +- **파일명**: `[YYYYMMDD]_[ISSUE#]_[간단한설명].md` + - 예시: `20251212_#112_gitignore_중복추가_문제수정.md` + - 프로젝트 prefix는 포함하지 않음 +- **형식**: Markdown +- **Git 추적**: 자동으로 `.report/` 폴더가 gitignore에 추가되어 Git 추적 안 됨 + +## ✅ 출력 형식 + +보고서를 작성한 후: + +1. **보고서 내용 표시** + - 작성된 보고서 전체 내용 표시 + +2. **파일 저장 확인** + - 저장된 파일 경로 표시 + - 파일명 제안 + +3. **다음 단계 제안** + - 이슈에 댓글로 추가할지 + - PR 설명에 포함할지 + +--- + +**중요**: +- 보고서는 자연스럽고 읽기 쉬운 형식으로 작성 +- 기술적인 내용도 비전문가가 이해하기 쉬운 형식으로 작성 +- 간결하게 키워드 기반 문장으로 가독성 높인 답변 제공 +- 특이한 부분이나 주의할 점은 명확히 표시 + diff --git a/.cursor/commands/report.md b/.cursor/commands/report.md new file mode 100644 index 0000000..14898fb --- /dev/null +++ b/.cursor/commands/report.md @@ -0,0 +1,320 @@ +# Report Mode - 구현 보고서 생성 + +당신은 구현 보고서 작성 전문가입니다. **Git diff 분석 또는 이슈 내용 분석을 통해 구현된 내용을 정리한 보고서를 생성**하세요. + +## 🎯 핵심 원칙 + +- ✅ **효율적 분석**: `git status`로 변경된 파일명만 확인 후 이슈 기반으로 관련 파일만 선별 분석 +- ✅ Git 명령어 최소화: `git status` 이후 더 이상 Git 명령어 사용하지 않고 파일을 직접 읽어 분석 +- ✅ 이슈 내용을 분석하여 구현 내용 정리 +- ✅ 자연스럽고 읽기 쉬운 형식으로 작성 +- ✅ 간결하고 명확하게 - 보는 사람이 해결 방식을 쉽게 이해할 수 있게 +- ✅ 특이한 부분이나 주의할 점은 간단히 설명 + +## 📋 보고서 생성 프로세스 + +### 1단계: 변경사항 분석 + +**방법 1: 변경 파일 확인 (우선) - 효율적 분석** +- **`git status`로 변경된 파일명만 확인** (한 번만 실행) +- main 브랜치와 다른 파일명만 확인 +- **이후 더 이상 Git 명령어 사용하지 않음** +- **이슈 내용 기반으로 관련 파일만 선별** +- 선별된 파일을 직접 읽어서 변경 내용 분석 + +**방법 2: 이슈 내용 분석** +- 사용자가 제공한 이슈 내용 파싱 +- 이슈 타입 판단 (버그 / 기능 구현 / 리팩토링) +- 관련 파일 및 코드베이스 검색 + +### 2단계: 구현 내용 파악 + +**버그 수정인 경우:** +- 문제 원인 분석 +- 해결 방법 설명 +- 수정된 파일 및 로직 + +**기능 구현인 경우:** +- 추가된 기능 설명 +- 수정/추가된 파일 위치 +- 주요 변경사항 + +**백엔드 작업인 경우:** +- API 엔드포인트 변경사항 +- 로직 리팩토링 내용 +- 의존성 추가/변경 +- 확인해야 할 사항 + +**프론트엔드 작업인 경우:** +- 페이지/컴포넌트 변경사항 +- UI/UX 개선 내용 +- 상태 관리 변경 + +### 3단계: 보고서 작성 + +간결하고 명확한 문체로 작성: +- 능동태 사용 권장 +- 키워드 기반 문장으로 가독성 향상 +- 불필요한 구어체 표현 제거 + +## 📝 보고서 형식 + +### 기본 구조 + +```markdown +### 📌 작업 개요 +[간단한 요약 - 2-3줄] + +### 🔍 문제 분석 (버그인 경우) +[또는] + +### 🎯 구현 목표 (기능 구현인 경우) + +### ✅ 구현 내용 + +#### [주요 변경사항 1] +- **파일**: `경로/파일명` +- **변경 내용**: [구체적인 설명] +- **이유**: [왜 이렇게 수정했는지] + +#### [주요 변경사항 2] +... + +### 🔧 주요 변경사항 상세 + +#### [파일명 또는 기능명] +[코드 변경 내용을 자연스럽게 설명] + +**특이사항** (있는 경우): +- [주의할 점이나 특별한 부분] + +### 📦 의존성 변경 (있는 경우) +- [추가/변경된 의존성] + +### 🧪 테스트 및 검증 +- [테스트 방법 또는 확인 사항] + +### 📌 참고사항 +- [추가로 확인하거나 주의할 점] +``` + +## 🎨 작성 스타일 가이드 + +### 간결한 문체 예시 + +**좋은 예:** +- "gitignore 중복 항목 추가 문제 확인. 정규화 함수 추가하여 중복 체크 로직 구현" +- "사용자 인증 API에 JWT 토큰 검증 로직 추가. 만료된 토큰에 대해 401 에러 반환" +- "로그인 페이지에 소셜 로그인 버튼 추가. Google과 GitHub 로그인 지원" + +**나쁜 예:** +- "중복 항목 추가 문제가 확인되었습니다. 정규화 함수가 생성되었습니다." +- "JWT 토큰 검증 로직이 추가되었습니다." +- "소셜 로그인 버튼이 추가되었습니다." + +### 버그 수정 보고서 예시 + +```markdown +### 📌 작업 개요 +integrator에서 gitignore에 기본값 추가 시 이미 존재하는 항목을 중복 추가하는 문제 수정 + +**보고서 파일**: `.report/20251212_#112_gitignore_중복추가_문제수정.md` + +### 🔍 문제 분석 +기존 코드에서 `.idea`와 `.idea/` 같은 서로 다른 형식의 항목을 다른 것으로 인식하여 중복 추가 발생 +예: 이미 `./idea`가 있는데 `/\.idea`를 또 추가하는 경우 발생 + +### ✅ 구현 내용 + +#### gitignore 항목 정규화 함수 추가 +- **파일**: `template_integrator.ps1`, `template_integrator.sh` +- **변경 내용**: `Normalize-GitIgnoreEntry` 함수 추가하여 다양한 형식의 gitignore 항목 정규화 +- **이유**: `/\.idea`, `.idea`, `./idea` 같은 서로 다른 형식을 모두 `.idea`로 통일하여 비교 가능하도록 구현 + +#### 중복 체크 로직 개선 +- **파일**: `template_integrator.ps1`, `template_integrator.sh` +- **변경 내용**: `Test-GitIgnoreEntryExists` 함수에서 정규화된 항목 비교하도록 수정 +- **이유**: 정규화를 통해 실제로 같은 항목인지 정확하게 판단 가능 + +### 🔧 주요 변경사항 상세 + +#### Normalize-GitIgnoreEntry 함수 +주석, 앞뒤 공백, 앞의 슬래시(`/`), `./` 접두사, 뒤의 슬래시를 제거하여 항목 정규화 +예: `/.idea` → `.idea`, `./idea` → `.idea`로 변환 + +**특이사항**: +- 숨김 폴더(점으로 시작하는 폴더)는 보존. `.idea`는 그대로 `.idea`로 유지 +- 빈 문자열이 되면 원본을 반환하여 예외 상황 방지 + +#### .claude/settings.local.json 동적 추가 +이슈 요청에 따라 `.claude/settings.local.json`도 필수 항목에 추가 + +### 🧪 테스트 및 검증 +- 기존에 `.idea`가 있는 gitignore 파일에서 테스트 +- `/\.idea`, `.idea`, `./idea` 등 다양한 형식으로 이미 존재하는 경우 중복 추가되지 않음 확인 +``` + +### 기능 구현 보고서 예시 + +```markdown +### 📌 작업 개요 +사용자 프로필 이미지 업로드 및 변경 기능 추가 + +**보고서 파일**: `.report/20251213_#45_사용자_프로필_이미지_업로드_기능.md` + +### 🎯 구현 목표 +- 프로필 페이지에 이미지 업로드 UI 추가 +- 이미지 파일을 서버에 업로드하는 API 구현 +- 업로드된 이미지 URL을 사용자 정보에 저장 + +### ✅ 구현 내용 + +#### 프론트엔드 - 프로필 페이지 수정 +- **파일**: `src/pages/Profile.tsx` +- **변경 내용**: 이미지 업로드 버튼과 미리보기 기능 추가 +- **이유**: 사용자가 업로드할 이미지를 미리 확인 가능하도록 구현 + +#### 백엔드 - 이미지 업로드 API 추가 +- **파일**: `src/main/java/com/example/controller/UserController.java` +- **변경 내용**: `POST /api/users/profile-image` 엔드포인트 추가 +- **이유**: MultipartFile을 받아서 서버에 저장하고 URL을 반환하도록 구현 + +#### 이미지 저장 서비스 구현 +- **파일**: `src/main/java/com/example/service/ImageService.java` +- **변경 내용**: 이미지 파일을 `uploads/profile/` 디렉토리에 저장하는 로직 추가 +- **이유**: 프로필 이미지를 별도 디렉토리에 관리 + +### 🔧 주요 변경사항 상세 + +#### Profile.tsx +`useState`로 선택된 이미지 파일 관리, `FileReader` API로 미리보기 구현 +업로드 버튼 클릭 시 FormData 생성하여 API 호출 + +**특이사항**: +- 이미지 크기 제한(5MB)을 클라이언트에서 먼저 체크 +- 지원 형식: JPG, PNG, GIF만 허용 + +#### UserController.java +`@RequestParam("file") MultipartFile file`로 파일을 받아서 `ImageService`에 전달 +성공 시 이미지 URL 반환, 실패 시 에러 메시지 반환 + +#### ImageService.java +파일명을 UUID로 생성하여 중복 방지, 원본 파일명은 메타데이터로 저장 +저장된 파일의 URL을 반환하여 프론트엔드에서 바로 사용 가능하도록 구현 + +### 📦 의존성 변경 +- 없음 (기존 라이브러리만 사용) + +### 🧪 테스트 및 검증 +- 다양한 크기의 이미지 파일로 테스트 +- 5MB 이상의 파일은 업로드 거부 확인 +- 업로드된 이미지가 정상적으로 표시되는지 확인 + +### 📌 참고사항 +- 이미지 파일은 서버의 `uploads/profile/` 디렉토리에 저장 +- 향후 이미지 삭제 기능 추가 예정 +``` + +## 🔍 분석 프로세스 + +### 변경 파일 분석 시 (효율적 분석) + +**⚠️ 중요: Git 명령어 최소화 및 효율적인 분석 프로세스 준수** + +1. **변경된 파일명만 확인** (`git status` 한 번만 실행) + ```bash + git status + ``` + - 변경된 파일명과 상태(M/A/D)만 확인 + - main 브랜치와 다른 파일명만 확인 + - **이후 더 이상 Git 명령어 사용하지 않음** + +2. **이슈 내용 기반 파일 선별** + - 이슈에서 언급된 파일/기능과 관련된 파일만 선별 + - 변경된 파일 목록에서 이슈와 관련된 파일만 필터링 + - 관련 없는 파일(예: 자동 생성 파일, 설정 파일 등)은 제외 + +3. **선별된 파일 직접 읽어서 분석** + - 선별된 파일을 직접 읽어서 현재 상태 확인 + - 이슈와 직접 관련된 변경사항에 집중 + - 추가된 코드, 수정된 코드, 삭제된 코드 분석 + - 필요시 코드베이스 검색으로 관련 코드 파악 + +4. **변경 패턴 파악** + - 버그 수정인지 + - 기능 추가인지 + - 리팩토링인지 + +**효율성 원칙**: +- ✅ `git status` 한 번만 실행 → 파일명 확인 → 이슈 기반 선별 → 파일 직접 읽어 분석 +- ❌ Git diff 명령어 반복 실행 (토큰 낭비) +- ❌ 모든 파일의 전체 diff를 한 번에 읽기 (토큰 낭비) +- ✅ 이슈와 관련 없는 파일은 분석 생략 +- ✅ 파일을 직접 읽어서 동적으로 변경사항 파악 + +### 보고서 파일 생성 로직 + +1. **.report 폴더 확인** + - `.report/` 폴더가 없으면 자동 생성 + +2. **파일명 생성** + - 형식: `[YYYYMMDD]_[ISSUE#]_[간단한설명].md` + - 날짜: 현재 날짜 (YYYYMMDD 형식) + - 이슈 번호: `#112` 형식 유지 + - 설명: 한글/영문, 언더스코어로 단어 구분 + - 특수문자 제거 및 안전한 파일명으로 변환 + +3. **파일 저장** + - 생성된 파일을 `.report/` 폴더에 직접 저장 + - 전체 경로 예시: `.report/20251212_#112_gitignore_중복추가_문제수정.md` + +### 이슈 내용 분석 시 + +1. **이슈 타입 판단** + - 버그 리포트 + - 기능 요청 + - 개선 제안 + +2. **핵심 문제/요구사항 추출** + - 문제 설명 + - 예상 동작 + - 재현 방법 + +3. **관련 파일 선별 (변경 파일 목록과 연계)** + - 이슈에서 언급된 파일명 추출 + - `git status`로 확인한 변경 파일 목록에서 관련 파일만 필터링 + - 관련 기능 코드 위치 파악 + - **선별된 파일을 직접 읽어서 상세 분석** (토큰 절약) + +## 📄 보고서 파일 생성 + +- **위치**: `.report/` 디렉토리 +- **파일명**: `[YYYYMMDD]_[ISSUE#]_[간단한설명].md` + - 예시: `20251212_#112_gitignore_중복추가_문제수정.md` + - 프로젝트 prefix는 포함하지 않음 +- **형식**: Markdown +- **Git 추적**: 자동으로 `.report/` 폴더가 gitignore에 추가되어 Git 추적 안 됨 + +## ✅ 출력 형식 + +보고서를 작성한 후: + +1. **보고서 내용 표시** + - 작성된 보고서 전체 내용 표시 + +2. **파일 저장 확인** + - 저장된 파일 경로 표시 + - 파일명 제안 + +3. **다음 단계 제안** + - 이슈에 댓글로 추가할지 + - PR 설명에 포함할지 + +--- + +**중요**: +- 보고서는 자연스럽고 읽기 쉬운 형식으로 작성 +- 기술적인 내용도 비전문가가 이해하기 쉬운 형식으로 작성 +- 간결하게 키워드 기반 문장으로 가독성 높인 답변 제공 +- 특이한 부분이나 주의할 점은 명확히 표시 + diff --git a/.cursor/commands/testcase.md b/.cursor/commands/testcase.md new file mode 100644 index 0000000..62ca157 --- /dev/null +++ b/.cursor/commands/testcase.md @@ -0,0 +1,373 @@ +# Testcase Generator + +당신은 **QA 테스트케이스 작성 전문가**입니다. GitHub 이슈를 분석하여 테스트 체크리스트를 생성하세요. + +## 🔍 프로세스 + +### 1단계: 프로젝트 타입 자동 감지 + +다음 파일들을 확인하여 프로젝트 타입을 판단하세요: + +**Spring Boot (백엔드)** +- `build.gradle` 또는 `pom.xml` 존재 +- `src/main/java/` 디렉토리 +- Controller, Service, Repository 패턴 + +**React/React Native (프론트엔드)** +- `package.json` 존재 +- `react` 또는 `react-native` 의존성 +- JSX/TSX 파일 + +**Flutter (모바일)** +- `pubspec.yaml` 존재 +- `lib/` 디렉토리 +- `.dart` 파일 + +**Python (백엔드)** +- `requirements.txt` 또는 `pyproject.toml` +- Flask/FastAPI/Django 프레임워크 + +### 2단계: GitHub 이슈 파싱 + +사용자가 제공한 GitHub 이슈 내용에서 다음을 추출하세요: +- 이슈 번호 (예: `#407`) +- 이슈 제목 (예: `닉네임 및 프로필 사진 변경`) +- 도메인/카테고리 (예: `[회원]`, `[채팅]`) +- 담당자 정보 +- PR 링크 (있는 경우) + +### 3단계: 관련 코드 탐색 + +이슈의 도메인을 기반으로 관련 파일을 탐색하세요: + +**Spring Boot** +- Controller 파일 검색 (API 엔드포인트 확인) +- Service 로직 확인 +- DTO/Request/Response 구조 파악 + +**React/Flutter** +- 관련 컴포넌트/위젯 파일 +- API 호출 로직 +- 화면 구조 + +### 4단계: 테스트케이스 템플릿 생성 + +프로젝트 타입에 맞는 테스트케이스를 생성하세요. + +--- + +## 📋 테스트케이스 템플릿 + +### 🔹 Spring Boot (백엔드) + +```markdown +## 🧪 테스트 케이스: [기능명] + +**이슈**: #[번호] +**기능**: [기능 설명] +**API**: `[HTTP메서드] /api/[경로]` +**담당자**: @[담당자] + +--- + +### ✅ 1. 기본 기능 동작 확인 + +#### 1.1 정상 케이스 +- [ ] API 정상 호출 (200/201 응답) + - 테스트: [구체적인 요청 예시] + - 예상: [예상 응답] + - 실제: + - 증빙: + +- [ ] DB 데이터 정상 저장/조회 + - 테스트: [확인할 쿼리] + - 예상: [예상 결과] + - 실제: + - 증빙: + +--- + +### ⚠️ 2. 엣지 케이스 테스트 + +- [ ] 빈 값/null 파라미터 처리 + - 테스트: + - 예상: + - 실제: + +- [ ] 최대 길이 초과 입력 + - 테스트: + - 예상: + - 실제: + +- [ ] 중복 요청 (멱등성 확인) + - 테스트: + - 예상: + - 실제: + +- [ ] 존재하지 않는 리소스 조회 + - 테스트: + - 예상: + - 실제: + +- [ ] 타 사용자 리소스 접근 시도 + - 테스트: + - 예상: + - 실제: + +--- + +### 📄 3. Swagger 문서 확인 + +- [ ] API 엔드포인트 정확히 명시 +- [ ] Request 파라미터 타입/필수 여부 명시 +- [ ] Response 스키마 정의 +- [ ] 에러 응답 코드 문서화 (400, 401, 403, 404) + +--- + +### 📊 테스트 결과 요약 + +- **테스트 일자**: YYYY-MM-DD +- **테스터**: @username +- **테스트 환경**: [ ] local [ ] test [ ] prod +- **전체 결과**: [ ] ✅ PASS [ ] ❌ FAIL + +#### 발견된 이슈 +1. +2. +``` + +### 🔹 React/React Native (프론트엔드) + +```markdown +## 🧪 테스트 케이스: [기능명] + +**이슈**: #[번호] +**화면**: [화면명] +**담당자**: @[담당자] + +--- + +### ✅ 1. 기본 기능 동작 확인 + +#### 1.1 화면 렌더링 +- [ ] 화면 정상 표시 + - 테스트: + - 예상: + - 실제: + - 증빙: + +#### 1.2 사용자 인터랙션 +- [ ] 버튼 클릭 동작 + - 테스트: + - 예상: + - 실제: + +- [ ] 입력 필드 동작 + - 테스트: + - 예상: + - 실제: + +#### 1.3 API 연동 +- [ ] 데이터 로딩 + - 테스트: + - 예상: + - 실제: + +- [ ] 데이터 저장/수정 + - 테스트: + - 예상: + - 실제: + +--- + +### ⚠️ 2. 엣지 케이스 테스트 + +- [ ] 로딩 상태 표시 + - 테스트: + - 예상: + - 실제: + +- [ ] 빈 데이터 처리 + - 테스트: + - 예상: + - 실제: + +- [ ] 긴 텍스트 UI 깨짐 확인 + - 테스트: + - 예상: + - 실제: + +- [ ] 빠른 연속 클릭 방지 + - 테스트: + - 예상: + - 실제: + +- [ ] 네트워크 에러 처리 + - 테스트: + - 예상: + - 실제: + +--- + +### 🎨 3. UI/UX 확인 + +- [ ] 디자인 시안과 일치 +- [ ] 반응형 레이아웃 (다양한 화면 크기) +- [ ] 다크모드 지원 (있는 경우) +- [ ] 애니메이션/전환 효과 + +--- + +### 📊 테스트 결과 요약 + +- **테스트 일자**: YYYY-MM-DD +- **테스터**: @username +- **테스트 환경**: [ ] local [ ] dev [ ] prod +- **테스트 기기**: [디바이스/브라우저 정보] +- **전체 결과**: [ ] ✅ PASS [ ] ❌ FAIL + +#### 발견된 이슈 +1. +2. +``` + +### 🔹 Flutter (모바일) + +```markdown +## 🧪 테스트 케이스: [기능명] + +**이슈**: #[번호] +**화면**: [화면명] +**담당자**: @[담당자] + +--- + +### ✅ 1. 기본 기능 동작 확인 + +#### 1.1 화면 렌더링 +- [ ] 위젯 정상 표시 (Android) + - 테스트: + - 예상: + - 실제: + - 증빙: + +- [ ] 위젯 정상 표시 (iOS) + - 테스트: + - 예상: + - 실제: + - 증빙: + +#### 1.2 사용자 인터랙션 +- [ ] 터치/제스처 동작 + - 테스트: + - 예상: + - 실제: + +#### 1.3 데이터 처리 +- [ ] API 호출 및 데이터 표시 + - 테스트: + - 예상: + - 실제: + +--- + +### ⚠️ 2. 엣지 케이스 테스트 + +- [ ] 로딩 인디케이터 +- [ ] 빈 데이터 화면 +- [ ] 에러 화면 +- [ ] 네트워크 끊김 처리 +- [ ] 백그라운드 복귀 시 상태 유지 + +--- + +### 🎨 3. UI/UX 확인 + +- [ ] 디자인 시안 일치 +- [ ] 다양한 화면 크기 (Tablet/Phone) +- [ ] Android/iOS 플랫폼별 UI 차이 +- [ ] 애니메이션 부드러움 + +--- + +### 📊 테스트 결과 요약 + +- **테스트 일자**: YYYY-MM-DD +- **테스터**: @username +- **테스트 기기**: + - [ ] Android [버전] + - [ ] iOS [버전] +- **전체 결과**: [ ] ✅ PASS [ ] ❌ FAIL + +#### 발견된 이슈 +1. +2. +``` + +--- + +## 🎯 출력 규칙 + +### ⚠️ 필수: MD 파일 생성 + +**반드시 프로젝트 루트 경로에 마크다운 파일을 생성하세요!** + +- **파일명 형식**: `testcase-[이슈번호]-[간단한설명].md` + - 예: `testcase-407-닉네임변경.md` + - 예: `testcase-123-채팅기능.md` + +- **파일 위치**: 프로젝트 루트 디렉토리 (`.claude/`, `src/`와 같은 레벨) + +- **이유**: + - Cursor/Claude Code 내부에서 마크다운 출력만 하면 복사하기 어려움 + - 파일로 생성하면 GitHub 이슈 댓글에 바로 붙여넣기 가능 + - 테스트 이력 관리 용이 + +### 추가 출력 규칙 + +1. **프로젝트 타입 명시**: 감지된 타입을 명확히 표시 +2. **관련 파일 탐색**: Controller, API, 컴포넌트 등 관련 코드 찾기 +3. **구체적인 테스트 항목**: "닉네임 변경"이면 "닉네임 길이 제한(1~20자)" 등 구체화 +4. **GitHub 댓글용 마크다운**: 복사-붙여넣기 가능한 형식 +5. **간결함 유지**: 체크리스트 중심, 장황한 설명 지양 + +## 📌 특별 지시사항 + +- **백엔드**: Swagger 문서 완성도를 반드시 체크리스트에 포함 +- **프론트엔드**: UI/UX 시각적 확인 항목 포함 +- **공통**: 보안 관련 테스트 (권한, 인증) 자동 포함 +- **엣지 케이스**: 큰 값, 특수문자, 중복 호출 등 자동 생성 + +--- + +## 예시 + +**입력**: +``` +⚙️ [기능추가][회원] 닉네임 및 프로필 사진 변경 #407 +닉네임, 프로필 사진 변경하는 API 없음 +백엔드: @nayoung04 +``` + +**출력**: Spring Boot 테스트케이스 템플릿 + 관련 Controller 파일 경로 + 구체적인 엣지 케이스 (닉네임 중복, 파일 크기 제한 등) + +--- + +## ✅ 완료 후 사용자에게 안내 + +테스트케이스 파일 생성 완료 후 다음 메시지를 출력하세요: + +``` +✅ 테스트케이스 생성 완료! + +📄 파일 위치: `testcase-[번호]-[설명].md` + +GitHub 이슈에 댓글로 붙여넣는 방법: +1. 생성된 MD 파일 열기 +2. 전체 내용 복사 (Ctrl+A → Ctrl+C) +3. GitHub 이슈 댓글란에 붙여넣기 +4. 테스트 진행하면서 체크박스 체크 및 결과 작성 + +💡 팁: 파일을 Git에 커밋하면 테스트 이력 관리 가능합니다! +``` diff --git a/.gitignore b/.gitignore index 83f7d2d..0ebdcfd 100644 --- a/.gitignore +++ b/.gitignore @@ -85,6 +85,7 @@ celerybeat-schedule # Environments .env +.env.* .venv env/ venv/ diff --git a/app/config/database.py b/app/config/database.py index 80d75cc..973d0fd 100644 --- a/app/config/database.py +++ b/app/config/database.py @@ -1,2 +1,40 @@ -# 빈 파일 - DB 연결 설정 +from typing import AsyncGenerator +from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine, AsyncEngine + +from app.config.settings import get_settings +from app.utils.logger import logger + +_settings = get_settings() + +_engine = create_async_engine( + _settings.postgres_url, + pool_pre_ping=True, + echo=False, # SQL 쿼리 로깅 +) + +_async_session_factory = async_sessionmaker( + bind=_engine, + expire_on_commit=False, + autoflush=False, +) + + +def get_async_engine() -> AsyncEngine: + return _engine + + +def get_async_session_factory() -> async_sessionmaker[AsyncSession]: + return _async_session_factory + + +async def get_async_session() -> AsyncGenerator[AsyncSession, None]: + async with _async_session_factory() as session: + try: + yield session + except Exception as e: + logger.error(f"Postgres DB 에러: {e}") + await session.rollback() + raise + finally: + await session.close() diff --git a/app/config/settings.py b/app/config/settings.py index c17f4ec..d23d74d 100644 --- a/app/config/settings.py +++ b/app/config/settings.py @@ -1,2 +1,47 @@ -# 빈 파일 - 환경 변수 설정 +from functools import lru_cache +from pydantic_settings import BaseSettings, SettingsConfigDict + + +class Settings(BaseSettings): + """ + .env 에서 환경변수 로딩 + """ + + model_config = SettingsConfigDict( + env_file=".env", + env_file_encoding="utf-8", + case_sensitive=False, + extra="ignore" + ) + + # GitHub API 설정 + github_api_base_url: str + github_api_token: str | None = None + + # Ollama 설정 + ollama_base_url: str + ollama_api_key: str + ollama_model: str + ollama_timeout_seconds: int + + # Qdrant 설정 + qdrant_base_url: str + qdrant_collection: str + qdrant_api_key: str + + # 텍스트 청크 설정 + text_chunk_max_chars: int + text_chunk_overlap_chars: int + text_chunk_hard_max_chars: int + + # 동시성 설정 + concurrency_embedding_max_concurrency: int + + # PostgreSQL 설정 + postgres_url: str + + +@lru_cache(maxsize=1) +def get_settings() -> Settings: + return Settings() diff --git a/app/db/__init__.py b/app/db/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/db/init_db.py b/app/db/init_db.py new file mode 100644 index 0000000..7c386ea --- /dev/null +++ b/app/db/init_db.py @@ -0,0 +1,17 @@ +from sqlalchemy.ext.asyncio import AsyncEngine + +from app.models.base import Base +from app.utils.logger import logger + + +def _import_all_models() -> None: + from app.models.github_cursor import GithubCursorEntity + + +async def create_tables_if_not_exists(engine: AsyncEngine) -> None: + _import_all_models() + + async with engine.begin() as conn: + await conn.run_sync(Base.metadata.create_all) + + logger.info("DB 테이블 생성완료") diff --git a/app/main.py b/app/main.py index 18f44bd..e3de812 100644 --- a/app/main.py +++ b/app/main.py @@ -1,8 +1,35 @@ +from contextlib import asynccontextmanager +from pathlib import Path from typing import Dict from fastapi import FastAPI +from fastapi.staticfiles import StaticFiles -app = FastAPI() +from app.config.database import get_async_engine +from app.db.init_db import create_tables_if_not_exists +from app.utils.logger import logger +from app.views import pages + + +# 프로젝트 루트 경로 +BASE_DIR = Path(__file__).resolve().parent.parent + + +@asynccontextmanager +async def lifespan(app: FastAPI): + logger.info("ChatBot 애플리케이션 시작") + await create_tables_if_not_exists(get_async_engine()) + yield + logger.info("애플리케이션 종료") + + +app = FastAPI(lifespan=lifespan) + +# 정적 파일 서빙 +app.mount("/static", StaticFiles(directory=BASE_DIR / "static"), name="static") + +# 페이지 라우터 +app.include_router(pages.router) @app.get("/health") diff --git a/app/models/base.py b/app/models/base.py new file mode 100644 index 0000000..364c29f --- /dev/null +++ b/app/models/base.py @@ -0,0 +1,43 @@ +import uuid +from datetime import datetime + +from sqlalchemy import DateTime, func +from sqlalchemy.dialects.postgresql.base import UUID +from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column + + +class Base(DeclarativeBase): + """ + SQLAlchemy Declarative Base + - 모든 엔티티는 Base 상속 + """ + pass + + +class TimestampMixin: + """ + created_at, updated_at 자동 관리 Mixin + - created_at: DB 레벨 자동 설정 + - updated_at: 애플리케이션 레벨에서 명시적 관리 + """ + created_at: Mapped[datetime] = mapped_column( + DateTime(timezone=True), + nullable=False, + server_default=func.now(), # DB 레벨 - INSERT 시 자동 + ) + + updated_at: Mapped[datetime] = mapped_column( + DateTime(timezone=True), + nullable=False, + server_default=func.now(), # DB 레벨 - INSERT 시 자동 + ) + +class PrimaryKeyMixin: + """ + UUID Primary Key Mixin + """ + id: Mapped[uuid.UUID] = mapped_column( + UUID(as_uuid=True), + primary_key=True, + default=uuid.uuid4, + ) diff --git a/app/models/enums/__init__.py b/app/models/enums/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/models/enums/source_type.py b/app/models/enums/source_type.py new file mode 100644 index 0000000..9501338 --- /dev/null +++ b/app/models/enums/source_type.py @@ -0,0 +1,17 @@ +from enum import Enum + + +class SourceType(str, Enum): + """ + 깃허브 임베딩 대상 SourceType + - Repository: 레포 파일/문서 (README 등) + - ISSUE: 이슈 + - PULL_REQUEST: PR + - COMMIT: 커밋 + - RELEASE: 릴리즈 + """ + REPOSITORY = "REPOSITORY" + ISSUE = "ISSUE" + PULL_REQUEST = "PULL_REQUEST" + COMMIT = "COMMIT" + RELEASE = "RELEASE" diff --git a/app/models/github_cursor.py b/app/models/github_cursor.py new file mode 100644 index 0000000..990cdf2 --- /dev/null +++ b/app/models/github_cursor.py @@ -0,0 +1,20 @@ +from sqlalchemy import Enum as SqlEnum +from sqlalchemy import UniqueConstraint, Index, String +from sqlalchemy.orm import Mapped, mapped_column + +from app.models.base import Base, PrimaryKeyMixin, TimestampMixin +from app.models.enums.source_type import SourceType + + +class GithubCursorEntity(Base, PrimaryKeyMixin, TimestampMixin): + __tablename__ = "github_cursor" + __table_args__ = ( + UniqueConstraint("repository_name", "source_type", name="uq_github_cursor"), + Index("idx_github_cursor_repo_type", "repository_name", "source_type") + ) + + repository_name: Mapped[str] = mapped_column(String(200), nullable=False) + + source_type: Mapped[SourceType] = mapped_column(SqlEnum(SourceType, native_enum=False), nullable=False) + + cursor_value: Mapped[str] = mapped_column(String(500), nullable=False) diff --git a/app/models/github_issue.py b/app/models/github_issue.py deleted file mode 100644 index 4a402cb..0000000 --- a/app/models/github_issue.py +++ /dev/null @@ -1,2 +0,0 @@ -# 빈 파일 - GitHub 이슈 모델 - diff --git a/app/repositories/github_cursor_repository.py b/app/repositories/github_cursor_repository.py new file mode 100644 index 0000000..7a5e93d --- /dev/null +++ b/app/repositories/github_cursor_repository.py @@ -0,0 +1,53 @@ +import uuid +from typing import Optional + +from sqlalchemy import select, func +from sqlalchemy.dialects.postgresql import insert +from sqlalchemy.ext.asyncio import AsyncSession + +from app.models.enums.source_type import SourceType +from app.models.github_cursor import GithubCursorEntity + + +class GithubCursorRepository: + async def find_by_repository_name_and_source_type( + self, + session: AsyncSession, + repository_name: str, + source_type: SourceType, + ) -> Optional[GithubCursorEntity]: + """ + 특정 repository + source_type 커서 조회 + """ + query = select(GithubCursorEntity).where( + GithubCursorEntity.repository_name == repository_name, + GithubCursorEntity.source_type == source_type, + ) + result = await session.execute(query) + return result.scalar_one_or_none() + + async def upsert( + self, + session: AsyncSession, + repository_name: str, + source_type: SourceType, + cursor_value: str, + ) -> GithubCursorEntity: + """ + 커서 upsert (없으면 생성, 있으면 업데이트) + """ + query = insert(GithubCursorEntity).values( + id=uuid.uuid4(), + repository_name=repository_name, + source_type=source_type, + cursor_value=cursor_value, + ).on_conflict_do_update( + index_elements=["repository_name", "source_type"], + set_={ + "cursor_value": cursor_value, + "updated_at": func.now(), + }, + ).returning(GithubCursorEntity) + + result = await session.execute(query) + return result.scalar_one() diff --git a/app/utils/logger.py b/app/utils/logger.py index e4114fb..f6e39c8 100644 --- a/app/utils/logger.py +++ b/app/utils/logger.py @@ -10,61 +10,60 @@ def setup_logger( - name: str = "chatbot", - log_level: str = "INFO", - log_file: Optional[str] = None, - format_string: Optional[str] = None, + name: str = "chatbot", + log_level: str = "INFO", + log_file: Optional[str] = None, + format_string: Optional[str] = None, ) -> logging.Logger: - """ - 로거를 설정하고 반환합니다. + """ + 로거를 설정하고 반환합니다. - Args: - name: 로거 이름 (기본값: "chatbot") - log_level: 로그 레벨 (DEBUG, INFO, WARNING, ERROR, CRITICAL) - log_file: 로그 파일 경로 (None이면 파일 로깅 안 함) - format_string: 커스텀 포맷 문자열 (None이면 기본 포맷 사용) + Args: + name: 로거 이름 (기본값: "chatbot") + log_level: 로그 레벨 (DEBUG, INFO, WARNING, ERROR, CRITICAL) + log_file: 로그 파일 경로 (None이면 파일 로깅 안 함) + format_string: 커스텀 포맷 문자열 (None이면 기본 포맷 사용) - Returns: - 설정된 Logger 인스턴스 - """ - logger = logging.getLogger(name) - - # 이미 핸들러가 설정되어 있으면 기존 로거 반환 - if logger.handlers: - return logger + Returns: + 설정된 Logger 인스턴스 + """ + logger = logging.getLogger(name) - # 로그 레벨 설정 - level = getattr(logging, log_level.upper(), logging.INFO) - logger.setLevel(level) + # 이미 핸들러가 설정되어 있으면 기존 로거 반환 + if logger.handlers: + return logger - # 기본 포맷 설정 - if format_string is None: - format_string = ( - "%(asctime)s - %(name)s - %(levelname)s - " - "%(filename)s:%(lineno)d - %(message)s" - ) - - formatter = logging.Formatter(format_string, datefmt="%Y-%m-%d %H:%M:%S") + # 로그 레벨 설정 + level = getattr(logging, log_level.upper(), logging.INFO) + logger.setLevel(level) - # 콘솔 핸들러 설정 - console_handler = logging.StreamHandler(sys.stdout) - console_handler.setLevel(level) - console_handler.setFormatter(formatter) - logger.addHandler(console_handler) + # 기본 포맷 설정 + if format_string is None: + format_string = ( + "%(asctime)s - %(name)s - %(levelname)s - " + "%(filename)s:%(lineno)d - %(message)s" + ) - # 파일 핸들러 설정 (선택적) - if log_file: - log_path = Path(log_file) - log_path.parent.mkdir(parents=True, exist_ok=True) - - file_handler = logging.FileHandler(log_file, encoding="utf-8") - file_handler.setLevel(level) - file_handler.setFormatter(formatter) - logger.addHandler(file_handler) + formatter = logging.Formatter(format_string, datefmt="%Y-%m-%d %H:%M:%S") - return logger + # 콘솔 핸들러 설정 + console_handler = logging.StreamHandler(sys.stdout) + console_handler.setLevel(level) + console_handler.setFormatter(formatter) + logger.addHandler(console_handler) + + # 파일 핸들러 설정 (선택적) + if log_file: + log_path = Path(log_file) + log_path.parent.mkdir(parents=True, exist_ok=True) + + file_handler = logging.FileHandler(log_file, encoding="utf-8") + file_handler.setLevel(level) + file_handler.setFormatter(formatter) + logger.addHandler(file_handler) + + return logger # 기본 로거 인스턴스 생성 logger = setup_logger() - diff --git a/app/views/pages.py b/app/views/pages.py index 3a9d0ab..733e6b1 100644 --- a/app/views/pages.py +++ b/app/views/pages.py @@ -1,2 +1,83 @@ -# 빈 파일 - 페이지 라우팅 (Jinja2 템플릿) +from pathlib import Path +from fastapi import APIRouter, Request +from fastapi.responses import HTMLResponse +from fastapi.templating import Jinja2Templates + + +# 템플릿 경로 설정 +BASE_DIR = Path(__file__).resolve().parent.parent.parent +templates = Jinja2Templates(directory=BASE_DIR / "templates") + +router = APIRouter() + +# 목업 데이터 +MOCK_REPOS = [ + { + "owner": "Team-Romi", + "name": "romi-chatbot", + "issue_count": 150, + "last_synced": "5분 전", + "status": "synced" + }, + { + "owner": "Team-Romi", + "name": "frontend", + "issue_count": 45, + "last_synced": "1시간 전", + "status": "synced" + }, +] + +MOCK_CHAT_MESSAGES = [ + {"role": "bot", "content": "안녕하세요! 이 레포지토리에 대해 무엇이든 물어보세요."}, + {"role": "user", "content": "로그인 기능 누가 만들었어?"}, + {"role": "bot", "content": "로그인 기능은 @developer1님이 #123 이슈에서 개발했습니다.\n\n📎 관련 이슈: #123 - 로그인 기능 구현"}, +] + + +@router.get("/", response_class=HTMLResponse) +async def index(request: Request): + """메인 페이지 - 레포지토리 목록""" + return templates.TemplateResponse( + request=request, + name="index.html", + context={"repos": MOCK_REPOS} + ) + + +@router.get("/{owner}/{repo}", response_class=HTMLResponse) +async def chat(request: Request, owner: str, repo: str): + """챗봇 페이지""" + repo_info = next( + (r for r in MOCK_REPOS if r["owner"] == owner and r["name"] == repo), + {"owner": owner, "name": repo, "issue_count": 0, "last_synced": "없음", "status": "unknown"} + ) + return templates.TemplateResponse( + request=request, + name="chat.html", + context={ + "owner": owner, + "repo": repo, + "repo_info": repo_info, + "messages": MOCK_CHAT_MESSAGES + } + ) + + +@router.get("/{owner}/{repo}/settings", response_class=HTMLResponse) +async def repo_settings(request: Request, owner: str, repo: str): + """레포 설정 페이지""" + repo_info = next( + (r for r in MOCK_REPOS if r["owner"] == owner and r["name"] == repo), + {"owner": owner, "name": repo, "issue_count": 0, "last_synced": "없음", "status": "unknown"} + ) + return templates.TemplateResponse( + request=request, + name="repo_settings.html", + context={ + "owner": owner, + "repo": repo, + "repo_info": repo_info + } + ) diff --git a/requirements.txt b/requirements.txt index 3e3d573..6e1246b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,13 +1,45 @@ +alembic==1.17.2 annotated-doc==0.0.4 annotated-types==0.7.0 anyio==4.12.0 +asyncpg==0.31.0 +certifi==2025.11.12 +cffi==2.0.0 +charset-normalizer==3.4.4 click==8.3.1 -fastapi==0.124.4 +cryptography==46.0.3 +Deprecated==1.3.1 +fastapi==0.127.0 +greenlet==3.3.0 +grpcio==1.76.0 +grpcio-tools==1.76.0 h11==0.16.0 +h2==4.3.0 +hpack==4.1.0 +httpcore==1.0.9 +httpx==0.28.1 +hyperframe==6.1.0 idna==3.11 +Mako==1.3.10 +MarkupSafe==3.0.3 +numpy==2.4.0 +portalocker==3.2.0 +protobuf==6.33.2 +pycparser==2.23 pydantic==2.12.5 +pydantic-settings==2.12.0 pydantic_core==2.41.5 +PyGithub==2.8.1 +PyJWT==2.10.1 +PyNaCl==1.6.1 +python-dotenv==1.2.1 +qdrant-client==1.16.2 +requests==2.32.5 +setuptools==80.9.0 +SQLAlchemy==2.0.45 starlette==0.50.0 typing-inspection==0.4.2 typing_extensions==4.15.0 -uvicorn==0.38.0 +urllib3==2.6.2 +uvicorn==0.40.0 +wrapt==2.0.1 diff --git a/sql/V20251222_141233__create_github_cursor_table.sql b/sql/V20251222_141233__create_github_cursor_table.sql new file mode 100644 index 0000000..4e52192 --- /dev/null +++ b/sql/V20251222_141233__create_github_cursor_table.sql @@ -0,0 +1,16 @@ +CREATE TABLE IF NOT EXISTS github_cursor ( + id UUID PRIMARY KEY, + repository_name VARCHAR(200) NOT NULL, + source_type VARCHAR(50) NOT NULL, + cursor_value VARCHAR(500) NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + CONSTRAINT uq_github_cursor UNIQUE (repository_name, source_type), + + CONSTRAINT ck_github_cursor_source_type + CHECK (source_type IN ('REPOSITORY', 'ISSUE', 'PULL_REQUEST', 'COMMIT', 'RELEASE')) +); + +-- 인덱스 생성 +CREATE INDEX IF NOT EXISTS idx_github_cursor_repo_type + ON github_cursor (repository_name, source_type); \ No newline at end of file diff --git a/templates/base.html b/templates/base.html index a0a640c..9f2764e 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,2 +1,62 @@ -{# 빈 파일 - 기본 레이아웃 템플릿 #} + + + + + + {% block title %}ROMI{% endblock %} + + + + + + + + + +
+ +
+ + +
+ {% block content %}{% endblock %} +
+ + + + + {% block scripts %}{% endblock %} + + diff --git a/templates/chat.html b/templates/chat.html new file mode 100644 index 0000000..f533dd6 --- /dev/null +++ b/templates/chat.html @@ -0,0 +1,74 @@ +{% extends "base.html" %} + +{% block title %}{{ owner }}/{{ repo }} - ROMI{% endblock %} + +{% block content %} +
+ +
+ + + + + 목록으로 + +

{{ owner }}/{{ repo }}

+ + + + + + +
+ + +
+
+ +
+ {% for msg in messages %} + {% if msg.role == 'bot' %} + +
+
+
+ 🤖 +
+
+
{{ msg.content }}
+
+ {% else %} + +
+
+
+ 👤 +
+
+
{{ msg.content }}
+
+ {% endif %} + {% endfor %} +
+ + +
+ + +
+

+ * 백엔드 구현 후 활성화됩니다 +

+
+
+
+{% endblock %} diff --git a/templates/index.html b/templates/index.html index 091359d..6fb092c 100644 --- a/templates/index.html +++ b/templates/index.html @@ -1,2 +1,64 @@ -{# 빈 파일 - 메인 페이지 템플릿 (챗봇 인터페이스) #} +{% extends "base.html" %} +{% block title %}ROMI - GitHub 지식 베이스{% endblock %} + +{% block content %} +
+ +
+

ROMI

+

GitHub 지식 베이스

+
+ + +
+
+

연결된 레포지토리

+ + {% if repos %} +
+ {% for repo in repos %} +
+
+
📁
+
+
{{ repo.owner }}/{{ repo.name }}
+
+ 이슈 {{ repo.issue_count }}개 · 마지막 동기화: {{ repo.last_synced }} +
+
+
+ + 채팅하기 → + +
+ {% endfor %} +
+ {% else %} +
+ 연결된 레포지토리가 없습니다. +
+ {% endif %} +
+
+ + +
+
+

새 레포지토리 추가

+
+ + +
+

+ * 백엔드 구현 후 활성화됩니다 +

+
+
+
+{% endblock %} diff --git a/templates/repo_settings.html b/templates/repo_settings.html new file mode 100644 index 0000000..a32f655 --- /dev/null +++ b/templates/repo_settings.html @@ -0,0 +1,78 @@ +{% extends "base.html" %} + +{% block title %}{{ owner }}/{{ repo }} 설정 - ROMI{% endblock %} + +{% block content %} +
+ +
+ + + + + 챗봇으로 + +

{{ owner }}/{{ repo }} 설정

+
+ + +
+
+

동기화 상태

+ +
+
+ 상태 + + + + + 연결됨 + +
+ +
+ 이슈 수 + {{ repo_info.issue_count }}개 +
+ +
+ 마지막 동기화 + {{ repo_info.last_synced }} +
+
+ +
+ +
+ + +
+

+ * 백엔드 구현 후 활성화됩니다 +

+
+
+ + +
+
+

위험 구역

+ +

+ 이 레포지토리 연결을 해제하고 모든 데이터를 삭제합니다. + 이 작업은 되돌릴 수 없습니다. +

+ +
+ +
+

+ * 백엔드 구현 후 활성화됩니다 +

+
+
+
+{% endblock %}