[HTTP] 커넥션 관리에 대해서

dev stefanCho·2022년 3월 1일
0

http-definition-guide

목록 보기
3/3
post-thumbnail

이번에는 다소 와닿지 않는 내용에 대해서 정리하고자 합니다.
HTTP의 커넥션이 어떻게 만들어지는지 유지되는지에 대해서 설명해봅니다.

Network Protocol Stacks

우선 Network Protocol Stack에 대해 알아야합니다.

우선 우리가 다루는 HTTP는 Application Layer에 있습니다. 바로 아래에 TCP(Transport Layer)과 IP(Network Layer)가 있습니다.
HTTPS의 경우 HTTP와 TCP사이에 TLS/SSL(Security Layer)가 추가로 있습니다.

TCP 커넥션을 해야합니다.

우선 HTTP 커넥션이 일어나기전에 TCP 커넥션(연결)이 되어야합니다.
HTTP는 TCP 커넥션을 통해서 메시지 데이터를 순차적으로 보내기 때문입니다.

TCP 커넥션이란?

그래서 TCP 커넥션은 무엇일까요?
TCP 커넥션은 발신지(클라이언트)의 IP와 Port, 수신지(서버)의 IP와 Port 이렇게 4가지 값으로 식별합니다.

<발신지 IP 주소, 발신지 Port, 수신지 IP 주소, 수신지 Port>

식별이라는것은 유일함을 의미합니다. 즉 이 4가지 값의 조합은 단 1개만 존재할 수 있습니다.

TCP 커넥션의 과정

위 이미지를 바탕으로 설명을 해보겠습니다.

  • 서버는 S1~S4까지 TCP 연결준비를 합니다.
  • 클라이언트에서 서버연결을 요청하면(C3), 서버는 이것을 받아서(S5) 연결이 되었다고 응답을 보내줍니다. (C4)
  • 그리고 클라이언트는 HTTP 요청을 보내고(C5) 서버는 이 메시지를 처리합니다.(S7)
  • 서버는 처리한 후에 다시 클라이언트로 응답을 보냅니다.(C7)
  • 그리고 TCP연결이 종료됩니다.

HTTP 트랜젝션 지연


이런 트렌젝션 과정에서는 커넥션 설정 과정에서 지연이 발생하게 됩니다. (커넥션 하는 시간 자체가 지연으로 느껴지는 것)
실제로 처리(Process)시간보다 연결(DNS를 찾아서 TCP 커넥션을 하는 것)하고 끊는데에 시간을 많이 쓰는 것입니다.(요청을 전달하고 응답을 전달하는데에도 시간이 걸리고)
작은 메시지를 처리하기 위해서 이런 TCP 연결을 자주하는 것은 여러가지 환경에 영향을 크게 받을 것입니다.

예를 들면 TCP 네트워크 지연은 하드웨어 성능, 네트워크와 서버의 전송속도, 요청과 응답 메시지의 크기, 클라이언트와 서버 간의 거리에 따라 크게 달라 질 수 있습니다.

TCP 커넥션 핸드쉐이크 지연

새로운 TCP커넥션을 열때는 커넥션을 맺기 위한 조건을 맞추기 위해서 연속으로 IP 패킷을 교환합니다.(여기에서 시간지연이 발생함)
크기가 작은 HTTP 트렌젝션은 50%이상의 시간을 이러한 TCP를 구성하는데 쓰게 됩니다.

TCP의 느린시작(slow start)

TCP 커넥션은 최초로 만들어졌다면 시간이 좀 더 걸립니다. 최초 커넥션에는 최대속도를 제한하고 데이터를 성공적으로 보내는것에 주력합니다.
이 후부터는 자체적으로 튜닝을 하여 속도제한을 높여갑니다. 이렇게 조율하는 것을 TCP 느린 시작(slow start)라고 합니다.
이 때문에 새로운 커넥션은 어느정도 데이터를 주고 받은 튜닝된 커넥션보다 항상 느립니다.
이를 보완하기 위해서 지속 커넥션이라는 것이 있습니다.

HTTP 커넥션

HTTP 커넥션은 몇가지 방식이 있습니다.

HTTP Connection 헤더에 관하여

Connection이라는 헤더는 클라이언트와 서버간의(혹은 서버와 서버, 프록시와 서버 등등) 연결을 유지하기 위해서 사용합니다.
HTTP는 클라이언트와 서버사이에 프록시 서버, 캐시 서버 등의 중개 서버가 놓이는 것을 허락합니다. 이런 중간의 서버들 포함해서 연결을 유지하기 위해서 명확히 Connection 헤더를 처리할 필요가 있습니다. (Connection 헤더에 관한것은 다소 내용이 지루하므로 생략합니다.)

순차적 트랜젝션 처리에 의한 지연(Serial Transaction Delays)


순차처리는 이미지와 같이 커넥션연결, 끊음을 반복하는 것입니다.
위 이미지는 한 웹페이지에서 HTML페이지를 가져오고 이미지 3개를 가져오는것을 예로 든 것입니다.

병렬 커넥션(Parallel Connections)

여러개의 TCP 커넥션을 통해서 동시에 HTTP 요청을 하는 것입니다.

