diff --git a/.claude/agents/release-ops.md b/.claude/agents/release-ops.md index 7dd4901..0065b05 100644 --- a/.claude/agents/release-ops.md +++ b/.claude/agents/release-ops.md @@ -31,7 +31,8 @@ tools: Read, Grep, Glob, Edit, Write, Bash, Skill - **env 파일 존재**: 루트 `.env.{APP_ENV}` 와 `backend/.env.{APP_ENV}` 가 둘 다 있어야 기동한다. - **운영 배포 전**: `BACKEND_API_URL`·`CORS_ORIGIN` 이 실제 도메인인지 확인한다. `localhost`·`example.com` 이 남아 있으면 백엔드가 기동에 실패한다 ([[env-structure]]). -- **프론트엔드**: 개발에서는 컨테이너로 띄우지 않는다(profile `frontend` 뒤에 있다). 운영만 nginx 정적 호스팅이다. +- **프론트엔드**: 개발·운영 모두 컨테이너로 띄우지 않는다(base 의 profile `frontend` 뒤에 있다). + 관리자 화면은 아임웹 코드 위젯이다. nginx 정적 호스팅이 필요할 때만 `COMPOSE_PROFILES=frontend` 로 켠다. ## 완료 기준 (실행하고 결과를 보고한다) diff --git a/.claude/skills/docker/SKILL.md b/.claude/skills/docker/SKILL.md index d6c0256..54f9d31 100644 --- a/.claude/skills/docker/SKILL.md +++ b/.claude/skills/docker/SKILL.md @@ -32,9 +32,13 @@ docker compose -f docker-compose.yml -f docker-compose.dev.yml --env-file .env.d > ⚠️ `.env.production` 의 `BACKEND_API_URL`·`CORS_ORIGIN` 을 **실제 도메인으로 교체**해야 한다. > `localhost` 나 예시 도메인(`example.com`)이 남아 있으면 백엔드가 기동에 실패한다 ([[env-structure]]). > 로컬에서 운영 이미지를 검증하느라 일부러 localhost 를 쓰는 경우에만 `ALLOW_LOCALHOST_URL=true` 를 함께 준다. +> +> **운영에서도 프론트엔드 컨테이너는 기본 비활성이다** (base `docker-compose.yml` 의 profile `frontend`). +> 관리자 화면은 아임웹 코드 위젯(`imweb/`)으로 제공하므로 backend + db 만 빌드·기동한다. +> nginx 정적 호스팅이 필요해지면 루트 `.env.production` 에 `COMPOSE_PROFILES=frontend` 를 넣는다. ```bash -# 운영 환경 배포 +# 운영 환경 배포 — backend + db sudo docker compose --env-file .env.production up -d --build # 로그 확인 @@ -77,7 +81,8 @@ COMPOSE_PROFILES=frontend - 호스트 vite 와 컨테이너 vite 는 같은 호스트 포트(`FRONTEND_PORT`)를 쓴다 — **동시에 띄우지 말 것.** - 컨테이너 **내부** 포트는 5173 고정이다 (compose 의 `--port`·healthcheck·포트 매핑이 함께 묶여 있다). 루트 env 는 컨테이너 안에 없으므로 `vite.config.ts` 는 기본값으로 떨어지고, compose 의 `--port` 가 이긴다. -- 운영(`docker-compose.yml` 단독)에는 profile 이 없으므로 nginx 정적 호스팅이 그대로 동작한다. +- profile `frontend` 는 base `docker-compose.yml` 에 걸려 있어 **운영에서도 기본 비활성**이다. + 운영에서 같은 profile 을 켜면 dev 오버라이드가 없으므로 vite 대신 nginx 정적 호스팅(8080)으로 뜬다. --- diff --git a/.env.production.example b/.env.production.example index 4c3ab00..281d9df 100644 --- a/.env.production.example +++ b/.env.production.example @@ -70,9 +70,11 @@ DB_SYNCHRONIZE=false # ========================================== # 선택적 서비스 (Compose profiles) # -# 기본값(비어 있음) = redis 를 기동하지 않는다. -# 캐시·세션 공유가 필요해지면 아래를 redis 로 바꾸면 컨테이너가 함께 뜬다. -# COMPOSE_PROFILES=redis +# 기본값(비어 있음) = redis·frontend 를 빌드·기동하지 않는다 (backend + db 만 뜬다). +# redis 캐시·세션 공유가 필요해질 때 → COMPOSE_PROFILES=redis +# frontend Vue 화면을 nginx 로 서빙해야 할 때 → COMPOSE_PROFILES=frontend +# (관리자 화면은 아임웹 코드 위젯이라 지금은 쓰지 않는다) +# 둘 다 → COMPOSE_PROFILES=redis,frontend # 일회성으로 켜려면: docker compose --profile redis ... up -d # ========================================== COMPOSE_PROFILES= diff --git a/README.md b/README.md index 460b77a..c456a12 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,8 @@ cd frontend && npm install && npm run dev > vite 를 컨테이너에서 돌리면 소스가 Windows 바인드 마운트 너머에 있어 첫 서빙까지 수 분이 걸립니다. > 호스트에서 `npm run dev` 로 띄우면 1~2초이고, `/api` 요청은 vite 프록시가 백엔드 컨테이너로 넘깁니다. > 컨테이너로 띄워야 한다면 `--profile frontend` 를 붙이세요 (아래 "프론트엔드 실행 방식" 참조). -> 운영(`docker-compose.yml` 단독)은 그대로 nginx 정적 호스팅으로 동작합니다. +> **운영에서도 프론트엔드 컨테이너는 기본 비활성입니다.** 관리자 화면은 아임웹 코드 위젯(`imweb/`)으로 제공하므로 +> 운영 배포는 backend + db 만 빌드·기동합니다. nginx 정적 호스팅이 필요해지면 `COMPOSE_PROFILES=frontend` 를 설정하세요. > Redis 는 기본적으로 뜨지 않습니다. 필요해지면 루트 `.env.{env}` 에 `COMPOSE_PROFILES=redis` 를 설정하세요. @@ -58,7 +59,7 @@ cd frontend && npm install && npm run dev | --- | --- | --- | --- | | **호스트 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` | - | 배포 | +| nginx 정적 (운영, 기본 비활성) | `docker compose --env-file .env.production --profile frontend up -d --build` | - | Vue 화면을 배포할 때 | > 컨테이너 방식을 상시 사용하려면 루트 `.env.development` 에 `COMPOSE_PROFILES=frontend` 를 넣습니다. > (redis 와 함께 켤 때는 `COMPOSE_PROFILES=frontend,redis`) diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index fde0463..f5c3df6 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -1,6 +1,6 @@ services: # ---------------------------------------- - # frontend — dev 에서는 기본 기동하지 않는다 (profile 로 숨김) + # frontend — 기본 기동하지 않는다 (profile 은 base 에서 지정 — docker-compose.yml) # # vite 를 컨테이너에서 돌리면 소스가 Windows 바인드 마운트(./frontend:/app) 너머에 있어 # 수천 개 파일을 매 요청마다 가상 파일시스템으로 읽는다. 여기에 폴링 감시까지 겹쳐 @@ -14,7 +14,6 @@ services: # 또는 루트 .env.development 에 COMPOSE_PROFILES=frontend # ---------------------------------------- frontend: - profiles: ["frontend"] # dev에서는 Docker Desktop 시작 시 자동 실행 방지 (수동 up 때만 실행) restart: "no" build: diff --git a/docker-compose.yml b/docker-compose.yml index f589241..435b0e9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,8 +1,14 @@ services: # ---------------------------------------- - # 1. Frontend (Nginx 정적 호스팅) + # 1. Frontend (Nginx 정적 호스팅) · 기본 비활성 + # + # 관리자 화면은 아임웹 코드 위젯(imweb/imweb-members.html)으로 제공하므로 + # Vue 프론트엔드는 개발·운영 모두 빌드·기동하지 않는다. + # 루트 .env.{APP_ENV} 에서 COMPOSE_PROFILES=frontend + # 또는 일회성으로 docker compose --profile frontend up -d # ---------------------------------------- frontend: + profiles: ["frontend"] container_name: ${PROJECT_NAME}-frontend build: context: ./${FRONTEND_DIR}