HTTP 헤더와 바디

2024년 3월 31일

- HTTP 헤더와 바디

헤더바디는 HTTP 통신을 할때 중요한 구성요소이다.

우선적으로 간단히 요약해보자면 헤더는 요청에 관한 메타데이터, 즉 데이터에 대한 정보와 전송 지시사항을 담고 있다.

바디는 위의 헤더의 지시사항에 따른 실질적으로 전송하고자 하는 데이터를 담고 있다.

클라이언트가 서버로 요청하는 데이터, 또는 서버가 클라이언트에게 응답으로 보내는 데이터를 포함한다.

바디의 내용은 대표적으로 HTML 문서, 이미지, JSON 데이터를 담지만, 바이너리 코드로 변환할수 있는 모든 데이터를 담을 수 있다.

헤더는 데이터의 타입, 인증 정보, 상태 코드 등을 정의한다.

- 과거의 HTTP 헤더 (RFC2616)

과거에는 헤더 안에서도 각각 카테고리에 맞는 헤더가 존재했다.

1. General 헤더

요청메세지든 응답메세지든 구분 없이 메세지 전체에 적용되는 정보이다.

예) Connection : close

2. Request 헤더

서버로 요청을 할때 포함되는 정보들을 담고 있다.

예) User-Agent : Mozilla/5.0 (Macintosh..)

3. Response 헤더

요청을 받아서 처리하는 서버 정보를 담고 있다. 예) Server : Apache

4. Entity 헤더

이는 실제로 바디에 들어가는 컨텐츠와 관련된 내용을 담고 있다.

예) Content-Type : text/html, Content-length : 3423

- 과거 RFC2616의 HTTP BODY

메세지 본문(message body)은 엔티티 본문(entity body)을 전달하는데 사용 된다.

여기서의 엔티티는 HTTP 프로토콜에서 사용되는 용어로, 요청이나 응답 메시지와 함께 전송되는 실제 데이터의 패키지 또는 정보 단위를 의미한다.

엔티티 본문은 요청이나 응답에서 전달할 실제 데이터를 의미한다. 즉 현재 상황에서는 body에 담을 컨텐츠라고 생각하면 된다.

하지만 시간이 지나고, 웹이 발전함에 따라서 위의 RFC2616의 구조에서는 여러가지의 문제점이 발생하게 되었다.

1. 의미의 모호성

엔티티라는 용어는 전송되는 데이터의 실제 내용, 즉 바디 컨텐츠 뿐만 아니라 컨텐츠에 대한 메타데이터 (데이터 유형, 길이, 압축 정보)를 포함하는 개념이었다.

이 용어만으로는 메타데이터와 실제 데이터 사이의 구분이 명확하지 않았고, 개발자들 사이에서 혼란을 초래했다.

2. 확장성과 유연성의 부족

웹이 발전하게 됨에 따라서, 주고 받는 데이터의 종류 또한 다양해졌다.

하지만 이 RFC2616 같은 경우에 지원하는 데이터 형식이나, 인코딩 방식의 한계가 존재 했다.

3. 효율성과 성능 개선의 필요성

웹의 급속한 성장에 따라서, 네트워크와 관련된 요청 응답 또한 그에 맞는 성능 향상이 필요했다.

하지만 기존 HTTP 방식에는 이러한 요구사항에 충족하지 못했다.

그래서 2014년에 RFC7230 ~ RFC7235 버전의 스펙으로 변화하게 된다.

- RFC7230 ~ 7235 (HTTP 1.1)

HTTP의 스펙이 변화하게 되면서 엔티티(Entity)라는 용어는 표현(Representation) 으로 변화하게 되었다.

여기서 Representationrepresentation Metadata + Representation Data이다.

즉, 표현이라는 것은 표현 메타데이터 + 표현 데이터이며, 요청이나 응답에서 전달할 실제 데이터이다.

바뀐 형식에서는, 메세지 본문에 엔티티 본문이 아닌, 표현 데이터를 전달한다.

실제 전송, 응답하고 싶은 실질적인 데이터(ex: JSON이나 파일 등)를 페이로드라고 한다.

- 현재 크롬에서의 요청 헤더 속성 살펴보기

- :authority

authority는 서버의 도메인 이름이다.

어떤 호스트로 보내질지 지정 된다.

- :method

HTTP 요청 메서드를 지정한다.

GET은 리소스를 요청할때 사용한다.

- :path

요청된 리소스의 경로이다. / 는 루트 페이지를 나타낸다.

- :scheme

요청된 리소스의 프로토콜을 지정한다. https는 암호화된 연결을 의미한다.

위의 4가지 속성 같은 경우 콜론(:)이 앞에 추가 되었는데, 콜론으로 시작하는 헤더 필드들은 HTTP/2에서 도입 된 가상 헤더 필드이다.

이 헤더들은 HTTP/1.x 에서는 볼수 없는 특별한 경우의 헤더로, 요청이나 응답의 컨텍스트를 정의하는데에 사용 된다.

이 가상 헤더 필드들은 HTTP 메세지의 의미를 분명히 하기 위해 필요하며, 일반 헤더 필드와는 달리 콜론(:)으로 시작함으로써 구별 된다.

