본문 바로가기

CS/네트워크

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

반응형

 

 

 

HTTP 헤더 개요

과거의 HTTP 헤더(RFC2616)

헤더 분류

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

HTTP Body

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

 

하지만,

  • 헤더에 User-Agent, Server 등 엔티티와 전혀 관련이 없는 정보들도 들어 있음.
  • 그래서 199년 RFC2616 폐기
  • 2014년 RFC7230~7235 로 HTTP 표준 스펙 변경
  • 변경되면서 엔티티 바디라는 개념이 사라짐

 

RFC723x 변화

  • 엔티티(Entity) ⇒ 표현(Representation)
  • Representation = Representation Metadata + Representation Data

HTTP Body

  • 표현: 요청이나 응답에서 전달할 실제 데이터
  • 표현 헤더: 표현 데이터를 해석할 수 있는 정보 제공
  • 메시지 본문을 통해 표현 데이터 전달함 (엔티티 본문 → 표현 데이터)
  • 메시지 본문 = 페이로드(payload)
    • 페이로드: 데이터를 전달하는 실제 데이터
  • 표현 헤더는 표현 메타데이터와 페이로드 메시지로 명확히 구분되어야 하나, 여기서는 생략함

 

왜 표현으로 바뀌었을까?

회원이라는 리소스가 실제 데이터로 전송될 때는 HTML, JSON, XML 등으로 전송이 될 수 있음.

그래서 실제 전달되는 데이터를 “표현”이라고 명확하게 용어를 정의함.

  • 리소스는 사실 추상적임
  • 클라이언트와 서버간에 리소스를 주고 받을 때, 서로간에 이해할 수 있는 뭔가로 변환을 해서 데이터를 전달함
  • 그래서 이 리소스들을 XML, HTML, JSON으로 표현함
💡 Representation에서의 R이 Restful API의 R과 동일함

 

 

표현

리소스들이 표현되는 정보들을 자세히 작성

  • 표현 헤더는 전송/응답 둘다 사용함

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를 사용하면 안됨(추후 설명 예정)

 

콘텐츠 협상(Content Negotiation)

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

 

협상과 우선순위(1) - Quality Values(q)

  • 0~1, 클수록 높은 우선순위를 가짐 (default: 1)
  • ex. Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
    • ko-KR;q=1 (q생략)
    • ko;q=0.9
    • en-US;q=0.8
    • en;q=0.7
  • 예시
    • 만약 응답에서 다중 언어 지원 서버를 하는데, 1순위:de, 2순위:en 이라면
    • 서버에서 헤더에 “Content-Language: en”를 담고, 영어 언어를 적용한 내용을 담아서 응답을 보냄

 

협상과 우선순위(2) - 구체적인 것을 우선적으로

  • Accept: text/*, text/plain, text/plain;format=flowed, /
    1. text/plain;format=flowed
    2. text/plain
    3. text/*
    4. */*

 

