[HTTP 완벽가이드] 커넥션 관리

은승균·2022년 7월 13일
0

커넥션관리

이번장에서는 HTTP 커넥션과 관련된 내용을 다룬다.

  • HTTP는 어떻게 TCP 커넥션을 사용하는가
  • TCP 커넥션의 지연, 병목, 막힘
  • 병렬 커넥션, keep-alive 커넥션, 커넥션 파이프라인을 활용한 HTTP 최적화
  • 커넥션 관리를 위해 따라야 할 규칙

TCP 커넥션

모든 HTTP통신은 가장 널리 쓰이는 패킷 교환 네트워크 프로토콜의 계층화 된 집합인 TCP/IP를 통해 이루어진다.
TCP 통신은 신뢰성을 보장하는 연결 방식이다.

신뢰성을 보장한다는 것은 데이터가 중간에 손실 되거나 순서가 뒤바뀌지 않을 것을 보장한다는 것이다.

TCP/IP을 통해 서버의 리소스를 요청하는 과정은 아래와 같다.
리소스 URL
http://www.joes-hardware.com:80

  1. 브라우저가 www.joes-hardware.com 이라는 호스트의 IP를 검색한다.

  2. 브라우저가 포트번호(80)를 얻는다.

  3. 브라우저가 서버로 HTTP GET 요청 메시지를 보낸다.

  4. 브라우저가 HTTP 응답 메시지를 읽는다.

  5. 브라우저가 커넥션을 끊는다.

    위에서 볼 수 있듯이 HTTP연결은 IP와 포트번호를 이용하여 커넥션을 맺은 이후에 메시지를 주고받게된다.

TCP 스트림은 세그먼트로 나뉘어 IP 패킷을 통해 전송된다.

TCP 프로토콜은 세그먼트라는 단위로 데이터 스트림을 잘게 나누고, 이 세그먼트를 IP패킷 이라고 불리는 봉투에 담아서 데이터를 전달한다.

해당 과정은 TCP/IP 소프트웨어에 의해 처리되어 HTTP 프로그래머에게 보이지 않는다.

IP 패킷은 보통 3가지 부분으로 나누어 여러 정보를 담는다.

  • IP패킷 헤더 (보통 20바이트)

    • 발신자 및 목적지 IP 주소
    • 크기
    • 기타 플래그 등
  • TCP 세그먼트 헤더 (보통 20바이트)

    • TCP 포트번호
    • TCP 제어 플래그
    • 데이터 순서, 무결성 검사를 위한 값
  • TCP 데이터 조각(0 혹은 그 이상의 바이트)

생각해볼 점!
HTTP 프로토콜은 기본적으로 TCP/IP 연결을 통해서 이루어져 왔는데 HTTP/3.0에서는 왜 UDP를 채택했는가?

TCP 커넥션 유지하기

TCP는 포트를 통해 연결이 된다. 즉, 컴퓨터 한 대에는 여러 TCP 커넥션이 유지되고 있다는 것을 유추해볼 수 있다.
포트 번호는 회사의 내선 번호라고 생각하면된다. 한 컴퓨터(한 IP주소) 내에서 연결을 구분할 수 있다.

TCP 연결은 IP주소와 포트번호를 이용해 유일한 커넥션을 식별한다.

<발신지 IP주소, 발신지 포트, 수신지 IP주소, 수신지 포트>

유일한 커넥션을 위한 구성요소는 다른 TCP연결 끼리는 같을 수 없다. 일부분은 같을 수 있지만 다른 연결은 다른 조합을 가지고있다.

TCP 소켓 프로그래밍

TCP 커넥션을 위한 소켓 API가 있다. 소켓 API를 사용하면 TCP 엔드포인트 데이터 구조를 생성하고, 원격 서버의 TCP 엔드포인트에 해당 구조를 연결하여 데이터 스트림을 읽고 쓸 수 있다.
이러한 TCP API는 기본적인 네트워크 프로토콜의 핸드셰이킹과 TCP 데이터 스트림과 IP 패킷 간의 분할 및 재조립에 대한 모든 세부사항을 외부로부터 숨긴다.

TCP 성능에 대한 고려

HTTP 프로토콜읜 TCP 위의 계층이기 때문에 HTTP 트랜잭션의 성능은 TCP 성능에 영향을 받는다. 그러므로 성능 좋은 HTTP 애플리케이션 설계를 위해서는 TCP 성능의 특성에 대한 이해가 필요하다.

