HTTP - "모든 개발자를 위한 HTTP 웹 기본 지식" 정리노트 - 4

송준섭 Junseop Song·2023년 6월 30일
0

네트워크

목록 보기
4/6
post-thumbnail

⛳️ 목적

이 글은 김영한님의 인프런 강의 '모든 개발자를 위한 HTTP 웹 기본 지식' 강의를 듣고 배운 것을 두고두고 보기 위해 정리하는 글이다.


🗓️ 2023.06.30 작성 ▽

⑦ HTTP 헤더2 - 일반 헤더

📌 HTTP 헤더 개요

❗️ HTTP 헤더
header-field = field-name ":" OWS field-value OWS (OWS: 띄어쓰기 허용)
field-name은 대소문자 구분 X

❗️ HTTP 헤더 용도
HTTP 전송에 필요한 모든 부가정보
ex) 메시지 바디의 내용, 메시지 바디의 크기, 압축, 인증, 요청 클라이언트, 서버 정보, 캐시 관리 정보, ,,,
표준 헤어가 많고 필요시 임의의 헤더 추가가 가능

❗️ HTTP 헤더 분류

RFC2616(과거) 헤더 분류

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

message body - RFC2616(과거)

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

그러나 HTTP 표준에서 RFC2616(1999년)이 폐기되고 RFC7230~7235(2014년)이 등장함

📌 RFC723x

❗️ RFC723x

변화

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

message body - RFC7230(최신)

  • 메세지 본문(message body)를 통해 표현 데이터 전달
  • 메세지 본문 = 페이로드(payload)
  • 표현은 요청이나 응답에서 전달할 실제 데이터
  • 표현 헤더표현 데이터를 해석할 수 있는 정보 제공
    • 데이터 유형(html, json), 데이터 길이, 압축 정보 등

❗️ 표현

표현 헤더는 전송, 응답 둘다 사용

  • Content-Type
    표현 데이터의 형식
    미디어 타입, 문자 인코딩
    ex) text/html; charset=utf-8, application/json, image/png, ,,,

  • Content-Encoding
    표현 데이터의 압축 방식
    표현 데이터를 압축하기 위해 사용
    데이터를 전달하는 곳에서 압축 후 인코딩 헤더 추가
    데이터를 읽는 쪽에서 인코딩 헤더의 정보로 압축 해제
    ex) gzip, deflate, identity, ,,,

  • Content-Language
    표현 데이터의 자연 언어
    ex) ko, en, en-US, ,,,

  • Content-Length
    표현 데이터의 길이
    바이트 단위
    Transfer-Encoding(전송 코딩)을 사용하면 Content-Length는 사용 X

❗️ 협상(콘텐츠 네고시에이션)

