코드 저장소

공부에는 끝이 없다!

HTTP

HTTP - HTTP 일반 헤더(2)

VarcharC2K 2024. 1. 23. 12:15

협상(콘텐츠 네고시에이션) 헤더

협상이란 클라이언트가 선호하는 표현 요청을 이야기 한다.

좀 더 쉽게 설명하자면 클라이언트가 선호하는 표현을 요청하면 서버에서 여러가지 표현 방법 중 클라이언트가 선호하는 표현으로 응답을 만들어 보내는 것을 말한다.

협상에는 미디어 타입, 인코딩, 자연언어 등이 표현되며 각각을 표현하는 요청 헤더는 다음과 같다.

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

이러한 협상 헤더는 클라이언트가 보내는 것이기에 요청시에만 사용되는 것이 특징이다.

또한, 협상의 경우 클라이언트가 선호 방식을 알려주는 것이기에 서버가 요청한 방식으로 못 보내줄 수도 있다.

다만 협상을 사용하는 경우 여러가지 선택지 중에서 클라이언트가 선호하는 방식을 알려주고 우선순위로 해당 방식을 받는 것이라고 생각하면 좋을 것이다.

예를 들어, 내가 한국어를 사용하고 서버가 다중언어를 사용하는데 기본 자연언어가 영어로 되어있다고 생각해보자.

그럼 한국어 브라우저에서는 Accep-Language를 통하여 한국어로 데이터 요청을 보낸다고 가정해보자.

GET /data
Accept-Language: ko

요청 메시지는 위와 같이 구성될 것이고, 서버에서는 다중언어를 지원하기 때문에 클라이언트가 한국어를 요청한다고 판단하여 응답 메시지를 한국어로 보내 줄 수 있는것이다.

만약 이런 협상 헤더가 없었다면 우리는 기본적으로 영어로 응답 받게 될 것이다.

이런식으로 클라이언트가 필요에 따라 선호하는 것을 요청할 수 있게 만든 것이 협상 헤더이다.


조금 복잡한 상황을 가정해 보자

이전과 요청은 동일 하지만 서버에서 다중언어를 지원하되 기본 언어가 독일어이고 영어를 지원한다고 생각해보자.

그럼 우리는 이전과 같은 요청을 보낼 것이다.

GET /data
Accept-Language: ko

그럼 서버에서는 지원 언어에 한국어가 없기 때문에 기본 언어인 독일어로 응답을 보내게 될 것이다.

그런데 우리는 독일어 보다는 영어가 보다 이해하기 쉽기 때문에 만약 한국어가 없는 경우 영어로 응답을 받으려 한다.

이런 경우는 협상 헤더를 어떤식으로 만들어야 할까?


우선순위를 만들자!

이런 상황을 해결하기 위하여 협상에서는 우선순위(Quality Values)라는 개념이 존재한다.

우선 순위란 문자 그대로 클라이언트가 선호하는 방식의 우선 순위를 서버에 알려주는 것이다.

Quality Values(q)라는 값을 사용하며 0~1까지 범위에서 높을수록 높은 우선 순위를 가지게 되며 생략하며 1의 값을 가지게 된다.

예를 들어서 위의 예제를 다시 생각해보자.

우리는 기본적으로 한국어를 지원 받는것을 원하지만 한국어를 지원하지 않는 경우 영어로 응답을 받고자 한다.

그럼 협상헤더는 다음과 같이 구성 될 수 있다.

GET /data
Accept-language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7

위 메시지를 살펴보면 총 4가지의 자연언어가 나열되어 있다.

가장 높은 순위는 ko-KR이며 생략 되어있기 때문에 1의 우선순위를 가진다.

다음은 ko이며 q=0.9이기 때문에 우선순위는 0.9이다.

다음은 en-US이며 0.8의 우선순위기 때문에 위의 자연언어가 없는 경우 다음 우선 순위를 가진다.

이런식으로 내가 선호하는 방식의 순위를 주어 서버에 요청 시 해당 언어가 없는 경우 다음 경우의 수를 가정할 수 있게 되는 것이다.

우선순위는 구체적인 것이 우선한다!

우선 순위는 q를 주는 것 외에도 구체적으로 적은 것을 우선한다는 특징이 있다.

예를 들어 Accept을 이용하여 텍스트 파일 방식을 요청한다고 가정해보자.

