본문 바로가기
BackEnd

[모든 개발자를 위한 HTTP 웹 기본 지식] 7. HTTP 헤더 1 - 일반 헤더

by kkkdh 2022. 12. 25.
728x90

HTTP message 중에서도 header에 대한 간단한 복습

  • header-field = field-name":" OWS field-value OWS (OWS는 띄어쓰기 허용을 의미)
  • field-name에는 대소문자 구분이 없다. 

노란색 박스 안의 부분이 header-field에 해당한다.

HTTP header 용도

  • HTTP 전송에 필요한 모든 부가 정보를 담는 부분이다.
  • 예) 메시지 바디의 내용, 메시지 바디의 크기, 압축, 인증, 요청 클라이언트, 서버 정보, 캐시 관리 정보 등등..
  • 표준 헤더가 너무 많다.
  • 필요시 임의의 헤더 추가가 가능하다.
    • helloworld: hihi 이런 식으로?

과거의 HTTP 헤더 분류

  • General 헤더: 메시지 전체에 적용되는 정보, 예) Connection: close
  • Request 헤더: 요청 정보, 예) User-Agent: Mozilla/5.0 (Macintosh; ..)
  • Response 헤더: 응답 정보, 예) Server: Apache
  • Entity 헤더: 엔티티 바디 정보, 예) Content-Type: text/html, Content-Length: 3244

  • 메시지 본문 (message body)는 엔티티 본문 (entity body)를 전달하는 데 사용
  • 엔티티 본문은 요청이나 응답에서 전달할 실제 데이터에 해당
  • 엔티티 헤더엔티티 본문의 데이터를 해석할 수 있는 정보를 제공하는 공간이다.
    • 데이터 유형(html, json..), 데이터 길이, 압축 정보 등등이 담긴다.

최신 스펙에서 변화한 부분 (RFC723x)

  • 엔티티(Entity) -> 표현(Representation)
  • Representation = Representation Meta Data + Representation Data
  • 표현 = 표현 메타데이터 + 표현 데이터

위와 같이 개념을 부르는 명칭이 변화함

  • 메시지 본문(message body)을 통해 표현 데이터 전달
  • 메시지 본문 = 페이로드(payload)
  • 표현은 요청이나 응답에서 전달할 실제 데이터를 의미
  • 표현 헤더는 표현 데이터를 해석할 수 있는 정보 제공
    • 데이터 유형(html, json...), 데이터 길이, 압축 정보 등등이 담긴다.
  • 참고: 표현 헤더는 표현 메타데이터와, 페이로드 메시지를 구분해야 하지만, 여기서는 생략

엔티티라는 단어가 다 사라짐

 

표현이라고 부르는 이유:

어떠한 데이터를 전송할 때, 위와 같은 상황에서는 이걸 HTML이라는 형식으로 표현하여 전달하는 것과 같다. 그리고 이러한 데이터를 HTML, json 등 다양한 형태로 표현할 수 있어 실제로 전달하는 것을 표현이라는 용어로 정리했다고 한다.


표현

resource는 굉장히 추상적인 개념, 이걸 서버와 클라이언트 간에 실제로 주고받을 때에는 서로 간에 이해할 수 있는 형태로 변환해서 데이터를 전달한다.

  • Content-Type: 표현 데이터의 형식 설명 (text/html, application/json, image/png..)
  • Content-Encoding: 표현 데이터의 압축 방식 (gzip, deflate, identity...)
    • 표현 데이터를 압축하기 위해서 사용
    • 데이터를 전달하는 곳에서 압축한 후 인코딩 헤더를 추가한다.
  • Content-Language: 표현 데이터의 자연 언어 (한국어, 영어..)
    • ko, en, en-US..
  • Content-Length: 표현 데이터의 길이
    • 바이트 단위로 작성한다
    • Transfer-Encoding(전송 코딩)이라는 것을 사용하면, Content-Length를 사용하면 안 된다고 함
  • 표현 헤더는 request, response 두 상황 모두 HTTP message에 사용될 수 있다. 

표현 헤더 예시 1
표현 헤더 예시 2


