스프링 인프런 김영한

HTTP 헤더1 - 일반 헤더

25. HTTP 헤더1

일반 헤더
HTTP 헤더 개요
HTTP 헤더
header-field = field-name ":" OWS field-value OWS (OWS:띄어쓰기 허용)
field-name은 대소문자 구문 없다.

용도
HTTP 전송에 필요한 모든 부가정보를 담는다.
예) 메시지 바디의 내용, 메시지 바디의 크기, 압축, 인증, 요청 클라이언트, 서버 정보, 캐시 관리 정보...
표준 헤더가 굉장히 많다.
https://en.wikipedia.org/wiki/List_of_HTTP_header_fields

필요시 임의의 헤더 추가 가능하다
helloworld: hihi

분류
과거에는 4가지로 분류했다. RFC2616(과거)

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

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

그런데 표준이 변경되었다.
HTTP 표준
1999년 RFC2616 폐기되었다.
2014년 RFC7230~7235 등장

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

message body - RFC7230(최신)
메시지 본문(message body)을 통해 표현 데이터 전달한다.
메시지 본문 = 페이로드(payload) - post요청시 값이 있는곳
표현은 요청이나 응답에서 전달할 실제 데이터
표현 헤더는 표현 데이터를 해석할 수 있는 정보 제공
데이터 유형(html, json), 데이터 길이, 압축 정보 등등

참고
표현 헤더는 표현 메타데이터와 페이로드 메시지를 구분해야 하지만 여기서는 생략한다.

왜 표현이라하냐면 리소스를 html로 표현한 것이다.
실제 데이터에서 전송됫을때는 json으로 표현할 수도 있다.
그래서 표현이라는 의미가 생겨났다.

26. 표현

리소스를 html표현으로 전달할거야 json표현으로 전달할거야
이런것을 이해할 수 있도록 바꾼다의 의미를 가진다.

Content-Type: 표현 데이터의 형식
Content-Encoding: 표현 데이터의 압축 방식
Content-Language: 표현 데이터의 자연 언어(한국언지 영어인지 등)
Content-Length: 표현 데이터의 길이
표현 헤더는 전송 응답 둘다 사용한다.

26.1 Content-Type

컨텐트 바디에 들어가는게 무엇인가에 대한 내용이다.
표현 데이터의 형식 설명
미디어 타입, 문자 인코딩
예)
text/html; charset=utf-8
application/json
image/png

26.2 Content-Encoding

표현 데이터 인코딩
표현 데이터를 압축하기 위해 사용
데이터를 전달하는 곳에서 압축 후 인코딩 헤더 추가하면
데이터를 읽는 쪽에서 인코딩 헤더의 정보로 압축 해제한다.
예)
gzip
deflate
identity 등

26.3 Content-Language

표현 데이터의 자연 언어
표현 데이터의 자연 언어를 표현한다.
예)
ko
en
en-US
큰 공식사이트를 들어가면 영어 등으로 표현되는데 언어를 바꾸게 선택하는 등의 일을 할 수 있다.

Content-Length
표현 데이터의 길이
바이트 단위
Transfer-Encoding(전송 코딩)을 사용하면 Content-Length를 사용하면 안된다.

27. 콘텐츠 협상

협상(콘텐츠 네고시에이션)
처음 공부하면 이해가 안된다. 원리는 간단하다?
클라이언트와 서버가 있는데 클라이언트가 원하는 우선순위에 맞춰서 달라고 정하는 것이다.
json이 좋아 json으로 달라이런식으로 할 수 있다.
물론 서버가 못줄수도 있는데 서버가 최대한 노력을 해볼게 라는 것이다.

클라이언트가 선호하는 표현 요청
Accept: 클라이언트가 선호하는 미디어 타입 전달
Accept-Charset: 클라이언트가 선호하는 문자 인코딩
Accept-Encoding: 클라이언트가 선호하는 압축 인코딩
Accept-Language: 클라이언트가 선호하는 자연 언어
협상 헤더는 요청시에만 사용한다.

Accept-Language 적용 전
한국어 브라우저 사용시 서버는 정보가 없으니 기본값인 영어를 준다.
여기서 Accept-Language가 발동해서 선호하는게 한글이에요 해서 한글로 전달해준다.
작지만 헤더로 이런것을 처리하니 장점이 있다.

