본문 바로가기

CS 전공수업/컴퓨터 네트워크

[네트워크] QUIC 프로토콜

QUIC을 왜 쓰냐?

 

 

지난 40여년간 통신 쪽을 꽉 잡고 있었던 TCP도, 한계는 있었다.

예를 들어, 연결 설정 지연, HOL 블로킹, 복잡한 프로토콜 스택 등이다.

QUIC은 한마디로, TCP의 한계점들을 해결하기 위해 드드등장했다. 위의 한계점들을 아래와 같이 극복한다.

 

1 연결 설정 지연:

TCP는 연결 설정을 위해 3-way handshake를 사용했고, TLS를 쓰면 추가적인 3-way handshake를 해야하기에 2번의 3-way HS가 필요했다. 이에 비해 QUIC은, 연결 설정 시 0 또는 1 RTT 핸드셰이크를 사용함. 심지어 한 번 연결했더라면, 0RTT로 가능함. 그리고, QUIC은 TLS를 자체 프로토콜 내에 통합했기 때문에, 별도의 TLS 핸드셰이크가 필요하지 않기 때문에 더욱 편리함.

 

2 헤드 오브 라인 블로킹:

TCP는 패킷이 순서대로 도착해야 하기 때문에, 중간에 손실된 패킷이 있으면 해결 전까지 이후 패킷 처리할 수 없음.

-> HTTP 1.1 때는 HTTP 자체 기술적으로 결함이 있었기 때문에 HOL이 있었고, HTTP2에서는 멀티플렉싱을 적용했으나 HTTP가 주로 TCP 위에서 이뤄졌기 때문에 TCP의 결함으로 HTTP2의 멀티플렉싱이 무용지물이 되었다. 그런데 이제 TCP 대신 QUIC을 쓰기 때문에, HTTP2의 멀티플렉싱 기능을 활용할 수 있게 됨.

 

3 UDP 기반:

QUIC는 TCP 대신 UDP를 사용하기 때문에, UDP의 장점인 적은 패킷 지연연결 설정 노필요라는 큰 장점을 그대로 가져옴.

 

 

QUIC 동작 원리

1 초기 핸드셰이크:

  • 클라이언트 -> 서버: 초기 패킷(클라이언트 암호화 키와 TLS 초기 데이터)을 전송하여 연결 요청.
  • 서버 -> 클라이언트: 요청 수락하고, 자신 암호화 키와 인증서를 포함한 응답 패킷 전송.
  • 클라이언트: 서버 응답 받아 연결 설정됨.
  • 만약 이전에 연결이 있었다면, 즉시 재개 가능.

2 데이터 전송:

  • 스트림 기반 전송: 여러 개의 스트림을, 독립적으로 동시에 처리할 수 있음.
  • TCP처럼 손실된 패킷을 재전송하는 매커니즘. 이때도 스트림 간의 독립성을 유지한다는 게 핵심.
  • 물론 스트림끼리의 독립성 덕에 문제의 스트림 제외 나머지는 정상이지만, 해당 스트림 내의 지연은 여전함.

 

Frame < Packet < Stream < Connection

 

QUIC 스트림(Streams)

스트림은 QUIC 연결 내에서 독립적으로 데이터를 전송할 수 있는 논리적인 단위. QUIC는 여러 스트림을 단일 연결 내에서 멀티플렉싱할 수 있으며, 각 스트림은 독립적으로 데이터를 전송하고 수신할 수 있습니다.

각 스트림은 고유한 스트림 ID를 가지며, 이는 스트림을 식별하는 데 사용됩니다.

QUIC 패킷(Packets)

패킷은 QUIC 데이터 전송의 기본 단위입니다. 패킷은 여러 프레임을 포함할 수 있으며, UDP 데이터그램으로 전송됩니다.

  • 초기 패킷 (Initial Packet): 연결 설정을 시작하기 위해 사용됩니다. 클라이언트에서 서버로 전송되며, 클라이언트의 암호화 키와 TLS 1.3 초기 데이터가 포함됩니다.
  • 핸드셰이크 패킷 (Handshake Packet): 연결 설정 중에 사용됩니다. 서버가 클라이언트에게 응답할 때 전송됩니다.
  • 단계별 패킷 (Short Header Packet): 연결 설정 후에 사용됩니다. 데이터 전송 및 ACK를 포함할 수 있습니다.

QUIC 프레임(Frames)

프레임QUIC 프로토콜의 데이터 전송 단위입니다. 하나의 스트림 내에서 여러 프레임이 전송될 수 있으며, 각 프레임은 특정 데이터 세그먼트를 포함합니다.

  • 스트림 프레임: 스트림 데이터의 일부를 포함합니다. 스트림 ID와 오프셋 정보가 포함되어 있어, 수신자가 데이터를 재조립할 수 있습니다.
  • ACK 프레임: 수신자가 송신자에게 수신 확인을 보내기 위해 사용됩니다. 패킷 손실을 감지하고 재전송을 요청하는 데 사용됩니다.
  • 패딩 프레임: 특정 목적 없이 패킷의 크기를 채우기 위해 사용됩니다.

 

=> 그러니까 QUIC은, stream이라는 도로 위에, packet이라는 트럭 속에, frame이라는 물건들을 넣고 옮기는 행위다. 그러나 정확한 예시는 아니다. 하나의 packet 속에 여러 개의 stream 소속 frame들이 들어갈 수 있기 때문.

 

데이터 전송 예시

  1. 클라이언트가 스트림 A와 스트림 B를 통해 데이터를 전송:
    • 스트림 A: "Hello, "
    • 스트림 B: "World!"
  2. 데이터를 프레임 단위로 나눔:
    • 스트림 A 프레임 1: "He"
    • 스트림 A 프레임 2: "llo, "
    • 스트림 B 프레임 1: "Wo"
    • 스트림 B 프레임 2: "rld!"
  3. 패킷에 프레임을 포함하여 전송:
    • 패킷 1: 스트림 A 프레임 1, 스트림 B 프레임 1
    • 패킷 2: 스트림 A 프레임 2, 스트림 B 프레임 2

이 구조를 통해, QUIC는 다양한 스트림의 데이터를 하나의 패킷에 실어 전송할 수 있습니다. 이를 통해 네트워크 효율성을 극대화하고, 데이터 전송의 신뢰성을 높입니다.

데이터 수신 및 재조립

  1. 서버가 패킷을 수신:
    • 패킷 1을 수신하고, 스트림 A 프레임 1과 스트림 B 프레임 1을 추출합니다.
    • 패킷 2를 수신하고, 스트림 A 프레임 2와 스트림 B 프레임 2를 추출합니다.
  2. 프레임 재조립:
    • 서버는 스트림 A의 데이터를 재조립: "He" + "llo, " = "Hello, "
    • 서버는 스트림 B의 데이터를 재조립: "Wo" + "rld!" = "World!"

예시

패킷 손실 시나리오

  1. 패킷 P가 전송되었으나 네트워크 문제로 인해 손실되었습니다.
  2. 수신자는 패킷 P가 도착하지 않았음을 인지하고, 이후 전송된 패킷에서 해당 패킷을 ACK하지 않습니다.
  3. 송신자는 특정 시간 동안 해당 패킷에 대한 ACK를 받지 못하면 패킷 P가 손실되었다고 간주합니다.
  4. 송신자는 패킷 P에 포함된 모든 프레임을 손실된 것으로 간주하고, 이 프레임들을 다시 전송하기 위해 새 패킷에 포함시킵니다.
  5. 새로운 패킷에 포함된 손실된 프레임들은 다시 전송되고, 수신자는 이를 받아서 처리합니다.