협상 (Content Negotiation)

클라이언트가 선호하는 표현을 요청하는 것을 의미한다.

  • Accept: 클라이언트가 선호하는 미디어 타입 전달
  • Accept-Charset: 클라이언트가 선호하는 문자 인코딩
  • Accept-Encoding: 클라이언트가 선호하는 압축 인코딩
  • Accept-Language: 클라이언트가 선호하는 자연 언어

최대한 이거에 맞춰서 표현(representation)을 전달해주라는 요청에 담기는 전달 사항이다.

위 예시와 같이 다중 언어 지원 서버에서 내가 원하는 언어를 선택하기 위해 사용할 수 있다.

위와 같이 내가 원하는 언어 서비스를 서버가 제공하면 좋지만, 그렇지 않은 다음과 같은 경우 또한 존재한다.

해당 서버는 한국어를 지원하지 않는다.. 이럴땐 어떻게?

이런 복잡한 상황에서 내가 더 선호하는 언어를 선택하는 구조를 다음과 같이 만들 수 있다.

협상과 우선순위 1

Quality Values(q)를 사용한다!!

  • Quality Values(q) 값을 사용한다.
  • 0 ~ 1 사이의 값을 갖고, 큰 값일수록 높은 우선순위를 갖는다.
  • 생략하면 1로 취급
  • Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
    1. ko-KR;q=1 (1이기 때문에 q값을 생략한 케이스)
    2. ko;q=0.9
    3. en-US;q=0.8
    4. en;q=0.7

ko-KR은 한국 사람들이 쓰는 한국어, ko는 한국 공통어(?), en-US는 미국 사람들이 쓰는 영어, en은 공통 영어

q값을 사용하면 복잡한 예시에서도 선호하는 언어를 선택할 수 있게 된다!!

협상과 우선순위 2

  • 구체적인 것이 우선한다!!
  • Accept: text/*, text/plain, text/plain;format=flowed, */*
    1. text/plain;format=flowed
    2. text/plain
    3. text/*
    4. */*
  • 위와 같이 더 구체적으로 Accept field의 값을 작성한 것을 우선하여 content-type을 요청하게 되는 것을 의미한다.

협상과 우선순위 3

사실 이렇게 디테일하게까지 내려갈 일은 많이 없다고 하지만, 정리하자

  • 구체적으로 작성된 기준을 우선으로 미디어 타입을 맞춘다.
  • Accept: text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5
  • 이렇게 Accept field를 작성하는 경우

위 표와 같이 Q값이 할당되는 것과 같다고 한다.


전송방식

전송 방식에는 4가지가 존재한다.

  • 단순 전송
  • 압축 전송
  • 분할 전송
  • 범위 전송

하나씩 정리해 보자.

 

단순 전송, Content-Length

단순하게 요청한 content 전체를 그대로 클라이언트로 주는 형태의 전송 방식

전체 컨텐츠를 하나의 HTTP message에 전달하는 경우

Content-Length field에 작성된 길이가 content 자체의 길이에 해당한다. 압축 같은 거 없이 그대로 요청된 컨텐츠가 전달되는 방식을 의미한다.

 

압축 전송, Content-Encoding

요청한 컨텐츠를 압축해서 전송하는 방식, 대신에 Content-Encoding이라는 field를 추가로 작성해줘야 한다.

gzip 방식으로 컨텐츠가 압축되어 전송되는 형태

 

분할 전송, Transfer-Encoding

Transfer-Encoding이라는 field를 사용하고, 컨텐츠 덩어리를 분할해서 준비되는 대로 부분 부분이 클라이언트로 전송되는 방식이다.

용량이 큰 컨텐츠를 전송하는 경우 로딩되는 시간이 발생하기 때문에, 분할하여 전송해 일부라도 먼저 컨텐츠를 제공할 수 있도록 하기 위한 전송 방식이다.

Transfer-Encoding: chunked 라고 작성되어야, chunk 단위로 컨텐츠가 전달된다.

분할 전송 시에는 Content-Length가 작성되면 안 됨. 왜냐하면 컨텐츠의 길이를 예상할 수 없기 때문이다.

 