우리는 다음과 같은 4가지 방법을 협상 헤더를 통하여 요청하였다.

GET /data
Accept: text/*, text/plain, text/plain;format=flowed, */*

요청 메시지를 보면 4가지 방법이 나와있다.

이 중 구체적인 것이 우선한다는 이야기는 세밀하게 적은것이 우선된다는 이야기 이며 위의 메시지에서의 우선순위는 다음과 같다.

  1. text/plain;format=flowed
  2. text/plain
  3. text/*
  4. */*

또한 구체적인 것을 기준으로 미디어 타입을 맞추게 된다는 특징이 있다.


HTTP 일반 헤더의 전송방식

일반 헤더의 전송방식에는 크게 4가지로 분류 할 수 있다.

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

단순 전송은 컨텐츠의 길이를 알수 있는 경우에 사용된다.

예를 들어 우리가 요청을 통해 html을 응답 받는다고 할때, 이 html의 전체 길이를 서버가 알 수 있으므로 content-Length를 이용하여 컨텐츠의 길이를 주어 보내는 것이다.

그런데 이런 컨텐츠가 굉장히 큰 사이즈를 가진다고 생각해 보자.

이런 경우 당연히 그대로 보낼 순 없고 특정한 포맷으로 압축하여 보내야 할 것이다.

이럴 때 사용되는 것이 압축 전송이다.

압축 전송에서는 Content-Encoding 헤더 필드를 이용하여 어떤 방식으로 압축이 되어있는 지를 보내주어야 하며 단순 전송과 달리 컨텐츠의 길이를 몰라도 상관이 없다.

분할 전송은 Transfer-Encoding이라는 헤더 필드를 이용하여 여러 조각으로 분할하여 전송하는 형태를 말한다.

예를 들어 서버에 /data로 요청하여 다음과 같은 응답 메시지가 왔다고 생각해보자.

HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked

7
Flower
4
Good
0
/r/n

잘보면 바디 부분에 컨텐츠가 특정한 형태로 존재하는 것을 볼 수 있다.

길이 바이트 수와 컨텐트로 나뉘어져 있는데 마치 분할 된 것 같다고 하여 분할 전송이라고 부르는 것이다.

위의 메시지에서는 FlowerGood 이라는 메시지가 응답 된 것이며 분할 전송의 특징은 각각의 덩어리 마다 클라이언트가 미리 받아 볼 수 있다는 특징이 있다.

 

압축전송과 분할전송의 차이는 압축은 대용량을 한번에 받는 것이라면 분할은 여러번에 걸쳐 나누어 받는 것이다.

따라서, 분할은 모든 데이터가 다 도착하지 않아도 한 덩어리마다 미리 볼 수 있다는 특징이 있다.

또한, 분할의 경우 각각의 길이가 다 존재하기 때문에 Content-Length필드를 넣으면 안된다.

 

범위 전송은 Content-Range 필드를 이용하여 범위를 지정 할 수 있다.

범위 전송의 특징은 클라이언트에서 Range를 지정할 수 있는 것인데 이렇게 하면 특정 범위의 데이터만 요청하여 받을 수 있다.

예를 들어 0~2000 Bytes의 컨텐츠가 있다고 생각해보자.

우리가 응답메시지를 통해 받던 중 1000에서 에러가 나서 중간에 데이터 전송이 끊어졌다.

그럼 우리는 다음과 같은 요청 메시지를 통하여 우리가 받지 못한 이후 부분의 컨텐츠만 다운로드 요청을 할 수 있다.

GET /data
Range: bytes=1001-2000

위와 같은 요청 메시지를 받으면 서버에서는 1001부터 데이터를 보내게 될 것이다.

HTTP/1.1 200 OK
Content-Type: text/plain
Content-Range: bytes 1001-2000 / 2000

qlkewjivnoi1n23n12lnk23k4nk23sdmvposdvsd

이런 식으로 범위를 지정하여 보내는 방법을 범위 전송이라고 한다.

 

'HTTP' 카테고리의 다른 글

HTTP - HTTP 일반헤더와 쿠키  (0) 2024.04.30
HTTP - HTTP 일반 헤더(3)  (1) 2024.01.23
HTTP - HTTP 일반 헤더(1)  (0) 2024.01.19
HTTP - HTTP 상태코드 (2)  (0) 2024.01.17
HTTP - HTTP 상태코드 (1)  (1) 2024.01.16