사전 헤더
개념

헤더

gabury1고친 사람 github-actions[bot]

헤더는 보내는 데이터 앞에 붙어서 받는 쪽에게 이 데이터를 어떻게 다룰지 알려 줍니다. 목적지나 길이 같은 안내가 여기 적힙니다. 중간 장비와 받는 프로그램은 데이터 본문을 열기 전에 헤더부터 읽습니다.

쉽고 빠른 이해

무슨 일을 하는 물건인가 — 데이터에 붙이는 안내문입니다. 택배 상자에 붙은 송장이 받는 주소와 무게와 취급 주의를 알려 주듯, 헤더는 데이터가 어디로 가고 어떻게 읽혀야 하는지를 알려 줍니다.

왜 이렇게 하나 — 받는 쪽이 본문만 받으면 그게 누구에게 온 것인지, 어디서 끝나는지, 글자인지 그림인지 알 길이 없습니다. 안내를 본문과 떼어 앞에 두면 중간 장비는 본문을 열지 않고도 일을 처리합니다.

어떻게 도나

  1. 보내는 쪽이 본문 앞에 안내 정보를 붙입니다
  2. 중간 장비는 안내만 읽고 다음 장비로 넘깁니다
  3. 받는 쪽이 안내를 읽고 떼어 낸 뒤 본문을 알맞게 처리합니다

대가 — 안내문도 선 위를 지나가는 바이트입니다. 본문이 작을수록 안내가 차지하는 몫이 커집니다. 안내가 잘못 적히면 멀쩡한 본문도 버려집니다.

상세

이 절은 통신에서 쓰는 헤더를 중심으로 봅니다.

편지 봉투를 떠올리면 쉽습니다. 우체국은 봉투 겉면의 주소만 보고 편지를 나릅니다. 안의 편지는 받는 사람만 뜯어 읽습니다.

헤더와 페이로드

데이터 단위 하나는 대개 두 부분으로 나뉩니다. 앞부분이 헤더이고 뒷부분이 페이로드입니다. 페이로드는 실제로 보내려던 내용입니다.

둘을 나누는 까닭은 읽는 사람이 다르기 때문입니다. 네트워크를 지나는 동안 여러 장비가 이 데이터 단위를 만집니다. 그 장비들이 알아야 하는 것은 목적지와 길이 같은 안내뿐입니다. 내용은 몰라도 됩니다.

그래서 라우터 같은 중간 장비는 헤더만 읽고 페이로드는 건드리지 않습니다. 페이로드가 암호화돼 있어도 전달에는 지장이 없습니다. 안내는 늘 같은 모양으로 앞에 있으니, 장비는 데이터 단위마다 내용을 해석하지 않고도 빠르게 넘깁니다.

데이터 단위 끝에 붙는 정보도 있습니다. 이것은 트레일러라고 부릅니다. 전부 받은 뒤에야 계산할 수 있는 검사값처럼, 앞에 둘 수 없는 정보가 뒤로 갑니다.

헤더에 담기는 정보

헤더의 칸 구성은 프로토콜마다 다릅니다. 프로토콜은 두 쪽이 데이터를 주고받는 약속입니다. 약속이 달라도 헤더에 자주 들어가는 정보는 몇 가지로 추려집니다.

정보 무엇을 적나 없으면 무엇이 곤란한가
주소 보낸 쪽과 받을 쪽 어디로 넘길지 모른다
길이 헤더나 페이로드가 몇 바이트인지 이 데이터 단위가 어디서 끝나는지 모른다
종류 페이로드에 무엇이 들었는지 받은 바이트를 어느 프로그램에 넘길지 모른다
순서 몇 번째 데이터 단위인지 뒤바뀌어 도착한 데이터 단위를 바로 세우지 못한다
검사값 바이트로 계산한 요약값 오는 길에 깨진 것을 못 알아챈다
버전 어느 판의 약속으로 적었는지 새 판과 옛 판을 구별하지 못한다

표의 검사값은 흔히 체크섬이라고 부릅니다. 보내는 쪽이 바이트로 값을 계산해 적습니다. 받는 쪽은 같은 계산을 다시 해서 두 값을 견줍니다. 다르면 오는 길에 비트가 뒤집힌 것이라 데이터 단위를 버립니다.

