HTTP & HTTPS

HTTP

HTTP는 클라이언트 - 서버 모델을 따르는 프로토콜로 TCP/IP 위에서 동작하며 80번 포트를 사용하여 동작한다.

특징(HTTP/1.1 기준)

비연결 지향(Connectionless)

클라이언트가 서버에게 리소스를 요청한 후 응담을 받으면 연결을 끊어버리는 특징이다. 상당히 많은 클라이언트에게 요청을 받는 웹서버의 경우 연결을 유지하게 되면 서버에 많은 부담을 줄 수 있기 때문에 응답을 처리하면 연결을 끊는다.

단, 이로인해 리소스를 요청할 때마다 연결해야 하는 오버헤드 비용이 발생한다. 이를 해결하기 위해선, 요청 헤더에 Connection : keep-alive 속성으로 기존의 연결을 재사용하여 지속적 연결 상태를 유지할 수 있다. HTTP 1.1 부턴 지속적 연결 상태가 default이다!

무상태성 (Stateless)

각각의 요청이 독립적으로 여겨지는 특징으로, 서버는 클라이언트의 상태를 유지하지 않는다. 즉, 각 클라이언트에 맞게 리소스를 응답하는 것은 불가능하다. 이를 해결하기 위해, 쿠키나 세션 또는 토큰 방식의 OAuth 및 JWT가 사용된다.

Method

image

클라이언트가 서버에 요청하는 방법을 정의하는 것으로 주어진 리소스에 수행하길 원하는 행동을 나타낸다.

  • GET : 서버에게 조회할 리소스를 요청한다. (READ, 조회)
  • POST : 서버에게 본문(body)에 생성할 데이터를 삽입하여 전송한다. (CREATE, 생성)
  • PUT : 서버에게 본문에 수정할 데이터를 삽입하여 전송한다. (UPDATE, 수정)
  • DELETE : 서버에게 삭제할 리소스를 요청한다. (DELETE, 삭제)
  • PATCH : PUT과 비슷하지만 일부만 수정한다는 점에서 다르다.

응답 상태코드

2xx - 성공

200번대의 상태 코드는 대부분 성공을 의미한다.

  • 200 : GET 요청에 대한 성공
  • 204 : No Content. 성공했으나 응답 본문에 데이터가 없음
  • 205 : Reset Content. 성공했으나 클라이언트의 화면을 새로 고침하도록 권고
  • 206 : Partial Conent. 성공했으나 일부 범위의 데이터만 반환

3xx - 리다이렉션

300번대의 상태 코드는 대부분 클라이언트가 이전 주소로 데이터를 요청하여 서버에서 새 URL로 리다이렉트를 유도하는 경우이다.

  • 301 : Moved Permanently, 요청한 자원이 새 URL에 존재
  • 303 : See Other, 요청한 자원이 임시 주소에 존재
  • 304 : Not Modified, 요청한 자원이 변경되지 않았으므로 클라이언트에서 캐싱된 자원을 사용하도록 권고. ETag와 같은 정보를 활용하여 변경 여부를 확인

4xx - 클라이언트 에러

400번대의 상태 코드는 대부분 클라이언트의 코드가 잘못된 경우이다. 유효하지 않은 자원을 요청했거나 요청이나 권한이 잘못된 경우 발생한다.

  • 400 : Bad Request, 잘못된 요청
  • 401 : Unauthorized, 권한 없이 요청. Authorization 헤더가 잘못된 경우
  • 403 : Forbidden, 서버에서 해당 자원에 대해 접근 금지
  • 404 : Not Found, 요청한 자원이 서버에 없는 경우
  • 405 : Method Not Allowed, 허용되지 않은 요청 메서드
  • 409 : Conflict, 최신 자원이 아닌데 업데이트하는 경우. ex) 파일 업로드 시 버전 충돌

5xx - 서버 에러

500번대 상태 코드는 서버 쪽에서 오류가 난 경우이다.

헤더

