일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 메타버스
- docker
- 클라우드자격증
- MAB
- Collaborative Filtering Bandit
- llm
- BERT
- nlp
- BANDiT
- aws자격증
- transformer
- 언어모델
- 자연어처리
- HTTP
- TFX
- RecSys
- MLOps
- 머신러닝
- MSCS
- AWS
- 미국석사
- 클라우드
- 머신러닝 파이프라인
- 중국플랫폼
- COFIBA
- 네트워크
- BERT이해
- 추천시스템
- chatGPT
- 플랫폼
- Today
- Total
Julie의 Tech 블로그
웹, HTTP - (2) HTTP 메시지와 커넥션 본문
앞서 HTTP 프로토콜에 대해 개략적으로 알아보고, 클라이언트와 서버간 HTTP 프로토콜로 어떻게 데이터를 주고 받는지를 볼 수 있었다.
이번 글에서는 HTTP 메시지에 대해 좀 더 구체적으로 알아볼 것이다.
HTTP 메시지는 요청과 응답에 대한 메타 데이터와 그에 따른 데이터를 선택적으로 주고받는다.
서버 방향으로 향하는 것을 인바운드, 서버를 거쳐 클라이언트 방향으로 응답하는 것을 아웃바운드 메시지라 부른다.
메시지는 시작줄, 헤더블록, 본문 이렇게 세 가지로 이루어져있다.
시작줄에는 어떤 메시지인지를 표현하고 있고, 헤더에는 속성값을, 본문에는 데이터를 포함하고 있다.
데이터는 선택적인 것이라 본문이 없을 수도 있다.
메시지의 간단한 예를 들어보면,
-----------------------------------
시작줄 - HTTP/1.0 200 OK
헤더 - Content-type : text/plain
Content-length : 19
본문 - Hi! I'm a message!
------------------------------------
위와 같이 볼 수 있다.
메시지는 요청/응답 각 타입에 따라 형식이 조금씩 다르다.
요청 메시지의 경우 <메서드> <요청 URL> <버전> <헤더> <엔티티 본문> 이다.
응답 메시지의 경우 <버전> <상태 코드> <사유 구절> <헤더> <엔티티 본문> 이다.
둘 간의 차이는 시작줄에서만 드러난다. 그 이유는 요청 메시지가 클라이언트 > 서버로 무언가를 수행해주길 바라기 때문이다.
시작줄
모든 HTTP 메시지는 시작줄로 시작하는데, 시작줄은 대략적으로 어떤 수행을 필요로 하는지 / 일어났는지를 담고 있다.
시작줄에는 메서드/상태코드, 요청줄/응답줄, 사유구절, 버전 번호로 구성된다.
메서드는 GET, POST, HEAD와 같은 서버에게 수행해야하는 것을 말해주고,
상태코드는 클라이언트에게 어떤 일이 결과적으로 일어났는지를 말해준다.
상태코드는 100 단위로 묶이는데, 200~299는 성공을 의미하고, 300~399는 리소스가 옮겨졌다고 말한다, 500~599는 서버 에러이다.
사유구절은 상태코드에 대해 사람이 읽기 위함으로 붙이는 것으로써, 200 OK에서 OK와 같은 것들이다.
버전 번호는 HTTP 어플리케이션들에게 각자 자신이 따르는 프로토콜을 상대에게 알리기 위해 사용된다.
버전 번호는 어플리케이션이 이해할 수 있는 최대의 버전으로서, .을 기점으로 각기 다른 숫자로 이해해야한다.
(HTTP/2.22와 HTTP/2.3 중에서 전자가 더 큰 버전이다.)
헤더
시작줄 다음에는 0개 이상의 여러개 헤더가 올 수 있다. 추가 정보를 더하는 것인데, 키 : 값 쌍들의 목록이다.
ex) Date : Tue, 3 Oct 1997 00:00:00 GMT
Content-type : image/jpeg
다섯가지로 분류되는데,
1) 일반 헤더 : 클라이언트와 서버 양쪽이 사용하는 것으로, 다양한 목적으로 사용된다. ex) Date
2) 요청 헤더 : 요청 메시지를 담은 요청 헤더, 데이터 타입과 같은 부가적인 정보 제공 ex) Client-IP, From, Host, Accept
3) 응답 헤더 : 클라이언트에게 제공하기 위한 서버만의 헤더
4) 엔티티 헤더 : 엔터티 본문에 대한 헤더, 데이터 타입 등이 해당된다.
5) 확장 헤더 : App 개발자들이 만들었지만 아직 승인되지 않은 비표준 헤더
엔터티 본문
메시지가 본격적으로 담고자 하는 데이터이며, HTML문서, 비디오, 이미지 등 여러 종류의 데이터를 담을 수 있다.
메서드
- GET : 가장 흔한 메서드로서, 서버로부터 무언가를 달라고 요청하는 것이다
- HEAD : GET과 유사하지만, 헤더만을 받게 된다. 리소스를 직접 가져오지 않더라도 어떤 것인지/변경되었는지를 파악할 수 있다.
- PUT : GET은 안전한 메서드인 반면, PUT은 서버에 문서를 작성하기 때문에 콘텐츠를 변경할 여지가 있다.
- POST : 서버에 데이터를 입력하는 용도인데, HTML 폼을 지원한다. PUT과 다른 점은, PUT은 서버에 있는 리소스에 데이터를 입력한다.
- TRACE : 클라이언트에게 서버까지 보낸 메시지의 경로가 어떻게 되는지를 보여준다. 주로 진단을 하기 위해 사용된다.
(클라이언트는 서버에게 지속적으로 요청/응답을 트래킹하면서 메시지가 망가졌는지 수정되었는지를 확인한다.)
- OPTIONS : 서버에게 지원범위에 대해 물어본다. 어떤 메서드가 지원될 수 있는지 물어볼 수 있다.
- DELETE : 요청 URL로 지정한 리소스를 삭제할 것을 요청한다.
앞선 글에서 TCP 커넥션을 통해 HTTP 메시지를 주고받는다고 이야기했었다.
전세계 모든 HTTP 통신은 TCP/IP 를 통해 이루어진다.
TCP/IP 커넥션이 맺어지면 메시지가 손상되거나, 뒤섞이는 일은 없다.
하나의 컴퓨터는 여러개의 TCP 커넥션을 갖는데, 각각 포트넘버로 관리된다.
TCP가 어떻게 안전하게 전달될 수 있도록 보장해줄까?
TCP는 데이터를 세그먼트 단위로 나누고, IP패킷에 담아 전달한다.
이 세그먼트는 하나의 IP주소에서 다른 IP주소로 IP패킷에 담겨 전달되는데, IP패킷 헤더 - TCP 세그먼트 헤더 - TCP 데이터 조각으로 이루어진다.
TCP 성능
TCP는 HTTP의 바로 아래 계층으로, HTTP 통신 성능은 TCP 성능에 많이 좌우된다.
TCP 커넥션을 맺는 과정을 살펴보면, 우선 맨 처음 URL을 DNS서버를 통해 IP주소와 매핑해야하는데, 이 과정에서 소요시간이 조금 생긴다.
클라이언트는 서버로 TCP 커넥션 요청을 보내고, 서버로부터 응답하기를 기다려야한다.
우선 커넥션이 셋팅되면, TCP파이프를 통해 요청을 보내고, 서버는 요청 메시지를 읽고 처리한다.
응답을 보내면, 또 받는데까지 시간이 소요되게 된다.
네트워크 편에서도 잠시 보았던 것인데, TCP커넥션을 최초에 맺기 위해서는 서버와 클라이언트 간 핸드셰이크가 발생한다.
가장 처음 SYN 플래그를 전송하여 커넥션을 맺기를 요청하고, 서버는 ACK 플래그를 통해 커넥션이 생성되었다는 응답을 보내게 된다.
클라이언트는 마지막으로 커넥션이 잘 생성되었다는 의미에서 확인 응답을 보내게 된다. 그 이후 데이터를 주고받게 된다.
TCP 세그먼트는 데이터의 안전한 수발신을 위해 각각 순번과 체크섬을 갖게 된다.
세그먼트를 수신하게 되면 확인 패킷을 송신자에게 보내게 되는데, 송출하는 데이터 패킷에 작은 버퍼를 구현하여 그곳에 편승한다.
이러한 확인응답이 잦을 경우, 지연이 발생할 수 있다.
만약 여러개의 요청이 동시다발적으로 들어왔을 때, 순차적으로 트랜잭션을 처리하게 되면 소요시간이 꽤 길 것이다.
이에 따라 HTTP 커넥션의 성능을 높이기 위한 여러 방법들이 등장했다.
- 병렬 커넥션, 지속 커넥션, 파이프라인 커넥션, 다중 커넥션
병렬 커넥션의 경우 여러개의 요청-응답 간 지연시간을 겹치게 하여 빠르게 처리할 수 있도록 돕는다.
하지만 이 방법이 늘 빠른 것은 아니며, 네트워크 대역폭이 좁은 경우에는 순차적으로 데이터를 내려받는 것이 더 빠를 수 있다.
그럼에도 불구하고 사용자에게 동시에 여러개의 데이터를 내려받고 있다는 느낌을 주기 때문에 빠른 것처럼 보일 수 있다.
지속 커넥션의 경우 locality 특성을 이용한 것인데, TCP커넥션을 유지하여 다른 HTTP요청에도 응답하도록 하는 것이다.
TCP커넥션을 맺는 데에 소요되는 시간을 줄일 수 있다는 장점이 있다.
지속 커넥션과 병렬 커넥션에는 각각 장단점이 있다.
지속 커넥션은 커넥션을 생성하는 데에 소요되는 시간을 줄여주지만 계속 연결되어있는 상태를 유지하면서 불필요한 소모를 발생시키기도 한다.
이에 따라 지속 커넥션과 병렬 커넥션을 함께 사용하는 것이 효율적인데, 이 과정에서 keep-alive와 지속 커넥션 두 타입의 개념이 등장한다.
Keep-alive는 요청 헤더에 Connection:Keep-alive가 담기며, 서버에서 아무런 응답이 없을 경우 클라이언트는 응답 메시지를 수신하고 난 뒤 둘 간의 커넥션이 끊어질 것을 예상한다. 즉 커넥션을 유지하기를 요청하는 것이다.
Keep-alive를 하기 위해서는 엔터티 본문의 길이를 알 수 있어야 한다. 이에 따라 커넥션을 유지할 수 있기 때문이다.
HTTP/1.1에서는 Keep-alive를 다른 방식으로 유도하여 이용한다. 서버로 Connection:close 헤더를 명시하지 않으면 서버는 커넥션을 유지한다.
이번 글에서는 HTTP 메시지와 TCP 커넥션이 어떻게 맺고, 어떻게 효율적으로 성능을 낼 수 있는지에 대해 살펴보았다.
다음 글에서는 서버- 웹 서버와 프락시 서버에 대해 살펴볼 것이다.
참고도서
https://book.naver.com/bookdb/book_detail.nhn?bid=8509980
HTTP 완벽 가이드
성공적인 웹 트랜잭션 뒤의 숨은 핵심, HTTP의 모든 것『HTTP 완벽 가이드』는 HTTP 규약이 어떻게 작동하고 웹 기반 애플리케이션을 개발하는 데 어떻게 사용하는지 설명하고, HTTP가 효율적으로 동작하도록 함께 사용하는 다른 핵심 인터넷 기술에 대해서 소개한 책이다. 책에서는 HTTP 메서드, 헤더, 상태 코드, 프락시와 캐시의 최적화, 웹 로봇과 크롤러 설계 전략, 쿠키, 인증, 보안 HTTP, 국제화와 내용 협상, 리다이렉션과 부하 균형 전략, 더 좋은 성능의 HTTP, HTTP/2.0에 대해서 다루고 있다. 또한, 10...
book.naver.com
'Tech' 카테고리의 다른 글
HTTP - (3) 웹서버, 프락시에 대해 (0) | 2021.05.16 |
---|---|
Docker, getting-started with Python (0) | 2021.05.15 |
웹, HTTP - (1) HTTP 개괄, URL에 대하여 (0) | 2021.05.14 |
컨테이너 개념 이해 - (1) 가상화 (0) | 2021.05.14 |
인프라 구조 - 안정성과 성능 (0) | 2021.05.14 |