ABOUT

성능과 운영 안정성을 함께 끌어올리는 개발자입니다.

92% Positional Error Reduction
79% p95 Latency Improvement
90%+ Long Tasks Reduction

2022.02 · 한국장학재단

우수 멘티

한국장학재단 사회 리더 대학생 멘토링 IT

2022.10 · 동작구청

우수 인재상

동작구청 우수 SW 인재

2025.05 · (주) 그랩

프로그래밍 우수상

(주) 그랩 우수 프로그램 개발

2025.05 · AWSKRUG

AWS한국사용자모임 발표

AI agent 스크립트 튜닝 관련 발표

ComputerScience

Development

Engineering

Trouble Shooting

GUESTBOOK

첫 마음부터
함께 나누는 온기

방명록 작성하러 가기

SUBSCRIBE

최신소식을
편하게 만나보세요.

hop-by-hop 헤더

도입

hop-by-hop 헤더의 핵심은 HTTP 메시지 전체에 끝까지 전달되는 정보가 아니라, 현재 연결의 바로 다음 수신자에게만 의미가 있는 연결 전용 메타데이터를 구분하는 데 있다

HTTP를 공부하다 보면 hop-by-hop 헤더라는 표현을 자주 보게 됩니다. 이름만 보면 단순히 “중간에 거치는 헤더”처럼 들리지만, 실제 의미는 더 정확합니다.

이 개념은 프록시, 게이트웨이, CDN, 로드 밸런서처럼 중간자가 있는 환경에서 특히 중요합니다. 어떤 필드는 최종 목적지까지 그대로 전달되어야 하지만, 어떤 필드는 현재 연결에서만 의미가 있으므로 다음 홉으로 그대로 넘기면 안 됩니다. hop-by-hop 헤더는 바로 이 둘을 구분하는 개념입니다.

필요성

hop-by-hop 헤더를 이해하면 프록시 체인에서 왜 어떤 헤더는 반드시 제거해야 하고, 왜 잘못 전달된 헤더 하나가 요청 스머글링이나 프로토콜 오류로 이어질 수 있는지 설명할 수 있다

애플리케이션 개발자는 보통 HTTP를 클라이언트와 서버의 단순한 1:1 통신으로 생각하기 쉽습니다. 하지만 실제 운영 환경에는 리버스 프록시, API 게이트웨이, CDN, 서비스 메시, 로드 밸런서 같은 중간자가 많습니다.

이 환경에서 connection-specific 정보가 다음 홉으로 잘못 전달되면, 뒤쪽 서버가 잘못된 연결 상태를 가정하거나, 지원하지 않는 필드를 받아 프로토콜 위반으로 처리하거나, 심하면 보안 문제로 이어질 수 있습니다. 따라서 hop-by-hop 헤더는 단순 문법이 아니라 중간자 환경의 안전 규칙에 가깝습니다.

정의

hop-by-hop 헤더는 현재 연결의 즉시 수신자에게만 의미가 있는 필드이며, 최종 수신자까지 그대로 전달되는 end-to-end 헤더와 구분된다

HTTP Semantics는 `Connection` 헤더가 현재 연결에만 적용되는 필드를 선언적으로 구분하는 장치라고 설명합니다. 이때 그 즉시 수신자에게만 의미가 있는 필드를 hop-by-hop, 체인상의 모든 수신자에게 의미가 있는 필드를 end-to-end로 구분합니다.

쉽게 말하면 hop-by-hop 헤더는 “지금 이 연결에만 필요한 메타데이터”이고, end-to-end 헤더는 “최종 목적지까지 유지되어야 하는 메타데이터”입니다. 이 차이를 모르면 프록시가 무엇을 전달하고 무엇을 끊어야 하는지 판단하기 어렵습니다.

핵심 문장
hop-by-hop은 “한 홉까지만 유효한 연결 전용 정보”이고, end-to-end는 “중간자를 지나 최종 수신자까지 의미를 유지해야 하는 정보”입니다.

핵심 원리

hop-by-hop 헤더의 핵심 설계는 Connection 헤더가 “이 필드는 현재 연결까지만 유효하다”는 선언을 실어 주고, 중간자는 이를 보고 해당 필드와 Connection 자체를 제거한 뒤 다음 홉으로 전달하는 데 있다

현재 HTTP Semantics 기준에서 hop-by-hop 여부를 구분하는 중심은 `Connection` 헤더입니다. 어떤 필드가 현재 연결에 대한 제어 정보를 제공한다면, 발신자는 그 필드 이름을 `Connection` 안에 함께 적어야 합니다.