HTTP 트랜잭션 지연

HTTP의 커넥션, 전송, 처리의 지연은 TCP 커넥션에 비해 매우 짧다. 대부분읜 HTTP 지연은 TCP네트워크 지연때문에 발생한다.

HTTP 트랜잭션 지연 원인

  1. 최근에 방문한 적이 없는 URI의 호스트에 접속할 때는 DNS 인프라를 통해 호스트명의 IP를 알아내는 지연시간.

    최근에는 밀리초 단위로 DNS 이름 분석이 끝난다고 한다.

  2. HTTP 요청을 할 때마다 TCP 연결을 시도하고 응답을 받으면 끊기 때문에 HTTP트랜잭션이 일어날 때마다 TCP연결을 하는 시간이 발생한다.

    HTTP/1.0까지는 한 커넥션에 한 번의 요청만 가능했지만 버전이 올라가며 한 커넥션애 여러 요청을 보낼 수 있게 되었다.

  3. 요청 메시지가 인터넷을 통해 전달되고 서버에 의해 처리되는데 걸리는 시간
  4. 웹 서버가 HTTP 응답을 보내는 시간

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

TCP프로토콜의 기술적인 복잡성도 지연에 큰 영향을 끼친다.

성능 관련 중요 요소

  • TCP 커넥션의 핸드셰이크 설정
  • Congestion Control을 위한 TCP 느린 시작
  • 데이터를 한데 모아 한 번에 전송하기 위한 네이글(nagle) 알고리즘
  • TCP의 편승(piggyback) 확인응답(acknowledgement)을 위한 확인응답 지연 알고리즘
  • TIME_WAIT 지연과 포트 고갈

고성능의 HTTP 소프트웨어를 개발을 위해서는 위 항목을 잘 숙지하고 있어야한다.

TCP 커넥션 핸드셰이크 지연

HTTP 통신은 stateless 라는 특징이 있다고들 한다. 이 말은 HTTP 통신을 위해 TCP 커넥션을 매번 맺고 끊기 때문이다.
TCP 커넥션을 맺고 끊는다는 것은 핸드셰이크를 매번 한다는 것이다. 작은 크기의 요청을 여러번 하게 된다면 핸드셰이크로 인한 지연이 발생할 것을 짐작해볼 수 있다.

핸드셰이크 과정

  1. 클라이언트에서 서버로 SYN 플래그가 담긴 TCP 패킷을 보낸다.
  2. 서버는 패킷을 받아 SYNACK가 담긴 TCP패킷을 클라이언트에게 보낸다.
  3. 클라이언트는 커넥션이 잘 맺어졌음을 알리기 위해 확인 응답을 보낸다. 이때 확인 응답과 함께 데이터를 보낼 수 있다.

HTTP 프로그래머는 이러한 과정을 보지 못한다. TCP 패킷은 TCP 소프트웨어가 관리한다.
크기가 작은 HTTP 트랜잭션에서는 핸드셰이크 과정이 눈에 띄는 지연을 발생시킨다. HTTP 트랜잭션의 50%의 시간은 TCP를 구성하는데에 쓰인다.

확인 응답 지연

TCP는 신뢰성 있는 연결을 보장한다. 하지만 이러한 과정은 브라우저가 하지 않는다. 브라우저는 과부하가 걸렸을 때 마음대로 패킷을 버릴 수 있다. 그래서 TCP 패킷을 성공적으로 주고 받기 위해서 자체적인 확인 체계를 가진다.
TCP 세그먼트는 수신자가 잘 받았다는 확인 메시지를 보낸다. 확인 메시지는 충분히 작기 때문에 데이터 패킷에 확인 응답을 편승(piggyback) 시킨다.
하지만 HTTP 동작방식은 요청응답으로만 이루어져 있으 확인 응답이 송출 데이터 패킷에 편승할 기회를 감소시킨다. 편승을 할 수 있는 패킷이 막상 많지 않기 때문에 확인응답 지연 알고리즘으로 인한 지연이 자주 발생한다. 때문에 관련 기능을 지연의 원인이 되는 확인응답 지연 관련 기능을 수정하거나 비활성화 할 수 있다.

TCP 느린 시작(slow start)

TCP 커넥션이 맺어진 이후 시간이 지남에 따라 자체적으로 튜닝되어 데이터 전송 속도가 달라질 수 있다. 점차적으로 속도 제한을 해제하며 성능을 높여가는 것을 보고 느린 시작이라고 부른다.
이는 급작스러운 부하와 혼잡을 방지하는 데 쓰인다.

