모든 것이 HTTP
HTTP는 Hyper Text Transfer Protocol의 약자로 Hyper Text인 html을 전송하는 프로토콜로 시작했습니다. 하지만 지금은 아래와 같은 모든 것을 HTTP에 담아서 전송합니다.
HTML, TEXT 뿐만이 아닌
- Image, 음성, 영상, 파일
- JSON, XML (API)
- 거의 모든 형태의 데이터 전송 가능
- 서버간에 데이터를 주고 받을 때도 대부분 HTTP 사용
HTTP 역사
- HTTP/0.9 1991년 : GET 메서드만 지원, HTTP 헤더 X
- HTTP/1.0 1996년 : 메서드, 헤더 추가
- HTTP/1.1 1997년 : 가장 많이 사용, 우리에게 가장 중요한 버전
- RFC2068 (1997) -> RFC2616 (1999) -> RFC7230~7235 (2014)
- HTTP/2 2015년 : 성능 개선
- HTTP/3 진행중 : TCP 대신 UDP 사용, 성능 개선
기반 프로토콜
- TCP : HTTP/1.1, HTTP/2
- UDP : HTTP/3 - TCP는 3 way hanshake, 기본적인 데이터가 많은 등의 문제로 속도가 빠른 매커니즘이 아닙니다. 그래서 HTTP/3는 UDP 프로토콜위에 애플리케이션 레벨에서 성능을 최적화하도록 새로 설계해서 나온 것입니다.
- 현재 HTTP/1.1 주로 사용
- HTTP/2, HTTP/3 점점 증가
실제 어떤 것들이 HTTP 버전으로 통신이 되고있는지 확인해보겠습니다. 크롬 브라우저에서 F12 (윈도우), alt+command+i (mac)을 누르면 개발자 도구가 나옵니다. Network 탭을 누른 뒤 아래 Name 탭에서 오른쪽 마우스를 눌러 Protocol을 체크해줍니다. 그 후 구글에 들어가 hello라고 검색해보면, 프로토콜에서 h2 혹은 h3라고 나와있을텐데 h2는 HTTP/2, h3는 HTTP/3입니다. 현재 제가 해본 결과 h3를 구글에서는 주로 사용하네요. 네이버도 확인해보니 네이버는 h2를 대부분 사용하고 있었습니다.
HTTP 특징
- 클라이언트 서버 구조
- 무상태 프로토콜(stateless), 비연결성
- HTTP 메시지
- 단순함, 확장 가능
클라이언트 서버 구조
HTTP의 특징 중 하나 입니다. HTTP는 클라이언트가 HTTP 메시지를 통해 서버 요청을 보내고, 클라이언트는 서버에서 응답이 올때까지 기다립니다. 서버가 클라이언트의 요청에 대한 결과를 만들어서 응답을 하게되면 응답 결과를 클라이언트가 받고 열어서 동작하게 됩니다.
비즈니스 로직과 데이터 같은 것들은 서버에 밀어 넣고, 클라이언트는 UI/UX에 집중합니다. 이렇게 하게되면 좋은 점은 클라이언트와 서버가 각각 독립적으로 진화를 할 수 있습니다. 예를들어, 클라이언트는 복잡한 비즈니스 로직과 데이터 같은 것들이 없기 때문에 UI/UX에만 집중할 수 있습니다. 반대로 서버는 트래픽 폭주 시에 클라이언트를 손대지 않고 서버를 고도화하고 진화하는 것에만 집중할 수 있습니다.
즉, 이렇게 분리를 하는 이유는 클라이언트와 서버 각각 독립적으로 진화를 할 수 있습니다.
Stateful, Stateless
Stateless
- 서버가 클라이언트의 상태를 보존하지 않는다.
잘 이해가 가지않을 텐데요. 아래의 예시로 이해해봅시다. 예시는 고객과 점원 사이의 노트북 구매 플로우로 들도록 하겠습니다.
예를들어, Stateful인 경우는 아래와 같습니다.
Stateful에서 점원이 중간에 바뀌는 경우는 아래와 같습니다.
Stateful을 정리하자면 아래와 같습니다.
Stateless의 경우를 봐봅시다. 이번것만 보면 Stateful과 별로 다를게 없습니다.
그렇다면, 점원이 바뀌는 경우를 Stateless로 봐봅시다. Stateful과 다르게 점원이 바뀌어도 새로운 점원과 의사소통의 문제가 일어나지 않습니다.
- 장점 : 서버 확장성 높음 (스케일 아웃 - 서버를 늘립니다. 수평 확장)
- 단점 : 클라이언트가 추가 데이터 전송
Stateful, Stateless 차이
- 상태 유지 : 중간에 다른 점원으로 바뀌면 안됩니다.
(중간에 다른 점원으로 바뀔 때 상태 정보를 다른 점원에게 미리 알려줘야 합니다.) - 무상태 : 중간에 다른 점원으로 바뀌어도 됩니다.
- 갑자기 고객이 증가해도 점원을 대거 투입할 수 있습니다.
- 갑자기 클라이언트 요청이 증가해도 서버를 대거 투입할 수 있습니다. (때문에 확장성이 높습니다.)
- 무상태는 응답 서버를 쉽게 바꿀 수 있습니다. -> 무한한 서버 증설 가능
상태 유지의 경우 위처럼 서버 1이 클라이언트A의 요청 정보를 유지하고 있습니다. 하지만 이렇게 정보를 유지하다가 서버 1이 장애가 발생하면 어떻게 될까요?? 이럴경우 클라이언트A는 기존에 했던 작업들의 정보가 사라지기 때문에 다시 처음부터해야합니다.
하지만 Stateless의 경우는 클라이언트가 요청할 때부터 데이터를 다 담아서 보냅니다. 서버는 응답만하고 상태를 보관하지 않기때문에 서버 1이 장애가 발생해도 중계서버에서 요청을 서버2로 보내서 처리하기만하면 되기때문에 클라이언트A에게 다시 정보를 요청하지 않아도 됩니다. 상태를 유지하지 않기 때문에 서버 확장에 유리합니다.
여기까지만 보면 Stateful은 쓸 이유가 없고 Stateless만 사용하면 되는 것 아닌가라는 생각이 듭니다. 하지만, Stateless에도 한계가 있습니다.
Stateless 실무 한계
- 모든 것을 무상태로 설계할 수 있는 경우도 있고 없는 경우도 있다.
- 무상태
- 예) 로그인이 필요 없는 단순한 서비스 소개 화면
- 상태 유지
- 예) 로그인
- 로그인한 사용자의 경우 로그인을 했다는 상태를 서버에 유지
- 일반적으로 브라우저 쿠키와 서버 세션등을 사용해서 상태 유지
- 상태 유지는 최소한만 사용
- 데이터를 너무 많이 보내는 경우가 생길 수 있다.
비연결성(connectionless)
TCP/IP의 경우는 연결을 유지한 상태로 클라이언트와 서버가 데이터를 주고 받습니다. 한대면 상관이 없지만, 여러대가 서버에 연결을 계속 유지하는 경우 클라이언트가 놀고있어도 서버는 연결을 유지해야하기 때문에 자원을 소모하게 되는 단점이 있습니다.
그렇다면 위의 방법대로 요청할때만 연결하여 데이터를 주고받은 뒤, 사용하지 않고있을 때는 연결을 끊는 방법이 있습니다. 이렇게하면 위의 방식의 단점을 보완할 수 있습니다.
비 연결성
- HTTP는 기본이 연결을 유지하지 않는 모델
- 일반적으로 초 단위 이하의 빠른 속도로 응답
- 1시간 동안 수천명이 서비스를 사용해도 실제 서버에서 동시에 처리하는 요청은 수십개 이하로 매우 작음
- 예) 웹 브라우저에서 계속 연속해서 검색 버튼을 누르지는 않는다.
- 서버 자원을 매우 효율적으로 사용할 수 있음
하지만, 비 연결성에도 단점이 있습니다.
비 연결성 한계와 극복
- TCP/IP 연결을 새로 맺어야 함. 3 way handshake 작업을 연결할 때마다 해야함.
- 웹 브라우저로 사이트를 요청하면 HTML 뿐만 아니라 자바스크립트, css, 추가 이미지 등등 수 많은 자원이 함께 다운로드
- 지금은 위의 문제를 HTTP 지속 연결(Persistent Connections)로 문제 해결
- HTTP/2, HTTP/3(UDP를 사용해서 연결 속도에서부터 시간을 많이 단축시킴)에서 더 많은 최적화
Stateless를 기억하자
- 정말 같은 시간에 딱 맞추어 발생하는 대용량 트래픽
- 예) 선착순 이벤트, 명절 KTX 예약, 학과 수업 등록
- 예) 저녁 6:00 선착순 1000명 치킨 할인 이벤트 -> 수만명 동시 요청
위의 문제를 해결하기 위해서는 최대한 Stateless하게 설계하는 것이 중요합니다. Stateless하게 설계되었다면 위의 이벤트가 발생해도 잠깐동안 서버를 늘려서 대응할 수 있기 때문입니다.
HTTP 메시지
HTTP는 요청 메시지와 응답 메시지의 구조가 아래와 같이 다릅니다.
HTTP 메시지의 구조는 아래와 같습니다.
시작 라인 - 요청 메시지
- start-line = request-line / status-line
- request-line = method SP(공백) request-target(path) SP HTTP-version CRLF(엔터)
- HTTP method
- GET : resource를 보내줘
- POST : resource를 처리해줘
- DELETE : resource를 삭제해줘
- 요청 대상 (/search?q=hello&hl=ko)
- absolute-path[?query] (절대경로[?쿼리])
- 절대경로 = "/"로 시작하는 경로
- HTTP Version
시작 라인 - 응답 메시지
- start-line = request-line / status-line
- status-line = HTTP-version SP status-code SP reason-phrase CRLF(엔터)
- HTTP version
- HTTP 상태 코드
- 200 : 성공
- 400 : 클라이언트 요청 오류
- 500 : 서버 내부 오류
- 이유 문구 : 사람이 이해할 수 있는 짧은 상태 코드 설명 글
HTTP 헤더
- header-field = field-name ":" OWS field-value OWS (OWS:띄어쓰기 허용)
- field-name은 대소문자 구문 없음
HTTP 헤더 용도
- HTTP 전송에 필요한 모든 부가정보가 다 들어있다. (message body빼고 필요한 메타정보가 다 있습니다.)
- 예) 메시지 바디의 내용, 메시지 바디의 크기, 압축, 인증, 요청 클라이언트(브라우저) 정보, 서버 애플리케이션 정보, 캐시 관리 정보...
- 표준 헤더가 너무 많다.
- 필요시 임의의 헤더 추가 가능
- 임의의 헤더를 추가하는 경우엔 약속한 클라이언트와 서버만 이해가 가능
HTTP 메시지 바디 용도
- 실제 전송할 데이터
- HTML 문서, 이미지, 영상, JSON 등등 byte로 표현할 수 있는 모든 데이터 전송 가능
출처
'spring > 인프런 강의 정리' 카테고리의 다른 글
[HTTP 웹 기본 지식] 5. HTTP 메서드 활용 (0) | 2022.01.13 |
---|---|
[HTTP 웹 기본 지식] 4. HTTP 메서드 (0) | 2022.01.13 |
[HTTP 웹 기본 지식] 2. URI와 웹 브라우저 요청 흐름 (0) | 2022.01.12 |
[HTTP 웹 기본 지식] 1. 인터넷 네트워크 (0) | 2022.01.12 |
[Spring/기본편] 8. 빈 스코프 (0) | 2021.12.26 |