중간자는 메시지를 포워딩하기 전에 `Connection`에 적힌 각 connection-option 이름과 동일한 헤더/트레일러 필드를 제거하고, `Connection` 헤더 자체도 제거하거나 자기 연결에 맞는 값으로 다시 만들어야 합니다. 즉, hop-by-hop 헤더는 “자동으로 다 알 수 있는 목록”이 아니라, 기본적으로는 `Connection`이 선언하는 연결 전용 필드들입니다.

GET / HTTP/1.1
Host: example.com
Connection: close
GET /chat HTTP/1.1
Host: example.com
Connection: Upgrade
Upgrade: websocket

기본 구조

hop-by-hop 헤더를 실무에서 이해하려면 Connection 헤더, connection-specific 필드, 중간자 제거 규칙, 그리고 반대편의 end-to-end 헤더를 함께 봐야 한다
구성 요소 의미 실무 포인트
Connection 현재 연결에 대한 제어 옵션 선언 hop-by-hop 필드 구분의 중심
Connection Option 현재 연결 전용 필드 이름 또는 옵션 토큰 대소문자 구분 없이 해석
Intermediary 프록시, 게이트웨이, CDN 같은 중간자 포워딩 전에 hop-by-hop 항목 제거 책임이 있음
End-to-End Header 모든 수신자 체인에 의미가 있는 필드 예를 들어 Cache-Control을 Connection 옵션으로 쓰면 안 됨

패턴 1. Connection 헤더가 중심인 이유

현대 HTTP/1.1에서 hop-by-hop 여부는 Connection 헤더가 선언하는 방식이 기본이며, 새 연결 전용 필드를 정의해도 결국 이 메커니즘을 따라야 한다

RFC 9110은 어떤 필드가 현재 연결을 위한 제어 정보를 실을 때, 발신자가 반드시 그 필드 이름을 `Connection` 헤더 안에 적어야 한다고 설명합니다. 그리고 중간자는 그 이름들을 보고 동일한 이름의 헤더나 트레일러를 제거해야 합니다.

또한 `Connection` 옵션은 현재 메시지에 실제 필드가 꼭 존재하지 않아도 될 수 있지만, 반대로 connection-specific 필드가 `Connection` 옵션 없이 나타났다면 대개 중간자가 잘못 전달한 것일 가능성이 높다고 설명합니다. 즉, Connection은 단순 참고 정보가 아니라 중간자 처리 규칙을 활성화하는 핵심 스위치입니다.

GET /resource HTTP/1.1
Host: example.com
Connection: TE
TE: trailers

위 예시처럼 `TE`를 보내려면 `Connection: TE`도 함께 보내야 합니다. 이 규칙이 없으면 중간자가 `TE`를 end-to-end 필드로 오해하고 다음 홉으로 잘못 전달할 수 있습니다.

패턴 2. 대표적인 connection-specific 필드

현재 RFC 9110이 중간자가 제거하거나 교체해야 하는 대표적인 connection-specific 필드 예로 드는 것은 Proxy-Connection, Keep-Alive, TE, Transfer-Encoding, Upgrade 이다

공식 문서는 중간자가 `Connection`에 이름이 올라왔는지와 상관없이, 의미상 제거가 필요한 것으로 알려진 필드들도 제거하거나 교체해야 한다고 설명하면서 대표 예를 직접 나열합니다.

필드 의미 실무 포인트
Connection 현재 연결 제어 옵션 목록 포워딩 전에 자체도 제거 대상
Keep-Alive 역사적으로 연결 유지 협상에 쓰인 필드 프록시 체인에서 잘못 전달되면 오동작 여지
Proxy-Connection 예전 프록시 호환 시도에서 나온 비표준 필드 현재는 보내지 말도록 권고됨
TE 전송 코딩과 trailer 수용 능력 표시 HTTP/1.1에서는 Connection 옵션 동반 필요
Transfer-Encoding 현재 연결에서의 전송 인코딩/프레이밍 HTTP/2·HTTP/3에서는 금지
Upgrade 같은 연결 위 프로토콜 전환 제안 `Connection: Upgrade`와 같이 가야 함

여기서 특히 `Proxy-Connection`은 주의할 만합니다. HTTP/1.0 시절 프록시 호환 문제를 풀기 위한 시도로 등장했지만, 다단 프록시 환경에서는 같은 문제가 반복되어 결국 잘 작동하지 않았고, 현재 RFC 9112는 클라이언트가 이 필드를 보내지 않도록 권고합니다.

