본문으로 건너뛰기

도메인과 리버스 프록시

IP 주소 대신 도메인(특히 HTTPS)으로 스튜디오를 서비스할 때의 설정입니다. 이 장은 순서대로 다 해야 동작합니다. 하나라도 빠지면 "프리뷰가 빈 화면", "빌드 채팅이 연결 오류", "배포앱에서 데이터가 401" 같은 서로 달라 보이는 증상이 제각각 나타납니다.


도메인은 하나입니다

프리뷰와 배포앱은 스튜디오와 같은 도메인의 /container/ 아래에서 서빙됩니다.

https://studio.company.com/ → 스튜디오 UI + API
https://studio.company.com/container/… → 프리뷰 · 배포앱

필요한 것은 DNS 레코드 1개, 인증서 1장, vhost 1개입니다.

예전에는 도메인이 2개였습니다

2026-08-23 이전에는 앱을 별도 호스트(studio-apps.company.com)로 분리하고 그 주소를 APPS_ORIGIN 이나 환경설정의 "앱 오리진"으로 알려 줘야 했습니다. 그 설정은 없어졌습니다.

없앤 이유는 그 값 하나가 비면 서버가 프리뷰 URL 을 요청호스트:5171 로 만들어 내는데, 80/443 만 공개하는 리버스 프록시 구성에서는 브라우저가 거기에 붙지 못해 라이브 프리뷰가 통째로 빈 화면이 됐기 때문입니다. 상대 경로만 쓰면 애초에 틀릴 수가 없습니다.

.env 나 환경설정에 옛 APPS_ORIGIN 값이 남아 있어도 지금은 읽지 않습니다.

대가 — 오리진 분리를 포기했습니다

프리뷰·배포앱은 채팅으로 생성된 코드, 즉 신뢰할 수 없는 콘텐츠입니다. 예전 구조는 오리진을 분리해 그 자바스크립트가 스튜디오 로그인 토큰에 접근하지 못하게 막았습니다. 지금은 같은 오리진에서 돌아 그 격리가 없습니다. 도메인을 하나로 줄이는 대가로 감수한 판단입니다.

따라서 신뢰할 수 없는 사용자에게 앱 생성 권한을 주지 마세요. 빌더 역할은 사내 운영자에게만 부여하는 것을 전제로 한 구성입니다.


준비물 체크리스트

  • DNS A 레코드 1개
  • 해당 호스트네임의 TLS 인증서
  • 리버스 프록시에서 스튜디오 박스의 :80 에 도달 가능
  • 스튜디오 박스 방화벽에서 프록시 → :80 허용
:5171 은 열지 않아도 됩니다

앱 리스너(:5171)는 스튜디오 박스 안의 web nginx 가 /container/ · /apps/ · /preview/ 를 넘겨주므로 바깥에 노출할 필요가 없습니다. 리버스 프록시 없이 포트로 직접 접속하는 설치에서만 방화벽을 열어 주세요.


1. 프록시에 vhost 추가

바깥 프록시는 전부 스튜디오 박스의 :80 으로 넘기기만 하면 됩니다. /container/ · /apps/ · /preview/ 분기는 박스 안의 web nginx 가 이미 처리합니다.

반드시 들어가야 하는 4가지

빠뜨렸을 때 나타나는 증상이 서로 달라 원인을 찾기 어려우므로, 아래 예시를 그대로 복사해 쓰는 것을 권장합니다.

설정빠지면 생기는 증상
proxy_set_header Host $http_host라우팅·링크 생성이 어긋납니다
Upgrade / Connection 헤더프리뷰 실시간 갱신(HMR) 웹소켓이 끊겨 코드 수정이 화면에 반영되지 않습니다
proxy_read_timeout 3600s빌드 채팅이 "연결 오류: network error" — 에이전트가 도구 실행으로 수십 초 침묵하면 기본 60초 타임아웃이 스트림을 끊습니다
proxy_buffering off스트리밍 응답이 버퍼에 고여 답변이 뭉텅이로 늦게 뜹니다
SSE(서버 전송 스트리밍)가 핵심입니다

빌드 채팅과 질의 응답은 SSE 로 실시간 전송됩니다. 서버가 25초마다 하트비트를 보내므로 프록시 타임아웃이 그보다 길기만 하면 되지만, 3600s 는 실제 운영에서 검증된 값입니다.

nginx 설정 예시

server {
listen 80;
server_name studio.company.com;

location / {
proxy_pass http://<스튜디오박스>:80;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s; # 에이전트 SSE(빌드 채팅) — 필수
proxy_buffering off; # 스트리밍 즉시 전달 — 필수
client_max_body_size 64M; # 사진·도면 첨부
}
}

HTTPS 는 certbot 등으로 발급합니다 — listen 443 ssl 블록이 위 설정을 그대로 상속하면 됩니다.

스튜디오 박스의 web nginx 안에 vhost 를 추가하는 경우