협상과 우선순위(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

 

 

전송 방식

단순 전송

  • 한 번에 요청하고, 한 번에 모든 응답을 받음
  • Content-Length가 가장 길다

 

압축 전송

  • Content-Encoding 필요
  • 한 번 요청하면, 압축 후 모든 응답을 받음
  • 단순 전송보다 Content-Length가 절반 이상 줄어듦

 

분할 전송

  • Transfer-Encoding 필요
  • Transfer-Encoding: chunked
    • 5byte 먼저 보낼 것, 내용은 Hello
    • 5byte 보낼 것, 내용은 World
    • 0byte 보낼 것, 종료
    • 내용이 너무 큰 경우, 기다릴 필요 없이 분할하여 전송. 오는대로 바로 표현 전송 가능
  • 5 Hello 5 World 0 /r/n
  • Content-Length를 넣으면 안됨 (예상할 수 없기 때문)

 

범위 전송(Range, Content-Range)

  • 클라이언트가 응답 받을 데이터의 범위를 지정하여 전송
  • ex
    • 클라이언트 - Range: bytes=1001-2000
    • 서버 - Content-Range: bytes 1001-2000 / 2000(끝길이)

 

일반 정보

From

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

  • 일반적으로 잘 사용X
  • 검색 엔진에서 주로 사용
    • 내 사이트 크롤링 되었을 때, 내 이메일 정보 넣음
  • 요청에서 사용

 

Referer

이전 웹 페이지 주소

  • A→B로 사이트 이동 시, B를 요청할 때 Referer: A를 포함하여 요청함
  • Referer를 사용하여 유입 경로 분석시 사용
  • 요청에서 사용함
  • (+) 참고: referer는 단어 referrer의 오타임. 근데 이미 HTTP에서 내버려서 변경 불가

 

User-Agent

유저 클라이언트의 애플리케이션 정보(웹 브라우저 정보 등)

  • 통계 정보 시 사용(어떤 브라우저에서 가장 많이 유입되는지)
  • 어떤 종류의 브라우저에서 장애가 발생하는지 파악 가능
  • 요청에서 사용함

 

Server

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

  • ORIGIN 서버
    • 내 표현을 만들어준 진짜 서버
    • HTTP는 중간에 여러 프록시 서버들을 거치게 되는데, 이러한 프록시 서버들을 거치기 전, 실제 내 진짜 서버를 말함
  • Server: Apache/2.2.22 (Debian)
  • server: nginx
  • 응답에서 사용함

 

Date

메시지가 발생한 날짜와 시간

  • 응답에서 사용함
    • 과거에는 요청에서도 사용됐지만, 최근에는 응답에서만 사용함

 

특별한 정보

Host

요청한 호스트 정보(도메인)

  • 요청에서 사용
  • 필수 헤더임!
  • 하나의 서버가 여러 도메인을 처리해야할 경우 / 하나의 IP 주소에 여러 도메인이 적용되어 있을 경우
    • 헤더 필드에 호스트 넣기 전
      • 하나의 서버 IP: 200.200.200.2 안에, 여러 개의 애플리케이션이 실제 다른 도메인으로 구동되어 있을 수 있음
      • 만약 클라이언트 IP:100.100.100.1에서 GET /hello HTTP/1.1 요청을 보냄. 서버는 해당 요청이 어느 애플리케이션에 들어가야할지 구분하지 못함. 왜냐하면 IP로만 통신하기 때문. (aaa.com, bbb.com, ccc.com 중 어느 도메인으로 해당 요청이 들어가야할까?)
    • 헤더 필드에 호스트 넣은 후
      • 클라이언트에서 헤더에 Host: aaa.com을 넣어 보내므로, 서버에서는 해당 애플리케이션에 요청을 받음.
      • 이를 “가상 호스팅”이라고 함

 

Location

페이지 리다이렉션

  • 응답코드 3xx 참고
  • 201 (Created): Location 값은 요청에 의해 생성된 리소스 URI
  • 3xx (Redirection): Location 값은 요청을 자동으로 리다이렉션하기 위한 대상 리소스를 가리킴

 

Allow

허용 가능한 HTTP 메서드

  • 응답에 405(Method Not Allowed)를 포함해야 함
    • ex. Allow: GET, HEAD, PUT
  • 하지만 실제로는 서버에 많이 구현되어 있진 않음. 그냥 참고용으로만 알고 있자.

 

Retry-After

유저 에이전트가 다음 요청을 하기까지 기다려야 하는 시간

  • 503(Service Unavailable): 서비스가 언제까지 불능인지 알려줘야 함
  • [날짜 표기] Retry-After: Fri, 31 Dec 1999 23:59:59 GMT
  • [초단위 표기] Retry-After: 120
  • 하지만 실제로는 사용하기가 쉽진 않음

 

 

인증

Authorization

클라이언트 인증 정보를 서버에 전달

  • 인증하는 메커니즘이 여러 가지 있는데(ex. OAuth, …) 각각 이 Authorization에 들어가야하는 value가 다름
  • 어떤 인증 메커니즘인지에 상관없이 헤더는 무조건 제공함. 여기에 인증과 관련된 value를 작성함

 

WWW-Autenticate

리소스 접근 시 필요한 인증 방법 정의

  • 401 Unauthorized 응답과 함께 사용
  • 인증하려면 이러한 정보를 참고하여 제대로된 인증을 만들라고 지시해주는 것
  • WWW-Authenticate: Newauth realm=”apps”, type=1, title=”Login to \”apps\””, Basic realm=”simple”

 

 

쿠키

쿠키를 사용할 땐 아래 두 개의 헤더를 사용함

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

 

쿠키 미사용 시

로그인

  • 클라이언트에서 user에 대한 정보를 넘긴 후, 동일한 페이지에 재접근하게 되면 서버는 user에 대한 정보가 없음
  • HTTP는 무상태(Stateless) 프로토콜이다!
    • 클라이언트와 서버가 요청과 응답을 주고 받으면 (Connection으로 인해 어느정도 연결하고 있긴 하지만, 모든 응답을 주고 받으면) 연결이 끊어짐
    • 클라이언트가 다시 요청하면 서버는 이전 요청을 기억 못함
    • 클라이언트와 서버는 서로의 상태를 유지하지 않음

 

대안 - 모든 요청에 사용자 정보 포함

  • 쿼리 파라미터에 사용자 정보를 항상 포함
  • 하지만 문제가 있음
    • 개발자가 모든 요청에 사용자 정보를 항상 포함하도록 개발 해야 함
    • 보안 문제
    • 브라우저를 완전히 종료하고 다시 열면 정보 없음 (web storage로 개발 구현은 가능하지만.. 할 때마다 다 넘기기 힘들다)

 

쿠키

1) 로그인

  1. 서버가 헤더에 Set-Cookie: user=홍길동 을 생성함
  2. 서버는 세션 키: 세션ID(ex.user=홍길동)를 생성하여 DB에 저장함
    1. 보안상의 문제로 인해
  3. 서버는 세션 ID를 클라이언트에게 반환함
  4. 클라이언트는 응답을 받고 쿠키 저장소에 user=홍길동 정보를 저장함