패턴 3. TE 와 Trailer, HTTP/2·HTTP/3 차이

hop-by-hop 헤더를 공부할 때 가장 많이 헷갈리는 부분은 TE 와 Trailer 를 한 묶음으로 보거나, HTTP/2와 HTTP/3에서도 HTTP/1.1 방식의 connection-specific 필드가 그대로 통한다고 생각하는 데 있다

TE는 클라이언트가 transfer coding과 trailer section 처리 능력을 알리는 필드입니다. HTTP/1.1에서는 이 필드를 보내는 쪽이 반드시 `Connection: TE`도 함께 보내야 하므로, 분명한 connection-specific 필드입니다.

반면 Trailer는 “이 메시지의 trailer section에 어떤 필드가 올 수 있는가”를 미리 알리는 필드입니다. 이 필드는 trailer metadata 예고에 가깝고, 현재 RFC 9110이 대표적인 connection-specific 제거 목록으로 직접 든 필드에는 포함되지 않습니다. 즉, 실무에서 `TE`와 `Trailer`를 같은 급의 hop-by-hop 필드로 기계적으로 묶으면 틀리기 쉽습니다.

또한 HTTP/2와 HTTP/3에서는 상황이 더 엄격합니다. 두 프로토콜 모두 `Connection`을 이용한 connection-specific 필드 방식을 쓰지 않으며, `Connection`, `Keep-Alive`, `Proxy-Connection`, `Transfer-Encoding`, `Upgrade` 같은 필드를 포함한 메시지는 malformed로 처리해야 합니다. 예외는 `TE`뿐인데, 이때도 값은 오직 `trailers`만 허용됩니다.

# HTTP/1.1에서는 가능
Connection: TE
TE: trailers

# HTTP/2 / HTTP/3에서는 TE가 있더라도 값은 "trailers"만 허용
TE: trailers
실전 팁
HTTP/2·HTTP/3 프록시나 게이트웨이를 다룰 때 `Connection`, `Keep-Alive`, `Transfer-Encoding`, `Upgrade`가 보이면 먼저 경계해야 합니다. HTTP/1.1 감각으로 그냥 넘기면 프로토콜 오류를 만들기 쉽습니다.

프록시와 게이트웨이 처리 원칙

중간자는 hop-by-hop 헤더를 단순 전달하면 안 되고, 현재 연결에서 의미를 해석한 뒤 다음 홉에 맞게 제거하거나 다시 생성해야 한다

RFC 9110은 중간자가 받은 `Connection` 헤더를 먼저 파싱하고, 그 안에 들어 있는 각 connection-option 이름과 동일한 헤더/트레일러를 제거한 뒤, `Connection` 자체도 제거하거나 새 연결의 제어 옵션으로 교체하라고 요구합니다.

또한 어떤 필드가 content 전체 수신자에게 의미가 있는 end-to-end 필드라면, 그것을 `Connection` 옵션으로 올리면 안 됩니다. 공식 문서는 `Cache-Control`을 대표적인 반례로 직접 듭니다. 즉, connection-specific와 representation/control metadata를 혼동하면 안 됩니다.

프록시가 해야 하는 일
1) Connection 헤더를 먼저 본다
2) 거기 적힌 이름과 같은 필드를 제거한다
3) Connection 헤더 자체도 제거하거나 새로 쓴다
4) 다음 홉에 맞는 연결 제어 정보만 다시 만든다

한계와 주의점

hop-by-hop 규칙은 HTTP/1.1 중간자 환경에서는 매우 중요하지만, 프로토콜 버전이 바뀌면 같은 필드도 해석이 크게 달라질 수 있기 때문에 버전 감각 없이 적용하면 오히려 위험하다

HTTP/1.1에서는 `Connection`이 connection-specific 필드를 선언하는 중심입니다. 하지만 HTTP/2와 HTTP/3에서는 그 메커니즘 자체가 사라졌습니다. 따라서 “예전부터 프록시에서 쓰던 헤더니까 그냥 넣자”는 태도는 매우 위험합니다.

또한 connection-specific 필드를 제거했다고 해서 모든 프록시 문제가 해결되는 것도 아닙니다. Hop-by-hop 헤더는 연결 전용 메타데이터를 다루는 규칙일 뿐이고, 캐시, 인증, 압축, 보안 헤더 같은 다른 end-to-end 의미까지 대신 설명해 주지는 않습니다.