패키징된 web nginx 컨테이너의 conf.d 에 직접 vhost 파일을 마운트한다면, 파일명을 zz- 로 시작하게 하세요. nginx 는 알파벳순으로 첫 번째 server 블록을 기본 서버로 삼기 때문에, 이름이 앞서면 매칭되지 않는 모든 요청이 엉뚱한 곳으로 빠져 스튜디오 전체가 죽습니다(실제 발생한 사고입니다).


2. 재로그인 (필수)

도메인 설정을 마쳤으면 모든 사용자가 한 번 로그아웃 후 다시 로그인해야 합니다.

로그인 쿠키는 발급 시점의 호스트 전용입니다. IP 로 접속해 로그인해 둔 세션은 도메인으로 바꾼 뒤 전달되지 않아 데이터 요청이 401 로 실패합니다.


3. 확인

확인 항목방법
스튜디오가 뜬다https://studio.company.com 접속 → 로그인
프리뷰가 뜬다프로젝트 열기 → 프리뷰 화면 표시, 콘솔에 Mixed Content 없음
앱 경로가 뚫려 있다https://studio.company.com/container/ 접속 → 404/앱 목록이면 정상(연결됨)
실시간 갱신채팅으로 문구 하나 수정 → 프리뷰가 자동 갱신
긴 빌드빌드 채팅 1분 이상 실행 → "연결 오류" 없이 완주
배포앱 데이터배포된 앱 열기 → 실데이터 표시(401 없음)

주의사항

IP 와 도메인을 섞어 쓰지 마세요

도메인을 붙인 뒤에는 도메인으로만 접속하세요. IP 로 접속한 사용자는 쿠키가 달라 배포앱 데이터가 401 이 됩니다.

Cloudflare 를 앞단에 둘 때
  • WebSocket 은 기본 지원되므로 별도 설정이 필요 없습니다.
  • 무료 유니버설 인증서는 1단 서브도메인만 커버합니다(studio.company.com ✅, apps.studio.company.com ❌).
첨부 파일 크기

현장 사진·도면을 채팅에 첨부하므로 client_max_body_size 64M 를 넣으세요. 빠지면 큰 사진 업로드가 413 으로 실패합니다.


리버스 프록시 없이 HTTPS 만 붙이기

별도 프록시 서버가 없고 스튜디오 박스에서 바로 TLS 를 종단하려면 운영 패키지의 TLS 오버레이를 씁니다.

cd /opt/kopens/plantpulse-studio-docker
cp tls/nginx-tls.conf.example tls/nginx-tls.conf # server_name 등 수정
# tls/cert.pem, tls/key.pem 배치(사내 CA 또는 공인 인증서)
docker compose -f docker-compose.yml -f docker-compose.tls.yml up -d
TLS 오버레이 예시 파일은 아직 옛 구조를 담고 있습니다

tls/nginx-tls.conf.example 에는 /container/ 블록이 없고, 주석이 아직 없어진 APPS_ORIGIN 과 별도 포트(5443)를 안내합니다. 그대로 쓰면 프리뷰·배포앱 주소 (/container/…)가 404 가 됩니다.

당분간은 사본(tls/nginx-tls.conf)에 /container/ 블록을 직접 추가하세요 — 위쪽 nginx 설정 예시의 헤더 4종을 그대로 쓰고, 접두사를 떼어 앱 리스너로 넘기면 됩니다. APPS_ORIGIN 줄은 넣지 마세요(읽지 않습니다).


증상 → 원인 빠른 대조

도메인 배포에서 실제로 자주 겪는 것들입니다. 더 넓은 범위는 트러블슈팅에 있습니다.

증상원인조치
프리뷰·배포앱이 빈 화면, 콘솔에 Mixed Content스튜디오는 HTTPS 인데 앱 자산이 HTTP 로 요청됨프록시에 X-Forwarded-Proto $scheme 추가 후 전체를 HTTPS 로
배포앱에서 실데이터가 401도메인 붙이기 전에 로그인한 세션로그아웃 후 재로그인 1회
빌드 채팅이 오래 걸리면 "연결 오류: network error"프록시 무전송 타임아웃(기본 60초)proxy_read_timeout 3600s
코드 수정이 프리뷰에 반영 안 됨HMR 웹소켓이 업그레이드되지 않음Upgrade / Connection 헤더 추가
답변이 뭉텅이로 늦게 뜸proxy_buffering 이 켜져 있음(기본값)proxy_buffering off
아무 도메인이나 엉뚱한 곳으로 빠짐web nginx conf.d 로드 순서(첫 server 가 기본 서버)vhost 파일명을 zz- 로 시작
/container/… 가 404TLS 오버레이 사본에 /container/ 블록이 없음위 경고 참조
포트로 직접 쓰는 설치에서 앱이 안 뜸방화벽에서 5171 차단방화벽 개방 후 curl -I http://<박스>:5171/ 로 확인

관련 문서