범위 전송, Range, Content-Range

컨텐츠의 일부만 다시 전송받고 싶은 경우에 사용하는 전송 방식이다. 클라이언트는 HTTP message에 Range라는 field를 작성해 서버로 보내고, 서버는 그에 대한 응답으로 Content-Range에 전송하는 컨텐츠의 범위를 작성해서 응답으로 전달한다.

1001-2000 범위의 컨텐츠만 전송한다.


일반 정보

쉽고 단순한 HTTP header에 대해 정리해 보자. 단순한 정보성 헤더들이다.

  • From: 유저 에이전트의 이메일 정보
  • Referer: 이전 웹 페이지의 주소
  • User-Agent: 유저 에이전트 애플리케이션 정보
  • Server: 요청을 처리하는 오리진 서버의 소프트웨어 정보
  • Date: 메시지가 생성된 날짜

하나씩 정리해보자.

 

From - 유저 에이전트의 이메일 정보

  • 일반적으로 잘 사용되지 않는다.
  • 검색 엔진 같은 곳에서, 주로 사용됨
  • 사이트 담당자 입장에서 내 사이트 정보를 크롤링하는 검색 엔진 정보를 확인할 때 사용할 수 있다고..
  • 요청에서 사용

 

Referer - 이전 웹 페이지 주소

정말 많이 사용한다

  • 현재 요청된 페이지 이전의 웹 페이지 주소
  • A -> B로 이동하는 경우 B를 요청할 때 "Referer: A"를 포함해서 요청한다.
  • Referer를 사용해서 유입 경로 분석이 가능하다.
  • 요청에서 사용한다.
  • 정보: 사실 referer은 단어 referrer의 오타

 

User-Agent - 유저 에이전트 애플리케이션 정보(웹 브라우저 정보)

  • 예시) user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/ 537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36
  • 클라이언트의 애플리케이션 정보 (웹 브라우저 정보 등등..)
  • 서버에서 통계 정보로 사용
  • 어떤 종류의 브라우저에서 장애가 얼마큼 발생하는지와 같은 정보를 파악하기 위해 사용할 수 있다
  • 요청에서 사용한다.

 

Server - 요청을 처리하는 ORIGIN 서버의 소프트웨어 정보

http 요청을 거치면서 사실은 수많은 proxy server를 건너게 된다. 이 과정에서 실제로 나의 요청에 응답하기 위한 정보를 제공하는 서버가 있을 것인데, 이것을 ORIGIN 서버라고 부른다.

  • Server: Apache/2.2.22 (Debian)
  • server: nginx
  • 응답에서 사용

 

 Date - message가 발생한 날짜와 시간

  • Date: Tue, 15 Nov 1994 08:12:31 GMT
  • 응답에서 사용

특별한 정보

조금 특별한 정보 전달을 위한 HTTP header들을 살펴보자.

  • Host: 요청한 호스트 정보(도메인)
  • Location: 페이지 리다이렉션
  • Allow: 허용 가능한 HTTP method
  • Retry-After: 유저 에이전트(웹 브라우저 등..)가 다음 요청을 하기까지 기다려야 하는 시간

 

Host - 요청한 호스트 정보(도메인), 필수 헤더이다.

  • 하나의 IP 주소에 여러 도메인이 적용되어 있는 경우가 있다.
  • 이때, 구분을 해주기 위해 사용한다.
  • 요청에서 사용
  • 필수로 사용되는 헤더이다.

host 내의 aaa.com으로 들어갈 수 있다.

서버가 하나의 도메인이 아닌 여러 개의 도메인으로 이루어진 경우, 서버로 온 요청이 어느 도메인으로 향해야 하는지 알 수 있는 방법이 없다.

 

여기서 TCP/IP는 IP 주소로만 통신? 부분에서 의문이 들었는데, 아래의 질문글에서 해답을 얻을 수 있었다.

같은 ip + port#에서 서로 다른 도메인으로 사용가능한데, 이러한 경우를 구분하기 위해 사용하는 것 같다.

그래서 Host 헤더를 필수로 포함하도록 스펙에 지정해서, 도메인 구분이 가능하도록 하고 있다고 한다.

 

