Envoy Gateway Route 타입 치트시트: HTTPRoute, GRPCRoute, TCPRoute, 아니면 TLSRoute?

8 min read

앞선 글들을 읽었다면 지금 여러분을 가장 많이 막고 있는 질문은 "Gateway API를 이해 못하겠다"가 아니라, 아마 이쪽일 겁니다:

"그래서 실제로 뭘 써야 하죠? HTTPRoute, GRPCRoute, TCPRoute, 아니면 TLSRoute?"

이 글은 바로 그 실타래를 풀기 위해 존재합니다. 주머니 속 참고표처럼 두세요. 새로운 서비스가 생길 때마다 먼저 이것부터 확인하면, YAML을 감으로 쓰다가 condition status에게 교육당하는 일을 줄일 수 있습니다.

결론부터: Route 네 종류, 목적도 네 가지

Route 타입 트래픽 계층 무엇을 검사하나 가장 잘 맞는 용도 맞지 않는 용도
HTTPRoute L7 HTTP/HTTPS host, path, header, query, method 웹사이트, REST API, 일반 웹 트래픽 raw TCP, TLS passthrough
GRPCRoute L7 gRPC hostname, service, method, header gRPC service/method 라우팅 일반 REST API, raw TCP
TCPRoute L4 TCP Listener와 연결 수준 정보 데이터베이스, 커스텀 TCP 프로토콜, 비 HTTP 서비스 path/header 검사가 필요한 시나리오
TLSRoute L4/L5 TLS TLS SNI hostname TLS passthrough, end-to-end 암호화 유지 복호화 후 HTTP 세부 정보를 봐야 하는 경우

아주 짧게 말하면:

  • pathheader를 봐야 한다 → HTTPRoute
  • gRPC service/method를 봐야 한다 → GRPCRoute
  • TCP 연결만 전달하면 된다 → TCPRoute
  • TLS termination 없이 SNI로만 라우팅한다 → TLSRoute

3단계 판단법: 감으로 고르지 말자

이 순서로 생각하세요:

  1. Gateway가 이 트래픽에서 HTTP 의미 체계를 파싱해야 하는가?
  2. 그렇다면 일반 HTTP/REST인가, 아니면 gRPC인가?
  3. 아니라면 raw TCP인가, 아니면 TLS passthrough인가?

정리하면:

  • HTTP path/header/method를 검사해야 한다 → HTTPRoute
  • gRPC service/method를 검사해야 한다 → GRPCRoute
  • L7 규칙 없이 TCP 포워딩만 한다 → TCPRoute
  • TLS를 백엔드까지 유지하고 싶다 → TLSRoute

이 결정은 정말 중요합니다. 많은 사람이 본능적으로 먼저 HTTPRoute부터 쓰다가, 반쯤 가서 자신이 다루는 게 데이터베이스 트래픽이라는 사실을 깨닫습니다. 그러면 YAML 전체가 "내가 지금 대체 뭘 하고 있지" 모드로 들어갑니다.

최소 YAML 예제: 한눈에 각 타입 알아보기

각 타입을 가장 짧고 알아보기 쉽게 보여주는 예시를 보겠습니다.

HTTPRoute

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: web-route
spec:
  parentRefs:
    - name: eg
      sectionName: http
  hostnames:
    - "app.example.com"
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /api
      backendRefs:
        - name: api-service
          port: 8080

path, hostnames, backendRefs가 보이면 이 타입입니다.

GRPCRoute

apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
  name: user-grpc
spec:
  parentRefs:
    - name: eg
      sectionName: grpc
  hostnames:
    - "grpc.example.com"
  rules:
    - matches:
        - method:
            service: com.example.User
            method: Login
      backendRefs:
        - name: user-grpc-service
          port: 50051

method.servicemethod.method가 보이면 일반 HTTP가 아니라 gRPC 의미 체계를 매칭하고 있는 것입니다.

TCPRoute

apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
  name: postgres-route
spec:
  parentRefs:
    - name: eg
      sectionName: postgres
  rules:
    - backendRefs:
        - name: postgres
          port: 5432

TCPRoute에는 path/header 개념이 거의 없습니다. 왜냐하면 그걸 보지 않기 때문입니다. 좀 더 정확히 말하면 "이 listener로 들어오는 TCP 연결은 이 backend로 보낸다"에 가깝습니다.

TLSRoute

apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TLSRoute
metadata:
  name: passthrough-route
spec:
  parentRefs:
    - name: eg
      sectionName: tls
  hostnames:
    - "db.example.com"
  rules:
    - backendRefs:
        - name: db-service
          port: 5432

보통 protocol: TLS listener와 짝을 이룹니다. 핵심은 복호화가 아니라 SNI 기반 라우팅입니다.

💡 TCPRouteTLSRoute는 Gateway API 버전에 따라 experimental 채널에 있는 경우가 많습니다. 적용 전에 클러스터에 설치된 CRD 버전을 꼭 확인하세요.

흔한 함정 네 가지

1. gRPC가 반드시 GRPCRoute를 요구하는 것은 아니다

gRPC 트래픽을 그냥 흐르게만 하면 되는 경우, 구현체에 따라 gRPC가 HTTP/2 위에서 동작하므로 HTTPRoute로도 지원될 수 있습니다. 하지만 gRPC service/method 의미 체계로 매칭하고 싶다면, GRPCRoute가 더 올바르고 읽기 쉬운 선택입니다.

2. TLSRoute는 "고급 HTTPS"가 아니다

이게 가장 흔한 오해입니다.

  • HTTPS listener + HTTPRoute: Gateway가 TLS를 종료하고, 그 뒤 HTTP 규칙 적용
  • TLS listener + TLSRoute: Gateway가 TLS를 종료하지 않고, SNI만 보고 라우팅

하나는 복호화해서 L7에서 동작합니다. 다른 하나는 트래픽을 암호화 상태로 유지한 채 passthrough 합니다. 완전히 다른 세계입니다.

3. TCPRoute는 Path/Header를 볼 수 없다

만약 요구사항이 다음과 같다면:

  • /api는 A로
  • /admin은 B로

이건 TCPRoute의 일이 아닙니다. TCPRoute는 HTTP 세부 정보를 이해하지 못합니다. 여기에 그런 요구를 억지로 밀어 넣으면, 결국 본인만 괴로워집니다.

4. parentRefs.sectionName은 중요하다

Gateway에 listener가 여러 개라면 sectionName을 쓰세요:

parentRefs:
  - name: eg
    sectionName: https

이렇게 해야 route가 정확히 의도한 listener에 붙습니다. 이게 없으면 VIP 룸 예약했다고 생각했는데 엉뚱한 홀에 들어가는 일이 벌어질 수 있습니다.

한 줄 요약

먼저 내가 다루는 것이 HTTP, gRPC, TCP, 아니면 TLS passthrough인지 파악하고, 그다음 맞는 route 타입을 고르세요. Route를 제대로 고르면 YAML의 80%는 자연스럽게 풀립니다. 반대로 잘못 고르면 condition status와 끝없는 싸움에 갇히게 됩니다.

다음 단계

Route 타입을 이해했다면 다음으로 흔히 막히는 지점은 이것입니다: 같은 Gateway에 listener가 많을 때, 어떻게 구조를 잡아야 혼란이 생기지 않을까?

다음 글에서는 멀티 listener 설계를 다룹니다: 👉 Listener 설계 가이드