Delphi 및 C++ Builder용 QUIC 클라이언트 및 서버 컴포넌트 | eSeGeCe 블로그

Delphi 및 C++ Builder용 QUIC 클라이언트 및 서버 컴포넌트

· 컴포넌트
sgcQUIC QUIC 클라이언트 및 서버 컴포넌트

sgcQUICQUIC 전송 프로토콜(RFC 9000)을 Delphi, C++ Builder 및 .NET에 제공합니다. 두 개의 새로운 컴포넌트 TsgcQUICClientTsgcQUICServer를 제공하며, 둘 다 OpenSSL 3.5의 네이티브 QUIC 엔진 위에 구축되어 있어 전송과 TLS 1.3 핸드셰이크가 하나의 플라이트로 실행됩니다.

QUIC는 HTTP/3의 기반이 되는 프로토콜이지만, 그 자체로도 유용합니다. UDP 위에서 실행되며, 하나의 연결에서 여러 독립적인 스트림을 다중화하고, 0-RTT로 재개하며, 연결 마이그레이션 덕분에 네트워크 변경에도 살아남습니다. 이 글에서는 원시 QUIC 계층을 다룹니다. 다음 글에서는 그 위에 얹히는 HTTP/3 컴포넌트를 다룹니다.

QUIC를 사용하는 이유

전통적인 TLS-over-TCP 연결은 애플리케이션 데이터의 첫 바이트가 전송되기 전에 TCP 핸드셰이크에 이어 TLS 핸드셰이크가 필요합니다. QUIC는 이 둘을 하나의 교환으로 합치므로, 새 연결은 단일 왕복으로 준비되고, 재개된 연결은 0-RTT로 데이터를 보낼 수 있습니다.

각 QUIC 스트림은 개별적으로 전달되기 때문에, 한 스트림에서 패킷이 손실되어도 다른 스트림이 멈추지 않습니다. 이는 단일 TCP 소켓 위에서 다중화할 때 발생하는 헤드 오브 라인 블로킹을 제거합니다. QUIC 연결은 IP와 포트 쌍이 아니라 연결 ID로 식별되므로, 연결이 끊기지 않고 Wi-Fi에서 모바일 데이터로 마이그레이션할 수 있습니다.

QUIC 클라이언트

HostPort를 설정하고 이벤트를 할당한 다음 Active를 True로 설정합니다. 핸드셰이크는 하나의 플라이트로 완료되며, WriteData는 QUIC 스트림으로 바이트를 전송합니다.

uses
  sgcQUIC_Client;

var
  oClient: TsgcQUICClient;
begin
  oClient := TsgcQUICClient.Create(nil);
  oClient.Host := 'www.example.com';
  oClient.Port := 443;
  oClient.OnQUICConnect    := OnQUICConnect;
  oClient.OnQUICStreamData := OnQUICStreamData;
  oClient.OnQUICDisconnect := OnQUICDisconnect;

  oClient.Active := True;          // TLS 1.3 handshake in a single flight
  oClient.WriteData('ping');       // send bytes on a QUIC stream
end;

수신 바이트는 스트림 ID와 페이로드를 보고하는 OnQUICStreamData 이벤트로 도착합니다:

procedure TForm1.OnQUICStreamData(Sender: TObject; aStreamId: Int64;
  aUnidirectional: Boolean; const aData: TBytes);
begin
  Memo1.Lines.Add('stream ' + IntToStr(aStreamId) + ': ' +
    TEncoding.UTF8.GetString(aData));
end;

QUIC 서버

서버는 UDP 포트에서 수신 대기하며 PEM 형식의 인증서와 개인 키가 필요합니다. QUIC는 항상 TLS 1.3 위에서 실행되므로 인증서는 필수입니다. 클라이언트 바이트는 OnQUICData로 도착하며, 응답하려는 연결을 전달하여 WriteData로 회신합니다.

uses
  sgcQUIC_Server;

var
  oServer: TsgcQUICServer;
begin
  oServer := TsgcQUICServer.Create(nil);
  oServer.Port := 443;
  oServer.QUICOptions.SSLOptions.CertFile := 'cert.pem';
  oServer.QUICOptions.SSLOptions.KeyFile  := 'key.pem';
  oServer.OnQUICConnect := OnQUICConnect;
  oServer.OnQUICData    := OnQUICData;
  oServer.Active := True;
end;

procedure TForm1.OnQUICData(Sender: TObject;
  aConnection: TsgcQUICServerConnection; const aData: TBytes);
begin
  // echo the message back to the client that sent it
  oServer.WriteData(aConnection, aData);
end;

다중화 스트림

단일 QUIC 연결은 여러 스트림을 동시에 전달할 수 있습니다. 연결하기 전에 EnableMultiStream을 호출한 다음 필요한 만큼 스트림을 엽니다. 양방향 스트림은 요청과 그 응답을 전달하고, 단방향 스트림은 한 방향으로 데이터를 푸시합니다.

oClient.EnableMultiStream;
oClient.OpenStream;                 // a new bidirectional stream
oClient.OpenStream(True);           // a unidirectional stream

다중 스트림 모드는 내장 OpenSSL 3.5 QUIC 엔진을 사용합니다. 각 스트림은 개별적으로 흐름 제어되므로, 느리거나 멈춘 스트림이 나머지를 차단하지 않습니다.

0-RTT 및 연결 마이그레이션

첫 번째 핸드셰이크가 성공한 후, 클라이언트는 세션 티켓을 유지하고 0-RTT로 재연결하여 바로 첫 패킷에 애플리케이션 데이터를 보낼 수 있습니다. 연결 마이그레이션은 네트워크 변경 전반에 걸쳐 세션을 유지하며, 이는 Wi-Fi와 셀룰러 사이를 오가는 모바일 클라이언트에게 중요합니다. 둘 다 기반 QUIC 엔진이 처리합니다.

제공 정보

sgcQUIC는 별도의 패키지로, sgcWebSockets Enterprise의 애드온으로 라이선스가 부여됩니다. 모든 라이선스에는 전체 Pascal 소스 코드와 1년간의 업데이트가 포함됩니다. 컴포넌트는 SGC QUIC 팔레트에 설치되며 Delphi 및 C++ Builder 7부터 13까지 지원하고, 동일한 Tsgc 클래스 이름을 사용하는 .NET 포트도 제공합니다.

HTTP/3 클라이언트 및 서버 컴포넌트는 다음 글에서 다룹니다. sgcQUIC 제품 페이지에서 체험판을 다운로드하고 전체 컴포넌트 레퍼런스를 읽을 수 있습니다.

질문이나 피드백이 있으신가요? 문의하기, 코드를 작성한 사람들로부터 답변을 받으실 수 있습니다.