완전하게 이해했는지 잘 모르겠지만, 앞으로 더 공부하다 보면 깨닫지 않을까 싶다.

 

Location - page redirection

  • 웹 브라우저는 3XX 응답 결과를 받았을 때, Location header가 있으면, Location header에 작성된 위치로 자동으로 이동하고 이를 redirection이라고 한다.
  • 응답 코드 3XX 관련 부분에서 정리한 바가 있다.
  • 201(Created): 여기서 Location header의 값은 요청에 의해 생성된 resource URI를 의미했다.
  • 3XX(Redirection): 여기서의 Location header의 값은 자동으로 redirection 하기 위한 대상 resource를 가리킨다.

 

Allow -  허용 가능한 HTTP method

url 경로는 있는데, 어떤 HTTP method가 사용 가능한지 알려줄 때 사용한다.

  • 405 (method not allowed)에서 응답에 포함되어야 한다.
  • 예시) Allow: GET, HEAD, PUT
  • 사실 서버에서 많이 구현되어 있지는 않다고 한다.

 

Retry-After - 유저 에이전트가 다음 요청을 하기까지 기다려야 하는 시간을 알려줄 때

  • 503 (Service Unavailable): 서비스가 언제까지 불능한 지 알려줄 수 있다.
  • Retry-After: Fri, 32 Dec 1999 23:59:59 GMT (날짜 형식의 표기)
  • Retry-After: 120 (초단위 남은 시간 표기)
  • 실제로는 사용하기가 쉽지 않다.

인증

인증과 관련된 헤더

  • Authorization: 클라이언트 인증 정보를 서버에 전달
  • WWW-Authenticate: 리소스 접근 시 필요한 인증 방법를 정의

하나씩 보자.

 

Authorization

클라이언트 인증 정보를 서버에 전달. 인증과 관련해서는 여러 가지 메커니즘이 있는데, 메커니즘마다 Authorization header에 들어가는 value가 천차만별 직접 공부해보면 좋을 것 같다.

  • Authorization: Basic xxxxxxxxxxxxxxxx

 

WWW-Authenticate

리소스 접근 시에 필요한 인증 방법을 정의하는 헤더

  • 리소스 접근시 필요한 인증 방법 정의
  • 401 Unauthorized 응답과 함께 사용하는 헤더
  • WWW-Authenticate: Newauth realm="apps", type=1, title="Login to \"apps\"", Basic realm="simple"

쿠키

상당히 많이 사용하고 중요한 쿠키를 정리해 보자. 일단 쿠키를 사용하기 위해서 두 개의 헤더를 사용한다.

  • Set-Cookie: 서버에서 클라이언트로 쿠키 전달 (response)
  • Cookie: 클라이언트가 서버에서 받은 쿠키를 저장하고, 갖고 있는 쿠키를 HTTP 요청 시 서버로 전달한다.

 

HTTP는 기본적으로 

Stateless

  • 무상태 프로토콜이다.
  • 클라이언트와 서버가 요청과 응답을 주고받으면 연결이 끊어진다.
  • 클라이언트가 다시 요청하면, 서버는 이전 요청을 기억하지 못한다.
  • 클라이언트와 서버는 서로 상태를 유지하지 않는다.

이러한 대안들이 있으나, 완전한 해결책이 되지 못한다.

이러한 특성으로 인해서 쿠키를 사용하지 않고서는 로그인을 설령 하더라도 여러 가지 문제들로 인해서 사용자별 커스터마이징이 어렵다. (stateless 하기 때문에)

 

그럼 모든 요청에 정보를 넘기면?

  • 모든 요청에 사용자 정보가 포함되도록 개발을 해야 (개발자가 힘들어)
  • 하지만, 브라우저가 완전히 종료되고 다시 열면?
  • 이것도 해결책이 못된다.

 

서버가 로그인한 클라이언트의 정보를 쿠키로 만들어 다시 클라이언트로 전달한다.