2) 로그인 이후 welcome 페이지 접근

  1. 웹 브라우저가 쿠키 저장소에서 user=홍길동을 조회함
  2. 클라이언트가 서버에게 요청의 헤더에 쿠키에 세션ID를 담아서 보냄
  3. 서버가 클라이언트에게 받은 요청의 Cookie의 세션ID를 통해 유저의 정보를 알아냄

3) 쿠키는 모든 요청에 쿠키 정보를 자동으로 포함함

웹브라우저가 어느 페이지로 보내든, 지정한 페이지에는 자동으로 모든 요청에 쿠키를 자동으로 담아서 보내게 됨

 

쿠키의 제약 방식

하지만, 모든 요청에 쿠키를 보내게 되면 보안상 문제가 있다. 그래서 제약하는 방법이 있음.

  • set-cookie: sessionId=abcde1234; expires=Sat, 26-Dec-2020 00:00:00 GMT; path=/; domain=.google.com; Secure
    • sessionId
    • expires: 쿠키가 만료되는 시간
    • path: 허용되는 경로
    • domain: 허용되는 경로
    • Secure: 보안

쿠키의 사용처

  • 사용자 로그인 세션 관리
  • 광고 정보 트레킹
    • 해당 웹브라우저를 사용하는 사람들이 이런 광고들을 주로 보는 구나!

쿠키 정보는 항상 서버에 저장됨

  • 네트워크 트래픽 추가 유발
    • 몇 가지 정보가 더 추가적으로 계속 추가되어 전송하게 되므로
    • 따라서 최소한의 정보만 사용해야만 함 (ex. 로그인 -세션 ID, oAuth-인증 토큰, …)
    • 서버에 전송하지 않고, 웹 브라우저 내부에 데이터를 저장하고 가지고 있고 필요할 때마다만 클라이언트에서 서버에게 보내고 싶다면, 웹 스토리지(localStorage, sessionStorage)를 이용함

주의!

  • 보안에 민감한 데이터는 저장하면 안됨 (ex. 주민번호, 신용카드 번호 등)

 

쿠키 - 생명 주기 (Expires, max-age)

  • expires: 만료일이 되면 쿠키 삭제(GMT기준 작성)
  • max-age: 초 단위로 입력함. 0 혹은 음수를 지정하면 쿠키가 삭제됨
  • 세션 쿠키: 만료 날짜를 생략하면 브라우저 종료시까지만 유지
    • 그래서 브라우저 종료하고 로그인을 다시 해야하는 사이트는 세션 쿠키를 사용하고 있다고 생각하면 됨
  • 영속 쿠키: 만료 날짜를 입력하면 해당 날짜까지 유지

 

쿠키- 도메인 (Domain)

  • 명시: 명시한 문서 기준 도메인 + 서브 도메인 포함 모두 쿠키 전송
    • domain=example.org를 지정해서 쿠키 생성한다면,
      • example.org는 물론이고
      • dev.example.org도 쿠키 접근 가능
  • 생략: 현재 문서 기준 도메인만 적용
    • example.org에서 쿠키를 생성하고 domain 지정을 생략함
      • example.org에서만 쿠키 접근 가능
      • dev.example.org는 쿠키 접근 불가능

 

쿠키 - 경로

  • ex) path=/home
  • 이 경로를 포함한 하위 경로 페이지만 쿠키 접근 가능
  • 일반적으로 path=/ 루트로 지정
  • ex
    • path=/home 지정
    • /home → 쿠키 전송 O
    • /home/level1 → 쿠키 전송 O
    • /home/level1/level2 → 쿠키 전송 O
    • /hello → 쿠키 전송 X

 

쿠키 - 보안 (Secure, HttpOnly, SameSite)

Secure

  • 쿠키는 http, https를 구분 않고 모두 전송함
  • Secure를 적용하면 https인 경우만 전송함

HttpOnly

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

SameSite

  • XSRF 공격 방지
  • 요청 도메인과 쿠키에 설정된 도메인이 같은 경우에만 쿠키 전송 가능함
  • 기능이 적용된지 얼마 되지 않았으므로, 지원되는 브라우저를 확인 후 적용하는 것이 좋음
반응형