HTTP(Hyper Text Transfer Protocol)란?
HTTP(Hyper Text Transfer Protocol)란 서버-클라이언트 모델을 따르면서 request/response 구조로 웹 상에서 데이터를 주고 받을 수 있는 프로토콜(규칙)이다. TCP/IP 기반으로 작동하며, HTTP의 가장 큰 특징은 Connectionless와 Stateless 가 있다. 또한TCP/IP socket을 이용해서 연결된다.
웹문서간에 링크를 통해 연결할 수 있는 프로토콜이며, 문서뿐 아니라 다음과 같은 여러 종류의 데이터들을 폭 넓게 전송할 수 가 있다.
- HTML, TEXT
- 이미, 음성, 영상, 파일
- JSON, XML(API)
- 거의 모든 형태의 데이터가 전송 가능
서버간에 데이터를 주고 받을 때 대부분 HTTP라는 프로토콜을 사용해서 통신한다.
예를들어 인터넷 주소를 지정할때 http://www.naver.com 와 같이 시작하는 것은 www.naver.com 이라는 인터넷 주소가 가진 데이터 정보 등의 교환을 HTTP의 통신 규약대로 처리하라는 것을 의미한다고 볼 수 있다.
또한 인터넷 기반 서비스에는 HTTP 외에도 Email, FTP, DNS, NEWS 등이 있다.
HTTP는 인터넷에서 하이퍼텍스트를 교환하기 위한 통신 규약으로, 80번 포트를 사용하고 있다. 따라서 HTTP 서버가 80번 포트에서 요청을 기다리고 있으며, 클라이언트는 80번 포트로 요청을 보내게 된다.
HTTP는 1989년 팀 버너스 리(Tim Berners Lee)에 의해 처음 설계되었으며, WWW(World-Wide-Web) 기반에서 세계적인 정보를 공유하는데 큰 역할을 하였다.
URL
URL(Uniform Resource Locators)은 서버에 자원을 요청하기 위해 입력하는 영문 주소다. 아무래도 숫자로 되어 있는 IP 주소보다는 훨씬 기억하기 쉽기 때문에 사용하는 것 같다. URL 구조는 아래와 같다.
HTTP의 역사
1. HTTP/0.9 (1991년) : GET 메서드만 지원, HTTP 헤더 X
2. HTTP/1.0 (1996년) : 메서드, 헤더, 상태코드 추가
- 요청 헤더 : http 버전이 생김
- 응답 헤더 : 상태코드와 content-type이 생겨 html 파일 외 다른 타입의 파일도 전송
- 단기커넥션 : connection 하나당 1 요청, 1 응답만 처리 가능. 그래서 매번 새로운 연결로 선능 저하 및 서버 부하 비용 증가
3. HTTP/1.1 (1997년) : 현재 가장 많이 사용하며, 대부분의 기능이 추가
- Persistent connection : 지정한 timeout 동안 연속적인 요청 사이에 커넥션을 닫지 않음
- Pipelining : 하나의 커넥션에서 응답을 기다리지 않고 순차적인 여러 요청을 연속적으로 보내 그 순서에 맞춰 응답을 받는 방식으로 지연 시간을 줄이는 방식. 그러나 Head Of Line Blocking와 같은 문제점이 많아 사장됨
- Head Of Line Blocking : 우선순위로 들어온 요청의 응답 시간이 길어지면 후 순위에 있는 요청의 응답 시간도 길어진다는 단점
- 우리가 아는 대부분의 HTTP 기능이 1.1에 구현 된 것이고, 2와 3에서는 성능 개선에 초점이 맞춰져 있다.
4. HTTP/2.0 (2015년) : HTTP 1.1 성능 개선 및 확장
- 메시지 전송 방식의 변화 : 바이너리 프레이밍 계층 사용
- 파싱, 전송속도 증가
- 오류 발생 가능성 저하
- 멀티플렉싱
- HPACK 압축 : 헤더 중복값 개선
5. HTTP/3.0 (2019년 ~ 진행중): TCP 대신에 UDP를 이용한 QUIC 프로토콜 사용
- UDP 기반의 QUIC 프로코콜 바탕으로 제작
- 기존 TCP의 고질적인 지연시간(RTT)를 해결함
※ 참고
HTTP/1.1, HTTP/2는 TCP 기반이며 HTTP/3는 UDP 기반 프로토콜이다.
기존 TCP는 3 way hanshake부터 내부적으로 포함하거나 추가해야하는 작업들이 너무 많아서 신뢰성이나 연결성은 보장되지만 속도가 떨어진다. 그렇기에 UDP프로토콜을 애플리케이션 레벨에서 재설계를 해서 나오는게 HTTP/3이다.
HTTP 1.1
HTTP는 Connectionless 특징을 가진다고 하였다. 즉 1회성으로 reqeust/ response를 한다는 것이다.
HTTP 1.1은 keepalive기능을 통해, 서버에서 설정된 keepalive timeout까지는 연경 과정이 없이 데이터 송수신이 가능하다. 즉, 내부적으로 결국 매번 TCP 3-way handshake 과정을 거칠 필요가 없다.
HTTP의 통신 구조
HTTP 통신은 클라이언트(Front-End)와 서버(Back-End)로 나뉘어진 구조로 되어있다.
클라이언트가 요청(Request)하면 서버가 응답(Response) 하는 것이다.
예를들어 클라이언트가 HTTP 메세지를 만들어 보내고 , 서버에서 요청에 대한 응답이 올 때까지 기다린다. 그리고 서버는 요청에 대한 결과를 만들어서 응답한다.
그럼 HTTP 통신하는데 있어, 어째서 이렇게 클라이언트와 서버를 분리해야만 할까?
이유는 각자의 역할에 집중할 수 있기 때문이다.
클라이언트에서는 복잡한 비즈니스 로직이나 데이터를 다룰 필요없고, UI를 그리는데 집중할 수 있다.
서버에서는 복잡한 비즈니스 로직이나, 데이터를 다루는데만 집중하면 된다. 만약 트래픽이 폭주해 고도화가 필요한 경우 클라이언트는 신경쓰지 않고 서버만 개선하면 된다.
즉, 클라이언트와 서버를 독립적으로 구분한다는 것은 각자의 책임을 나눠 해당 책임에만 집중하여, 클라이언트와 서버 양쪽이 각각 독립적으로 고도화 할수 있다는 것이다.
HTTP의 특징
앞서 HTTP의 주된 특징으로 Connectionless와 Stateless가 있다고 했다.
HTTP는 서버에 연결 후 요청에 응답을 받으면 연결을 끊어버리는 Connectionless 특성을 갖는다. 이로 인해 많은 사람이 웹을 이용하더라도 실제 동시 접속을 최소화하여 더 많은 유저의 요청을 처리할 수 있다.
하지만 연결을 끊었기 때문에, 클라이언트의 이전 상태(로그인 유무 등)를 알 수가 없다는 Stateless 특성이 생기게 된다. 정보를 유지할 수 없는 Connectionless, Stateless 특성을 가진 HTTP의 단점을 해결하기 위해, cookie, session, jwt 등이 도입되었다.
HTTP의 무상태성 (Stateless)
- 무상태(Stateless) : 클라이언트와 서버 사이에 상태를 유지하지 않는다.
- 장점: 서버 확장성 높음(스케일 아웃)
- 단점: 클라이언트가 추가 데이터 전송 (메모리 ↑)
상태유지(Stateful)
- 서버가 클라이언트의 상태를 보존한다.
- 가장 대표적인 예로 홈페이지에서 회원 로그인을 하면, 페이지를 옮겨가도 서버는 클라이언트의 상태를 보존하기 때문에 그 클라이언트가 회원인지 안다.
- 하지만 중간에 서버가 장애나면 클라이언트는 처음부터 다시 작업을 요청해야한다.
- 그래서 서버가 바뀔때마다 클라이언트의 내용을 기록해서 상태를 유지해야 되는데 쉽지 않다.
무상태(Stateless)
- 서버가 클라이언트의 상태를 보존하지 않는다.
- 홈페이지에서 회원 로그인을 하고 페이지를 옮겼는데 또 로그인을 하라는 페이지가 뜬다. 왜냐하면 서버는 클라이언트의 상태를 보존하지 않기 때문에 그 클라이언트가 회원인지 모르기 때문이다.
- 따라서 무상태 환경에선 회원 정보를 서버가 아닌 클라이언트가 토큰 형태로 들고 있으면서, 서버와 통신할때 실어 보내 인증하는 식이다.
- 이러한 무상태 환경은 클라이언트가 상태 정보를 갖고 있는 것이기 때문에, 아무 서버나 호출해도 되기 때문에 서버의 스케일아웃(수평확장)에 유리하다.
- 하지만 상태유지(Stateful)보다 데이터를 많이 사용한다는 단점이 있다.
HTTP의 비연결성 (Connectionless)
- HTTP는 기본이 연결을 유지하지 않는 모델이다.
- 즉, 서버와 클라이언트의 Connection 연결을 지속하지 않는다.
- 1시간동안 수천명 이상이 서비스를 사용해도 실제 서버에서 동시에 처리하는 요청은 수십개 이하로 적다.
예를들어 웹 브라우저 검색페이지에서 검색버튼만 연타하면서 이용하지는 않는듯이 말이다. - 이러한 비연결성 특성 때문에 서버 자원을 매우 효율적으로 사용할 수 있다.
※ 참고
[ Stateless 와 Connectionless 차이 ]
Stateless (무상태성)
: 필요한 상태에 대한 정보를 클라이언트가 가지고 있기 때문에 클라이언트의 요청에 어느 서버가 응답해도 상관 없음. 따라서 클라이언트의 요청이 대폭 증가하면 서버를 증설해 해결할 수 있음
Connectionless (비연결성)
: 클라이언트가 서버에 요청을 하고 응답을 받으면 바로 TCP/IP 연결을 끊어 연결을 유지하지 않음으로써 서버의 자원을 효율적으로 관리하고 수 많은 클라이언트의 요청에 대응할 수 있게 함
즉, 무상태성은 클라이언트와 서버 간에 상태 정보를 들고있지않아 클라이언트가 상태 정보를 일일히 http에 실어 요청해야되는 것을 말하고, 비연결성은 클라이언트와 서버 간에 네트워크 연결이 끊어져 단절된다고 이해하면 된다.
연결을 유지하는 모델
- 연결을 유지한다면, 서버와 클라이언트의 연결은 서로의 네트워킹 요청이 없더라도 계속해서 유지된다.
- 자원이 계속해서 사용된다. (이러한 점 때문에, HTTP는 기본적으로 연결을 유지하지 않는 모델이다)
연결을 유지하지 않는 모델
- 연결을 유지하지 않는다면, 서버의 자원을 효율적으로 사용할 수 있다.
- 다만, 클라이언트가 연결을 계속 끊는 다는 것은 TCP/IP 연결을 매번 새롭게 맺어야 한다는 것을 뜻한다.
- 즉, TCP 3 way handshake를 매번 해야하고, 이는 시간이 걸린다.
- 이러한 문제는 지금 HTTP 지속 연결(Persistent Connections)로 문제 해결하고 있다.
- HTTP/2, HTTP/3에서 더 많은 최적화가 이루어 졌다.
비연결성 한계 - 단기 커넥션
- HTTP 초기 - 연결, 종료 낭비
- 웹 브라우저로 사이트를 요청하면 HTML 뿐만 아니라 자바스크립트, css, 추가 이미지 등등 수 많은 자원이 함께 다운로드 되는데, 새로 연결을 맺을 때 마다 TCP Handshake가 발생한다는 문제점이 있음
- 그래서 HTTP 초기에는 모든 자료에 대해서 비연결성으로 각각의 자원에 대해 연결/응답/종료를 반복하다보니 대략적으로 1초가량 소모되었다.
비연결성 극복 - HTTP 지속 연결
- 클라이언트는 서버와 소켓 연결을 한 다음 필요한 자원을 요청/응답으로 다운로드받는다.
- 소켓 연결을 일정 시간 동안 더 유지함으로써, 필요한 자원들을 모두 다운받을때까지 연결이 종료되지않고 요청/응답이 반복된 뒤 종료
HTTP 상태 코드
상태 코드는 클라이언트가 보낸 요청의 처리 상태를 응답에서 알려주는 기능으로서, 3자리 숫자로 만들어져 있으며, 100 ~ 500 번대 숫자로 이루어져 있다.
예를 들어 첫번째 자리가 4와 5인 경우는 정상적인 상황이 아니기 때문에 사이트 관리자가 즉시 알아야 하는 정보이다.
- 1xx(정보) : 요청을 받았으며 프로세스를 계속 진행
- 2xx(성공) : 요청을 성공적으로 받았으며 인식했고 수용
- 3xx(리다이렉션) : 요청 완료를 위해 추가 작업 조치가 필요
- 4xx(클라이언트 오류) : 요청의 문법이 잘못되었거나 요청을 처리할 수 없음
- 5xx(서버 오류) : 서버가 명백히 유효한 요청에 대한 충족을 실패
HTTP 메세지
개발자 도구의 네트워크 창에서 서버로 부터 다운 받은 파일을 눌러보면 아래 사진과 같이 Headers 부분에 뭐라뭐라 적혀져 있는 것을 보았을 것이다. 이것은 클라이언트와 서버 간에 HTTP 메세지를 통해 통신한 이력이라고 이해하면 된다.
Request Headers 는 클라이언트가 서버에게 보내는 HTTP 메세지 이력이며, Response Headers 는 서버가 클라이언트에게 응답하는 HTTP 메세지 이력이다.
HTTP 메세지 구조
HTTP 메시지는 기본적으로 위에서부터 차례대로 시작 라인(Start Line), 헤더(Header), 공백 라인(Empty Line), 바디(Message Body)로 구성되어 있다.
참고로 공백 라인은 HTTP 메세지 값 구분을 하기 위한 라인이므로, 단순히 보기 편하게 넣는 것을 넘어서 반드시 있어야 한다. 만약 보낼 메세지 바디가 없다면 공백만 넣고 끝내면 된다. 그리고 HTTP 요청 종류에 따라 Message Body가 포함될 수도 있고 아닐 수도 있다.
전체적인 구조는 위와 같고 HTTP 요청(Request)냐 응답(Response)냐에 따라 안의 내용물이 약간 다르다.
HTTP 요청 메세지
- 시작 라인(Start Line)
- Method : GET / POST / PUT / DELTE 등 (HTTP 메서드)
- URL : 요청 대상 경로 표시
- Version : 사용된 http 버전
- 헤더(Header)
- Headers : HTTP 전송에 필요한 모든 부가 정보를 담고 있다. (메세지 크기, 압축 여부, 인증, 브라우저 정보, 서버 정보, 캐시 ..등)
- 공백 라인(Empty Line) : 헤더와 바디를 구분하기 위한 라인
- 바디(Message Body)
- Message Body : 실제 전송할 데이터 (HTML 문서, 이미지, 영상, JSON 등)
HTTP 응답 메세지
- 시작 라인(Start Line)
- Version : 사용된 http 버전
- Status Code : 클라이언트가 보낸 요청이 성공인지 실패인지 숫자 코드로 나타낸다. (200, 404, 505)
- Status Message : Status Code 에 대한 결과를 사람이 이해할 수 있는 글로 표현
- 헤더(Header)
- Headers : HTTP 전송에 필요한 모든 부가 정보를 담고 있다. (메세지 크기, 압축 여부, 인증, 브라우저 정보, 서버 정보, 캐시 ..등)
- 공백 라인(Empty Line) : 헤더와 바디를 구분하기 위한 라인
- 바디(Message Body)
- Message Body : 전송 받은 데이터
HTTP 메서드
HTTP 메서드란, 클라이언트가 서버에게 사용자 요청의 목적을 알리는 '수단'이다.
쉽게 말하면 서버에 주어진 리소스에 수행하길 원하는 행동, 서버가 수행해야 할 동작을 지정하여 요청을 보내는 방법이다.
HTTP 메서드 종류
HTTP 메소드의 종류는 총 9가지가 있다. 이 중 주로 쓰이는 메소드는 5가지가 있다.
주요 메소드 5가지
- GET : 리소스 조회
- POST : 요청 데이터 처리, 주로 데이터 등록에 사용
- PUT : 리소스를 대체, 해당 리소스가 없으면 생성
- PATCH : 리소스를 일부만 변경
- DELETE : 리소스 삭제
기타 메소드 4가지
- HEAD: GET과 동일하지만 메시지 부분을 제외하고, 상태 줄과 헤더만 반환
- OPTIONS: 대상 리소스에 대한 통신 가능 옵션을 설명(주로 CORS에서 사용)
- CONNECT: 대상 자원으로 식별되는 서버에 대한 터널을 설정
- TRACE: 대상 리소스에 대한 경로를 따라 메시지 루프백 테스트를 수행
HTTP 메서드 특성
안전성(Safe)
- 호출해도 리소스 변경이 일어나지 않는 속성
- 여기서 안전의 기준은 오직 리소스 변경 가능성이며, 외적인 요소는 포함하지 않는다.
- GET, HEAD를 안전한 메소드라고 볼 수 있다. (POST, PUT, PATCH, DELETE는 리소스를 변경하는 메소드이므로)
멱등성(Idempotent)
- 동일한 요청을 여러 번 보내도 한 번 보내는 것과 같은 것
- 같은 행위를 여러 번 반복하더라도 같은 효과를 받으며, 서버의 상태로 동일하게 남음
- 멱등성은 요청의 결과를 보고 판단
- TimeOut 등으로 클라이언트가 서버로부터 정상 응답을 받지 못 했을 때 같은 요청을 다시 해도 되는지 판단하는 근거
- GET : 몇 번을 조회하더라도 같은 결과가 조회된다. ⇒ 회원 정보를 몇번을 조회한다고 정보가 달라지지 않는다.
- PUT : 결과를 대체한다. 따라서 같은 요청을 여러번해도 최종 결과는 같다.
- DELETE : 결과를 삭제한다. 같은 요청을 여러번 해도 삭제된 결과는 같다.
- POST : 멱등이 아니다. 두 번 호출하면 에러가 발생할수 있다. ⇒ POST로 주문을 두 번 호출하면 결제가 중복될 수 있다.
캐시 가능 (Cacheable)
- 응답 결과를 캐시해 사용할 수 있는 속성이다.
- GET, HEAD, POST, PATCH가 캐시 가능하나, Message Body의 캐시 키의 복잡성 문제로 실제로는 GET, HEAD만 사용
※ 참고
HTTP는 암호화가 되지 않은 평문 데이터를 전송하는 프로토콜이였기 때문에 중간에 패킷을 가로챌 수 있고, 수정할 수 있다. 따라서 보안이 취약해짐을 알 수 있다. 이를 보완하기 위해 나온 것이 HTTPS다. 중간에 암호화 계층을 거쳐서 패킷을 암호화한다.
참고
- https://www.zerocho.com/category/HTTP/post/5b344f3af94472001b17f2da
- https://surprisecomputer.tistory.com/54
- https://velog.io/@surim014/HTTP%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80
- 모든 개발자를 위한 HTTP 웹 기본 지식 - 김영한
- https://medium.com/@maheshlsingh8412/cookie-session-story-of-a-stateless-http-3cd09cc01541
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview
- https://community.safe.com/s/article/HTTP-Requests-With-The-HTTPCaller