refactor: .claude 규칙 체계를 skills·rules 구조로 재편
- 슬래시 커맨드(nestjs/vue3/flutter)를 정식 스킬(.claude/skills)로 전환하고 docker 스킬을 신설(루트 command.md 이관) - 공통 규칙을 .claude/rules 로 모듈화(coding-common·response-format·error-codes· git-convention·security·env-structure·testing·checklist)하고 CLAUDE.md 에서 @import - 파일·식별자 네이밍 규약, 테스트 규칙 추가 - .claude/settings.json(권한·환경) 추가 - CLAUDE.md·README.md 참조 갱신, 단독 실행(non-Docker) 안내 정리 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,114 +2,38 @@
|
||||
|
||||
이 저장소는 **풀스택 모노레포 기본 템플릿**이다. 누구나 클론하여 바로 개발을 시작할 수 있도록 공통 규칙과 언어별 규칙을 정의한다.
|
||||
|
||||
| 디렉터리 | 스택 | 역할 | 개발 규칙 (슬래시 명령) |
|
||||
| ----------- | -------------- | ------------------------ | ---------------------------------------- |
|
||||
| `backend/` | NestJS (TS) | REST API 서버 | `/nestjs` → @.claude/commands/nestjs.md |
|
||||
| `frontend/` | Vue 3 (TS) | 웹 프론트엔드 | `/vue3` → @.claude/commands/vue3.md |
|
||||
| `flutter/` | Flutter (Dart) | 모바일 앱 | `/flutter` → @.claude/commands/flutter.md |
|
||||
| 루트 | Docker Compose | 로컬/운영 오케스트레이션 | @command.md |
|
||||
| 디렉터리 | 스택 | 역할 | 개발 규칙 (스킬) |
|
||||
| ----------- | -------------- | ------------------------ | ----------------------------------------- |
|
||||
| `backend/` | NestJS (TS) | REST API 서버 | `/nestjs` → @.claude/skills/nestjs/SKILL.md |
|
||||
| `frontend/` | Vue 3 (TS) | 웹 프론트엔드 | `/vue3` → @.claude/skills/vue3/SKILL.md |
|
||||
| `flutter/` | Flutter (Dart) | 모바일 앱 | `/flutter` → @.claude/skills/flutter/SKILL.md |
|
||||
| 루트 | Docker Compose | 로컬/운영 오케스트레이션 | `/docker` → @.claude/skills/docker/SKILL.md |
|
||||
|
||||
세 클라이언트는 동일한 **표준 응답 포맷**과 **에러 코드 맵**을 공유한다 (아래 참조).
|
||||
세 클라이언트는 동일한 **표준 응답 포맷**과 **에러 코드 맵**을 공유한다 (아래 공통 규칙 참조).
|
||||
|
||||
> 규칙은 `.claude/` 아래로 모듈화되어 있다.
|
||||
> - `.claude/rules/` — 세 플랫폼 공통 규칙 (코딩·응답 포맷·에러 코드·커밋·보안·환경변수)
|
||||
> - `.claude/skills/` — 도메인별 개발 규칙 (스킬). 슬래시 명령(`/nestjs` 등) 또는 해당 디렉터리 작업 시 자동 적용
|
||||
> - `.claude/settings.json` — Claude Code 권한·환경 설정
|
||||
|
||||
---
|
||||
|
||||
## 코딩 규칙
|
||||
## 공통 규칙 (모든 디렉터리 적용)
|
||||
|
||||
### 공통
|
||||
|
||||
- 모든 코드 주석은 **한국어**로 작성
|
||||
- 웹(`frontend`)·서버(`backend`)는 100% TypeScript, 모바일(`flutter`)은 Dart Sound Null Safety 준수
|
||||
- 컴파일러/린터 **Warning 방치 금지** — 커밋 전 각 프로젝트 `lint` / `analyze` 통과
|
||||
- 유틸 함수는 순수 함수로 분리 — TS는 `shared/utils/`, Dart는 `core/utils/`
|
||||
- 매직 넘버·하드코딩 문자열 지양 → 상수 또는 환경변수로 분리
|
||||
- 절대경로 alias 사용 (TS `@/`, Dart `package:`), 깊은 상대경로(`../../`) 지양
|
||||
|
||||
### 표준 응답 포맷 (Global Response Wrapper)
|
||||
|
||||
모든 API 응답은 아래 구조로 통일한다.
|
||||
(SSOT: backend `TransformInterceptor` + `HttpExceptionFilter`)
|
||||
|
||||
```jsonc
|
||||
// 성공
|
||||
{ "success": true, "data": { /* ... */ } }
|
||||
|
||||
// 실패
|
||||
{ "success": false, "error": { "code": "VAL_001", "message": "..." } }
|
||||
```
|
||||
|
||||
- 프론트/플러터 인터셉터는 `success: true` 면 `data` 만 언래핑하여 반환한다.
|
||||
- `success: false` 이거나 HTTP 4xx/5xx 면 `error.code` 로 메시지를 매핑한다.
|
||||
|
||||
### Git 커밋 컨벤션
|
||||
|
||||
`<type>: <제목>` 형식 — type: **feat / fix / refactor / docs / chore / perf / test / style**
|
||||
|
||||
- 예: `feat: 사용자 목록 페이지네이션 추가`
|
||||
- 제목은 한국어, 명령형 현재 시제로 작성
|
||||
- 한 커밋은 하나의 논리적 변경만 포함
|
||||
|
||||
### 에러 코드 맵핑
|
||||
|
||||
세 플랫폼이 공유하는 **단일 진실 공급원(SSOT)**. 메시지를 수정할 때는 아래 세 파일을 함께 갱신한다.
|
||||
|
||||
- backend: `src/common/filters/http-exception.filter.ts`
|
||||
- frontend: `src/composables/useApi.ts` (`ErrorCodeLexicon`)
|
||||
- flutter: `lib/core/api/error_lexicon.dart` (`ErrorLexicon`)
|
||||
|
||||
| 코드 | HTTP / 상황 | 메시지 |
|
||||
| -------- | -------------------- | ------------------------------------------------------- |
|
||||
| SYS_001 | 500 / 미정의 예외 | "일시적인 시스템 오류가 발생했습니다. 잠시 후 다시 시도해 주세요." |
|
||||
| AUTH_001 | 401 | "로그인이 필요한 서비스입니다. 로그인 후 이용해 주세요." |
|
||||
| AUTH_002 | 세션 만료 (클라이언트) | "안전을 위해 로그아웃 되었습니다. 다시 로그인해 주세요." |
|
||||
| AUTH_003 | 403 | "해당 메뉴나 기능에 접근할 수 있는 권한이 없습니다." |
|
||||
| VAL_001 | 400 / 422 (Validation) | "입력하신 정보를 다시 확인해 주세요. (필수값 누락 또는 형식 오류)" |
|
||||
| RES_001 | 404 | "요청하신 정보나 페이지를 찾을 수 없습니다." |
|
||||
| BIZ_001 | 200(비즈니스 실패) / 기타 | "요청하신 작업을 완료하지 못했습니다. 다시 시도해 주세요." |
|
||||
|
||||
> 비즈니스 예외는 `HttpException` 응답의 `message` 로 사용자 노출 문구를 재정의할 수 있다.
|
||||
|
||||
### 보안
|
||||
|
||||
- `.env*` 등 민감정보 Git 커밋 금지 (`.gitignore` 확인) — 예시는 `*.example`(예: `.env.development.example`, `.env.example`) 로만 공유
|
||||
- JWT는 HttpOnly·Secure 쿠키 사용 (웹 `localStorage` 금지) / 모바일은 `flutter_secure_storage` 사용
|
||||
- TypeORM ORM 쿼리 사용으로 SQL Injection 차단 (Raw 쿼리 시 파라미터 바인딩 필수)
|
||||
- 입력값은 DTO(`class-validator`) 검증을 거친 뒤 서비스 계층에 전달
|
||||
- 보안 헤더(`helmet`)·CORS·Rate Limiting(`@nestjs/throttler`) 적용
|
||||
- Docker 컨테이너 내부 root 실행 금지 (비-root 사용자로 구동)
|
||||
@.claude/rules/coding-common.md
|
||||
@.claude/rules/response-format.md
|
||||
@.claude/rules/error-codes.md
|
||||
@.claude/rules/git-convention.md
|
||||
@.claude/rules/security.md
|
||||
@.claude/rules/env-structure.md
|
||||
@.claude/rules/testing.md
|
||||
@.claude/rules/checklist.md
|
||||
|
||||
---
|
||||
|
||||
## 환경변수 구조 (단일 진실 공급원: 루트 `.env`)
|
||||
## 도메인별 개발 규칙 (스킬)
|
||||
|
||||
이 템플릿은 **루트 `.env.{APP_ENV}` 가 모든 설정의 단일 진실 공급원(SSOT)** 이다.
|
||||
값을 한 곳에서만 관리하기 위해, 서비스(backend/frontend)는 자체 env에 값을 중복 작성하지 않고 **루트 → docker-compose 가 주입한 값을 그대로 사용**한다.
|
||||
|
||||
```
|
||||
루트 .env.{APP_ENV}
|
||||
│ (docker compose --env-file 로 로드)
|
||||
├─▶ backend : env_file + environment 로 DB/Redis/CORS/포트 주입
|
||||
│ (backend/.env.{APP_ENV} 는 "존재"만 하면 됨, 내용 최소)
|
||||
├─▶ frontend : BACKEND_API_URL → build arg(VITE_API_BASE_URL) 로 주입
|
||||
├─▶ db : DB_USER/DB_PASSWORD/DB_NAME, DB_DATA_DIR 볼륨
|
||||
└─▶ redis : REDIS_PASSWORD, REDIS_DATA_DIR 볼륨
|
||||
```
|
||||
|
||||
규칙:
|
||||
|
||||
- **새 설정값은 루트 `.env.{APP_ENV}` 에 먼저 추가**하고, 필요한 서비스에 `docker-compose.yml` 의 `environment` / `args` 로 전달한다.
|
||||
- 서비스 자체 env 파일에는 **루트에서 내려주지 않는 고유 값만** 작성한다. (예: 백엔드 `JWT_SECRET`)
|
||||
- `docker-compose.yml` 의 `env_file` 지시자 때문에 `backend/.env.{APP_ENV}` 파일은 비어 있어도 **존재해야 한다.**
|
||||
- **단독 실행(non-Docker)** 시에는 주입이 없으므로, 각 서비스 `.env.{APP_ENV}` 의 주석 처리된 예시 값을 활성화해 사용한다.
|
||||
- **Flutter 는 예외** — docker-compose 대상이 아니므로 `flutter/.env` 에서 `API_URL` 을 독립적으로 관리한다.
|
||||
- 모든 env 파일은 커밋 금지, `*.example` 만 커밋한다. (`.gitignore` 의 `!*.example` 재포함 규칙)
|
||||
|
||||
> 루트 env의 대표 키: `PROJECT_NAME`, `APP_ENV`, `BUILD_MODE`, 각종 `*_PORT`, `BACKEND_API_URL`, `CORS_ORIGIN`, `DB_*`/`DB_DATA_DIR`, `REDIS_*`/`REDIS_DATA_DIR`. 실제 목록은 `.env.development.example` 참조.
|
||||
|
||||
---
|
||||
|
||||
## 개발 규칙 참조
|
||||
|
||||
- 백엔드(NestJS): @.claude/commands/nestjs.md
|
||||
- 프론트엔드(Vue 3): @.claude/commands/vue3.md
|
||||
- 모바일(Flutter): @.claude/commands/flutter.md
|
||||
- 실행/배포 명령어: @command.md
|
||||
- 백엔드(NestJS): @.claude/skills/nestjs/SKILL.md
|
||||
- 프론트엔드(Vue 3): @.claude/skills/vue3/SKILL.md
|
||||
- 모바일(Flutter): @.claude/skills/flutter/SKILL.md
|
||||
- 실행/배포(Docker): @.claude/skills/docker/SKILL.md
|
||||
|
||||
Reference in New Issue
Block a user