이러한 TCP 느린시작은 한 번에 전송할 수 있는 패킷의 수를 제한한다. 패킷이 성공적으로 전달되는 시점에 송신자는 추가로 2개의 패킷을 더 전송할 수 있는 권한을 얻는다.
한 번에 보낼 수 없는 양을 슬라이드를 밀어가며 보내는 방식으로 요청을 하는데, 이를 혼잡 윈도우를 연다라고 한다.

패킷을 1개부터 점차적으로 늘려가면서 슬라이딩 윈도우 방식으로 튜닝을 한다

혼잡 제어 때문에 이미 어느정도 데이터를 주고받은 튜닝 된 커넥션보다 느리다.

네이글(Nagle) 알고리즘와 TCP_NODELAY

애플리케이션에서 어떤 크기의 데이터든지 TCP 스택으로 전송할 수 있도록 TCP는 데이터 스트림 인터페이스를 제공한다.
하지만 TCP 세그먼트의 헤더는 최소 40바이트 상당의 정보를 포함하기 때문에 아주 작은 크기의 데이터를 실어서 보낸다면 이것은 매우 비효율적이게 된다.
매우 작은 크기의 데이터를 여러번에 걸쳐 실어서 보내게 된다면 매 요청마다 핸드셰이크를 하게 될 것이기 때문에 성능이 매우 떨어질 것을 예상할 수 있다.

이러한 문제점을 해결하기 위해 네이글 알고리즘이란 것을 사용한다. 이 알고리즘은 패킷을 전송하기 전에 많은 양의 TCP 데이터를 한 개의 덩어리로 합친다.
네이글 알고리즘은 패킷의 최대 크기 (LAN상에서는 1500바이트, 인터넷 상에서는 수백 바이트)를 채우지 않으면 전송을 하지 않는다.

단, 모든 패킷이 확인응답을 받았을 경우에는 최대 크기보다 작은 패킷의 전송을 허락한다.

현재 보내고 있는 패킷이나, 응답을 기다리는 패킷이 있다면 지금 보낼 데이터는 버퍼에 저장된다. 전송한 패킷에 대해 확인 응답을 받거나 버퍼에 충분한 데이터가 찼다면 새로운 패킷을 전송한다.

성능 문제

위의 설명대로라면 네이글 알고리즘을 사용한다면, 패킷을 바로 보내지 않아 성능상 문제가 발생할 것을 예상해볼 수 있다.
1. 크기가 작은 HTTP 요청에 대해서는 패킷을 채우지 못하기 때문에 지연될 것이다.
2. 확인응답 지연과 함께 쓰일경우 형편없이 동작한다.

확인 응답 알고리즘 : 확인 응답을 100~200밀리 초 지연시킨다. 이 시간동안 편승시킬 데이터를 찾는다.
네이글 알고리즘 : 확인 응답이 도착할 때까지 데이터 전송을 멈추고 있게 된다.

비활성화 방법

이러한 네이글 알고리즘을 비활성화 할 수 있다.
HTTP 스택에 TCP_NODELAY 파라미터 값을 설정하여 비활성화 시킬 수 있다.
비활성화를 했다면, 너무 작은 패킷이 생기지 않도록 직접 큰 크기의 데이터 덩어리를 만들어야 한다.

TIME_WAIT의 누적과 포트 고갈

보통 실제 상황에서는 문제를 발생시키지 않지만 성능 측정시에는 심각한 성능 저하를 가져온다고 한다.
TCP 커넥션의 엔드포인트에서 연결을 끊으면, 엔드포인트에서는 커넥션의 IP주소와 포트번호를 메모리에 기록해 놓는다. 보통 세그먼트의 생명주기의 2배(약 2분정도) 정도의 시간동안 같은 엔드포인트에 대해서 TCP 커넥션이 생기지 않도록 하기 위함이다.

현대의 라우터의 성능이 매우 좋아졌기 때문에 더 짧은 시간으로 설정하기도 하지만 조심해야한다.

이렇게 설정하는 이유는 이전 커넥션과 관련된 패킷이 같은 주소와 포트번호를 가지는 새로운 커넥션에 삽입되는 문제를 방지하기 위함이다. 즉, 목적지는 같지만 자신의 커넥션이 아닌 새로운 커넥션에 영향을 주지 않기 위해서 설정되었다.

만약 이전 커넥션의 패킷이 새로운 커넥션에 삽입된다면, 패킷은 중복되고 TCP 데이터는 충돌하게 된다.