클라이언트가 선호하는 표현 요청
요청시에만 사용

  • Accept
    클라이언트가 선호하는 미디어 타입 전달
    • Accept: text/*, text/plain, text/plain;foramt=followed, ,,,
      위와 같이 우선 순위를 정할 수 있음
      구체적인 것이 우선 (1등 text/plain;format=flowed, 2등 text/plain, ,,,)
    • 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-Charset
    클라이언트가 선호하는 문자 인코딩

  • Accept-Encoding
    클라이언트가 선호하는 압축 인코딩

  • Accept-Language
    클라이언트가 선호하는 자연 언어
    한국어 브라우저를 사용한다면 기본 언어가 한국어가 아닌 서버에서도 한국어를 지원하는 서버라면 Accept-Language: ko로 한국어 언어 지원을 받을 수 있음
    만약 한국어를 지원하지 않는 서버라면 서버의 기본 언어로 응답

    • Accept-Language:ko-KR,ko;q=0.9,en-US;q=0.8, ,,,
      위와 같이 q값을 이용해 우선 순위를 설정하는 것도 가능(0~1의 값)

🗓️ 2023.07.04 작성 ▽

📌 전송 방식

  • 단순 전송(Content-Length)
  • 압축 전송(Content-Encoding)
  • 분할 전송(Transfer-Encoding)
  • 범위 전송(Range, Content-Range)

📌 일반 정보

  • Form
    유저 에이전트의 이메일 정보
    일반적으로 잘 사용되지 않음
    검색 엔진 같은 곳에서 주로 사용
    요청에서 사용
  • Referer
    현재 요청된 페이지의 이전 웹 페이지 주소
    A->B로 이동하는 경우 B를 요청할 때 Referer:A를 포함해서 요청
    유입 경로 분석 가능
    요청에서 사용
    사실 Referrer의 오타임(굳어져서 그대로 사용)
  • User-Agent
    유저 에이전트(클라이언트) 애플리케이션 정보(웹 브라우저 정보 등)
    통계 정보
    어떤 종류의 브라우저에서 장애가 발생하는지 파악 가능
    요청에서 사용
    ex) 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 서버의 소프트웨어 정보
    응답에서 사용
    ex) Server: Apache/2.2.22 (Debian), server: nginx
  • Date
    메시지가 발생한 날짜와 시간
    응답에서 사용
    ex) Date: Tue, 15 Nov 1994 08:12:31 GMT

📌 특별한 정보

  • Host
    요청한 호스트 정보(도메인)
    필수 정보
    하나의 서버가 여러 도메인을 처리해야 할 때
    하나의 IP 주소에 여러 도메인이 적용되어 있을 때
    요청에서 사용
    ex) 200.200.200.2 IP에 aaa.com, bbb.com, ccc.com 도메인이 적용되어 있을 때 어디로 가는가? -> 요청 메시지에 Host: aaa.com가 있다면 결정 가능
  • Location
    페이지 리다이렉션
    3xx 응답의 결과에 Location 헤더가 있으면 Location 위치로 자동 이동(리다이렉트)
    201 (Created)에서의 Location 값은 요청에 의해 생성된 리소스 URI
    3xx (Redirection)에서의 Location 값은 요청을 자동으로 리디렉션하기 위한 대상 리소스
  • Allow
    허용 가능한 HTTP 메서드
    405 (Method Note Allowed)에서 응답에 포함해야함
    ex) Allow: GET, HEAD, PUT
  • Retry-After
    유저 에이전트가 다음 요청을 하기까지 기다려야 하는 시간
    503 (Service Unavailable)에서 서비스가 언제까지 불능인지 알려줄 수 있음
    ex) Retry-After: Fri, 31 Dec 1999 23:59:59 GMT (날짜로 표기하는 방법), Retry-After: 120 (초단위로 표기하는 방법)

📌 인증

  • Authorization
    클라이언트 인증 정보를 서버에 전달
    ex) Authorization: Basic xxxxxxxxxxxxxxxx
  • WWW-Authenticate
    리소스 접근시 필요한 인증 방법 정의
    401 Unauthorized 응답과 함께 사용
    ex) WWW-Authenticate: Newauth realm="apps", type=1, title="Login to \"apps\"", Basic realm="simple"

📌 쿠키

  • Set-Cookie
    서버에서 클라이언트로 쿠키 전달(응답)
  • Cookie
    클라이언트가 서버에서 받은 쿠키를 저장하고, HTTP 요청시 서버로 전달

HTTP는 무상태 프로토콜
클라이언트와 서버가 요청과 응답을 주고 받은 후에는 연결이 귾김
클라이언트가 다시 요청을 해도 서버는 이전 요청을 기억하지 못함
-> 로그인을 했어도 항상 다시 로그인?

쿠키 미사용 예로, 로그인을 해도 로그인을 하지 않은 것과 같은 응답을 받음
이 대안으로는 모든 요청에 사용자 정보를 포함하는 것이 있음
ex) GET /welcome?user=홍길동 HTTP/1.1

그러나 이와 같은 대안은 모든 요청에 민감한 정보인 사용자 정보가 포함되도록 개발해야한다는 단점이 있음
또한 브라우저를 완전히 종료하고 다시 연다면 초기화 됨

쿠키는 브라우저의 쿠키 저장소에 저장됨
사용자가 로그인을 한다면 응답 메시지에 "Set-Cookie: user=홍길동"과 같은 메시지를 포함하여 쿠키를 저장할 수 있음
쿠키가 저장된 이후부터는 쿠키 저장소에서 조회된 사용자 정보로 로그인을 한 서비스를 받을 수 있음
보안에 민감한 데이터는 저장하면 안됨
모든 요청에는 쿠키 정보가 자동으로 포함 됨("Cookie: user=홍길동")
-> 최소한의 정보만 사용하여 네트워크 트래픽 최소화

  • 쿠키 생명주기
    Expires, max-age를 이용해 쿠키의 생명주기를 정해줄 수 있음
    ex) Set-Cookie: expires=Sat, 26-Dec-2020 04:39:21 GMT(만료되면 쿠키 삭제), Set-Cookie: max-age=3600(3600초 후 쿠키 삭제, 값에 0이나 음수를 지정하면 쿠키 삭제)
    세션 쿠키: 만료 날짜를 생략하면 브라우저 종료시 까지만 유지
    영속 쿠키: 만료 날짜를 입력하면 해당 날짜까지 유지

  • domain
    쿠키가 사용될 도메인을 지정
    domain=example.org라면 dev.example.org도 쿠키 접근 가능
    example.org에서 domain지정을 하지 않고 쿠키를 생성한다면 dev.example.org에서는 접근 불가

  • path
    경로 지정
    path=/home을 지정한다면 /home/level1, /home/level1/level2 등 하위 경로 페이지 쿠키 접근 가능
    /hello -> 불가능
    일반적으로 path=/ 처럼 루트로 지정

  • 보안
    Secure: 적용하면 https인 경우만 전송(원래 http, https 구분 X)
    HttpOnly: XSS 공격 방지, 자바스크립트에서 접근 불가(document.cookie). HTTP 전송에만 사용
    SameSite: XSRF 공격 방지, 요청 도메인과 쿠키에 설정된 도메인이 같은 경우만 쿠키 전송



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

📌 캐시 기본 동작

❗️ 캐시가 없을 때

캐시가 없다면 어떠한 파일을 요청했을 때 서버에서 항상 파일을 내려줌

단점

  • 데이터가 변경되지 않아도 게속 네트워크를 통해서 데이터를 다운로드 받아야 함
  • 인터넷 네트워크는 매우 느리고 비쌈
  • 브라우저 로딩 속도가 느림
  • 느린 사용자 경험

❗️ 캐시 적용

max-age값(초단위)동안 다시 요청이 들어온다면 파일을 내려주지 않고 브라우저 캐시에서 그대로 파일을 가져옴

장점

  • 캐시 가능 시간동안 네트워크를 사용하지 않아도 됨
  • 비싼 네트워크 사용량을 줄일 수 있음
  • 브라우저 로딩 속도가 매우 빠름
  • 빠른 사용자 경험

캐시 시간이 초과한 경우 서버에서 다시 파일을 내려주고 max-age값이 다시 초기화됨


📌 검증 헤더와 조건부 요청 1

❗️ 캐시 시간 초과

캐시 유효 시간이 초과해서 서버에 다시 요청하면 다음 두 가지 상황이 나타남

  1. 캐시 유효 시간 사이에 서버 기존 데이터가 변경됨
  2. 서버에서 기존 데이터를 변경하지 않음

1번의 경우(캐시 만료후에도 서버에서 데이터를 변경하지 않은 경우) 데이터를 전송하는 대신 저장해 두었던 캐시를 재사용
이 경우 클라이언트의 데이터와 서버의 데이터가 같다는 사실을 확인할 수 있는 방법이 필요
-> 검증 헤더 추가

❗️ 검증 헤더 추가

Last-Modified 헤더로 마지막으로 데이터가 수정된 시간을 받아올 수 있음

첫 번째 요청시 파일을 내려받음과 동시에 Last-Modified 값을 받음
캐시 시간이 초과되지 않으면 브라우저 캐시에서 파일을 가져오고, 아니면 서버에 요청
이때 if-modified-since 헤더로 만약 최종 수정일이 같다면(데이터가 수정되지 않았다면) 서버에서 304 Not Modified를 반환
이때 HTTP Body(파일 값)은 없기 때문에 파일의 용량만큼 절약이 됨

이때 다시 캐시 유효 시간이 초기화 됨

❗️ 정리

  • 캐시가 있다면 네트워크 통신 비용을 줄일 수 있음
  • 캐시 유효 시간이 초과하지 않는다면 브라우저 캐시에 저장되어 있는 데이터를 재활용
  • 캐시 유효 시간이 초과해도, 서버의 데이터가 갱신되지 않으면 304 Not Modified + 헤더 메타 정보만 응답함(HTTP Body 포함 X)
  • 클라이언트는 서버가 보낸 응답 헤더 정보로 캐시의 메타 정보를 갱신(캐시 유효 시간 등)

📌 검증 헤더와 조건부 요청 2

❗️ 검증 헤더

캐시 데이터와 서버 데이터가 같은지 검증하는 데이터
ex) Last-Modified, ETag

❗️ 조건부 요청 헤더

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

❗️ Last-Modified, If-Modified-Since 단점

  • 1초 미만(0.x초) 단위로 캐시 조정 불가능
  • 날짜 기반의 로직 사용
  • 데이터를 수정했지만 결과가 똑같은 경우 수정 날짜가 달라져 다시 다운로드
  • 서버에서 별도의 캐시 로직을 관리하고 싶은 경우
    • ex) 스페이스나 주석처럼 크게 영향이 없는 변경에서는 캐시를 유지하고 싶은 경우

❗️ ETag(Entity Tag), If-None-Match

ETag는 캐시용 데이터에 임의의 고유한 버전 이름을 달아둔 것
ex) ETag: "v1.0", ETag: "a2jiodwjekjl3"
데이터가 변경되면 ETag는 바뀜(Hash를 다시 생성)
ex) ETag: "aaaaa" -> Etag: "bbbbb"
단순히 ETag가 만 보내서 같으면 유지, 다르면 다시 다운로드
같다면 응답 메시지에 HTTP Body가 없고 304 Not Modified

캐시 제어 로직을 서버에서 완전히 관리함
클라이언트는 단순히 이 값을 서버에 제공(클라이언트는 서버 캐시 메커니즘을 모름)
ex) 서버는 베타 오픈 기간인 3일 동안 파일이 변경되어도 ETag를 동일하게 유지, 애플리케이션 배포 주기에 맞춰 ETag 모두 갱신


📌 캐시와 조건부 요청 헤더

❗️ 캐시 제어 헤더

  • Cache-Controle
    캐시 지시어(directives)
    Cache-Control: max-age: 캐시 유효 시간, 초 단위
    Cache-Control: no-cache: 데이터는 캐시해도 되지만, 항상 원(origin) 서버에 검증하고 사용
    Cache-Control: no-store: 데이터에 민감한 정보가 있어 저장하면 안됨(메모리에서 사용하고 최대한 빨리 삭제)

  • Pragma
    캐시 제어(하위 호환)
    이제는 대부분 쓰이지 않음
    PRAGMA: no-cach: HTTP 1.0 이하에서 사용

  • Expires
    캐시 만료일 지정(하위 호환)
    캐시 만료일을 정화한 날짜로 지정
    HTTP 1.0 부터 사용
    지금은 더 유연한 Cache-Control: max-age 권장(함께 사용하면 Expires가 무시됨)
    expires: Mon, 01 Jan 1990 00:00:00 GMT

❗️ 검증 헤더와 조건부 요청 헤더

  • 검증 헤더 (Validator)
    ETag: "v1.0", ETag: "asdid93jad"
    Last-Modified: Thu, 04 Jun 2020 07:19:24 GMT

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


📌 프록시 캐시

미국에 있는 원 서버(Origin 서버)에 항상 직접 접근한다고 가정
네트워크 통신 비용이 높음

그러나 한국 어딘가에 프록시 캐시 서버가 있다면?
첫 요청에 원 서버에서 프록시 캐시 서버로 데이터가 보내지고 프록시 캐시 서버에서 개인 웹 브라우저 데이터가 보내짐
처음에는 같은 비용이 발생하지만 프록시 캐시 서버에 캐시가 존재한다면 원 서버에 직접 통신을 했을 때보다 비용이 매우 낮아짐
프록시 캐시 서버의 캐시를 public 캐시, 개인 웹 브라우저의 캐시를 private 캐시라고 함

Cache-Controle: public: 응답이 public 캐시에 저장되어도 됨
Cache-Controle: private: 응답이 해당 사용자만을 위한 것임, private 캐시에 저장해야 함(기본값)
Cache-Controle: s-maxage: 프록시 캐시에만 적용되는 max-age
Age: 60 (HTTP 헤더): 오리진 서버에서 응답 후 프록시 캐시 내에 머문 시간(초)


📌 캐시 무효화

확실한 캐시 무효화

위에서 설명한 Cache-Control: no-cache, Cache-Control: no-store, Pragma: no-cache도 캐시 무효화 옵션

Cache-Control: must-revalidate 옵션은 캐시 만료 후 최초 조회시 원 서버에 검증해야하고 원 서버 접근 실패시 반드시 오류가 발생해야 함 (504 Gateway Timeout)
또한 캐시 유효 시간이라면 캐시를 사용함

  • no-cache 기본 동작

  • must-revalidate 기본 동작



📚 마무리

여기까지 김영한님의 이번 강의는 마무리가 되었다.
웹 개발자라면 기본적으로 알아야할 HTTP 지식들을 정말 접근하기 좋게 알려주신 것 같다.
김영한님은 개발계의 현우진이라는 말이 있다.
강의를 들으면 들을수록 그 말이 정말 공감이 되고 항상 감사한 마음이 든다.
모두 김영한님 강의 들으세요~~~
얻는 것에 비하면 진짜 가격도 싸다고 느껴집니다!!!!

이 다음부터는 고재성님, 이상훈님이 저자이신 "IT 엔지니어를 위한 네트워크 입문" 책을 읽을 예정이다.
이 또한 공부하면서 블로그에 정리노트를 포스팅 할 예정이다!

0개의 댓글

관련 채용 정보