From 55ee968f9d76d3fdd92d749b6b257b3d39729ed2 Mon Sep 17 00:00:00 2001 From: hbyang Date: Mon, 7 Sep 2026 16:19:34 +0900 Subject: [PATCH] =?UTF-8?q?[fix]=20deploy:=20=EC=95=B1=EC=9D=B4=20?= =?UTF-8?q?=EB=B6=80=EB=A5=B4=EB=8A=94=20API=20=EC=A3=BC=EC=86=8C=EB=A5=BC?= =?UTF-8?q?=20=ED=95=9C=20=EC=98=A4=EB=A6=AC=EC=A7=84=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=E2=80=94=20:9800=20=EA=B8=B0=EB=B3=B8=EA=B0=92=EC=9D=B4=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=EC=9D=84=20=EB=A7=89=EC=95=98?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nginx/site.conf 는 /v1 을 같은 오리진으로 프록시하고 주석에도 "앱과 같은 오리진이라 프리플라이트가 아예 발생하지 않는다" 고 적혀 있는데, compose 빌드 인자 기본값이 VITE_API_BASE_URL=http://localhost:9800 이었다. :80 으로 앱을 열면 번들이 :9800 을 부르므로 스스로 크로스 오리진이 되고, CLIENT_URL 기본값(3000~3005)에 http://localhost 가 없어 로그인만 실패한다. 증상이 사람을 속인다 — 서버는 200 에 토큰까지 내려보내고 브라우저가 allow-origin 이 없어 그 응답을 버리므로, 화면에는 "로그인에 실패했습니다" 만 뜬다. 비밀번호를 의심하게 된다. - docker-compose.yml · .env.example: 기본값을 앱과 같은 오리진(http://localhost)으로. CORS 를 허용해 뚫는 게 아니라 크로스 오리진을 만들지 않는다 - .env.example: PUBLIC_API_BASE_URL 을 주석이 아니라 값으로 내놨다 — 주석으로 두면 compose 기본값이 이기고, 그 기본값이 문제였다 검증: down -v 후 up -d --build → 번들의 localhost:9800 참조 0건 · POST http://localhost/v1/auth/login 200(프리플라이트 없음) · 프리렌더 재굽기 2건 · / · /s/ · /s/ 전부 200. --- .env.example | 10 ++++++++-- docker-compose.yml | 4 +++- docs/DEVLOG.md | 22 ++++++++++++++++++---- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/.env.example b/.env.example index e945f04..0caa193 100644 --- a/.env.example +++ b/.env.example @@ -52,8 +52,14 @@ GOOGLE_CLIENT_ID= # ── solution/frontend 브라우저가 부르는 주소 (compose 가 VITE_* 로 주입) # ★ 브라우저가 부르는 주소다. 서버에 올리면 localhost 는 즉시 틀린다. -# PUBLIC_API_BASE_URL=http://localhost:9800 -# PUBLIC_WEB_BASE_URL=http://localhost:3000 +# ★ **앱과 같은 오리진을 적는다.** nginx(:80)가 /v1 을 같은 오리진으로 프록시하므로 +# (nginx/site.conf) 앱이 부를 주소는 `:9800` 이 아니라 앱 주소 그 자체다. `:9800` 을 적으면 +# 스스로 크로스 오리진을 만들어 CORS 가 붙고, 화면은 뜨는데 **로그인만 계속 실패한다** — +# 서버는 200 에 토큰까지 내려보내고 브라우저가 allow-origin 이 없어 그 응답을 버린다. +# 실측(2026-09-07): 이 기본값 그대로 띄우면 :80 으로 연 앱에서 로그인이 안 된다. +# ★ 값을 바꾸면 번들을 다시 구워야 한다: ./deploy.sh solution-site +PUBLIC_API_BASE_URL=http://localhost +PUBLIC_WEB_BASE_URL=http://localhost # ── solution/site 발행물 — solution/backend 도 같이 본다 # canonical·og:url·sitemap·IndexNow 가 전부 SITE_PUBLIC_HOST 를 쓴다. diff --git a/docker-compose.yml b/docker-compose.yml index 59f677a..f361e00 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -260,7 +260,9 @@ services: args: # ★ VITE_* 는 **번들에 구워진다.** .env 를 고쳐도 재빌드 전엔 안 바뀐다 # → 주소를 바꿨으면 `./deploy.sh solution-site`. - VITE_API_BASE_URL: ${PUBLIC_API_BASE_URL:-http://localhost:9800} + # ★ 기본값이 앱과 **같은 오리진**이다. nginx 가 /v1 을 프록시하므로 :9800 을 박으면 + # 스스로 크로스 오리진을 만들어 로그인만 조용히 실패한다(위 주석 · .env.example). + VITE_API_BASE_URL: ${PUBLIC_API_BASE_URL:-http://localhost} VITE_PUBLISH_HOST: ${SITE_PUBLIC_HOST:-localhost} VITE_SITE_PREVIEW_URL: ${PUBLIC_WEB_BASE_URL:-http://localhost} # ⚠️ 비어 있으면 자동 로그인은 아예 꺼진다(기본값 없음). 채우면 번들에 구워진다. diff --git a/docs/DEVLOG.md b/docs/DEVLOG.md index 717e63c..6be445e 100644 --- a/docs/DEVLOG.md +++ b/docs/DEVLOG.md @@ -21,11 +21,25 @@ DB 를 안 보므로 **200 healthy** 로 뜨고, **워커만 조용히 재시작 같은 모양이 5개였다: `COLLECT_USE_PERPLEXITY`(값 `0` 이 `"0 # ..."` 가 된다) · `KAKAO_REST_API_KEY` · `TOUR_API_KEY` · `INDEXNOW_KEY` · `AZURE_STORAGE_CONNECTION_STRING`. -**고친 것** — `.env.example`: `DB_HOST` 기본값을 `host.docker.internal` 로 바꾸고 네이티브 -실행 때만 127.0.0.1 이라는 것을 주석으로 남겼다. 값 뒤 주석은 전부 **윗줄로 올렸고**, -파일 머리에 "값 뒤에 주석을 붙이지 않는다" 를 근거와 함께 박았다. +**3) 앱이 스스로 크로스 오리진을 만든다.** `nginx/site.conf` 는 `/v1` 을 같은 오리진으로 +프록시하고 주석에도 "앱과 같은 오리진이라 프리플라이트가 아예 발생하지 않는다" 고 적혀 +있는데, compose 의 빌드 인자 기본값이 `VITE_API_BASE_URL=http://localhost:9800` 이었다. +`:80` 으로 앱을 열면 번들이 `:9800` 을 부르므로 크로스 오리진이 되고, `CLIENT_URL` 기본값 +(3000~3005)에 `http://localhost` 가 없어 **로그인만 계속 실패한다.** 증상이 사람을 속인다 — +서버는 200 에 토큰까지 내려보내고, 브라우저가 `allow-origin` 이 없어 그 응답을 버리므로 +화면에는 "로그인에 실패했습니다" 만 뜬다. 비밀번호를 의심하게 된다. -**검증** — 새 DB(`web4ai_db`)에 `init.sql` 적용 → `docker compose up -d` → 워커 정상 기동 → +**고친 것** +- `.env.example`: `DB_HOST` 기본값을 `host.docker.internal` 로. 값 뒤 주석은 전부 **윗줄로** + 올리고, 파일 머리에 "값 뒤에 주석을 붙이지 않는다" 를 근거와 함께 박았다 +- `.env.example` · `docker-compose.yml`: 앱이 부르는 API 주소 기본값을 **앱과 같은 오리진** + (`http://localhost`)으로. CORS 를 허용해서 뚫는 게 아니라 **크로스 오리진을 만들지 않는다** — + nginx 가 이미 같은 오리진으로 프록시하고 있었다. `PUBLIC_API_BASE_URL` 을 주석이 아니라 + 값으로 내놨다(주석으로 두면 compose 기본값이 이기고, 그 기본값이 문제였다) + +**검증** — 새 DB(`web4ai_db`)에 `init.sql` 적용 → `docker compose down -v` 후 `up -d --build` → +번들에 `localhost:9800` 참조 0건 · `POST http://localhost/v1/auth/login` 200(프리플라이트 없음) · +프리렌더가 기동하며 payload 2건 재굽기 → `/` `/s/` `/s/` 전부 200. 그리고 → `scripts/demo_build.py` 로 발행: 게이트 통과 · `published: true` · 프리렌더가 굽고 `http://localhost/s/` 200. ★ 참고로 `demo_build.py` 는 자기 안에서 워커를 한 번 돌리는데, compose 워커가 잡을 먼저 집어가므로 **스크립트 출력은 "게이트 거부"로 보인다** — 실제 결과는