유일한 커넥션을 만들기 위해서 포트번호만 바꿔가면서 연결하게 되는데 서버가 트랜잭션을 처리하는 시간이 매우 빠르다면 2분 동안 연결되지 못하는 상태에 있게되는 포트가 많아져 더 이상 연결할 수 있는 포트가 없게 되는 문제가 발생할 수도 있다.

HTTP 커넥션 관리

TCP 커넥션에 대해서 앞에서 알아보았다면 이 장에서부터는 HTTP 커넥션에 대해서 다룬다.

  • HTTP 커넥션 헤더
  • HTTP 커넥션 최적화 기술

위의 두가지를 다룬다.

Connection 헤더

HTTP 메시지는 클라이언트에서 서버까지 전달될 때 여러 중개 서버를 거칠 수 있다.
어떤 경우에는 현재 맺고 있는 커넥션에만 적용되어야 할 옵션을 설정해야할 때가 있다.

HTTP Connection 헤더 필드는 커넥션 토큰쉼표로 구분하고 있다. 이 값들은 다른 커넥션으로 전달되지 않는다.
Connection: close라고 명시하여 메시지를 보낸다음 끊어져야할 커넥션을 알릴 수 있다.

Connection 헤더에 전달될 수 있는 토큰 3가지 종류

  • HTTP 헤더 필드명 : 이 커넥션에만 해당되는 헤더들을 나열, 다른 커넥션으로 전달되면 안된다.
  • 임시적인 토큰 값 : 커넥션에 대한 비표준 옵션을 의미
  • close 값 : 작업이 종료되면 커넥션이 종료되어야 함을 의미

커넥션 헤더에는 홉별(hop-by-hop) 헤더 명을 기술한다. 홉별이란, 특정 두 서버간에만 영향을 미치고 다른 서버 간에는 영향을 미치지 않음을 의미한다.
그래서, 홉별 헤더를 통해 헤더를 다른 서버에게 전달되는 것을 막을 수 있다.
현재 홉에서 다음 홉으로 메시지를 보내기 전에 Connection 헤더의 값을 모두 지운다.

순차적 트랜잭션 처리에 의한 지연

순차적으로 처리한다는 것은 하나를 보내면 응답이 올때 까지 다음 트랜잭션을 처리하지 않는다는 것이다. 이러한 것은 한 트랜잭션에서 지연이 발생한다면 다른 모든 트랜잭션에도 영향을 미칠 수 있다는 것이다.

이것을 해결하는 방법은 크게 4가지가 있다.

병렬 커넥션

여러개의 TCP 커넥션을 이용해 동시 HTTP 요청

지속 커넥션

커넥션을 끊고 맺는 지연을 없애기 위한 TCP 커넥션 재활용

파이프라인 커넥션

공유 TCP 커넥션을 통한 병렬 HTTP 요청

다중 커넥션

요청과 응답들에 대한 중재(실험적)

병렬 커넥션

클라이언트가 여러개의 TCP 커넥션을 맺어 여러개의 HTTP 요청을 보낸다.

위의 그림과 같이 웹페이지의 각 컴포넌트들이 각각의 HTTP 커넥션에서 처리된다는 것을 볼 수 있다.

  • 커넥션이 동작하지 않는 시간 활용 가능
  • 병렬로 내려받아 각 지연시간을 겹치게 하여 총 지연 시간 단축 가능
  • 남는 대역폭을 다른 객체를 받아오는데에 사용 가능

항상 빠르지는 않다

일반적으로 병렬 커넥션이 빠르지만, 항상 그렇지는 않다.

  • 클라이언트의 대역폭이 좁을 때는 병렬로 내려받으려고 해도 제한이 생겨 의미가 없어진다.
  • 메모리를 많이 소모하고 자체적인 성능 저하문제 발생 가능
    • 클라이언트가 100개의 커넥션을 맺을 수 있다면, 사용자가 100명일 때 서버는 10000개의 커넥션을 맺어야 한다. 이는 고부하가 발생할 수 있다.

브라우저는 실제로 병렬 커넥션을 사용할 때 4개의 커넥션만 허용한다.

더 빠르게 느껴질 수 있다.

실제로 더 빠르게 내려받지 않는 경우도 있다. 하지만 동시에 여러 객체를 받아오는 것을 사람이 볼 때는 더 빠르게 내려받는 것으로 생각하게 된다.

지속 커넥션