「종류」 칸은 헤더를 여러 겹 쌓을 때 쓸모가 커집니다. 이 칸이 다음에 무엇이 오는지를 알려 주기 때문입니다. 뒤의 「헤더가 겹겹이 쌓이는 모양」 소절에서 이어서 봅니다.

바이트로 적는 헤더

데이터를 목적지까지 나르는 일을 맡은 프로토콜은 헤더를 바이트 단위로 적습니다. 칸마다 몇 번째 비트부터 몇 비트를 쓰는지가 정해져 있습니다. 받는 쪽은 글자를 해석할 필요 없이 정해진 위치에서 값을 꺼냅니다.

UDP(User Datagram Protocol, 사용자 데이터그램 프로토콜)의 헤더가 가장 단순한 예입니다. 네 칸이 16비트씩, 모두 8바이트입니다.

packet-beta
0-15: "출발 포트"
16-31: "도착 포트"
32-47: "길이"
48-63: "체크섬"

그림에서 포트 번호는 한 컴퓨터 안에서 어느 프로그램에게 줄지를 가리킵니다. 길이 칸은 헤더와 페이로드를 합친 크기입니다. 체크섬 칸은 앞에서 본 검사값입니다. 받는 쪽은 앞 8바이트를 떼어 읽고, 나머지를 도착 포트의 프로그램에 넘깁니다.

칸 크기를 미리 정해 두면 읽기가 빠릅니다. 대신 나중에 정보를 더 넣고 싶어지면 곤란합니다. 그래서 많은 프로토콜이 고정된 앞부분 뒤에 선택 사항을 붙일 여유를 둡니다.

IP(Internet Protocol, 인터넷 프로토콜)는 주소를 보고 데이터를 목적지까지 나르는 약속입니다. 그 4판인 IPv4가 이런 여유를 둡니다. 기본 헤더는 20바이트입니다.

그 뒤에는 옵션을 붙일 수 있습니다. 옵션은 꼭 필요하지는 않은 추가 정보를 담는 선택 칸입니다. 옵션이 붙으면 헤더 크기가 달라집니다. 그래서 IPv4 헤더에는 헤더 길이를 적는 칸이 따로 있습니다.

6판인 IPv6는 반대로 기본 헤더를 40바이트로 고정했습니다. 옵션은 기본 헤더에서 빼서 확장 헤더로 옮겼습니다. 확장 헤더는 필요할 때만 기본 헤더 뒤에 따로 붙는 헤더입니다.

글자로 적는 헤더

프로그램끼리 주고받는 내용을 정하는 프로토콜은 헤더를 사람이 읽을 수 있는 글자로 적기도 합니다. 대표가 HTTP(HyperText Transfer Protocol, 하이퍼텍스트 전송 프로토콜)입니다. 한 줄에 「이름: 값」 한 쌍을 적습니다. 빈 줄 하나로 헤더가 끝났음을 알립니다.

아래는 서버가 돌려준 HTTP 응답 하나입니다. 첫 줄은 결과를 알리는 상태 줄입니다. 그 아래 빈 줄 전까지가 헤더입니다. 빈 줄 다음이 본문입니다.

http
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 26
Cache-Control: max-age=60

{"id": 7, "name": "yuumi"}

방금 본 헤더는 세 가지를 알립니다. Content-Type 은 본문이 JSON(JavaScript Object Notation, 자바스크립트 객체 표기법)이라는 것을, Content-Length 는 본문이 26바이트라는 것을 알립니다. Cache-Control 은 이 응답을 60초 동안 다시 써도 된다는 것을 알립니다.

글자로 적는 헤더는 칸을 새로 만들기 쉽습니다. 새 이름 한 줄을 더하면 됩니다. 모르는 이름을 만난 쪽은 그 줄을 무시합니다. 대가는 크기와 읽는 수고입니다. 이름을 매번 글자로 보내니 바이트가 늡니다. 받는 쪽은 줄을 나누고 글자를 해석해야 합니다.

