우동체 제작기 #3 — 서울 서버인데 요청이 태평양을 두 번 건넜다

2026-11-02 11:20:00

우동체 운영자용 대시보드 API가 유난히 느렸다. 집계 쿼리가 많은 화면이라 처음엔 당연히 DB를 의심했다. 그런데 파고 들어가 보니 DB는 전혀 문제가 아니었고, 요청이 서울 → LA → 샌프란시스코 → 서울을 돌고 있었다.

의심 1: DB? 아니었다

pg_stat_statements는 체육관 지역 조회를 평균 69ms로 보고하고 있었다. 핫스팟을 찾은 줄 알았다. 그런데 같은 쿼리를 EXPLAIN (ANALYZE, BUFFERS)로 직접 돌려보니 1.6ms였다.

평균이 부풀어 있던 이유는 두 가지였다.

  • 같은 시기에 있었던 DB 락 대기열 사고 동안 기다린 시간이 실행 시간으로 같이 집계됐다.
  • 콜드 백엔드의 첫 실행(335ms, 플래닝만 27ms)이 평균을 끌어올렸다. 워밍업 후에는 1.6ms.

누적 통계는 "어디를 볼지" 알려주는 힌트일 뿐 근거가 아니다. 판단은 직접 재측정한 뒤에 내리기로 했다.

A/B로 범인 찾기

같은 코드, 같은 함수, 같은 DB에 도메인만 바꿔서 쟀다. 정식 도메인 wdcboxing.com(Cloudflare를 거침)과 Vercel이 주는 *.vercel.app 주소(직결)다.

요청wdcboxing.com (Cloudflare)*.vercel.app (직결)배수
x-vercel-id 진입 PoPsfo1icn1
DB를 안 타는 403 응답315ms50ms6.3×
DB 조회 API~450ms56ms8.0×
정적 파일 favicon (캐시 HIT)173ms24ms7.2×

여기서 결론이 거의 났다.

  • 직결 기준으로 DB가 더하는 시간은 6ms(50 → 56ms)뿐이다.
  • 아무 일도 안 하는 403이 315ms, 서버 로직이 0인 정적 파일도 173ms다.
  • 지연은 전부 네트워크 경로에서 생기고 있었다.

원인: 입구가 미국이었다

브라우저(서울)
  └→ Cloudflare PoP = LAX (로스앤젤레스)   ← 태평양 횡단 ①
       └→ Vercel 진입 = sfo1 (샌프란시스코)
            └→ Vercel 함수 = icn1 (서울)    ← 태평양 횡단 ②
                 └→ Supabase DB = 서울

/cdn-cgi/trace를 찍어보니 loc: KR인데 colo: LAX였다. 한국에서 접속했는데 LA 데이터센터에 붙고 있었다. Cloudflare 무료 플랜에서 한국 트래픽이 미국 서부로 라우팅되는 건 알려진 동작이다. 함수도 DB도 서울에 있는데 입구만 미국이라 매 요청이 태평양을 두 번 건넜다.

우동체 트래픽의 대부분은 한국 검색 유입이라, 이건 운영자 화면만의 문제가 아니라 모든 사용자의 모든 요청에 붙는 세금이었다. SSR 페이지의 TTFB에 그대로 실리니 SEO(Core Web Vitals)에도 불리했다.

끄기 전에 확인한 것

프록시를 끄면 Cloudflare 기능을 잃는다. 그래서 실제로 쓰고 있던 게 있는지부터 확인했다.

항목상태
WAF 사용자 규칙 / 속도 제한 / Page Rules전부 0개
Redirect·Transform Rules, Workers0개
SSL/TLS 모드Full (Flexible이었다면 끄는 순간 위험)
Vercel 대역폭 여유충분

캐싱도 보안도 안 쓰면서 지연만 내고 있었다. 한 가지 예외는 이미지 CDN 서브도메인이었다. 옛 영상 썸네일이 Cloudflare 이미지 변환(/cdn-cgi/media/…)을 쓰는데, 이건 프록시가 켜져 있어야 동작한다. 다행히 그 의존은 cdn. 서브도메인에만 있었다.

한 일

  1. wdcboxing.com, dev.wdcboxing.com의 Cloudflare 프록시를 끄고 DNS 전용(회색 구름)으로 바꿨다.
  2. 이미지 CDN 서브도메인은 프록시를 유지했다.
  3. www를 새로 만들어 apex로 308 리다이렉트했다.

3번에는 함정이 하나 있다. Vercel 도메인 추가 화면은 "apex를 www로 리다이렉트"가 기본 체크되어 있다. 우동체의 정식 도메인은 apex(사이트맵·canonical·검색 색인 전부)라서, 그대로 두면 사이트 전체가 도메인 이사를 하는 셈이 된다. 방향은 항상 www → apex.

결과

요청전후개선
x-vercel-idsfo1::icn1icn1::icn1진입이 서울로
DB 안 타는 API315ms51ms6.2×
DB 조회 API~450ms78ms5.8×
정적 파일173ms22ms7.9×

코드는 한 줄도 안 바꿨다. DNS 설정 하나로 전 사용자의 모든 요청이 6~8배 빨라졌다.

확인 방법 (브라우저 콘솔)

await fetch('/cdn-cgi/trace')  // 404면 프록시 OFF
const r = await fetch('/api/아무거나', { cache: 'no-store' });
r.headers.get('x-vercel-id')   // icn1::icn1::... 이면 서울 진입
r.headers.get('server')        // "Vercel"

남긴 교훈

  • 느리면 쿼리부터 의심하게 되는데, 아무 일도 안 하는 요청의 응답 시간부터 재보면 네트워크 문제인지 바로 갈린다.
  • 같은 백엔드에 도메인만 다른 주소로 A/B를 뜨는 게 가장 빠른 진단이었다.
  • "일단 Cloudflare 뒤에 두면 빨라진다"는 기본값이 아니다. 무엇을 위해 프록시를 켜는지 설명할 수 없으면 꺼보자.

← #2 좋아요 1개 눌렀는데 11이 됐다 · 우동체 제작기 목록