클라이언트는 보통 같은 사이트에 여러개의 커넥션을 맺는다. 같은 서버에 여러번 요청하게 되는데, 이것을 사이트 지역성(site locality)라고 부른다.
이런 특성을 활용하기 위해 HTTP/1.1 버전을 지원하는 기기는 HTTP 요청 처리가 완료 된 이후에도 TCP 커넥션을 유지하여 앞으로 있을 HTTP 요청에 재사용할 수 있다. 이러한 TCP 커넥션을 지속 커넥션 이라고 부른다.
이러한 지속 커넥션은 서버가 연결을 끊기 전까지 트랜잭션 간 커넥션이 유지된다. 이를 통해 TCP의 느린시작으로 인한 지연을 피할 수 있다.

장점

  • 커넥션을 맺기 위한 지연을 줄여준다.
  • 튜닝된 커넥션을 유지할 수 있다.
  • 커넥션의 수를 줄여준다.

단점

  • 지속 커넥션을 잘못 관리할 경우, 연결된 커넥션이 쌓이게 될 것이다.
  • 리소스의 불필요한 소모가 생길 수 있다.

지속 커넥션과 병렬 커넥션을 같이 사용할 때 가장 효과적이다. 적은 수의 병렬 커넥션만을 맺고 이 커넥션을 유지한다.

HTTP/1.0+의 Keep-Alive 커넥션

keep-alive의 장점은 아래의 그림에서 확인할 수 있다.

같은 HTTP 트랜잭션 4개에 대해서, 연속적으로 커넥션을 맺고 끊으면서 처리하는 방식과 하나의 커넥션을 유지하여 처리하는 방식을 비교하였다.

HTTP/1.1부터는 Keep-Alive를 사용하지 않기로 명세가 나왔지만, 여전히 Keep-Alive 핸드셰이크가 서버-브라우저 간에 사용되고 있기 때문에 처리할 수 있도록 개발해야한다.
처리하기 위해서 클라이언트는 요청에 Connection:Keep-Alive 헤더를 포함시킨다. 서버는 응답 메시지에 같은 헤더를 포함시켜 응답한다.
클라이언트는 응답에 이 헤더가 없을 때는 서버가 커넥션을 끊을 것이라고 추정한다.

Keep-Alive 옵션

Keep-Alive 헤더는 커넥션을 유지하기 바란다는 요청일 뿐이며, 클라이언트나 서버는 연결을 유지해야 할 의무는 없다. 언제든지 커넥션을 끊어 처리되는 트랜잭션의 수를 제한할 수 있다.

Keep-Alive 헤더의 쉼표로 구분된 옵션을 제어한다.

옵션

  • timeout : 얼마나 유지할 것인가
  • max : 몇 개의 HTTP 트랜잭션을 처리할 때까지 유지될 것인지
  • name[=value] : 디버깅을 주 목적으로하는 임의의 속성
  Connection: Keep-Alive
  Keep-Alive: max=5, timeout=20

제한과 규칙

  • HTTP/1.0으로부터 오는 Connection 헤더 필드는 무시해야한다. 오래된 프락시 서버로부터 실수로 전달될 수 있기 때문
  • Connection 헤더를 인식하지 못하는 프락시 서버와는 맺어지면 안된다.

멍청한(dumb) 프락시와의 전달에서 문제가 발생할 수 있다.
커넥션 헤더를 인식하지 못하기 때문에 클라이언트와 서버는 커넥션을 유지하지만 커넥션은 이를 수행하지 못하기 때문에 같은 커넥션으로부터 다른 요청이 올 것을 예상하지 못한다. 그렇기 때문에 타임아웃이 나서 커넥션이 끊길때 까지 기다린다.

  • 응답 전체를 받기 전에 연결이 끊어지면 클라이언트는 요청을 다시 보낼 수 있게 준비 되어야한다.

프락시와 홉별 헤더

일반적인 Connection 헤더가 아닌 홉별로 적용되는 홉별 헤더를 사용하면 이 문제를 어느정도 해결할 수 있다. 일반적인 커넥션 헤더는 다음 홉으로 무조건 보내버리지만, 홉별 헤더를 사용하면 다음 홉으로 보내지 않는다.

하지만 모두 멍청한 프락시 또는 모두 영리한 프락시로 이루어지지 않으면 문제가 발생한다.

그렇기 때문에 HTTP/1.1에서는 keep-alive 커넥션을 사용하지 않는다.

HTTP/1.1의 지속커넥션

