HTTP — 상태 없는 프로토콜과 연결 재사용
한 줄 요약
HTTP 는 요청 하나에 응답 하나를 돌려주는 상태 없는 규약이며, 성능의 역사는 그 위에서 TCP 연결을 어떻게 아껴 쓰느냐의 역사였다.
왜 이게 필요했나
HTTP/1.0 은 요청마다 TCP 연결을 새로 맺고 끊었다. 이미지 30개가 들어간 페이지를 열면 연결을 30번 맺는다. 연결 하나마다 왕복 한 번(TLS 까지 쓰면 두세 번)이 추가되므로 지연이 곧바로 사용자 체감으로 이어졌다.
주문 생성 요청의 응답만 유실된 상황을 시간 순서로 따라가 보자.
- 클라이언트 요청주문 생성 POST를 보낸다.
- 서버 처리주문을 저장했지만 응답이 클라이언트에 도착하지 않는다.
- 클라이언트 타임아웃주문이 없다는 뜻이 아니라 성공 여부를 모르는 상태다.
여기서 구분할 것 네트워크 오류와 업무 실패를 같은 값으로 처리하면 재시도가 중복 주문을 만들 수 있다.
잠깐, 예측해 보세요 같은 POST를 새 주문처럼 다시 보내면 어떤 위험이 있을까?
설명 확인 · 채점 없는 자가 점검
첫 요청이 이미 처리됐다면 중복 생성될 수 있다. API가 지원하는 멱등성 키나 요청 식별자로 이전 처리 결과를 확인하는 설계가 필요하다.
어떻게 동작하나
HTTP/1.1 의 keep-alive 는 응답 후에도 연결을 열어 두고 다음 요청에 재사용한다. 왕복 비용을 크게 줄였지만 한계가 있다. 한 연결에서 응답은 요청 순서대로 나와야 한다. 앞 요청이 느리면 뒤 요청이 기다린다(응용 계층의 헤드 오브 라인 블로킹). 브라우저들이 도메인당 연결을 6개쯤 여는 방식으로 우회했고, 그래서 자원을 여러 도메인에 흩뿌리는 기법까지 유행했다.
HTTP/2 는 한 연결 안에서 요청을 스트림으로 다중화해 이 문제를 없앴다. 헤더도 압축한다. 다만 여전히 TCP 한 연결 위에 있으므로 패킷 하나가 손실되면 그 뒤의 모든 스트림이 함께 멈춘다. 응용 계층의 줄서기를 없앴지만 전송 계층의 줄서기는 남았다.
HTTP/3 는 QUIC(UDP 기반) 위로 옮겨 스트림별 독립 전달을 얻었다. 한 스트림의 손실이 다른 스트림을 막지 않는다.
메서드의 의미도 규약의 일부다. GET 은 안전하고(부수 효과 없음) 멱등하며, PUT 과 DELETE 는 안전하지 않지만 멱등하고, POST 는 둘 다 아니다. 멱등성은 재시도 가능성과 직결된다. 타임아웃이 났을 때 요청이 서버에 도달했는지 알 수 없으므로, 멱등하지 않은 요청을 무심코 재시도하면 주문이 두 번 생긴다. 그래서 결제 API 들이 멱등성 키를 요구한다.
상태 코드도 뭉뚱그리면 안 된다. 4xx 는 요청을 고쳐야 하고 5xx 는 서버 문제이므로 재시도가 의미 있을 수 있다. 특히 502, 503, 504 는 원인이 다르다. 502 는 게이트웨이가 백엔드에서 잘못된 응답을 받았고, 503 은 서비스가 스스로 감당 못 한다고 말한 것이며, 504 는 게이트웨이가 백엔드를 기다리다 지친 것이다. 로그에서 이 셋을 구분하지 않으면 엉뚱한 곳을 파게 된다.
현장에서 만나는 모습
커넥션 풀 설정이 흔한 사고 지점이다. 클라이언트는 keep-alive 로 연결을 재사용하려는데 서버나 중간 로드밸런서의 유휴 타임아웃이 더 짧으면, 서버가 막 닫은 연결에 클라이언트가 요청을 보내는 경합이 생긴다. 증상은 간헐적인 연결 재설정이고 부하와 무관하게 일정 비율로 나타난다. 클라이언트의 유휴 타임아웃을 서버보다 짧게 잡는 것이 정석이다.
같은 TCP 연결을 다시 쓴다는 사실만으로 사용자를 기억하는 것은 아니다.
- 연결의 수명Keep-alive와 커넥션 풀은 새 연결을 맺는 비용을 줄인다.
- 업무 상태의 수명로그인·장바구니 상태는 쿠키, 토큰, 서버 저장소 등의 설계로 관리한다.
여기서 구분할 것 HTTP의 무상태성과 웹 서비스의 로그인 기능은 모순되지 않는다. 응용이 상태를 따로 관리한다.
잠깐, 예측해 보세요 연결이 새로 맺어지면 로그인도 반드시 풀릴까?
설명 확인 · 채점 없는 자가 점검
아니다. 유효한 세션 식별자와 서버 상태가 유지된다면 새 연결에서도 같은 사용자로 요청할 수 있다.
이어지는 퀴즈에서 확인할 것
버전별로 무엇이 해결되고 무엇이 남았는지, 멱등성이 왜 재시도 설계의 전제인지 설명할 수 있는지 확인한다.