Cloudturing blog

하나의 도메인에서 Web과 API를 나누는 GCLB Path Routing

Cloudturing Team 발행: 2026. 08. 29 16:00 수정: 2026. 08. 25 10:04

하나의 도메인에서 URL 경로로 Web과 API backend를 나누는 GCLB 구조

3줄 요약

  • 하나로 배포하던 Console을 Web과 API workload로 분리하면서도 기존 도메인과 URL은 바꾸지 않았다.
  • GCLB URL Map에서 API 경로는 새 API backend로, 그 밖의 경로는 Web backend로 보내도록 host rule·path matcher·default를 구성했다.
  • 안전한 전환의 핵심은 경로 규칙만 추가하는 것이 아니라 backend와 NEG를 먼저 준비하고 요청표로 exact·wildcard·fallback을 검증하는 것이다.

배경: 서버는 나누되 URL은 유지하고 싶었다

처음에는 한 Console 서버가 화면과 API를 함께 제공했다. 배포 단위가 하나라 단순했지만, 프런트 변경과 API 변경이 같은 image와 rollout에 묶였다. 리소스 사용 특성도 달랐다. Web은 정적 자산과 화면 응답이 중심이고 API는 인증, DB 접근과 비즈니스 로직이 중심이었다.

두 workload를 분리하면 독립적으로 배포하고 확장할 수 있다. 하지만 사용자와 브라우저가 보는 도메인까지 나누면 CORS, 쿠키 scope, OAuth redirect URI, CSP와 클라이언트 환경 설정을 함께 바꿔야 한다. 이미 사용 중인 URL 계약의 변경 비용이 서버 분리의 이익보다 커질 수 있었다.

그래서 외부에서는 계속 하나의 도메인으로 보이되 GCLB에서 경로를 기준으로 내부 backend만 나누기로 했다.

https://console.example.com/api/... → Console API
https://console.example.com/...     → Console Web

URL Map을 구성하는 네 요소

GCLB URL Map은 요청의 host와 path를 backend service 또는 backend bucket에 연결한다. 이번 전환에서 중요한 요소는 네 가지였다.

  1. hostRule: Console 도메인을 특정 path matcher에 연결한다.
  2. pathMatcher: 그 host 안에서 path별 목적지를 정의한다.
  3. pathRules: API exact 경로와 하위 경로를 API backend로 보낸다.
  4. defaultService: 어느 path rule에도 맞지 않는 요청은 Web backend로 보낸다.

