fix(web): API base 를 페이지 host 로 동적 해석 (LAN 접속 대응)

리뷰어 지적: docker-compose 가 NEXT_PUBLIC_API_BASE=http://localhost:8000 을
주입해서 클라이언트 번들에 localhost 가 inline 됨. 사금향 게임컴 (192.168.10.13)
브라우저에선 동작하지만, 같은 내부망의 다른 PC 또는 외부 검증자가
http://192.168.10.13:3000 에 접속하면 fetch 가 그 PC 의 localhost:8000 으로 가서
연결 실패. 백엔드는 정상인데도 '검색 결과 없음' 으로 보임.

해석 우선순위:
  1) NEXT_PUBLIC_API_BASE 가 비 localhost 값 → 그대로 (프로덕션 도메인 케이스)
  2) 브라우저 → window.location.hostname:8000 (LAN/localhost 자동 대응)
  3) SSR 폴백 → localhost:8000

localhost/127.0.0.1 판별은 //(localhost|127.0.0.1)(?::|$) 정규식 — 'localhost.evil.com'
같은 서브도메인 우회는 매치 안 됨. node 로 7케이스 검증 완료.

web/app 코드만이라 사금향 PC 는 restart.bat 으로 반영 (next dev hot-reload).
This commit is contained in:
tkrmagid
2026-05-21 21:52:09 +09:00
parent 659871118f
commit 78388d347e

View File

@@ -1,8 +1,31 @@
// Backend API client.
// NEXT_PUBLIC_API_BASE 는 docker-compose 에서 http://localhost:8000 으로 주입됨.
//
// API 베이스 해석 우선순위:
// 1) NEXT_PUBLIC_API_BASE 가 localhost/127.0.0.1 이 아닌 명시값 → 그대로 사용
// (예: 프로덕션 https://api.example.com)
// 2) 브라우저 환경 → window.location.hostname:8000 (LAN 접속도 자동 대응)
// 3) SSR 폴백 → http://localhost:8000
//
// docker-compose 가 NEXT_PUBLIC_API_BASE=http://localhost:8000 을 주입하는 경우가 흔한데,
// LAN 의 다른 PC 에서 http://<host>:3000 으로 접속하면 inline 된 localhost 가 그쪽 PC 의
// localhost 를 가리켜 깨진다. 그래서 localhost/127.0.0.1 값은 신뢰하지 않고 페이지 host 로
// 폴백.
const RAW_BASE = process.env.NEXT_PUBLIC_API_BASE ?? "http://localhost:8000";
export const API_BASE = RAW_BASE.replace(/\/$/, "");
function resolveApiBase(): string {
const raw = process.env.NEXT_PUBLIC_API_BASE;
const env = raw && raw.length > 0 ? raw.replace(/\/$/, "") : "";
const envIsLocal = !env || /\/\/(localhost|127\.0\.0\.1)(?::|$)/.test(env);
if (typeof window !== "undefined") {
if (envIsLocal) {
return `${window.location.protocol}//${window.location.hostname}:8000`;
}
return env;
}
// SSR
return env || "http://localhost:8000";
}
export const API_BASE = resolveApiBase();
export type Symbol = {
code: string;