단일 커넥션의 대역폭을 쪼개서 사용하는 것입니다. 따라서 다수의 커넥션을 병렬로 만들게 되면 메모리를 많이 소모하고 자체적 성능에 문제가 발생할 수 있습니다. 브라우저는 실제로 병렬 커넥션을 사용하긴 하지만 적은수(4개정도)만 허용합니다.
서버는 특정 클라이언트로부터 과도한 수의 커넥션이 맺어졌을 경우, 임의로 끊어버릴 수 있습니다.

지속 커넥션(Persistent Connections)

커넥션을 맺고 끊는데에 발생하는 지연을 제거하기 위해서 TCP 커넥션을 재활용합니다.
처리가 완료된 후에도 계속 연결된 상태를 유지하는 것이 지속 커넥션입니다.

지속 커넥션은 병렬 커넥션과 비교해서 장점과 단점이 있습니다.

장점 (병렬커넥션과 비교해서)

  • 병렬 커넥션은 병렬로 일어나는 각 커넥션에서 시간지연과 대역폭이 소요된다.
  • 병렬 커넥션에서 새로운 커넥션은 slow start에 의해 성능이 떨어진다.
  • 병렬 커넥션수는 제한이 있다.

단점 (지속 커넥션의 단점)

  • 지속 커넥션을 잘못 관리할 경우 계속 연결된 상태로 수많은 커넥션이 쌓이게 된다. 따라서 불필요한 리소스 소모를 발생할 수 있다.

이런 지속커넥션을 하기 위해서는 위에서 언급한 Connection 헤더를 통한 통신이 필요합니다.(Connection 헤더를 요청에 담는 것은 지속커넥션을 하고 싶다는 것을 의미합니다.)

HTTP/1.0+(HTTP/1.0의 개선버전)에서는 Keep-Alive라는 방식을 사용합니다.
Keep-Alive방식을 사용할때는 멍청한 프록시(dumb proxy)에 의해서 문제가 발생할 수 있습니다.
(특별히 HTTP/1.0을 사용할 일은 없을거라 생각하기 때문에 이 부분은 생략합니다.)

HTTP/1.1의 지속 커넥션

HTTP/1.1에서는 Keep-Alive를 지원하지 않습니다. 대신 기본으로 지속커넥션이 활성화 됩니다.
별도 설정을 하지 않는 이상 모든 커넥션을 지속 커넥션으로 취급하는 것입니다.
(커넥션을 끊을 수 없다는 것은 아니고, Connection: close 헤더를 이용하여 언제든 끊을 수 있습니다.)

파이프라인 커넥션(Pipelined Connections)

HTTP/1.1은 지속커넥션을 하면서 파이프라이닝(응답이 오기전에 다른요청을 계속 보내는것)을 할 수 있습니다.

파이프라이닝을 할 때 주의할 점은 nonidempotent요청을 보내지 않는 것 입니다.
(idempontent(멱등)는 unchanged value를 의미합니다. 따라서 nonidempotent(비멱등)는 value가 변경되는 것을 의미합니다.)

예를 들어 POST 요청은 응답처리를 하면 서버데이터를 요청할 때마다 변경시킵니다. 이것을 nonidempotent라고 합니다.
이런 요청은 중간에 끊어지게 되면 문제를 일으킬 수 있으므로, 파이프라이닝으로 처리하면 안됩니다.
브라우저에서 캐시된 POST 요청 페이지를 다시 load하려고 할때, 요청을 다시 보내겠냐고 묻는 경우가 바로 이런이유 때문입니다.

반면 GET, HEAD, PUT, DELETE, TRACE, OPTIONS와 같은 요청들은 여러번 발생하더라도 같은 결과를 반환하므로 idempotent하다고 할 수 있습니다.

TCP 커넥션 끊기

TCP 커넥션은 양방향입니다. 출력, 입력, 혹은 둘다 끊음으로서 연결을 종료할 수 있습니다.

우아한 커넥션 끊기(Graceful Connection Close)

커넥션을 끊는 방법은 서버의 출력을 끊기, 서버의 입력을 끊기, 서버 입/출력 모두 끊기 이렇게 3가지가 있습니다.
이중에서 서버의 출력만 끊는 것을 Graceful Connection Close라고 합니다.
(일반적으로 Graceful Connection Close는 자신의 출력을 먼저 끊고, 다른쪽 기기의 출력이 끊기는 것을 기다리는 것을 의미하기 때문입니다.)
보통은 커넥션의 출력 채널을 끊는 것이 안전하다고 합니다.

마치며

HTTP 메시지만을 주로 다루었지만, 그 기저에 있는 TCP와 IP에 대해서도 공부할 필요가 있었습니다. 프론트 개발을 하면서 직접 TCP통신을 마주할일은 없지만(확인할 방법도 없고..), 대략적인 느낌이라도 알아두는 것은 분명 큰 문제를 만났을 때 도움이 될 것 같습니다.
서로 다른 서버간의 트랜젝션이 어떻게 작동하고 유지되는지에 대한 내용이었습니다.

profile
Front-end Developer

0개의 댓글