특히 주의해야 할 지점
  • HTTP/1.1 규칙을 HTTP/2·HTTP/3에 그대로 적용하지 않기
  • `Connection`에 end-to-end 헤더 이름을 넣지 않기
  • `Proxy-Connection` 같은 역사적 필드를 습관적으로 쓰지 않기
  • `TE`와 `Trailer`를 기계적으로 같은 급의 필드로 보지 않기

자주 하는 실수

hop-by-hop 헤더를 배울 때 가장 흔한 실수는 Connection 없이 connection-specific 필드를 보내거나, HTTP/2/3에서 금지된 필드를 HTTP/1.1 감각으로 그대로 넘기는 데서 나온다
  • TE, Upgrade 같은 필드를 보내면서 Connection 옵션을 빼먹음
  • 프록시가 Connection과 지정된 필드를 제거하지 않고 그대로 전달함
  • Cache-Control 같은 end-to-end 필드를 hop-by-hop처럼 다룸
  • HTTP/2/3에서도 Connection, Keep-Alive, Transfer-Encoding를 그대로 사용함
  • Proxy-Connection을 아직도 정식 필드처럼 사용함
  • TrailerTE를 문맥 없이 같은 것으로 취급함

실무 루틴

hop-by-hop 관련 설정을 만질 때는 먼저 HTTP 버전을 확인하고, 그다음 이 필드가 현재 연결 전용인지 전체 수신자용인지부터 나누는 습관이 좋다
  1. 먼저 HTTP/1.1인지, HTTP/2인지, HTTP/3인지 확인한다.
  2. 필드가 현재 연결 전용인지 end-to-end인지 분리한다.
  3. 연결 전용이라면 Connection과의 관계를 점검한다.
  4. 프록시나 게이트웨이가 포워딩 전에 제거/교체하는지 확인한다.
  5. TE, Upgrade, Transfer-Encoding는 특히 주의해서 본다.
  6. 역사적 필드(Proxy-Connection)는 가능한 한 새 설계에서 피한다.

디버깅

hop-by-hop 관련 문제를 디버깅할 때는 헤더 값 자체보다 먼저 프로토콜 버전, 프록시 체인, Connection 제거 여부를 보는 편이 훨씬 빠르다
1
먼저 요청이 HTTP/1.1인지, HTTP/2인지, HTTP/3인지 확인한다.
2
Connection 헤더가 있는지, 있다면 어떤 옵션을 선언하는지 본다.
3
프록시 체인에서 Connection과 지정된 필드가 제대로 제거되는지 추적한다.
4
HTTP/2·HTTP/3 경계에서 금지된 connection-specific 필드가 유입되지 않는지 확인한다.
5
TE라면 값이 `trailers` 외 다른 값을 갖는지와 Connection: TE 동반 여부를 본다.
체크리스트
- HTTP 버전은 무엇인가?
- Connection 헤더가 있는가?
- 거기 선언된 이름과 같은 필드를 제거했는가?
- end-to-end 필드를 Connection 옵션으로 잘못 올리지는 않았는가?
- HTTP/2 / HTTP/3에서 금지 필드를 그대로 보내고 있지는 않은가?

요약

hop-by-hop 헤더의 본질은 현재 연결의 바로 다음 수신자에게만 의미가 있는 필드를 end-to-end 헤더와 구분하는 데 있으며, HTTP/1.1에서는 Connection 헤더가 그 구분을 선언하고 중간자는 이를 제거하거나 교체해야 하고, HTTP/2와 HTTP/3에서는 이런 connection-specific 필드 사용이 거의 금지된다는 점이 실무의 핵심이다
  • ✅ hop-by-hop 헤더는 현재 연결의 즉시 수신자에게만 의미가 있다.
  • ✅ end-to-end 헤더는 체인의 모든 수신자에게 의미가 있다.
  • ✅ HTTP/1.1에서는 Connection 헤더가 hop-by-hop 여부를 선언하는 중심이다.
  • ✅ 중간자는 Connection에 적힌 필드들과 Connection 자체를 제거하거나 교체해야 한다.
  • ✅ 대표적인 connection-specific 필드 예로 Proxy-Connection, Keep-Alive, TE, Transfer-Encoding, Upgrade가 자주 언급된다.
  • ✅ Cache-Control 같은 end-to-end 필드는 Connection 옵션으로 쓰면 안 된다.
  • ✅ HTTP/2와 HTTP/3에서는 connection-specific 필드가 금지되며 TE만 trailers 값으로 예외 허용된다.
  • ✅ 실무에서는 프록시 체인과 프로토콜 버전 경계를 같이 봐야 hop-by-hop 문제를 정확히 잡을 수 있다.
728x90