QUIC(Quick UDP Internet Connections) 프로토콜은 2015년부터 크롬 브라우저를 통한 구글 서비스에 사용하고 있는 프로토콜이다.
Quic연결은 두 QUIC엔드포인트 사이의 대화라고 할 수 있다. QUIC의 연결 설정은 버전 협상, 암호화, 전송 핸드쉐이크로 구성되어 있으므로 연결 설정의 지연시간을 줄여준다. 이러한 연결을 통해 실제 데이터를 보내려면 하나 이상의 스트림을 만들어서 사용해야 한다.
- 각 연결은 연결 식별자나 연결 ID를 가지므로 이를 통해 연결을 식별한다. 엔드포인트가 자유롭게 연결 ID를 선택한다. 각 엔드포인트는 엔드포인트의 peer가 사용할 연결 ID를 선택한다.
- 이 연결ID의 주요 기능은 하위 프로토콜 계층(UDP,IP 혹은 그 아래 계층)에서 주소가 변경되더라도 QUIC연결의 패킷이 잘못된 엔드포인트로 전달되지 않도록 보장하는 것이다.
- 연결 ID를 이용하면 TCP에서 불가능했던 방법으로 IP주소와 네트워크 인터페이스 사이에서 연결이 마이그레이션 할 수 있다. 예시로, 사용자가 자신의 기기를 들고 wifi가 지원되는 곳으로 이동했을 때 다운로드를 진행하면서 셀룰러 네트워크 연결에서 더 빠른 wifi연결로 변경되는 것이 이 마이그레이션을 통해 가능하다. 마찬가지로 wifi를 이용할 수 없게 되었을 때 셀룰러 연결을 통해 다운로드를 진행할 수 있다.
- QUIC이 UDP 위에 만들어졌으므로 들어오는 연결을 구분하기 위해 16비트 포트 번호 필드를 사용한다.
- 클라이언트는 QUIC 연결 요청에서 어떤 QUIC 프로토콜 버전으로 통신하고 싶은지 서버에게 알려주고 서버는 클라이언트가 선택할 수 있도록 지원하는 버전 목록을 응답한다.
- 초기 패킷이 연결을 설정하자마자 초기화하는 쪽에서 보안 계층 핸드쉐이크의 설정을 시작하는 암호화 프레임을 보낸다. 보안 계층은 TLS 1.3 보안을 사용한다.
- QUIC 연결에서는 반드시 TLS를 사용해야 한다. QUIC 프로토콜은 프로토콜 고착화를 방지하기 위해 미들박스가 조작하기 어렵게 설계되었다.
- 스트림은 개별적으로 흐름 제어가 되므로 엔드포인트가 메모리 사용을 제한할 수 있고, 백프레셔(back pressure)를 적용할 수도 있다. 스트림의 생성도 흐름 제어가 되고 각 피어는 일정 시간 동안 받고자 하는 최대 스트림ID를 정의할 수 있다.
- 스트림 ID라고 부르는 부호없는 62비트 정수로 스트림을 식별한다. 스트림 ID의 최하위 2비트를 스트림(단방향 OR 양방향)의 타입과 스트림을 시작한 쪽을 식별하는데 사용한다.
- 스트림 ID의 최하위 비트(Ox1)는 누가 스트림을 시작했는지를 식별한다. 클라이언트는 짝수의 스트림(최하위 비트가 0으로 설정된 스트림)을 초기화 하고 서버는 홀수의 스트림(최하위 비트가 1로 설정된 스트림)을 초기화한다.
- 스트림 ID의 두 번째 하위 비트(Ox2)는 단방향 스트림과 양방향 스트림을 구분한다. 단방향 스트림을 항상 이 비트를 1로 설정하고 양방향 스트림은 이 비트를 0으로 설정한다.
- QUIC에서는 임의의 스트림이 다수 동시에 동작할 수 있다. 엔드포인트는 최대 스트림 ID를 제한해서 동시에 받아들이는 활성 스트림의 수를 제한한다.
- 엔드포인트마다 최대 스트림 ID를 설정하고 설정을 받는 피어에만 적용된다.
- 엔드포인트는 스트림을 사용해서 데이터를 보내고 받고 이는 스트림의 원래 목적이다. 스트림은 순서가 맞는 바이트 스트림의 추상화다. 하지만 별도의 스트림은 원래 순서대로 전달되지 않는다.
- 스트림에 할당된 리소스의 우선순위가 제데로 설정되면 스트림 멀티플렉싱은 애플리케이션 성능에 상당한 영향을 준다. HTTP/2 같은 멀티플렉싱을 지원하는 다른 프로토콜의 경험에서 상당히 긍정적인 성능 효과를 보여주는 효율적인 우선순위 전력을 볼 수 있다.
- QUIC 자체에서 우선순위를 결정하는 정보를 교환하는 프레임을 제공하지는 않는다. 대신 QUIC을 사용하는 애플리케이션에서 우선순위 정보를 받는데 의존한다. QUIC을 사용하는 프로토콜은 애플리케이션의 의미에 적합한 우선순위 스키마를 정의할 수 있다.
- QUIC을 통해 HTTP/3을 사용할 때 우선순위는 HTTP 계층에서 동작한다.
- QUIC은 이론적으로 전송 왕복 시간(RTT, Round-Trip Time)이 0이다.
- TCP 기반의 통신을 수행할 경우를 생각해보면 기본적으로 Connection 수립을 위해 SYN 송신, SYN-ACK 수신, ACK 송신 과정을 거치게 된다. 거기에 SSL/TLS 암호화 통신을 적용한다면 Client Hello부터 Chiper Spec, FIN까지 송/수신 Handshake 과정이 필요하다. 실제 필요한 데이터를 전송하기도 전에 여러 단계의 Round Trip이 발생하게 된다.
- QUIC은 UDP 프로토콜 기반에서 동작하므로 기본적으로 Zero-RTT가 원칙이다. 따라서 당연히 Connection 수립을 위한 오버헤드가 획기적으로 감소한다.
- QUIC은 Connection UID라는 고유한 패킷 식별자를 사용하므로 한번이라도 클라이언트와 서버가 데이터 전송을 수행했다면 이동중 로밍이 발생하거나 심지어 IP주소가 변경되어도 커넥션을 다시 수립할 필요가 없다.
- QUIC은 TLS 암호화를 기본적으로 적용하고 있다. 과거 SPDY와 마찬가지로 구글에서 설계한 네트워크 프로토콜은 기본적으로 암호화를 적용하고 있다. 서버의 포트도 디폴트가 443 UDP 포트를 사용하고 있습니다.
- QUIC에서는 필요에 따라 Source Address Token을 발급하여 출발지 아이피를 변조 및 재생공격에 대한 검증을 수행한다. 마치 TCP 통신에서 Sequence Number를 이용하여 신뢰 관계를 맺은 클라이언트인지 검증하는 것과 같은 기능을 수행한다.
- 멀티플렉싱 기법은 QUIC프로토콜의 고유 특성은 아니다. TCP를 비롯한 다른 프로토콜에서도 단일 커넥션을 통해 하나의 통신 채널로 여러 데이터를 전송하는 기법들을 사용한다.
- QUIC에서는 좀 더 향상된 멀티플렉싱 기능을 제공한다.
- TCP통신에서는 다수의 개별 데이터를 하나의 통신채널로 전송중에 유실된 패킷이 발생하면 다른 데이터 역시 유실된 패킷이 재 전송 될 때까지 대기상태(Block)가 되지만, QUIC에서는 유실된 패킷이 속한 데이터를 제외한 다른 데이터는 별도의 Block없이 지속적으로 처리 할 수 있도록 설계되었다.
- QUIC은 전방 오류정정 FEC(Forward Error Correction) 방식을 이용한다. 패킷이 전송 중 변조나 훼손이 발생했을 경우 재전송(retransmission)요청을 통해 다시 패킷을 송신하는 후방 오류정정(BEC)이 아닌 정정비트를 통해 훼손된 비트를 복구하도록 설계되었다.
QUIC프로토콜은 위의 장점 외에도 성능 개선과 효율적인 전송을 위해 다양한 기능들을 가지고 있다. 구글의 시범적용한 결과를 측정해보니 유튜브 서비스의 경우는 30%의 버퍼링 감소가, 검색엔진은 가장 늦은 상위 1%의 컨텐츠에 대해 1초 이상 단축됐다고 한다.