[PonsLink] desk.ponslink.com은 어떻게 돌아가는가 — 배포 토폴로지 회고
PonsLink를 운영하면서 가장 자주 받는 질문은 단순하다. "이 서비스, 실제로 어떻게 붙어 있어요?" 마케팅 문구로는 "요청-우선 세션 데스크"라고 말하지만, 그 문장 뒤에는 nginx 한 줄, Node 컨테이너 한 개, Postgres 두 개의 DB, Redis, coturn, SFU, R2, 결제 공급자 네 곳이 동시에 움직인다. 이 글은 2026-08-07 기준 ssh ponslink에서 실측한 desk.ponslink.com의 배포 구조를 정리한다.
한 줄로 보면
브라우저 → nginx(TLS 443) → (정적 SPA | /api·/auth | /socket.io) → ponslink-api(Node 24, :6650) → Postgres / Redis / coturn / SFU / R2 / 외부 API.
프론트엔드는 React SPA다. nginx는 /home/declan/ponslink-frontend-dist를 루트로 두고, 앱 라우트(/public-desk, /room, /lounge, /login 등)는 app-shell.html로 떨어뜨린다. /assets/는 1년 캐시, sw.js는 no-cache다. 비즈니스 트래픽은 전부 같은 호스트의 upstream 127.0.0.1:6650으로 프록시된다.
API 컨테이너가 들고 있는 것
실측 env 기준 API는 다음을 동시에 붙잡는다.
- DB:
DATABASE_URL=.../ponslink(세션·미디어·웹훅 도메인). 같은 Postgres 인스턴스에ponswarpDB(계정·결제·클라우드 공유)가 나란히 있다. - Redis: Socket.IO 어댑터 + 레이트리밋.
- TURN:
turn.ponslink.com:3478udp/tcp,:5349tcp. HMAC 자격증명 TTL 600초. - SFU:
wss://ponslink.com/sfu/ws, RTC 포트 40000–40100. - 스토리지: Cloudflare R2 presigned URL, 객체 TTL 180분, 정리 스케줄러 가동.
- 결제:
PAYMENT_PROVIDER=polar. PayPal sandbox, LemonSqueezy/Stripe 웹훅 호환 유지. - 미디어/AI: Azure Translator·Speech, Deepgram, Google OAuth/Calendar/Translate, Giphy, OpenRouter.
모듈 경계는 소스 기준으로 auth / billing / signaling / turn / providers / store / webhooks / security로 나뉜다. routes.ts에는 260개 넘는 REST 라우트가 등록돼 있고, 실시간은 Socket.IO 브로커(signaling/broker.ts + redisAdapter.ts + replayStore.ts)가 맡는다.
왜 이렇게 쪼갰는가
초기에 "방만 만들면 된다"고 생각했다. 틀렸다. 요청 수집, 결제 게이트, 세션 미디어, 기록 보관은 실패 모드가 다르다. 그래서:
- 엣지(nginx) 는 TLS·정적·WebSocket upgrade만 담당한다.
- API 는 비즈니스 상태와 시그널링을 한 프로세스에서 처리하되, 미디어 중계는 SFU/TURN으로 넘긴다.
- 파일 바이트 는 API를 경유하지 않는다. R2 presigned URL로 클라이언트가 직접 PUT/GET 한다.
- 결제 상태 는 공급자 웹훅 + 이벤트 원장 + 멱등성 키로만 확정한다.
이 분리는 "데모는 되는데 운영이 흔들리는" 지점을 줄이기 위한 선택이었다. 다음 글에서는 그 상태를 담는 데이터 모델(ERD)을 풀어쓴다.
실측 체크리스트
cat /etc/nginx/sites-enabled/desk.ponslink.comdocker inspect docker-ponslink-api-1docker exec docker-postgres-1 psql -U ponswarp -d ponslink -c '\dt'docker exec docker-postgres-1 psql -U ponswarp -d ponswarp -c '\dt'systemctl status/docker ps— nginx, docker-ponslink-api-1, postgres, redis, coturn