❓왜 알아보게 되었나
Next.js를 사용하면서 미들웨어 로거를 작성하여 찍어보게 되었다. 이때 응답 헤더에서 connection 설정이 keep-alive로 설정되어있는 것을 확인하게 되었다. 이것이 HTTP/1.1 프로토콜의 기본동작이라고 한다. 보통 앱을 호스팅하는 웹서버(Nginx, Apache, Vercel)에 따라 결정된다. HTTP/2에서는 이 옵션이 무시되며, 해당 프로토콜이 사용하는 다른 메커니즘에 의해 처리된다. 또한 응답 형식이 ReadableStream임을 확인하였다. 이에 대해 알아보고자 하였다.
‼ Header 속성, Connection
Header에는 현재의 요청 전송이 완료된 후 네트워크 접속을 유지할 지 제어할 수 있는 설정값 connection을 갖고 있다. ‘keep-alive’ 연결을 사용하면 연결 재사용을 지원하여 후속 요청에 대해 빠르게 응답할 수 있도록 한다.
‼Stream 형식의 응답
이 연결 속성은 stream 형식의 응답도 지원한다. 이때 chuncked encoding을 지원하므로 응답을 보내기 전, 전체 크기에 대해 알 필요가 없어진다. 큰 응답을 작은 단위로 나누어 처리하여 네트워크 지연이 최소화 되고, 서버 메모리 사용량을 최적화 할 수 있다. 또한 네트워크 버퍼를 효율적으로 사용하여 지연시간을 줄일 수 있고, 부분적 전송 실패 시 재전송이 용이하다.
‼HTTP 버전에 따른 keep-alive 옵션의 변화
- HTTP/1.0
- 기본적으로 요청-응답 후 닫힘 non-persistent
- 명시적으로 추가하면 TCP연결을 재사용 → 성능 향상
- HTTP/1.1
- 별도로 명시하지 않아도 연결이 기본적으로 유지
Connection: close 을 명시하여 연결을 끊을 수 있음
- HTTP/2.0
- 연결 유지와 요청 다중화 기본 지원
- 더 이상 keep-alive 가 명시적으로 사용되지 않음
- 단일 TCP 연결 위에서 여러 스트림을 동시에 처리 ⇒ 연결 유지 내재화
- HTTP/3.0
- UDP 기반의 QUIC 프로토콜 사용
- 연결 유지개념이 QUIC 에 포함되어 keep-alive 헤더 필요 하지 않음.
<aside>
📌
QUIC Quick UDP Internet Connections
TCP/TLS 의 한계를 극복
UDP 기반으로 TCP의 신뢰성(패킷 손실 복구, 순서 보장)과 TLS의 보안성 제공
- UDP 연결 설정 속도를 높이고 네트워크 지연을 줄임. 3-way handshake가 없음.
- 내장된 암호화 모든 데이터가 기본적으로 암호화. 별도의 TLS handshake 필요 없음.
- 스트림 다중화 한 스트림에서 패킷 손실이 발생해도 다른 스트림은 영향 받지 않음
- 연결 마이그레이션 4tuple이 아닌 고유 ID로 연결 식별자를 관리하여 네트워크 변경 시에도 연결이 끊기지 않음.
- 헤드 오브 라인 블록킹 해결: 여러 데이터 스트림을 단일 연결에서 병렬로 전송. TCP에서는 한 패킷의 손실이 전체 연결을 지연시키지만, QUIC는 독립적인 스트림 단위로 처리해 지연을 최소화합니다.
</aside>
❓ 서버는 어떻게 고유한 클라이언트를 구분할 수 있는걸까
전송제어프로토콜 TCP Transmission Control Protocol
2개의 호스트를 연결하고 데이터 스트림을 교환하게 해주는 네트워크 프로토콜.
데이터와 패킷이 보내진 순서대로 전달하는 것을 보장한다.
- 연결 지향적(connection-oriented)
- 신뢰성 있는 데이터를 전송
- 네트워크 상에서 고유하게 식별되어야 하므로, 4-tuple이라 불리는 4가지 요소의 조합을 사용한다.
- 소스 IP 주소: 연결을 시작하는 쪽(보통 클라이언트)의 IP주소
- 소스 포트 번호: 호스트에서 사용하는 포트번호(연결마다 자동할당)
- 목적지 IP 주소: 목적지(보통 서버)의 IP주소
- 목적지 포트 번호
- 4 tuple의 조합이 전체 네트워크에서 유일해야 TCP 연결이 제대로 식별되고 관리된다.