HTTP/1.1에서는 keep-alive 커넥션을 지원하지 않는 대신, 설계가 더 개선된 지속 커넥션을 지원한다.
HTTP/1.1에서는 기본적으로 활성화 되어있다. 별도 설정을 하지 않는한 모든 커넥션을 지속 커넥션으로 취급한다. 오히려 커넥션을 끊기 위해 Connection:close 헤더를 명시해야한다.

지속 커넥션의 제한과 규칙

  • Connection: close 헤더를 포함했으면 해당 커넥션으로 추가적인 요청을 보낼 수 없다.
  • 클라이언트는 추가적이 요청을 보내지 않을 것이라면Connection: close 헤더를 보내야 한다.
  • 커넥션에 있는 모든 메시지가 자신의 길이 정보를 정확히 가지고 있을 때에만 지속시킬 수 있다.
  • HTTP/1.1 프락시는 클라이언트와 서버 각각에 대해 별도의 지속 커넥션을 맺고 관리해야 한다.
  • HTTP/1.1 프락시 서버는 클라이언트가 커넥션 관련 기능에 대한 클라이언트의 지원 범위를 알고 있지 않으면 지속하면 안된다.
  • HTTP/1.1 기기는 커넥션 헤더의 값과는 상관없이 언제든지 커넥션을 끊을 수 있다.
  • HTTP/1.1 애플리케이션은 중간에 끊어지는 커넥션을 복구할 수 있어야만 한다. 클라이언트는 다시 보내도 괜찮은 요청은 가능한 다시 보내야한다.
  • 클라이언트는 2개의 지속 커넥션만을 유지해야한다. 서버는 2N 개의 커넥션을 유지해야한다.

파이프라인 커넥션

지금까지 봐왔던 요청은 네크워크 상에서 요청->응답, 즉 메시지가 보내지면 돌아온 이후에 다음 요청을 수행하였다. 하지만 파이프라인 커넥션을 이용하면 처음 보낸 요청에 대한 응답이 도착하기 전까지 보내질 수 있다. 이는 전송 대기시간을 단축시킬 수 있는 효과가 있다.

하지만 모든 요청을 보낼 수 있는 것은 아니다. POST와 같이 반복해서 보낼 경우 문제가 생기는 요청은 파이프라인을 통해서 보내면 안된다.

커넥션 끊기

커넥션 관리 중 언제 어떻게 커넥션을 끊는가에는 명확한 기준이 없다.

다음과 같은 방법으로 커넥션 끊기를 관리한다

마음대로 끊기

보통은 메시지를 다 보낸 다음 끊지만, 에러가 있는 상황에서는 헤더의 중간이나 다른 엉뚱한 곳에서 끊길 수 있다.
파이프라인 지속 커넥션에서와 같이 HTTP 애플리케이션은 언제든지 지속 커넥션을 임의로 끊을 수 있다.
서버 쪽에서 임의로 커넥션을 끊게 된다면, 클라이언트 측에서 요청을 보낼 때 문제가 생기게 된다.

Content-Length와 Truncation

각 HTTP 응답은 본문의 정확한 크기 값을 가지는 Content-Length 헤더를 가지고 있어야 한다.
클라이언트는 실제 전달된 엔티티의 길이와 Content-Length의 값이 일치하지 않거나 헤더가 존재하지 않으면, 데이터의 정확한 길이를 서버에 물어봐야 한다.

수신자가 캐시 프락시일 경우, 캐시를 하지 않고 Content-Length 헤더를 수정하려고 하지 말고 그대로 전달해야 한다.

커넥션 끊기의 허용, 재시도, 멱등성

커넥션은 에러가 발생하지 않았어도 끊을 수 있다. 트랜잭션을 수행 중에 커넥션이 끊기게 되면, 클라이언트는 트랜잭션을 재시도하더라고 커넥션을 다시 맺고 한번 더 전송을 시도해야한다.

하지만 POST와 같은 부류의 요청은 여러번 반복하면 심각한 오류를 발생시킬 수 있다. 예를 들면, 온라인 주문 중에 POST요청을 여러번 하게 된다면 중복 주문이 생길 수 있다.

이와 반대로 여러번 실행해도 같은 결과를 반환한다면 멱등(indempotent)하다고 한다. GET,PUT,HEAD,DELETE,TRACE 그리고 OPTIONS 메서드는 멱등하다.

우아한 커넥션 끊기

profile
3대 500을 향해서

0개의 댓글