공식 동작에서 exact path가 먼저 매치되고, /* 형태가 여러 개라면 가장 긴 prefix가 선택되며, 일치 항목이 없으면 path matcher의 default로 간다. 따라서 default는 단순 보험이 아니라 정상 트래픽의 큰 부분을 담당하는 명시적 라우팅 계약이다.

exact 경로와 wildcard를 둘 다 둔 이유

/api/*만 설정하면 /api/users 같은 하위 경로는 처리하지만 /api 자체의 동작을 별도로 확인해야 한다. 반대로 /api만 설정하면 하위 endpoint가 따라오지 않는다. API root가 실제 기능을 제공하든 404를 반환하든, 어느 backend가 그 응답을 소유하는지는 일관돼야 한다.

그래서 API base path와 하위 path를 함께 API backend에 연결했다.

paths:
  - /api
  - /api/*
service: api-backend

실제 경로명은 서비스 계약에 따라 달라질 수 있다. 중요한 것은 /api-v2처럼 비슷하지만 API가 아닌 경로가 의도치 않게 매치되지 않는지 경계값을 시험하는 것이다.

Backend Service와 NEG가 먼저다

URL Map은 목적지를 가리킬 뿐 실제 Pod를 만들지 않는다. 새 API workload가 GKE에 배포돼 있고, Service가 container port와 올바르게 연결되며, NEG가 생성되고, backend service에 연결돼 healthy 상태여야 한다.

적용 순서는 다음처럼 잡았다.

1. Web/API Deployment와 Service 준비
2. 각 Service의 NEG와 Backend Service 준비
3. health check와 backend health 확인
4. URL Map에 새 목적지와 path rule 추가
5. 요청표 검증 후 기존 backend 의존 제거

URL Map을 먼저 바꾸면 새 경로가 비어 있거나 unhealthy인 backend로 향한다. 설정 파일이 문법상 유효하다는 것과 실제 요청이 성공한다는 것은 다른 검증이다.

같은 도메인이 줄여준 변경 범위

브라우저 기준 origin이 유지되므로 프런트가 호출하는 상대 URL을 계속 사용할 수 있었다. 인증 쿠키와 보안 헤더도 기존 origin 경계 안에서 유지됐다. DNS, 인증서와 외부 링크를 바꾸지 않고 서버 배포 단위만 분리할 수 있었다.

그렇다고 모든 문제가 자동으로 사라지는 것은 아니다. Web과 API가 서로 다른 backend가 된 뒤에도 다음 계약은 일치해야 한다.

  • API 응답의 cookie path와 SameSite 정책
  • forwarded host와 protocol을 신뢰하는 방식
  • Web의 SPA fallback과 API 404의 구분
  • 업로드나 긴 요청의 timeout
  • CDN/cache 정책이 API 응답에 적용되지 않는 경계

로드 밸런서는 경로만 나눈다. 애플리케이션 계층의 인증과 캐시 계약까지 대신 설계해 주지는 않는다.

Fallback을 Web으로 둔 이유와 위험

Console의 대부분 경로는 화면 route였기 때문에 default service를 Web으로 두는 편이 자연스러웠다. 새 화면 경로를 추가할 때마다 URL Map을 수정할 필요도 없다. SPA라면 Web 서버가 unknown path를 index.html로 처리할 수 있다.

하지만 API rule을 빠뜨리면 요청이 Web으로 떨어져 HTML 200을 반환할 수 있다. 클라이언트에서는 JSON parse 오류로 보이거나, 잘못된 성공 응답처럼 다뤄질 수 있다. 그래서 존재하는 endpoint만 확인하지 않고 “API처럼 보이는 미등록 path”도 요청표에 넣어야 한다.

Web fallback이 유효한지와 API 누락을 숨기지 않는지는 함께 검증해야 한다. 필요하다면 Web 서버에서 /api prefix를 명시적으로 거부하는 이중 경계를 둘 수 있다.

검증 요청표

전환 직전에는 대표 요청을 path별로 고정했다.

요청 기대 backend 확인할 결과
/ Web 초기 HTML과 정적 자산
/settings Web 직접 진입과 새로고침
/api API API root의 의도된 상태 코드
/api/health API API 식별 응답
/api/not-found API JSON 404, Web HTML 아님
/api-v2 Web 또는 명시 목적지 prefix 오매치 없음
정적 파일 경로 Web/CDN content type과 cache header

각 응답에는 backend를 구분할 수 있는 비민감 헤더나 로그 correlation을 잠시 사용하면 검증이 쉬워진다. 외부에 내부 service 이름을 영구 노출할 필요는 없다.

Rollback은 URL Map만 되돌릴 수 있어야 한다

새 Web/API workload를 기존 통합 서버와 잠시 함께 유지하면 라우팅만 이전 backend로 되돌려 빠르게 rollback할 수 있다. 데이터베이스 schema나 session format을 동시에 비호환으로 바꾸면 이 장점이 사라진다.

따라서 분리 배포의 첫 단계에서는 API 계약과 공유 상태를 호환되게 유지하고, 트래픽 경로 변경을 독립된 작업으로 다루는 편이 안전하다. backend 삭제는 라우팅 안정화 뒤에 한다.

지금 다시 한다면

URL Map 설정과 함께 작은 contract test를 저장한다. 설정 검증 명령으로 문법과 참조 backend 존재 여부를 확인하고, 배포 후에는 host header와 path 조합을 실제 load balancer에 보내 기대 상태 코드·content type을 비교한다.

트래픽 규모가 크거나 위험한 분리라면 처음부터 100% path 전환을 하기보다 별도 test host 또는 header 기반 route rule로 새 backend를 먼저 확인한다. 다만 규칙이 복잡해질수록 우선순위 해석도 어려워지므로, 이번처럼 단순한 경로 분리는 단순한 path rule과 명확한 default가 유지보수에 유리하다.

핵심은 DNS를 바꾸지 않는 기술이 아니다. 사용자가 의존하는 URL 계약을 고정하고, 그 뒤의 배포 경계만 단계적으로 움직이는 것이다.

참고 자료