HTTP의 통신에 있어서 서버와 클라이언트가 request, respose를 수송신할 때, 해당 트랜잭션을 어떻게 설정하고 유지하느냐가 쟁점일 것이다. 더 나아가 단 한 페이지가 요구하는 이미지와 데이터량이 계속하여 늘어나는 현 시대의 웹사이트에서 효율적인 커넥션은 매우 중요하다.
커넥션의 방식은 http 1.0과 1.1을 기준으로 아래와 같다.
- 순차적인 트랜잭션의 처리 (그림 1 상 short-lived connection)
- request와 response를 순차적으로 진행한다. 커넥션이 트랜잭션마다 새로 생성된다.
- 트랜잭션의 시작과 종료 마다 커넥션을 반복하기 때문에 성능상 문제가 발생할 수 있다. 그러니까 http의 통신의 처음과 끝을 계속 반복해야 한다. DNS resolution, tcp 커넥션의 요청과 응답의 과정으로 핸드셰이크 등을 반복. 오버헤드(실제 전송하고자 하는 데이타 이외의 데이타)가 과도하가 발생.
- 핸드셰이크 : 서버와 클라이언트가 커넥션을 맺기 위한 조건을 맞추기 위해 패킷을 교환한다. 핸드셰이크로 인해 수백 바이트가 소모된다. 이러한 핸드셰이크의 문제를 해소하기 위하여 이미 존재하는 커넥션을 재활용하는 지속 커넥션을 사용한다.
- TCP의 느린시작 : 커넥션이 처음 시작했을 때 인터넷의 과부화를 막기 위하여 커넥션의 최대속도를 제한한다. 데이타의 송신이 성공적으로 전송됨에 따라 속도제한을 점차 높혀간다. 커넥션이 새로 생성되면 느린시작을 다시 해야 하므로 속도 문제가 발생한다.
- 병렬 커넥션
그림 2 (출처 : https://www.oreilly.com)
- 순차적인 트랜잭션 처리의 문제를 해소하기 위하여 병렬 커넥션을 사용한다. 커넥션을 여러 개를 동시에 만드는 방식이다.
- 다수의 트랜잭션을 사용하기 때문에 속도가 빠르다.
- 하지만 다수의 트랜잭션을 동시에 사용하기 때문에 성능 문제가 발생한다. 성능 문제로 인한 과부하로 더 오래 걸릴 수도 있다.
- 네트워크 대역폭(최대 속도)이 너무 느려 여러개의 트랜잭션에 대한 최대 속도를 보장하지 못할 경우 성능 상 장점이 사라진다.
- 각 트랜잭션마다 커넥션을 연결하기 때문에, 다수의 커넥션으로 인한 성능 문제는 1. 순차적 트랜잭션의 처리와 다르지 않음.
- 지속 커넥션
- 그림 1의 persistent connection과 같이, 커넥션을 유지하는 방식이다. 반복적인 커넥션의 생성과 종료를 해결한다. 오늘날 웹에서는 병렬 커넥션과 지속 커넥션을 함께 사용.
- http 1.0 기준으로 지속 커넥션을 사용하기 위해서 connection:Keep-Alive를 헤더에 포함시킨다. HTTP 1.1을 기준으로 default 값이 되었다. HTTP 1.0을 사용하는 웹이 존재하므로 이에 대한 대응이 필요하다.
- 사용하지 않는 커넥션이 계속 연결되어 있으면 성능 저하 문제가 발생할 수 있다. 커넥션의 종료는 Connection:close로 커넥션 종료를 명시하는 방식과 Connection:Keep-Alive의 교환을 더 이상 하지 않는 방식이 있다.
- Connection은 hop-by-hop으로서 단 한 번의 전송만 목표로 한다. 그러니까 해당 헤더를 수신 받은 서버는 Connection 헤더를 지우고 다음 서버에 데이타를 발신해야 한다. 하지만 hop-by-hop임을 이해하지 못하는 프록시로 인해, 해당 필드를 삭제하지 않은 채 서버와 클라이언트에 헤더를 보낼 수 있다. 이로 인하여 서버와 클라이언트가 무의미하게 커넥션을 유지되는 경우도 있다. 이를 해소하기 위해 proxy-connection 을 사용하지만, 이 방법으로 문제가 완전하게 해결되지 않음. HTTP 1.1는 이 문제로부터 좀 더 자유롭다고 함.
- 결과적으로 커넥션을 재활용함에 따라 핸드쉐이크/지연로딩으로 인한 성능저하를 해결할 수 있음. 그러나 커넥션의 유지와 종료의 불완전성으로 인해 성능 문제가 발생할 수 있음.
- 파이프라인 커넥션
- 그림 1의 HTTP Pipelining과 같다.
- 지속 커넥션에서 여러 트랜잭션을 동시에 처리한다. 여러개의 request와 여러개의 response를 queue에 누적하여 처리한다. 하지만 요청에 대한 처리가 완벽하게 되었는지에 대하여 보장하지 않는다. 그러므로 POST와 같은 비멱등성(nonidempotent) 요청에 대해서는 사용해서는 안된다.
- 비멱등성이란, 연산이 일어날 때마다 결과가 변할 수 있음을 뜻한다. form 데이타는 요청에 따라 변경될 수 있지만 get 요청은 수십차례 요청해도 값이 변하지 않을 것이다.
참고 :
"http완벽가이드", 데이빗 고울리 외
https://developer.mozilla.org/ko/docs/Web/HTTP/Connection_management_in_HTTP_1.x