HTTP 알아보기
지금 시대에는 인터넷을 사용하지 않는 사람이 없다고 해도 무방할정도로 전 세계의 많은 사람들이 인터넷을 이용해서 통신을 하고있다. 이 통신에서 사용되는 프로토콜중 하나가 바로 HTTP이다.
HTTP는 HyperTextTransferProtocol의 약자로서 단어그대로 HyperText(html, text 등)를 전송하는 프로토콜로 만들어졌었다. 그런데 지금은 모든 데이터(이미지, 음성, 영상, JSON, XML 등)를 HTTP를 이용해서 통신을 하고있다.
HTTP 버전
HTTP도 역사적으로 버전이 있는데
- HTTP 0.9
- HTTP 1.0
- HTTP 1.1
- HTTP 2
- HTTP 3
등의 버전이 현재까지 나와있다. 이 중에서 현재 가장 보편적으로 사용되고 있는것이 1.1버전이고 2와 3의 버전은 성능개선의 변화만 있을 뿐이다.
1.1버전에서 대부분의 스펙이 만들어졌고 일상적으로 이야기하는 HTTP는 대부분 1.1을 이야기하기때문에 1.1의 스펙들을 알고있으면 2와 3의 스펙도 이해하기 쉬울 것이다.
그렇다면 HTTP를 이용해서 어떻게 통신하는 것인가?
인터넷을 이용한 통신을 위해서는 기본적으로 '클라이언트' 와 '서버' 라는 개념이 존재한다.
클라이언트(사용자)가 서버(요청 받는 곳)로 요청을 보내면 서버는 받은 요청에 대한 응답을 해주는 방식으로 동작한다.
예전에는 클라이언트와 서버가 분리되지 않고 하나로 동작했었지만 이제는 클라이언트와 서버를 분리해서 역할을 나눠서 동작한다.
클라이언트는 PC, 안드로이드, IOS 등 다양한 형태가 될 수 있기 때문에 이 형태에 맞는 UI에 집중하기만 하면되고
서버는 비지니스로직과 같은 기능이 동작하는 부분에 집중해주면 될 것이다.
Stateful, Stateless
HTTP의 중요한 특징 중 하나로 무상태(Stateless)가 있다.
HTTP는 클라이언트의 상태를 지속적으로 가지고있거나 하지않거나를 선택해야한다.
지속적으로 가지고 있는 경우를 '상태 유지(Stateful)', 가지고 있지 않는 경우를 '무상태(Stateless)'라고 한다.
(1) 상태 유지(Stateful)
상태를 유지한다는 것은 하나의 서버가 특정 클라이언트의 정보를 모두 가지고 통신한다는 것이다. 그리고 통신의 내용들을 서버가 기억하고 있으므로 이후의 통신들도 서버가 기억하는 정보들을 이용해서 이루어진다.
이러한 경우 클라이언트는 계속해서 중복된 내용들을 보낼 필요가 없으니 통신 데이터도 적어지며 원할하게 통신이 된다는 장점이 있지만 갑작스럽게 서버에 장애가 생기거나 갑작스러운 트래픽 증가로 인한 서버 증설의 경우 대처가 불가능하다는 단점이 있다. 또한 계속해서 상태를 유지하기 때문에 서버의 자원도 계속해서 사용되어야 할 것이다.
(2) 무상태(Stateless)
무상태는 '상태 유지'와는 완전히 반대의 경우이다.
서버가 클라이언트의 상태를 소유하고 있지 않기 때문에 갑작스런 서버장애의 경우 다른 서버와의 연결로 해결될 수 있고, 트래픽 증가로 인한 서버의 증설도 부담없이 진행 할 수 있게된다. 하지만 클라이언트는 필요 시 같은 데이터를 여러번 보내야 할 필요가 생긴다는 단점도 존재한다.
웹 애플리케이션을 설계를 할 때는 최대한 무상태로 설계를 하지만 어쩔 수 없이 상태유지가 필요한 경우가 있다. 그렇기 때문에 상태유지는 최소화하고 최대한 무상태로의 설계를 해야한다.
비 연결성(Connectionless)
HTTP는 클라이언트와 서버를 계속해서 연결시켜놓지 않는다. 클라이언트가 요청할 때마다 서버와 연결하고 다시 연결을 끊는 방식으로 통신한다.
만약 클라이언트와 서버가 계속해서 연결되어 있다면 한 번 통신이 이뤄지고 긴 시간동안 통신이 이뤄지지 않는 클라이언트와도 계속해서 연결되어 있어야하기 때문에 서버의 자원이 많이 낭비되기 때문이다.
그런데 여기서 문제가 발생한다.
클라이언트가 서버와 연결하기 위해서는 TCP프로토콜을 사용해서 연결하는데 이 프로토콜은 연결방식으로 '3 way handshake'를 사용한다. 그렇다보니 연결을 위해 기본적으로 3번의 통신이 이루어져야 한다.
문제는 클라이언트가 요청을 위해서 서버에 요청하는 데이터가 적지 않다는 것이다. html, css, js, 이미지 등 수 많은 데이터들을 서버에서 받아야하는데 이 모든 요청을 하나받고 연결끊고 다시 연결하고 하나받고 연결끊고 다시 연결하고... 이런식으로 통신하면 낭비되는 시간이 생기는 것이다. 이 문제를 해결하기 위해서 '지속 연결(Persistent Connection)'을 사용한다.
지속연결은 특정시간동안 계속 연결해 놓는 상태이다. 보통은 60초로 설정되어있는데, 클라이언트와 서버가 연결된 후 60초동안 연결을 끊지 않고 계속해서 요청을 받는 방식이다. 이렇게하면 계속해서 연결해서 자원을 낭비하지도 않고 너무 잦은 연결로 인해 시간을 낭비하지도 않게 된다.
이러한 서버와의 연결과 HTTP를 이용한 통신은 매우 빠른 속도로 이루어진다. 그렇기 때문에 1000명이 사용하는 웹 페이지라고 하더라도 초 단위로 나눈다면 순간적으로 연결되있는 사용자는 많지 않을 것이다. 만약 1000명이 동시에 요청을 누른다면...
가끔 이루어지는 특정 이벤트(수강신청, 쿠폰이벤트 등)때는 정해진 시간에 수 많은 사람들이 동시에 접근하므로 이런 경우는 순간적으로 트래픽이 비약적으로 증가 할 수 있다. 이런경우를 조심하자..
HTTP 메세지
HTTP는 서버로 요청하는 메세지와 서버에서 응답받는 메세지가 비슷하지만 다른형태로 존재한다.
전체적인 구조는 같다.
- start-line(시작 라인)
- header(헤더)
- empty line(공백 라인)
- message body(메세지 본문)
구조는 같지만 들어가는 세부적인 내용들이 조금씩 다르다.
(1) 요청 메세지
- 시작라인 : HTTP메소드 + 요청 대상 + HTTP버전
- 헤더 : field-name + ":" + OWS + field-value + OWS
- 공백
- 본문 : 필요시 추가
OWS는 띄어쓰기를 해도되고 안해도 된다는 의미이다.
(2) 응답 메세지
- 시작라인 : HTTP버전+ HTTP상태코드+ 상태문구
- 헤더 : HTTP전송에 필요한 모든 부가정보(바디의 내용, 크기, 압축, 인증, 요청 클라이언트 등등)
- 공백
- 본문 : 실제 전송할 데이터(html, json, xml, text 등 byte로 표현할 수 있는 모든 데이터 전송 가능)
HTTP공식페이지에서 소개하는 표준헤더는 상당히 많이있고 필요시 직접 헤더를 만들 수도 있다.(ex. imsiheader : dev)