그래서 HTTP 의 두 번째 판인 HTTP/2 는 같은 헤더를 이진 형식으로 바꾸고 압축해서 보냅니다. 요청마다 거의 같은 헤더가 되풀이되기 때문에 압축이 잘 됩니다. 이름과 값의 쌍이라는 뜻은 그대로 둡니다.

HTTP 헤더 이름은 대소문자를 가리지 않습니다. Content-Type 과 content-type 은 같은 헤더입니다. 코드에서 헤더를 꺼낼 때 대소문자를 맞춰 비교하면 가끔 못 찾는 까닭이 이것입니다.

헤더가 겹겹이 쌓이는 모양

네트워크는 일을 여러 계층으로 나눠 맡깁니다. 계층마다 자기 헤더가 있습니다. 위 계층이 만든 데이터 단위는 아래 계층에게는 통째로 페이로드일 뿐입니다. 아래 계층은 그 앞에 자기 헤더를 하나 더 붙입니다.

이렇게 감싸는 일을 캡슐화라고 부릅니다. 받는 쪽은 바깥 헤더부터 하나씩 읽고 벗겨 냅니다. 이때 앞에서 본 「종류」 칸이 다음 헤더가 무엇인지를 알려 줍니다.

아래 그림에는 이름 둘이 새로 나옵니다. 이더넷은 같은 선에 붙은 장비끼리 데이터를 주고받는 방식입니다. TCP(Transmission Control Protocol, 전송 제어 프로토콜)는 순서를 맞추고 잃어버린 데이터를 다시 보내는 전송 방식입니다.

flowchart TD
    A["이더넷 헤더 · 안에 IPv4 가 들었다"] --> B["IPv4 헤더 · 안에 TCP 가 들었다"]
    B --> C["TCP 헤더 · 도착 포트로 프로그램을 고른다"]
    C --> D["HTTP 헤더 · 본문은 JSON"]
    D --> E["본문"]

그림은 웹 요청 하나가 받는 컴퓨터에서 풀리는 순서입니다. 헤더마다 다음 겹을 누구에게 넘길지 적혀 있습니다. 받는 쪽은 이 사슬을 따라 본문까지 내려갑니다.

앞에서 본 「종류」 칸이 IPv4 헤더에서는 프로토콜 칸이라는 이름으로 있습니다. TCP 가 들었으면 6, UDP 가 들었으면 17 을 적습니다. IPv6 헤더에서는 같은 칸을 Next Header 칸이라고 부릅니다. 확장 헤더를 끼울 때도 이 칸으로 다음 헤더를 가리킵니다.

헤더가 드는 비용

헤더는 공짜가 아닙니다. 데이터 단위마다 붙으니 보내는 바이트가 그만큼 늘어납니다. 이렇게 본문 말고 덧붙는 몫을 오버헤드라고 부릅니다.

본문이 작을수록 이 몫이 두드러집니다. 한 글자짜리 채팅 메시지 하나를 보내도 선 위에서는 이더넷·IP·TCP 헤더가 함께 나갑니다. IPv4 헤더 기본 20바이트와 TCP 헤더 기본 20바이트만 합쳐도 40바이트입니다.

그래서 작은 데이터를 자주 보내는 쪽은 여러 개를 한 데이터 단위로 모아 보내곤 합니다. 헤더를 한 번만 붙이면 되기 때문입니다. 대신 모으는 동안 기다려야 하니 전달이 늦어집니다.

헤더가 틀리면 비용이 더 큽니다. 페이로드가 멀쩡해도 검사값이나 길이가 맞지 않으면 받는 쪽은 데이터 단위 전체를 버립니다.

백엔드 코드에서 만나는 헤더

백엔드 코드는 이더넷·IP·TCP 헤더를 거의 만지지 않습니다. 운영체제가 붙이고 떼는 일을 대신하기 때문입니다. 코드가 날마다 만나는 헤더는 HTTP 헤더입니다.

요청 헤더는 클라이언트가 자기 사정을 알리는 데 씁니다. Authorization 에는 인증 정보를 싣습니다. Accept 는 받고 싶은 형식을 알립니다. 쿠키는 Cookie 헤더에 실려 옵니다.