Accept-Language 복잡한 예시
한국어가 좋은데 한국어가 안되면 영어로 달라고 할 수 있다.

27.1 협상과 우선순위 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 (한국인이쓰는 한국어 q생략)
2.ko;q=0.9 (공통한국어)
3.en-US;q=0.8
4.en:q=0.7
등등
이런식으로 보내면 순서대로 우선순위 높은 것을 제공하게 된다.

27.2 협상과 우선순위 2

Quality Values(q)
구체적인 것이 우선된다.
Accept: text/, text/plain, text/plain;format=flowed, */
1.text/plain;format=flowed
2.text/plain
3.text/*
4./ 전부

27.3 협상과 우선순위3

Quality Values(q)
구체적인 것을 기준으로 미디어 타입을 맞춘다.
Accept: text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5

https://tools.ietf.org/html/rfc7231#section-5.3.2 참조하기

28. 전송 방식

Transfer-Encoding
Range, Content-Range
단순하게 4가지로 분류할 수 있다.
단순 전송
압축 전송
분할 전송
범위 전송

28.1 단순전송

Content-Length
요청을 하면 응답을 주는데 길이를 알 수 잇게 주는 것이다.

28.2 압축전송

Content-Encoding
gzip같은거로 용량을 줄여서 보낸다.
어떤 거로 압축했는지를 알려줘야 클라이언트가 받아서 볼 수 있다.

28.3 분할전송

서버에서 바이트를 만들어서 분할 해서 보낸다.
용량이 너무커서 한번에 보내면 기다려야하니 오는대로 표시할 수 있게 해준다.
분할 전송때는 Content-Length를 넣으면안된다.

28.4 범위 전송

Range, Content-Range
범위를 지정해서 보낼 수 있다.
이미지를 받다가 다시 처음부터 받으면 용량만 차지하니 나눠서 달라고 할 수 있다.

29. 일반정보

단순하게 정보성 헤더이다.

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

29.1 Form

유저 에이전트의 이메일 정보 등등
일반적으로 잘 사용되지 않고 검색엔진 곳에서 주로 사용한다.
요청에서 사용한다.

29.2 Referer

이건 많이 사용한다.
이전 웹 페이지 주소
현재 요청된 페이지의 이전 웹 페이지 주소
A -> B로 이동하는 경우 B를 요청할 때 Referer: A 를 포함해서 요청한다.
Referer를 사용해서 유입 경로 분석 가능하고 분석할때 사용한다.
요청에서 사용한다.

참고할 재밌는점 referer는 단어 referrer의 오타이다.

29.3 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

클라이언트의 애플리케이션 정보(웹 브라우저 정보, 등등)이다.
통계 정보 어느 브라우저에서 들어왔는지 등을 분석할 수 있다.
어떤 종류의 브라우저에서 장애가 발생하는지 파악 가능하다.
로그를 비교해봐서 어디서 문제가 발생했는지를 안다.
요청에서 사용한다.

29.4 Server

요청을 처리하는 ORIGIN 서버의 소프트웨어 정보이다.
사실 요청을 하면 여러 프록시 서버를 거치게 되는데 중간에 진짜 요청이 있는 마지막서버가 오리진서버이다.
Server: Apache/2.2.22 (Debian)
server: nginx
응답에서 사용한다.

29.5 Date

메시지가 발생한 날짜와 시간
Date: Tue, 15 Nov 1994 08:12:31 GMT
응답에서 사용한다.

30. 특별한 정보

Host: 요청한 호스트 정보(도메인) 진짜 중요하다.
Location: 페이지 리다이렉션
Allow: 허용 가능한 HTTP 메서드
Retry-After: 유저 에이전트가 다음 요청을 하기까지 기다려야 하는 시간

30.1 Host

요청한 호스트 정보(도메인)
진짜 중요하다.
요청에서 사용한다.
필수값이다.
하나의 서버가 여러 도메인을 처리해야 할 때 구분하기 위해 사용한다.
하나의 IP 주소에 여러 도메인이 적용되어 있을 때 사용한다.
도메인에서 어플리케션을 구분할때 사용한다.

30.2 Location

페이지 리다이렉션
웹 브라우저는 3xx 응답의 결과에 Location 헤더가 있으면 Location 위치로 자동 이동(리다이렉트)
응답코드 3xx에서 설명했엇다.
201 (Created): Location 값은 요청에 의해 생성된 리소스 URI
3xx (Redirection): Location 값은 요청을 자동으로 리디렉션하기 위한 대상 리소스를 가리킨다.

30.3 Allow

허용 가능한 HTTP 메서드
만약 url경로는 있는데 get head put만 제공하고 post를 제공안하면
405 (Method Not Allowed) 에서 응답에 포함해야한다.
Allow: GET, HEAD, PUT
실무에서는 잘 사용하지 않는다.

30.4 Retry-After

유저 에이전트가 다음 요청을 하기까지 기다려야 하는 시간이다.
503 (Service Unavailable): 서비스가 언제까지 불능인지 알려줄 수 있다.
Retry-After: Fri, 31 Dec 1999 23:59:59 GMT (날짜 표기)
Retry-After: 120 (초단위 표기)
실제 사용하기가 쉽지 않다.

31. 인증

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

인증마다 매커니즘이 달라서 이 헤더에 값을 넣는 방법이 다 다르다.

WWW-Authenticate
리소스 접근시 필요한 인증 방법 정의해준다.
이럴때 오류가 발생하는데 401 Unauthorized 응답과 함께 사용해야한다.
WWW-Authenticate: Newauth realm="apps", type=1, title="Login to "apps"", Basic realm="simple"

32. 쿠키

상당히 많이 사용하고 중요하다.
쿠키를 사용할때 두개의 헤드를 사용한다.
Set-Cookie: 서버에서 클라이언트로 쿠키 전달(응답)
Cookie: 클라이언트가 서버에서 받은 쿠키를 저장하고 HTTP 요청시 서버로 전달한다.

HTTP는 무상태(Stateless) 프로토콜이기 때문에
쿠키를 사용하지 않으면 모든 요청에 정보를 넘기는 문제가 발생한다.
모든 요청에 사용자 정보가 포함되도록 개발 해야한다.
브라우저를 완전히 종료하고 다시 열면 정보가 날라가게 된다.

모든 곳에 쿠키를 보내면 문제가 생기니 제약사항이있다.

예) set-cookie: sessionId=abcde1234; expires=Sat, 26-Dec-2020 00:00:00 GMT; path=/; domain=.google.com; Secure
주 사용처
-사용자 로그인 세션 관리
-광고 정보 트래킹
쿠키 정보는 항상 서버에 전송된다.
네트워크 트래픽 추가 유발시키기때문에 최소한의 정보만 사용(세션 id, 인증 토큰)한다.
서버에 전송하지 않고 웹 브라우저 내부에 데이터를 저장하고 싶으면 웹 스토리지 (localStorage, sessionStorage)에 추가해야한다.

주의!
보안에 민감한 데이터는 저장하면 안된다.(주민번호, 신용카드 번호 등등)

32.1 쿠키 - 생명주기

Expires, max-age
Set-Cookie: expires=Sat, 26-Dec-2020 04:39:21 GMT
만료일이 되면 쿠키 삭제된다.

Set-Cookie: max-age=3600 (3600초)
0이나 음수를 지정하면 쿠키 삭제

세션 쿠키: 만료 날짜를 생략하면 브라우저 종료시 까지만 유지
영속 쿠키: 만료 날짜를 입력하면 해당 날짜까지 유지

32.2 쿠키 - 도메인

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

32.3 쿠키 - 경로

Path
예) path=/home
이 경로를 포함한 하위 경로 페이지만 쿠키 접근
일반적으로 path=/ 루트로 지정
예)
path=/home 지정
/home -> 가능
/home/level1 -> 가능
/home/level1/level2 -> 가능
/hello -> 불가능

32.4 쿠키 - 보안

Secure, HttpOnly, SameSite
Secure
쿠키는 http, https를 구분하지 않고 전송한다.
Secure를 적용하면 https인 경우에만 전송한다.

HttpOnly
XSS 공격 방지
자바스크립트에서 접근 불가(document.cookie)
HTTP 전송에만 사용

SameSite
XSRF 공격 방지
요청 도메인과 쿠키에 설정된 도메인이 같은 경우만 쿠키 전송한다.

HTTP 헤더2 - 캐시와 조건부 요청

33. 캐시 기본 동작

33.1캐시가 미적용

첫 번째 요청시에 필요한 1.1M를 응답한다.
두번째 요청시에 또 필요한 용량만큼 응답한다.

데이터가 변경되지 않아도 계속 네트워크를 통해서 데이터를 다운로드 받아야 한다.
인터넷 네트워크는 매우 느리고 비싸다.
브라우저 로딩 속도가 느리다.
느린 사용자 경험을 일으킨다.

33.2 캐시 적용

cache-control: max-age=60에 캐시가 유효한 시간을 넣어줄 수 있다.
응답결과를 웹브라우저의 캐시저장소에 저장한다.
이러면 두번째 요청시 일단 캐시를 뒤져서 캐시에서 조회한다.

캐시 덕분에 캐시 가능 시간동안 네트워크를 사용하지 않아도 된다.
비싼 네트워크 사용량을 줄일 수 있다.
브라우저 로딩 속도가 매우 빠르다.
빠른 사용자 경험을 얻을 수 있다.

세 번째 요청
캐시 시간 초과되면 다시 요청을 해야한다.
기존 캐시를 지우고 다시 유효한 상태로 만든다.

캐시 유효 시간이 초과하면, 서버를 통해 데이터를 다시 조회하고, 캐시를 갱신한다.
이때 다시 네트워크 다운로드가 발생한다.

34.검증 헤더와 조건부 요청1

캐시가 시간초과되서 다시 받는다면
이미지가 새로운게 아니니 똑같다면 다시 받는게 손해같다.

캐시 유효 시간이 초과해서 서버에 다시 요청하면 다음 두 가지 상황이 나타난다.
1.서버에서 기존 데이터를 변경해서 새로운것을 줘야한다.
2.서버에서 기존 데이터를 변경하지 않아서 똑같은 것을 제공한다.

이것을 해결하는게 검증헤더와 조건부 요청이다.
캐시 만료후에도 서버에서 데이터를 변경하지 않는다.
생각해보면 데이터를 전송하는 대신에 저장해 두었던 캐시를 재사용 할 수 있다.
단 클라이언트의 데이터와 서버의 데이터가 같다는 사실을 확인할 수 있는 방법 필요하다.
그래서 검증헤더가 필요하다.

Last-Modified: 2020년 11월 10일 10:00:00를 추가해서 마지막으로 수정된 것을 넣어준다.

클라이언트가 최종 수정일을 보게 된다.
캐시에 최종수정일이 있다면 서버에서 요청을 일단 받고 수정되지 않았음을 알린다.
날짜를 보고 판단하고 httpbody를 붙이지 보낸다.
그래서 헤더만 응답해서 부하가 줄어든다.
캐시가 만료안됬다는 것을 보고 다시 캐시를 사용하도록 한다.

정리
검증헤더와 조건부 요청을 조합해서 사용한다.
캐시 유효 시간이 초과해도 서버의 데이터가 갱신되지 않으면
304 Not Modified + 헤더 메타 정보만 응답한다.(바디X)

클라이언트는 서버가 보낸 응답 헤더 정보로 캐시의 메타 정보를 갱신한다.
클라이언트는 캐시에 저장되어 있는 데이터 재활용한다.
결과적으로 네트워크 다운로드가 발생하지만 용량이 적은 헤더 정보만 다운로드 매우 실용적인 해결책이다.

웹브라우저들은 다 이 방식을 사용하고 있다.

35. 검증 헤더와 조건부 요청2

검증 헤더
캐시 데이터와 서버 데이터가 같은지 검증하는 데이터이다.
Last-Modified , ETag
검증할때 조건부 요청헤더를 만들어서 보내는것이다.

조건부 요청 헤더
검증 헤더로 조건에 따른 분기
If-Modified-Since: Last-Modified 사용
If-None-Match: ETag 사용
조건이 만족하면 200 OK
조건이 만족하지 않으면 304 Not Modified

35.1 If-Modified-Since

이후에 데이터가 수정되었는지 물어보는 것이다.
데이터 미변경 예시
캐시: 2020년 11월 10일 10:00:00 vs 서버: 2020년 11월 10일 10:00:00
304 Not Modified, 헤더 데이터만 전송(BODY 미포함)
전송 용량 0.1M (헤더 0.1M, 바디 1.0M)

데이터 변경 예시
캐시: 2020년 11월 10일 10:00:00 vs 서버: 2020년 11월 10일 11:00:00
200 OK, 모든 데이터 전송(BODY 포함)
전송 용량 1.1M (헤더 0.1M, 바디 1.0M)

Last-Modified, If-Modified-Since 단점
1초 미만(0.x초) 단위로 캐시 조정이 불가능하다.
날짜 기반의 로직 사용
데이터를 수정해서 날짜가 다르지만 같은 데이터를 수정해서 데이터 결과가 똑같은 경우
서버에서 별도의 캐시 로직을 관리하고 싶은 경우
예) 스페이스나 주석처럼 크게 영향이 없는 변경에서 캐시를 유지하고 싶은 경우

35.2 ETag, If-None-Match

ETag(Entity Tag)
캐시용 데이터에 임의의 고유한 버전 이름을 달아둔다.
예) ETag: "v1.0", ETag: "a2jiodwjekjl3"

데이터가 변경되면 이 이름을 바꾸어서 변경한다.(Hash를 다시 생성)
예) ETag: "aaaaa" -> ETag: "bbbbb"
진짜 단순하게 ETag만 보내서 같으면 유지 다르면 다시 받기를 할 수 있다.

ETag, If-None-Match 정리
진짜 단순하게 ETag만 서버에 보내서 같으면 유지, 다르면 다시 받기!
캐시 제어 로직을 서버에서 완전히 관리
클라이언트는 단순히 이 값을 서버에 제공(클라이언트는 캐시 메커니즘을 모름)
예)
서버는 배타 오픈 기간인 3일 동안 파일이 변경되어도 ETag를 동일하게 유지
애플리케이션 배포 주기에 맞추어 ETag 모두 갱신시키기

36. 캐시와 조건부 요청 헤더

캐시 제어 헤더
Cache-Control: 캐시 제어
Pragma: 캐시 제어(하위 호환)
Expires: 캐시 유효 기간(하위 호환)

다른것들은 하위호환이고 Cache-Control으로 다 제어할 수 있다.

36.1 Cache-Control

Cache-Control: max-age
캐시 유효 시간, 초 단위

Cache-Control: no-cache
데이터는 캐시해도 되지만 항상 원(origin) 서버에 검증하고 사용하기

Cache-Control: no-store
데이터에 민감한 정보가 있으므로 저장하면 안된다.
메모리에서 사용하고 최대한 빨리 삭제하게 한다.

36.2 Pragma

캐시 제어(하위 호환)
Pragma: no-cache
HTTP 1.0 하위 호환
거의 사용하지 않는데 하위호환때문에 사용하는 경우가 가끔있다.

36.3 Expires

캐시 만료일 지정(하위 호환)
expires: Mon, 01 Jan 1990 00:00:00 GMT
캐시 만료일을 정확한 날짜로 지정할 수 있다.
HTTP 1.0 부터 사용

초단위가 훨씬 유연하다.
지금은 더 유연한 Cache-Control: max-age 권장하고 있다.
Cache-Control: max-age와 함께 사용하면 Expires는 무시한다.

36.4 검증 헤더 (Validator)

ETag: "v1.0", ETag: "asid93jkrh2l"
Last-Modified: Thu, 04 Jun 2020 07:19:24 GMT

조건부 요청 헤더
If-Match, If-None-Match: ETag 값 사용
If-Modified-Since, If-Unmodified-Since: Last-Modified 값 사용

2023.05.31

헤더 부분에 대한 공부이다. 이것들을 직접 사용할지는 모르겠지만 직접 설정을 한적은 가끔씩 기억난다.
내용에 대해서 인지하고 필요할때 꺼내서 쓰는 것이 중요해보인다.

'기초단계 > SPRING' 카테고리의 다른 글

2023.05.29 Spring  (0) 2023.05.31
2023.05.27 Spring  (0) 2023.05.31
2023.05.24 Spring  (0) 2023.05.24
2023.05.22 Spring  (0) 2023.05.22
2023.05.20 Spring  (0) 2023.05.22

+ Recent posts