요청/응답 헤더 및 본문 헤더 등 다양한 속성들이 있지만 여기선 주요한 속성들만 명시한다.

요청 헤더

  • Host : 서버의 도메인 이름과 TCP 포트번호 (표준 포트는 생략 가능)

    • Host: en.wikipedia.org:8080
  • Content-Type : POST/PUT 메서드를 사용할 때 본문의 타입

    • Content-Type: application/x-www-form-urlencoded
  • If-Modified-Since : 명시한 날짜 이후로 변경된 리소스만 획득

    • If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
  • Origin : 요청이 어느 도메인에서 왔는지 명시, 서버의 Access-Control-* 속성에 필요

    • Origin: http://www.example-social-network.com
  • Cookie : 서버의 Set-Cookie 로 설정된 쿠키 값

    • Cookie: $Version=1; Skin=new;

응답 헤더

  • Access-Control-* : CORS를 허용하기 위한 웹사이트 명시

    • Access-Control-Allow-Origin: *
  • Set-Cookie : 클라이언트에 쿠키 설정

    • Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1
  • Last-Modified : 요청한 리소스가 마지막으로 변경된 시각

    • Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT
  • Location : 3xx 상태 코드일 때, 리다이렉션 되는 주소

    • Location: http://www.w3.org/pub/WWW/People.html
  • Allow : 요청한 리소스에 대해 가능한 메서드들

    • Allow: GET, HEAD

HTTPS

image

HTTPS는 기존의 HTTP를 암호화한 프로토콜이다. 약어에서의 S가 원래 SSL (Secure Socket Layer)의 약자였지만 SSL 3.1버ㅜ터 TLS(Transport Layer Security)로 명칭이 바뀌고 TLS와 혼용하고 있다. TCP의 연결이 이루어진 후 TLS를 통해 암호화 설정이 되고 통신을 하는 방식이다.

암호화 방식

HTTPS의 암호화 원리는 공개키 암호화 방식이다. 핵심 원리는 암호화, 복호화시킬 수 있는 서로 다른 키2개가 존재하는데 이 두개의 키는 서로 1번키로 암호화하면 반드시 2번키로만 복호화할 수 있고 2번 키로 암호화하면 1번키로만 복호화할 수 있다.

이 중에서 하나의 키는 모두에게 공개하는 공개키(예시로 1번키)로 만들어서 공개키 저장소(CA)에 등록해놓는다. 서버는 서버만 알 수 있는 개인키(2번 키)를 소유하고 있으면 된다.

1번키로 암호화된 HTTP요청 즉, HTTPS 요청을 서버가 받으면 2번 키(개인키)를 이용하여 1번키로 암호화된 데이터를 해독한다. 서버는 요청이 무엇인지 알게되고 개인키로 암호화하여 클라이언트에 HTTPS요처을 한다. 클라이언트는 공개키를 이용해서 2번키로 암호화된 HTTPS 응답을 해독하고 사용하는 시나리오이다.

그런데..공개키는 누구나 얻을 수 있고 공개키를 알면 서버가 주는 데이터를 알수 있는데 보안상의 의미가 있나?

보안상의 의미는 없다. 단 해당 서버로부터 온 응답임을 확신할 수 있다. 왜냐하면 공개키로 해독이 가능했으니까 반드시 해당 서버의 개인키로 암호화했다는 것을 보장하기 때문이다.

어떻게 공개키를 가져올까?

세게적으로 신뢰할 수 있는 CA (공개키 저장소) 기업의 공개키는 브라우저가 이미 알고있다. 브라우저가 CA기업의 리스트를 쭉 탐색하면서 인증서에 적혀있는 해당 기업의 공개키를 알아서 가져온다. 만약 신뢰할 수 없는 CA의 공개키를 암호화해서 사용한다면 https지만 우리가 가끔 보는 “주의 요함”, “안전하지 않은 사이트” 등의 알림을 보게된다.


HTTP/2