여기서 이 가상 헤더 필드들은, 효율성과 성능 개선, 명확한 의미를 부여하는 등의 이유로 :로 구분 된다.

:scheme를 통해 https를 명시적으로 요구 할 수 있어서 보안성을 높일 수 있다.

- Accept

클라이언트가 이해할 수 있는 컨텐츠 유형을 서버에 알린다.

위의 예시 사진에서는 HTML, XML, 이미지 등 다양한 유형의 데이터를 수용할 수 있음을 나타낸다.

- Accept-Encoding

클라이언트가 이해할 수 있는 컨텐츠 인코딩을 서버에 알린다.

gzip, deflate 등 다양한 압축 알고리즘을 지원한다.

- Accept-Language

클라이언트가 선호하는 언어를 서버에 알린다.

- Cache-Control

캐싱 동작을 제어한다.

여기선 no-cache를 설정해줌으로써 캐싱을 하지 않았다.

서버가 클라이언트에 저장한 데이터를 포함한다.

인증 토큰 같은 중요한 정보를 담을 수 있다.

- Dnt(Do Not Track)

사용자가 웹 추적을 원하지 않음을 나타낸다.

1은 추척하지 않았으면 좋겠다 라는 의미이고 0은 추적을 허용한다는 의미이다.

하지만 이런 부분은 단순히 사용자의 선호도를 표시하는 것일뿐, 실질적인 반영은 접속하는 사이트에 따라 다르다.

- Sec-Ch-Ua, Sec-Ch-Ua-Mobile, Sec-Ch-Ua-Platform

클라이언트의 브라우저와 운영 체제 정보를 제공한다.

여기서의 SecSecurity를 의미한다.

이 속성이 포함 된 값들은 사용자나 개발자가 임의로 변경할수 없다.

그렇기에 주로 웹 응용 프로그램의 보안을 강화하는데에 사용 된다. (CSRF 보호 등)

- Sec-Fetch-Dest

요청의 목적지 유형(document나 image)를 나타낸다.

이를 통해 서버는 요청이 로드되는 컨텍스트를 이해할 수 있다.

이미지 파일 자체를 받아와야 하는 경우,

fetch('example-image.png', {
  method: 'GET',
  headers: {
    'Sec-Fetch-Dest': 'image',
  },
})
  .then((response) => response.blob())
  .then((blob) => {});

이런식으로 데이터를 받아온다면, Set-Fetch-Dest: 'image' 가 된다.

- Sec-Fetch-Mode

요청의 모드, 예를 들어서 corsnavigate, no-cors same-origin, websoket 같은 속성들이 존재한다.

이는 요청이 리소스를 로드하는 방식이나, 원본간의 요청 여부를 서버에게 알리는 역할을 한다.

  • cors

이 모드는 다른 출처(origin)의 리소스를 요청할 때 사용된다.

예를 들어, 한 웹사이트가 다른 웹사이트의 폰트나 이미지 등을 요청할 때 CORS 요청이 필요할 수 있다.

  • navigate

이 모드는 사용자가 한 웹 페이지에서 다른 페이지로 네비게이션(이동)할 때 사용 된다.

예를 들어, 사용자가 링크를 클릭하거나 주소 표시줄에 URL을 입력할 때 발생한다.

  • no-cors

'no-cors' 모드의 요청은 CORS 정책을 준수하지 않는 제한된 요청을 의미한다.

이 모드로 요청된 리소스는 읽을 수 없는 상태로 반환될 수 있으며, 주로 서비스 워커나 웹 폰트에 대한 요청 등에 사용될 수 있다.

  • same-origin

이 모드는 요청이 현재 페이지와 동일한 출처에서 발생했음을 나타낸다.

즉, 동일한 도메인, 프로토콜, 포트에서의 요청을 의미한다.

  • websocket

이 모드는 웹소켓 연결을 초기화할 때 사용됩니다. 웹소켓은 브라우저와 서버 간에 양방향 통신을 가능하게 하는 프로토콜입니다.

- Sec-Fetch-Site

요청과 출처의 현재 사이트의 관계 (예: "same-origin", "cross-site") 를 나타낸다.

이를 통해 서버는 요청이 내부에서 발생했는지, 외부에서 발생했는지를 판단할 수 있다.

- Sec-Fetch-User

요청이 사용자의 직접적인 상호작용에 의해 발생하는지 여부를 나타낸다.

?1은 true를 의미한다.

이는 사용자가 직접적으로 발생시킨 요청을 구별하는데에 사용 된다.

- Upgrade-Insecure-Requests

클라이언트가 HTTP 요청을 보낼 때 Upgrade-Insecure-Requests: 1 헤더를 포함시킨다.

이 헤더를 수신한 서버는 클라이언트가 보안된 연결을 선호한다는 것을 인지하고, 가능한 경우 응답을 HTTPS URL로 리다이렉트한다.

이 과정은 사용자의 요청이 처음부터 보안 연결을 사용하여 처리될 수 있도록 돕는 역할을 한다.