드디어 http이다. 웹 통신에서 가장 중요한 http에 대해서 알아보자.
HTTP는 HTML(HyperText Markup Language) 문서를 교환하기 위해 만들어진 프로토콜이다. HTTP를 사용하여 통신을 하는 경우 반드시 한 쪽은 클라이언트 한 쪽은 서버가 된다. 일반적으로 클라이언트는 프론트엔드, 서버는 백엔드라고 칭한다.
이렇게 과거에는 HTML 문서를 전송하기 위한 프로토콜로서 만들어졌었지만 현재는 HTML을 포함하여 일반적인 TEXT, IMAGE, 음성, 영상, 파일, JSON, XML 등 거의 모든 형태의 데이터를 전송할 때 사용한다. 심지어 서버간 데이터를 주고 받을 때도 대부분 사용한다.
🔥 지금은 HTTP 시대라고해도 과언이 아니다!!
한줄로 정리해보자면, HTTP는 클라이언트와 서버의 역할을 명확하게 구분해주고 브라우저와 서버가 데이터를 어떻게 주고 받을지에 대한 통신 규약이라고 할 수 있겠다.
GET
메서드만 지원, HTTP 헤더는 없었다.HTTP/1.1에 상당히 많은 기능들이 추가되었고 2, 3은 성능 개선에 초점이 맞춰져 있다
HTTP Request와 HTTP Response를 교환하여 성립
HTTP 프로토콜을 사용하여 데이터를 주고 받기 위해서는 반드시 요청과 응답이 존재해야한다.
즉, 클라이언트 사이드에서 리퀘스트 없이 리스폰스를 받는 경우와 서버 사이드에서 리퀘스트의 수신없이 리스폰스가 발생하는 경우는 절대 없다.
요청 메시지의 예시를 먼저 살펴보자.
GET / index.html HTTP / 1.1
Host: www.navxx.com
"GET"은 요청 메서드를 나타내고 그 다음 index.html
은 요청 대상인 리소스를 의미한다. 리퀘스트 URI 라고도 부른다.
HTTP/1.1은 HTTP의 버전 정보를 나타낸다.
한마디로 서버 상의 /index.html 이라는 리소스를 요청한다는 메시지이다.
Request 메시지는 메서드, URI, 프로토콜 버전, 옵션 리퀘스트 헤더 필드, 엔티티로 구성되어있고,
Response 메시지는 프로토콜 버전, 상태 코드, 상태 코드 설명, 리스폰스 헤더필드, 바디로 구성되어 있다.
[Request Message]
POST /form/entry HTTP/1.1
HOST: hackr.jp
Connection : keep-alive
Content-Type : application/x-www-form-urlencoded
Content-Length : 16
name=ueno&age=37
Request Header + 빈 줄 + Request Body
[Response Message]
HTTP /1.1 200 Ok
Date : Tue, 10 Jul 2012 06:50:15 GMT
Content-Length: 362
Content-Type: text/html
<html>
...
Response Header + 빈 줄 + Response Body
HTTP 프로토콜은 stateless(무상태) 프로토콜을 지향한다
HTTP프로토콜은 stateless 프로토콜이라고 불리는데 이는 각각의 데이터 요청이 서로 독립적인 관계가 된다는 의미를 내포한다. 이전 데이터 요청을 다음 데이터 요청이 기억하지 못한다는 뜻이다.
예시를 들어보겠다. 고객이 노트북을 구매하는 시나리오이다.
Stateful
고객 : 이 노트북 얼마인가요?
점원A : 100만원 입니다.
고객 : 2개 구매할게요.
점원B : 200만원 입니다. 신용카드, 현금 어떤 걸로 구매하시겠어요?
고객 : 신용카드로 구매할게요.
점원C : 200만원 결제 완료되었습니다.
Stateful - 점원이 바뀌면? 장애 상황
고객 : 이 노트북 얼마인가요?
점원A : 100만원 입니다.
고객 : 2개 구매할게요.
점원B : ? 무엇을 2개 구매하신다는거에요?
고객 : 신용카드로 구매할게요.
점원C : 무슨 제품을 몇개 신용카드로 구매하시겠어요?
고객 : 이 노트북 얼마인가요?
점원 : 100만원 입니다.(노트북 상태 유지)
고객 : 2개 구매할게요.
점원 : 200만원 입니다. 신용카드, 현금 어떤 걸로 구매하시겠어요?(노트북, 2개 상태 유지)
고객 : 신용카드로 구매할게요.
점원 : 200만원 결제 완료되었습니다.(노트북,2개, 신용카드 상태유지)
Stateless
고객 : 이 노트북 얼마인가요?
점원 : 100만원 입니다.
고객 : 노트북 2개 구매할게요.
점원 : 노트북 2개는 200만원 입니다. 신용카드, 현금중에 어떤 걸로 구매하시겠어요?
고객 : 노트북 2개를 신용카드로 구매하겠습니다.
점원 : 200만원 결제 완료되었습니다.
stateless한 상태로 노트북을 구매하려고 하면 점원이 바뀐다하더라도 모든 정보를 제공하기 때문에 아무런 문제가 없지만, stateful은 점원이 바뀌면 장애가 발생할 수 밖에 없다
정리해보면
상태유지 : 중간에 다른 점원으로 바뀌면 안된다. (중간에 다른 점원으로 바뀔 때 상태 정보를 다른 점원에게 미리 알려줘야 한다.)
무상태 : 중간에 다른 점원으로 바뀌어도 된다.
무상태는 응답 서버를 쉽게 바꿀수 있다. -> 무한 서버 증설 가능
그림처럼 항상 같은 응답을 돌려주기 때문에 만약 서버하나에 장애가 나더라도 다른 서버에 요청을 보낼 수 있다.
🚨 하지만 꼭 좋은 점만 있는 것은 아니다.
예를 들어, 로그인이 필요 없는 단순한 서비스 소개 화면 같은 경우에는 무상태로만 설계할 수 있다.
로그인이 필요한 경우에는 상태 유지하는 것이 중요하다.
이외에도 너무 많은 데이터를 보낸다는 단점이 있다
이렇게 시대가 변하면서 stateless의 특성으로는 처리하기 어려운 일들이 생겨났고 이런 요소를 해결하기 위해 등장한 것이 쿠키이다.
HTTP는 기본이 연결을 유지하지 않는 모델이다.
이런 비 연결성도 단점을 가지고 있다.
GET과 POST 모두 Response로 리소스를 받을 수 있다는 공통점을 가지고 있다. 그러나 일반적으로 리소스를 받을 때는 GET, 리소스에 엔티티를 제출할 때는 POST 메서드가 사용된다. 이유가 뭘까?
이유를 알기 전에 멱등성이라는 단어에 대해 알아보자.
멱등법칙(冪等法則) 또는 멱등성(冪等性, idempotent)은 수학이나 전산학에서 연산의 한 성질을 나타내는 것으로, 연산을 여러 번 적용하더라도 결과가 달라지지 않는 성질을 의미한다.
GET은 Idempotent
하도록 설계되었다. 즉 것은 GET으로 서버에게 동일한 요청을 여러 번 전송하더라도 동일한 응답이 돌아와야 한다는 것을 의미합니다. 이에 따라 GET은 설계원칙에 따라 서버의 데이터나 상태를 변경시키지 않아야 Idempotent하기 때문에 주로 조회를 할 때에 사용해야한다.
반대로 POST는 Non-idempotent
하기 때문에 서버에게 동일한 요청을 여러 번 전송해도 응답은 항상 다를 수 있습니다. 이에 따라 POST는 서버의 상태나 데이터를 변경시킬 때 사용됩니다. POST로 요청을 하게 되면 서버의 무언가는 변경되도록 사용됩니다.
🕶 비슷한 듯 보이지만 큰 차이를 가지고 있기 때문에 HTTP/1.1 스펙인 RFC2616의 Section9.3의 설계원칙에 따라 적절한 메서드를 적절한 용도로 사용해야한다 🕶
김영환님 강의를 토대로 작성한 글입니다.