이제까지 전통적인 웹 브라우저와 웹 서버와의 통신 프로토콜은 HTTP/1.1 기준으로 동작했는데, 많은 문제점들과 개선할 부분들이 있었기 때문에 2015년에 HTTP/2가 등장하게 되었다.

HTTP/1.1의 문제점

HTTP/1.1는 기본적으로 Connection당 하나의 요청을 처리 하도록 설계 되어있다. 동시전송이 불가능하고 요청과 응답이 순차적으로 처리된다.

HOLB(Head Of Line Blocking)

HTTP/1.1에 들어오면서 파이프라이닝 기법을 통해 하나의 커넥션에서 여러개의 요청을 보내 여러개의 응답을 받을 수 있었다. 하지만 먼저 보내진 요청에 대한 응답이 오래 걸리는 경우, 그 다음 응답까지의 시간이 지연되는 현상이 발생하였다. 이를 HOLB라고 한다. (큐 생각)

무겁고 중복 많은 헤더 구조 ( 특히 쿠키 때문에 )

요청을 할 때 요청 헤더에 메타정보를 넣어서 보내게 되는데, 매 요청마다 보내는 정보가 많아져서 헤더가 무거워지고 중복되는 데이터를 계속 보내게 되는 문제가 발생하였다.

HTTP/1.1의 눈물겨운 노력들

Image Spriting

웹페이지를 구성하는 다양한 아이콘 이미지를 하나의 이미지로 만들어 css로 좌표값을 구하여 표시..

Domain Sharding

요즘 브라우저들은 http/1.1 단점을 해결하기 위해 하나의 connection에 여러개의 요청을 병렬적으로 보내기도한다. 하지만 Domain당 컨넥션 개수의 제한이 존재하고 근본적인 해결책은 아니다.

Minify Css/Javascript

전송되는 데이터 용량을 줄이기 위해 CSS/JS의 코드의 크기를 줄여서 전송하기도 한다.

Data URI Scheme

HTML 문서내 이미지를 Base64로 직접 기술하여, 요청을 한번이라도 적게 보내려는 노력이다.

HTTP/2의 개선방법들

멀티 플렉싱(Multiplexing)과 스트리밍(Streaming)

HTTP/2에서 요청 데이터는 헤더와 본문으로 구성되는데 이를 각각 프레임(Frame)이라는 단위로 지정하고 스트림(Stream)이라는 연결단위를 통해 헤더 프레임 혹은 본문 프레임을 보낻록 그 방식을 바꿨다. 하나의 스트림은 요청/응답으로 구성되고 여러개의 스트림을 생성할 수 있다. ( 병렬적으로 처리가 가능하네~) 이것이 스트리밍을 통한 멀티플렉싱이다. 이를 통해 기존의 HTTP/1.1의 문제였던 HOLB을 해결할 수 있었다. 또한 요청한 리소스같의 우선순위를 결정하기 때문에 스트림별로 가중치가 매겨지고 브라우저가 리소스들을 수신하는 순서를 적절하게 결정한다.

서버 푸시(Server Push)

브라우저가 요청하지 않으면 서버는 응답하지 않는 것이 보통이지만, 요청한 HTML문서에 리소스가 포함되어 있는 경우 서버가 브라우저에게 (알아서) 밀어주는 방식을 취하여 브라우저의 요청을 최소화시킨다.

헤더 압축

헤더 테이블을 사용하여 이전 헤더 정보를 유지하고 허프만 인코딩 기법으로 헤더를 압축해서 전송하여 중복과 크기를 줄였다.

Reference

  1. https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/network/http.md
  2. https://joshua1988.github.io/web-development/http-part1/
  3. https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/network/https.md
  4. https://jeong-pro.tistory.com/89
  5. [https://www.popit.kr/%EB%82%98%EB%A7%8C-%EB%AA%A8%EB%A5%B4%EA%B3%A0-%EC%9E%88%EB%8D%98-http2/](

Written by@[HongDongUk]
공부한 것을 소소하게 적는 블로그.

GitHubFacebook