From 43483c6c3811ff799499db187128e11b36f9a05d Mon Sep 17 00:00:00 2001 From: Mina Choi Date: Tue, 1 Sep 2026 11:49:07 +0900 Subject: [PATCH] =?UTF-8?q?[docs]=20deploy:=20=ED=95=9C=20=EC=98=A4?= =?UTF-8?q?=EB=A6=AC=EC=A7=84=20=EA=B5=AC=EC=84=B1=EA=B3=BC=20=EA=B3=B5?= =?UTF-8?q?=EA=B0=9C=20=EC=A3=BC=EC=86=8C=EB=A5=BC=20=EC=A7=80=EA=B8=88=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=EB=A1=9C=20=E2=80=94=20=EB=B0=96=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=97=AC=EB=8A=94=20=ED=8F=AC=ED=8A=B8=EB=8A=94=20?= =?UTF-8?q?30030=20=ED=95=98=EB=82=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 26 ++++++++++++++++++++------ docs/SERVERS.md | 37 ++++++++++++++++++++++++++----------- 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index de0e22b..b9b2a81 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -92,12 +92,19 @@ admin/ 우리 — backend(진입점만, :9801) · frontend(운영 화면) ## 실행 ```bash -docker compose up -d # api :9800 · api-admin :9801 · 워커 · web :3000 · admin :3002 · nginx :80 +docker compose up -d # api :9800 · 워커 · 프리렌더 · nginx :80 +docker compose --profile dev up -d # + 사장님 앱 HMR :3000 (로컬 전용) docker compose logs -f solution-worker ``` -- 사장님 앱 `:3000`(API :9800) · 내부 운영 `:3002`(API :9801, 로컬호스트에만 열림) -- 발행 사이트: `http://localhost:3000/s/` (빌더 Vite 가 :3001 정적서버로 프록시) +★ **운영에는 dev 서버를 띄우지 않는다.** `docker compose up -d` 가 올리는 nginx(`:80`)가 +사장님 앱(구운 번들) · 발행 사이트 · API 를 **한 오리진**으로 준다. `solution-frontend` +(Vite dev, `:3000`)는 `--profile dev` 로만 뜨고 HMR 이 필요할 때만 쓴다. + +- 한 오리진: `http://localhost/` 앱 · `http://localhost/s/` 발행 사이트 · `/v1/...` API +- 내부 운영 `:3002`(API :9801, 로컬호스트에만 열림) — `--profile admin` +- ★ **`VITE_*` 는 번들에 구워진다.** 주소를 바꾸면 `.env` 만 고쳐선 안 되고 + `./deploy.sh solution-site` 로 **다시 구워야** 한다 - **클론 직후 1회**: `cp .env.example .env` · `cp nginx/site.conf.example nginx/site.conf` (후자를 빼먹으면 Docker 가 그 자리에 디렉토리를 만들어 nginx 가 설정 없이 뜬다) - DB 는 compose 밖이다 (호스트 PostgreSQL, `host.docker.internal`). @@ -203,12 +210,19 @@ admin/ 우리 — backend(진입점만, :9801) · frontend(운영 화면) ## 실행 ```bash -docker compose up -d # api :9800 · api-admin :9801 · 워커 · web :3000 · admin :3002 · nginx :80 +docker compose up -d # api :9800 · 워커 · 프리렌더 · nginx :80 +docker compose --profile dev up -d # + 사장님 앱 HMR :3000 (로컬 전용) docker compose logs -f solution-worker ``` -- 사장님 앱 `:3000`(API :9800) · 내부 운영 `:3002`(API :9801, 로컬호스트에만 열림) -- 발행 사이트: `http://localhost:3000/s/` (빌더 Vite 가 :3001 정적서버로 프록시) +★ **운영에는 dev 서버를 띄우지 않는다.** `docker compose up -d` 가 올리는 nginx(`:80`)가 +사장님 앱(구운 번들) · 발행 사이트 · API 를 **한 오리진**으로 준다. `solution-frontend` +(Vite dev, `:3000`)는 `--profile dev` 로만 뜨고 HMR 이 필요할 때만 쓴다. + +- 한 오리진: `http://localhost/` 앱 · `http://localhost/s/` 발행 사이트 · `/v1/...` API +- 내부 운영 `:3002`(API :9801, 로컬호스트에만 열림) — `--profile admin` +- ★ **`VITE_*` 는 번들에 구워진다.** 주소를 바꾸면 `.env` 만 고쳐선 안 되고 + `./deploy.sh solution-site` 로 **다시 구워야** 한다 - **클론 직후 1회**: `cp .env.example .env` · `cp nginx/site.conf.example nginx/site.conf` (후자를 빼먹으면 Docker 가 그 자리에 디렉토리를 만들어 nginx 가 설정 없이 뜬다) - DB 는 compose 밖이다 (호스트 PostgreSQL, `host.docker.internal`). diff --git a/docs/SERVERS.md b/docs/SERVERS.md index 960e495..42af8d2 100644 --- a/docs/SERVERS.md +++ b/docs/SERVERS.md @@ -56,13 +56,23 @@ Ubuntu 18.04.6 LTS · 24 core · RAM 125G · Docker 24.0.2 · Docker Compose v2. | 서비스 | 컨테이너 포트 | 킹서버 | bind | 누가 보나 | |---|---|---|---|---| -| `solution-site` (발행 사이트) | 80 | **30030** | 0.0.0.0 | 방문자 | -| `solution-frontend` (사장님 앱) | 3000 | **30031** | 0.0.0.0 | 사장님 | -| `solution-backend` (솔루션 API) | 9800 | **30032** | 0.0.0.0 | 사장님 브라우저 | +| `solution-site` (**공개 진입점**) | 80 | **30030** | 0.0.0.0 | 방문자·사장님 | +| `solution-backend` (솔루션 API) | 9800 | 30032 | **127.0.0.1** | nginx 만 | +| `solution-prerender` (굽기) | — | — | — | — | | `solution-worker` (잡 러너) | — | — | — | — | | `admin-frontend` (어드민 화면) | 3002 | 3002 | **127.0.0.1** | 우리 | | `admin-backend` (어드민 API) | 9801 | 9801 | **127.0.0.1** | 우리 | +★ **밖으로 열린 포트는 30030 하나다.** 사장님 앱 · 발행 사이트 · API 가 전부 그 뒤에 있다 +(`nginx/site.conf`). API 를 따로 열지 않는 이유: 같은 오리진이면 CORS 가 아예 없고, +`robots.txt`·`sitemap.xml` 은 RFC 9309 상 **오리진 루트에서만** 읽힌다. + +| 경로 | 어디로 | +|---|---| +| `/` | 사장님 앱 — 이미지에 구워 넣은 정적 번들(`/srv/app`) | +| `/s/` · `/assets/` · `/robots.txt` · `/sitemap.xml` | `site-out` 볼륨 | +| `/v1/...` · `/healthz` · `/docs` | `solution-backend:9800` | + ★ 어드민 둘은 **기본 기동에서 빠져 있다**(compose 프로필). 켤 때는 `docker compose --profile admin up -d`. @@ -107,13 +117,18 @@ cd ~/data2/o2o-web4ai 붙여 두었으므로 **컴포즈를 고치지 않고 그대로 닿는다.** DB 는 만들어야 한다 — `postgres-init/init-data/init.sql` 한 벌이 스키마 전부다. -## 공개 주소 — 배포 전에 먼저 풀 것 +## 공개 주소 — `https://w4ai.o2o.kr` (2026-09-01 연결됨) -★ **`w4ai.o2o.kr` 은 지금 DNS 레코드가 없다.** (`dig +short w4ai.o2o.kr` → 빈 응답) -이 값이 `SITE_PUBLIC_HOST` 기본값이고 canonical·og:url·sitemap·IndexNow 에 전부 들어간다. -DNS 를 붙이기 전에 발행하면 **존재하지 않는 주소를 색인 통보한다** — 발행은 성공하므로 -아무도 눈치채지 못하는 종류의 오작동이다. [DEPLOY.md 0단계](DEPLOY.md)가 이걸 말한다. +``` +DNS A w4ai.o2o.kr → 59.14.81.3 + └ 앞단 Apache(2.4.18) → http://172.30.1.36:30030 → solution-site +``` -바깥에서 이 서버로 들어오는 입구는 **`59.14.81.3`** 이다 — `gitea.o2o.kr` 이 그 IP로 풀리고 -HTTPS 200 이 뜬다. 즉 앞단에 포워딩/리버스프록시가 있고, 우리 주소도 거기에 태워야 한다. -그 앞단은 이 레포 밖이라 인프라 담당에게 요청해야 한다. +`59.14.81.3` 은 사내망 입구다(`gitea.o2o.kr` 과 같은 IP). 킹서버의 `172.30.1.36` 은 **사설 +IP라 DNS 에 못 적는다** — 앞단 vhost 와 인증서는 이 레포 밖이고 인프라 담당이 잡는다. + +이 값이 `SITE_PUBLIC_HOST` 이고 canonical·og:url·sitemap·IndexNow 에 전부 들어간다. +바꾸면 **payload JSON 에 구워진 `origin` 까지 재발행**해야 한다([DEPLOY.md 0단계](DEPLOY.md)). + +★ **`.env` 를 고쳐도 화면 주소는 안 바뀐다.** `VITE_*` 는 `solution-site` 이미지의 번들에 +구워진다 — `./deploy.sh solution-site` 로 다시 굽는다.