perf(docker): 개발 프론트엔드를 컨테이너에서 호스트 vite 로 전환

Windows 바인드 마운트(./frontend:/app) 너머의 소스를 vite 가 모듈마다 읽는 데다
폴링 감시까지 항상 켜져 있어 첫 서빙에 수 분이 걸렸다. 호스트에서 띄우면 2초다.

- dev 오버라이드의 frontend 를 compose profile `frontend` 뒤로 숨긴다 (운영은 그대로)
- 폴링 감시는 CHOKIDAR_USEPOLLING 으로 컨테이너에서만 켠다
- dev 서버 포트·프록시 대상을 루트 .env.{mode} 에서 읽는다 (포트 SSOT 유지)
  포트 충돌 시 조용히 옮기지 않도록 strictPort — CORS_ORIGIN·포트 매핑이 묶여 있다

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-21 11:41:19 +09:00
parent 40af8a2e09
commit 94357d26bd
9 changed files with 195 additions and 38 deletions
+28 -2
View File
@@ -28,11 +28,14 @@ cp .env.development.example .env.development # ← 여기
cp backend/.env.development.example backend/.env.development # (존재 필요: JWT 등 고유 시크릿)
# frontend 는 compose 가 빌드 시 값을 주입하므로 자체 env 복사 불필요
# 2) 개발 환경 기동 (코드만 수정 시)
# 2) 백엔드 스택 기동 (backend + db)
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
# 4) 프론트엔드는 호스트에서 직접 띄운다 (컨테이너보다 수십 배 빠르다)
cd frontend && npm install && npm run dev
```
기동 후:
@@ -41,8 +44,31 @@ docker compose -f docker-compose.yml -f docker-compose.dev.yml --env-file .env.d
- API: <http://localhost:3000/api>
- Swagger 문서: <http://localhost:3000/api-docs>
> **개발 환경에서 프론트엔드는 컨테이너로 뜨지 않습니다.**
> vite 를 컨테이너에서 돌리면 소스가 Windows 바인드 마운트 너머에 있어 첫 서빙까지 수 분이 걸립니다.
> 호스트에서 `npm run dev` 로 띄우면 1~2초이고, `/api` 요청은 vite 프록시가 백엔드 컨테이너로 넘깁니다.
> 컨테이너로 띄워야 한다면 `--profile frontend` 를 붙이세요 (아래 "프론트엔드 실행 방식" 참조).
> 운영(`docker-compose.yml` 단독)은 그대로 nginx 정적 호스팅으로 동작합니다.
> Redis 는 기본적으로 뜨지 않습니다. 필요해지면 루트 `.env.{env}` 에 `COMPOSE_PROFILES=redis` 를 설정하세요.
### 프론트엔드 실행 방식
| 방식 | 명령 | 첫 서빙 | 용도 |
| --- | --- | --- | --- |
| **호스트 vite (개발 기본)** | `cd frontend && npm run dev` | 1~2초 (최초 의존성 사전번들 10초 내외) | 일상 개발 |
| 컨테이너 vite (선택) | `docker compose ... --profile frontend up -d` | 수 분 (Windows 바인드 마운트) | 호스트에 Node 를 둘 수 없을 때 |
| nginx 정적 (운영) | `docker compose --env-file .env.production up -d --build` | - | 배포 |
> 컨테이너 방식을 상시 사용하려면 루트 `.env.development` 에 `COMPOSE_PROFILES=frontend` 를 넣습니다.
> (redis 와 함께 켤 때는 `COMPOSE_PROFILES=frontend,redis`)
> 호스트 vite 와 컨테이너 vite 는 같은 호스트 포트를 쓰므로 **동시에 띄우지 마세요.**
> **포트는 루트 `.env.{env}` 를 따릅니다.** 호스트에서 띄우는 vite 도 `FRONTEND_PORT` 로 열리고,
> `/api` 프록시 대상은 `BACKEND_PORT` 에서 나옵니다 — `vite.config.ts` 가 루트 env 를 직접 읽습니다.
> 포트가 이미 사용 중이면 조용히 다른 포트로 옮기지 않고 **실패**합니다
> (`CORS_ORIGIN` 과 compose 포트 매핑이 그 값에 묶여 있어, 말없이 옮겨가면 원인 모르게 어긋납니다).
전체 실행/배포 명령어는 [`.claude/skills/docker/SKILL.md`](./.claude/skills/docker/SKILL.md) 참조.
## 모바일 앱 실행 (Flutter)
@@ -112,7 +138,7 @@ docker compose -f docker-compose.yml -f docker-compose.dev.yml --env-file .env.d
# 2) backend — DB_HOST 기본값이 localhost 라 그대로 붙는다
cd backend && npm ci && npm run start:dev
# 3) frontend — vite dev 서버가 /api 를 localhost:3000 으로 프록시한다
# 3) frontend — vite dev 서버가 /api 를 localhost:3000 으로 프록시한다 (개발 기본 방식)
cd frontend && npm ci && npm run dev
# 4) flutter