쿠키 저장소에 저장된 쿠키는 해당 서버와 통신할 때마다 request message에 실려서 서버로 전달된다. (클라이언트가 서버로 전송할 때 마다 쿠키 저장소를 뒤져서 보내는 구조)

 

이렇게 모든 요청에 쿠키 정보를 자동으로 포함한다.

그런데, 모든 곳에 이렇게 쿠키를 보내면 보안적으로도 여러 방면으로 문제가 생길 수 있어 이걸 제약하는 방법이 있다.

 

다시 쿠키에 대한 디테일한 설명

  • 쿠키 설정 예) set-cookie: sessionId=abcde1234; expires=Sat, 26-Dec-2020 00:00:00 GMT; path=/; domain=.google.com; Secure
    • session id, 만료 기간, 적용 경로, 도메인, 보안? 관련 정보를 담은 쿠키 생성
  • 사용처
    • 사용자 로그인 세션 관리 할 때 많이 사용됨 (보안상의 이유로 유저 정보를 서버에서 그대로 전달하지 않고, 세션을 만들어서 전달해 준다.)
    • 광고 정보 트래킹에 사용 (이 브라우저 사용자는 이러한 광고를 좋아하는구나)
  • 쿠키 정보는 항상 서버에 전송됨
    • 네트워크 트래픽 추가 유발
    • 최소한의 정보만 사용해야 한다.(세션 id, 인증 token)
    • 서버에 전송하지 않고, 웹 브라우저 내부에 데이터를 저장하고 싶으면 웹 스토리지(localStorage, sessionStorage)를 참고
  • 주의!
    • 보안에 민감한 데이터는 절대 저장하면 안됨! (주민번호, 신용카드 번호 등등)

 

쿠키 - 생명주기

Expires, max-age

  • Set-Cookie: expires=Sat, 26-Dec-2020 04:39:21 GMT
    • 만료일이 지나면 쿠키가 삭제된다.
  • Set-Cookie: max-age=3600 (3600초, 초단위로 값이 매겨진다.)
    • 0이나 음수를 지정하면 쿠키가 삭제
  • 세션 쿠키: 만료 날짜를 생략하면, 브라우저 종료 시까지만 쿠키가 유지된다.
  • 영속 쿠키: 만료 날짜를 입력하면 해당 날짜까지 쿠키가 유지된다.

 

쿠키 - 도메인

내가 가지고 있는 쿠키가 아무 사이트나 들어가면 안 되기 때문에, 쿠키에 도메인을 지정할 수 있다.

  • 예) domain=example.org
  • 명시: 명시한 문서 기준 도메인 + 서브 도메인 포함
    • domain=example.org를 지정해서 쿠키를 생성
      • example.org +
      • dev.example.org(하위 도메인)도 쿠키 접근
  • 생략: 현재 문서 기준 도메인만 적용된다.
    • example.org 에이서 쿠키를 생성하고 domain 지정을 생략한 경우
      • example.org에서만 쿠키 접근
      • dev.example.org(하위 도메인)는 쿠키 미접근

 

쿠키 - 경로

경로 지정 또한 가능하다.

  • 예) path=/home
  • 이 경로를 포함한 하위 경로 페이지만 쿠키 접근할 수 있다.
  • 일반적으로 "path=/"로, 즉 루트로 지정한다.
  • 예)
    • path=/home 지정 시
    • /home -> 가능
    • /home/level1 -> 가능
    • /home/level1/level2 -> 가능
    • /hello -> 불가

 

쿠키 - 보안

쿠키와 관련된 보안은 크게 3가지가 있다.

  • Secure
    • 원래 쿠키는 http, https를 구분하지 않고 전송한다.
    • Secure를 적용하면(작성하면), https인 경우에만 전송한다.
  • HttpOnly
    • XSS 공격 방지
    • 자바스크립트에서 쿠키에 접근 불가(document.cookie로 접근이 불가능 해진다고 한다.)
    • HTTP 전송에만 사용
  • SameSite
    • XSRF 공격 방지
    • 요청 도메인과 쿠키에 설정된 도메인이 같은 경우만 쿠키를 전송한다. (달라도 쿠키를 전송할 수 있는데 이것을 막는다.)
728x90

댓글