52b70363d96e10db7bc1ea48ed83a2a919f3cb5a
백엔드: - User 엔티티에 passwordResetTokenHash/passwordResetExpiresAt(select:false) 추가 - UserService: setPasswordResetToken/findByPasswordResetTokenHash/updatePassword - MailService: sendPasswordResetEmail (dev=로그 출력, prod=수신자만) - AuthService: requestPasswordReset(존재 비노출·로컬계정만·1시간 토큰), resetPassword(토큰 해시 검증→새 비번 저장→전 세션 폐기) - POST /auth/forgot-password(3/분)·/auth/reset-password(5/분), 가입과 동일 비번 규칙 - OAuth 콜백의 잔여 /repos 리다이렉트를 /projects 로 교정(리팩터 누락분) 프론트: - useAuth: forgotPassword/resetPassword - ForgotPasswordPage(/forgot-password), ResetPasswordPage(/reset-password, 토큰=쿼리) - LoginPage '비밀번호 찾기' 링크 연결 + 재설정 완료(?reset=1) 배너 런타임 검증: 재설정→새 비번 로그인 200·구 비번 거부·토큰 재사용 거부·약한 비번 VAL_001· 없는 이메일 동일응답(비노출). 백엔드 build/lint 0·14 tests, 프론트 type-check/lint/build 0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
풀스택 모노레포 기본 템플릿
NestJS(백엔드) · Vue 3(웹) · Flutter(모바일)를 하나의 저장소에서 운영하는 풀스택 템플릿입니다. 세 클라이언트는 동일한 표준 응답 포맷과 공통 에러 코드 맵을 공유하며, Docker Compose로 한 번에 구동됩니다.
구성
| 디렉터리 | 스택 | 역할 | 포트(기본) |
|---|---|---|---|
backend/ |
NestJS + TypeORM | REST API 서버 | 3000 |
frontend/ |
Vue 3 + Vite | 웹 프론트엔드 | 5173 |
flutter/ |
Flutter + Riverpod | 모바일 앱 | - |
db |
PostgreSQL | 데이터베이스 | 5432 |
redis |
Redis | 캐시 / 세션 | 6379 |
사전 요구사항
- Docker / Docker Compose (권장 구동 방식)
- 단독 실행 시: Node.js
^20.19 || >=22.12, Flutter SDK^3.11
빠른 시작 (Docker)
# 1) 환경변수 파일 생성 (예제 복사)
# 실제 설정값은 루트 .env.development 한 곳에서 관리한다 (SSOT).
# backend/frontend 는 docker-compose 가 값을 주입하므로 예제만 복사하면 된다.
cp .env.development.example .env.development # ← 여기에만 값 입력
cp backend/.env.development.example backend/.env.development # (존재만 필요, 내용 최소)
cp frontend/.env.development.example frontend/.env.development # (단독 실행 시에만 사용)
# 2) 개발 환경 기동 (코드만 수정 시)
docker compose -f docker-compose.yml -f docker-compose.dev.yml --env-file .env.development up -d
# 3) 의존성 변경 시에만 --build
docker compose -f docker-compose.yml -f docker-compose.dev.yml --env-file .env.development up -d --build
기동 후:
- 웹: http://localhost:5173
- API: http://localhost:3000/api
- Swagger 문서: http://localhost:3000/api-docs
전체 실행/배포 명령어는 command.md 참조.
단독 실행 (Docker 미사용)
# 백엔드
cd backend && npm install && npm run start:dev
# 프론트엔드
cd frontend && npm install && npm run dev
# 모바일
cd flutter && cp .env.example .env && flutter pub get && flutter run
단독 실행 시 백엔드
.env.development의DB_HOST/REDIS_HOST를localhost로 두고, PostgreSQL·Redis 를 별도로 띄워야 합니다.
환경변수
.env* 는 커밋하지 않습니다. 각 디렉터리의 *.example 파일을 복사해 사용하세요.
루트 .env.{env} 가 단일 진실 공급원(SSOT) 입니다. backend·frontend 는 docker-compose 가
루트 값을 주입하므로 자체 env 에 값을 중복 작성하지 않습니다. (자세한 위임 구조는 CLAUDE.md 의 "환경변수 구조" 참조)
| 파일 | 용도 | 값 작성 위치 |
|---|---|---|
.env.{env}.example |
루트 — 모든 설정의 SSOT (compose 주입) | ✅ 여기에 작성 |
backend/.env.{env}.example |
백엔드 — 고유 시크릿(JWT 등)만 | 최소 (존재 필수) |
frontend/.env.{env}.example |
프론트 — 단독 실행용 VITE_API_BASE_URL |
단독 실행 시에만 |
flutter/.env.example |
모바일 — API_URL (compose 비대상) |
✅ 독립 관리 |
{env} = development | production
표준 응답 포맷
// 성공
{ "success": true, "data": { /* ... */ } }
// 실패
{ "success": false, "error": { "code": "VAL_001", "message": "..." } }
에러 코드 맵과 코딩 규칙 전문은 CLAUDE.md 및 .claude/commands/ 의 언어별 규칙 문서를 참고하세요.
개발 규칙
| 영역 | 문서 |
|---|---|
| 공통/보안 | CLAUDE.md |
| NestJS | .claude/commands/nestjs.md |
| Vue 3 | .claude/commands/vue3.md |
| Flutter | .claude/commands/flutter.md |
디렉터리 구조
.
├── backend/ # NestJS API (Controller / Service / DTO / 공통 필터·인터셉터)
├── frontend/ # Vue 3 (pages / composables / stores / router)
├── flutter/ # Flutter (core / features / widgets)
├── docker-compose.yml # 베이스 정의
├── docker-compose.dev.yml # 개발 오버라이드 (핫리로드, 포트 노출)
├── CLAUDE.md # 공통 코딩 규칙 + 에러 코드 맵 (SSOT)
└── command.md # 실행/배포 명령어
Description
Languages
Go
68.4%
TypeScript
15%
Vue
14.4%
C++
0.6%
CMake
0.5%
Other
0.9%