응답 헤더는 서버가 본문을 어떻게 다룰지 알리는 데 씁니다. Content-Type 은 본문 형식을 알립니다. Cache-Control 은 캐싱 규칙을 정합니다. Set-Cookie 는 쿠키를 내려보냅니다.

본문을 열지 않고 헤더만 보는 중간 장비도 많습니다. 로드 밸런서는 Host 헤더를 보고 요청을 어느 서비스로 보낼지 정합니다. 프록시는 요청을 넘기면서 원래 클라이언트의 주소를 X-Forwarded-For 헤더에 적어 뒤쪽 서버에 알려 줍니다.

이 때문에 헤더 값은 믿기 전에 따져 봐야 합니다. 헤더는 클라이언트가 마음대로 적어 보낼 수 있는 글자입니다. 앞단 프록시가 적은 헤더인지, 클라이언트가 직접 적은 헤더인지를 가리지 않으면 가짜 주소나 가짜 권한을 믿게 됩니다.

헤더라는 이름의 다른 쓰임

헤더라는 말은 통신 밖에서도 쓰입니다. 뜻이 닮은 것도 있고 이름만 같은 것도 있습니다.

쓰임 무엇인가 통신 헤더와 닮았나
파일 헤더 파일 맨 앞에 형식과 크기를 적은 바이트 닮았다. 뒤따르는 내용을 읽는 법을 알린다
이메일 헤더 메일 본문 위의 보낸이·받는이·제목 줄 닮았다. HTTP 헤더와 같은 「이름: 값」 꼴이다
헤더 파일 C 와 C++ 에서 선언을 모아 둔 소스 파일 이름만 같다. 데이터에 붙는 안내가 아니다
화면 머리글 웹 페이지나 표 맨 위의 제목 영역 이름만 같다. 화면 배치를 가리킨다

파일 헤더에는 흔히 매직 넘버가 들어갑니다. 파일 맨 앞 몇 바이트에 적은 고정 값으로, 확장자와 상관없이 이 파일이 무슨 형식인지를 알려 줍니다. 프로그램은 이 값을 보고 파일을 어떻게 읽을지 정합니다.

헤더 파일은 전혀 다른 이야기입니다. 여러 소스 파일이 함께 쓰는 함수와 타입의 선언을 한 파일에 모아 둡니다. 소스 파일은 맨 위에서 이 파일을 불러옵니다. 맨 위에 둔다는 점에서 이름을 얻었을 뿐, 데이터에 붙는 안내 정보가 아닙니다.

관련 항목

헤더와 함께 데이터 단위를 이루는 구성 요소

페이로드 · 트레일러 · 체크섬 · 포트 번호 · IP 주소 · TTL · 확장 헤더 · 옵션

헤더를 달고 오가는 데이터 단위

패킷 · 프레임 · 세그먼트 · 데이터그램 · 메시지 · PDU

자기 헤더 형식을 정한 프로토콜

이더넷 · IP · IPv4 · IPv6 · TCP · UDP · ICMP · HTTP · HTTP/2 · QUIC

헤더를 붙이고 읽는 처리 단계

캡슐화 · 역캡슐화 · 다중화 · 역다중화 · 프레이밍 · 직렬화 · 헤더 압축 · HPACK

백엔드가 다루는 HTTP 헤더

Content-Type · Content-Length · Cache-Control · Authorization · Host · 쿠키 · Set-Cookie · X-Forwarded-For · 헤더 접기

헤더만 읽고 요청을 다루는 장비

라우터 · 로드 밸런서 · 프록시 · 리버스 프록시 · 방화벽

헤더를 채우거나 믿어서 생기는 비용과 위험

오버헤드 · MTU · 헤더 스푸핑 · 요청 스머글링 · 헤더 인젝션

헤더와 이름이 겹치는 다른 개념

헤더 파일 · 파일 헤더 · 매직 넘버 · 이메일 헤더 · 메타데이터

헤더가 속하는 상위 분류

프로토콜 · 계층 · OSI 모델 · 네트워크

다른 이름: header