2026.9.0이 모든 제품에 동시에 출시되었습니다: sgcWebSockets, sgcWebSockets .NET, sgcSign, sgcIndy 및 sgcOpenAPI. 올해 가장 규모가 큰 릴리스입니다. 완전히 새로운 패키지 두 개가 sgcWebSockets에 합류했고, 오랫동안 요청을 잃어버리게 만들던 문제를 중심으로 서버 엔진이 재작업되었으며, 서명 라이브러리는 서명을 그 자신이 아닌 다른 기준으로 검증할 수 있게 되었습니다.
이 글에서는 각 제품에서 중요한 부분을 짚어보며, 도움이 되는 곳에는 Delphi 코드를 함께 실었습니다. 모든 내용은 변경 이력에 있으며, 기존 동작을 바꾸는 부분은 업그레이드 전에 읽어볼 수 있도록 글 마지막 부분에 모아두었습니다.
4분 안에 보는 전체 릴리스. YouTube에서도 보기.
| 제품 | 신규 | 수정 | 호환성 변경 |
|---|---|---|---|
| sgcWebSockets | 25 | 56 | 22 |
| sgcSign | 25 | 70 | 21 |
| sgcOpenAPI | 9 | 25 | 5 |
| sgcWebSockets .NET | 5 | 24 | 10 |
| sgcIndy | 0 | 5 | 0 |
sgcWebSockets 2026.9.0
sgcWebRTC, 네이티브 WebRTC 미디어 엔진
새로운 sgcWebRTC 패키지는 TsgcRTCPeerConnection을 완전한 WebRTC 엔드포인트로 만듭니다. 음성 및 영상 통화, 화면 공유, SCTP 데이터 채널까지 모두 Pascal로 구현되어 있으며, 브라우저도 WebView 컨트롤도 외부 미디어 라이브러리도 필요하지 않습니다. Windows, Linux, macOS, iOS, Android에서 동작하고, 생성하고 처리하는 SDP가 실제 규격 그대로이기 때문에 반대편 피어가 브라우저여도 됩니다.
오퍼와 앤서 교환은 W3C 형태를 따르므로 CreateOffer, CreateAnswer, SetLocalDescription, SetRemoteDescription, AddIceCandidate는 이름 그대로 동작합니다. SDP는 이미 사용 중인 시그널링 채널로 전달하면 되며, 같은 라이브러리로 만든 WebSocket 서버를 그 채널로 쓸 수도 있습니다.
uses
sgcP2P;
var
oRTC: TsgcRTCPeerConnection;
begin
oRTC := TsgcRTCPeerConnection.Create(nil);
oRTC.RTCOptions.ICEServers.AddURL('stun:stun.l.google.com:19302');
oRTC.OnLocalDescription := OnLocalDescriptionHandler;
oRTC.OnICECandidate := OnICECandidateHandler;
oRTC.OnConnectionStateChange := OnConnectionStateChangeHandler;
oRTC.OnDataChannel := OnDataChannelHandler;
oRTC.CreateDataChannel('chat'); // forces RTCOptions.DTLS on
oRTC.CreateOffer; // gathers ICE candidates, builds the SDP offer
end;
procedure TForm1.OnLocalDescriptionHandler(Sender: TObject;
const aType, aSDP: string);
begin
// send aType + aSDP to the remote peer over your own signalling channel
end;
미디어도 같은 방식입니다. AddTrack은 Opus나 G.711 오디오 트랙, 또는 VP8, H.264, Motion JPEG 비디오 트랙을 연결하고, SendPCM과 SendVideoFrame은 캡처한 미디어를 밀어 넣으며, OnAudio와 OnVideoFrame은 디코딩된 원격 트랙을 전달합니다.
예전 브라우저 시절의 폴백은 반대 방향으로 정리되었습니다. AppRTC 프로토콜과 RTCMultiConnection API 지원이 제거되었고, 2020년에 수명이 끝난 Flash 폴백도 함께 제거되었습니다. 글 마지막의 업그레이드 참고 사항을 확인하세요.
sgcCrypto, OpenSSL이 필요 없는 암호화
두 번째 새 패키지는 sgcCrypto로, 대부분의 애플리케이션이 실제로 사용하는 기본 요소들을 순수 Pascal로 구현했습니다. AES와 ChaCha20/XChaCha20-Poly1305 인증 암호화, SHA-2와 SHA-3, 비밀번호와 키 유도를 위한 Argon2, scrypt, HKDF, Ed25519, Ed448, X25519, X448, secp256k1, RSA 키 생성, X.509 인증서와 CSR 생성, 그리고 양자 내성 알고리즘인 ML-KEM, ML-DSA, SLH-DSA를 제공합니다.
각 기본 요소는 평범한 함수 하나입니다. 생성하고 설정하고 해제해야 하는 컨텍스트 객체도 없고, 실행 파일 옆에 함께 배포해야 하는 DLL도 없습니다.
uses
sgcCrypto_Random, sgcCrypto_AES, sgcCrypto_Keccak, sgcCrypto_Ed25519,
sgcCrypto_MLKEM;
var
vKey, vIV, vPlain, vAAD, vTag, vCipher: TBytes;
vDigest, vSeed, vSignature, vMessage: TBytes;
vPublicKey, vPrivateKey, vSharedSecret, vCiphertext: TBytes;
begin
// AES-256-GCM: authenticated encryption in one call
vKey := sgcRandomBytes(32);
vIV := sgcRandomBytes(12);
vPlain := TEncoding.UTF8.GetBytes('confidential payload');
vCipher := sgcAES_GCM_Encrypt(vKey, vIV, vPlain, vAAD, vTag);
// SHA-3-256, one call, no context object to manage
vDigest := sgcSHA3_256(vPlain);
// Ed25519: sign, then verify
vSeed := sgcRandomBytes(32);
vMessage := TEncoding.UTF8.GetBytes('sign me');
vSignature := sgcEd25519_Sign(vSeed, vMessage);
// ML-KEM-768: post-quantum key encapsulation (FIPS 203)
sgcMLKEM_GenerateKeyPair(mlkem768, vPublicKey, vPrivateKey);
sgcMLKEM_Encapsulate(mlkem768, vPublicKey, vCiphertext, vSharedSecret);
end;
완성된 sgcHTML 애플리케이션 다섯 개
sgcHTML에 컴포넌트 네 개와 데모 다섯 개가 추가되었습니다. 컴포넌트는 브라우저에 내장된 스캐너로 바코드와 QR 코드를 읽고 언제나 수동 입력 대체 수단을 제공하는 라이브 카메라 패널 CameraScanner, 그리고 NumPad, CommandPalette, EmptyState입니다.
다섯 개의 데모는 조각 코드가 아닙니다. 각각 로그인, 데이터베이스, 인쇄 가능한 보고서를 갖춘 완전한 애플리케이션이며 Demos\60.HTML\01.RunTime 아래에 있습니다. 창고 관리, 판매 시점 관리, 리포팅 포털, 멀티 테넌트 SaaS 관리 콘솔, 현장 서비스 배차입니다.
새 도움말 항목인 Runtime vs Design-Time도 추가되었습니다. 코드로 구성하는 대신 VCL 폼에 컴포넌트를 올려 같은 페이지를 만드는 방법을 보여주는 데모가 함께 들어 있습니다.
리버스 프록시 뒤의 실제 클라이언트 주소
nginx, Apache 또는 클라우드 로드 밸런서 뒤에 있는 서버는 모든 연결에서 프록시의 주소를 보게 되며, 그 결과 블랙리스트, 화이트리스트, GeoIP, 그리고 직접 만든 규칙이 모두 엉뚱한 클라이언트를 보고 있었습니다. TsgcWebSocketFirewall의 새로운 ForwardedHeaders 설정은 프록시가 전달한 주소를 복원합니다.
설계는 의도적으로 의심이 많습니다. X-Forwarded-For나 X-Real-IP에 담긴 주소는 연결 자체가 TrustedProxies에 등록된 주소에서 들어왔을 때만 신뢰하므로 클라이언트가 주소를 지어낼 수 없고, 체인은 오른쪽에서부터 TrustedHops에 지정한 프록시 개수만큼 건너뛰며 읽습니다. 맨 왼쪽 항목은 클라이언트가 직접 넣은 값이기 때문입니다. 프록시는 서로 다른 호출자의 요청에 하나의 연결을 재사용하므로, 주소 확인은 매 요청마다 수행됩니다.
uses
sgcWebSocket;
begin
oFirewall.ForwardedHeaders.Enabled := True;
oFirewall.ForwardedHeaders.TrustedProxies.Add('10.0.0.0/8');
oFirewall.ForwardedHeaders.TrustedProxies.Add('::1');
oFirewall.ForwardedHeaders.TrustedHops := 1;
oServer.Firewall := oFirewall;
end;
procedure TForm1.OnServerConnectHandler(Connection: TsgcWSConnection);
begin
// Connection.IP is now the end client
// Connection.PeerIP is still the proxy that opened the socket
end;
확인된 주소는 모든 블랙리스트 항목, 모든 사용자 정의 규칙, 모든 이벤트, 그리고 직접 작성한 핸들러 코드가 보게 되는 주소가 됩니다. 이 설정은 http.sys 서버에서도 Indy 서버에서와 동일하게 동작하며, 같은 기능이 sgcSign Server에는 server.firewall.forwarded_headers로 제공됩니다.
측정할 수 있는 백프레셔
느린 클라이언트가 읽는 속도보다 빠르게 쓰면 무언가 무너질 때까지 송신 큐가 계속 커집니다. 애플리케이션 안에서는 그 상황을 확인할 방법이 없었기 때문에, 릴레이는 안전을 위해 네트워크 위에서 정지 후 대기 방식의 교환을 하게 되곤 했습니다.
두 가지 추가 기능이 이를 대체합니다. TsgcWSConnection의 PendingCount는 세 가지 우선순위 수준에 걸쳐 해당 연결에 아직 대기 중인 메시지 수를 알려주며, 읽을 때 메모리를 전혀 할당하지 않으므로 반복해서 조회해도 됩니다. OnQueueDrained는 연결의 큐가 메시지를 보유한 상태에서 빈 상태로 바뀔 때 연결 스레드에서, 큐가 비워진 직후이자 다음 읽기 전에 발생하므로 지연 없이 크레딧을 넘겨줄 수 있습니다.
procedure TForm1.OnQueueDrainedHandler(Connection: TsgcWSConnection);
begin
// raised on the connection thread: do not touch the user interface here
SendNextBatch(Connection);
end;
procedure TForm1.SendIfRoom(Connection: TsgcWSConnection; const aText: string);
begin
if Connection.PendingCount < 100 then
Connection.WriteData(aText);
end;
두 기능 모두 DLL 경계를 넘어가므로 .NET 래퍼와 sgcWebSockets.dll을 사용하는 다른 호스트에서도 쓸 수 있습니다. 새 익스포트는 뒤에 추가되었으므로 기존 익스포트 순서는 그대로입니다.
EPOLL 및 IOCP 엔진
고성능 엔진에는 원인이 하나인 결함 계열이 있었습니다. 요청이 한 번의 소켓 읽기로 도착한다고 가정한 것입니다. 루프백 테스트에서는 맞지만 MTU 경계, VPN 환경, 또는 큰 본문이 여러 패킷으로 나뉘는 경우에는 틀립니다.
전부 도착하지 않은 요청은 응답 없이 연결이 닫힌 채 버려졌고, 두 개의 TCP 세그먼트로 나뉜 TLS 레코드는 연결을 곧바로 끊었습니다. 두 문제 모두 수정되었으며, 새 PartialRequestTimeout 옵션이 서버가 나머지를 기다리는 시간을 제한합니다. 이 대기는 별도의 스레드 풀에서 처리되므로 느린 클라이언트가 다른 연결을 붙잡지 못합니다. EPOLL 엔진에서는 클라이언트가 연결을 닫아도 서버 연결이 전혀 해제되지 않아 OnDisconnect가 발생하지 않았고, 모든 브로드캐스트가 죽은 연결에 계속 쓰기를 시도했습니다.
WorkOpThreads의 의미가 바뀐 것도 같은 이유입니다. 이제는 연결을 하나의 스레드에 고정하지 않습니다. 요청의 나머지를 기다리는 연결이 같은 스레드의 다른 모든 연결을 붙잡고 있었기 때문입니다. 이제 이 값은 준비 상태로 유지되는 최소 작업자 수를 지정하며, 풀은 거기에서부터 늘어납니다.
QUIC 및 HTTP/3
QUIC 및 HTTP/3 클라이언트와 서버가 이제 IPv6를 지원합니다. 콜론이 포함된 주소는 IPv6로 처리되고, URL에서는 대괄호로 감싸 쓸 수 있으며, 호스트 이름은 두 주소 체계 모두에서 확인됩니다. 이전에는 IPv4만 시도했습니다. 호스트를 지정하지 않은 HTTP/3 리스너는 하나의 소켓으로 두 체계를 모두 서비스하고, HTTP3Options의 새 Host 속성으로 필요할 때 특정 인터페이스에 고정할 수 있습니다.
더 큰 변화는 HTTP/3 요청이 이제 HTTP/1.1 요청과 같은 경로를 따른다는 점입니다. OpenAPI, MCP, REST API 서버, 요청 전달, CORS, 멀티 테넌시, 메트릭은 HTTP/3에서 전혀 응답하지 않았습니다. 그 전송 계층이 자체 경로를 가지고 있었기 때문입니다. 이제 모두 동작합니다.
HTTP/3의 인증서 검증은 두 번 읽어볼 항목입니다. TsgcHTTP3Client에서 TLSOptions.VerifyCertificate는 기본값이 True였고 검사도 수행되었지만, 그 결과가 그대로 버려졌습니다. 그래서 모든 HTTP/3 클라이언트가 어떤 기관이 어떤 호스트에 발급한 인증서든 그대로 받아들였습니다. 이제 검사 결과가 실제로 적용되므로, 자체 서명 엔드포인트와 통신하던 HTTP/3 클라이언트는 신뢰 저장소나 인증서를 바로잡을 때까지 연결되지 않습니다.
거래소 API 클라이언트
바로 쓸 수 있는 거래소 클라이언트에는 훨씬 이상한 증상으로 나타나는 재연결 문제가 있었습니다. Bitstamp, Coinbase, Deribit, Huobi, Kraken 현물 및 선물, Kucoin, MEXC, ThreeCommas에서 주문, 잔고, 체결 피드 같은 비공개 구독이 재연결 후에 전혀 다시 등록되지 않았습니다. 해당 피드가 조용히 사라진 상태에서도 컴포넌트는 재연결이 성공했다고 보고했습니다. BitMEX, Bitfinex, Crypto.com, Deribit, Kraken 선물에서는 재등록이 인증보다 먼저 실행되었는데, 이 역시 동작할 수 없습니다. 수명이 짧은 자격 증명을 담은 프레임은 이제 그대로 다시 보내지 않고 재등록 시점에 새 자격 증명으로 다시 만들어집니다.
금액이 서명되기 전에 반올림되고 있었습니다. 소수점 여덟 자리로 고정된 마스크가 0.000000004 같은 수량을 0으로 만들었고, 시스템 로캘에 따라 값이 지수 표기법이나 쉼표 구분자로 전송될 수도 있었습니다. 이제 Binance, Bybit, Cex, Cryptohopper, Kucoin, MEXC, ThreeCommas에서 값은 손실 없이, 점을 소수점으로 쓰는 일반 십진수로 기록됩니다.
같은 영역의 새 기능으로는 v1과 함께 제공되는 Kraken WebSocket v2 컴포넌트, 내부적으로 두 번째 연결을 열어 하나의 인스턴스가 공개 데이터와 비공개 데이터를 동시에 처리하는 Huobi 클라이언트, 시계가 어긋난 호스트를 위한 Binance의 UseServerTimeOffset, 그리고 큰 구독이 거래소 요청 제한에 걸리지 않게 하고 재연결 시 재등록을 백그라운드 작업자로 옮기는 두 가지 조절 옵션 PaceBatch와 AsyncResubscribe가 있습니다.
sgcWebSockets .NET 2026.9.0
.NET 라이브러리는 Delphi 버전을 따라갑니다. OnQueueDrained와 PendingCount가 같은 의미로 추가되었고, 함께 Throttle.AsyncResubscribe, Cryptohopper 클라이언트의 AllowUnsignedWebhooks, 그리고 새 OnBinanceUserStreamSubscribed 이벤트가 들어왔습니다. 이제 사용자 데이터 스트림이 준비되었는지를 속성을 반복 조회해서 알아낼 필요가 없습니다.
위에 나열한 거래소 재연결 및 서명 수정은 여기에도 모두 적용되며, 제거된 항목도 마찬가지입니다. AppRTC 프로토콜, RTCMultiConnection API, Flash 폴백 클래스가 제거되어 TwsTransport의 번호가 다시 매겨집니다. 전송 방식 값을 숫자로 저장하거나 전송하던 코드는 다시 확인해야 합니다.
짚어둘 만한 누수가 두 가지 있습니다. 클라이언트가 아직 연결된 상태에서 해제된 WebSocket API 컴포넌트가 메시지 핸들러가 순회하는 목록에서 스스로를 제거하지 않았고, 컴포넌트를 파괴할 때마다 하트비트 타이머 스레드 두 개가 누수되었습니다. 정상 종료가 가끔 오류를 내던 이유가 바로 이것입니다.
sgcSign 2026.9.0
이번 릴리스의 대부분은 고객 요청에서 나왔으며, 세 가지 영역에 걸쳐 있습니다. 어떤 인증서로 서명하려는지 정확히 아는 것, 10년 뒤에도 검증기가 받아들일 서명을 만드는 것, 그리고 서명을 그 자신이 아닌 다른 기준으로 검증하는 것입니다.
선택할 수 있는 인증서 목록
인증서 열거는 예전에는 표시 이름만 돌려주었습니다. 콤보 박스를 채우기에는 충분하지만 판단을 내리기에는 부족합니다. 같은 기관이 같은 사람에게 발급한 카드 두 장은 그 목록에서 똑같아 보입니다. 이제 열거 결과에는 SHA-1 지문, 세금 식별자, 일련번호, 발급자, 유효 기간이 함께 담기며, Windows 인증서 저장소, PKCS#11 토큰, PFX 파일에서 모두 동일하게 제공됩니다.
uses
sgcSign_KeyProvider_WinCertStore, sgcSign_X509, sgcSign_Types;
var
oProvider: TsgcWindowsCertStoreProvider;
oList: TsgcX509CertificateList;
i: Integer;
begin
oProvider := TsgcWindowsCertStoreProvider.Create(nil);
Try
// only certificates that are still valid and hold a private key
oList := oProvider.EnumerateCertificateList([cfNotExpired, cfPrivateKey]);
Try
for i := 0 to oList.Count - 1 do
Memo1.Lines.Add(Format('%s | %s | %s .. %s | %s',
[oList[i].Subject, oList[i].SerialNumber,
DateToStr(oList[i].NotBefore), DateToStr(oList[i].NotAfter),
oList[i].Thumbprint]));
// and sign with exactly the one that was chosen
oProvider.SelectCertificateByThumbprint(oList[0].Thumbprint);
Finally
oList.Free;
End;
Finally
oProvider.Free;
End;
end;
서로 다른 PIN 뒤에 별도의 인증서를 두는 폴란드 적격 서명 카드에서 흔한 다중 슬롯 PKCS#11 카드도 이제 PIN 없이 전체 목록을 확인할 수 있습니다. EnumerateCertificateListAllSlots는 모든 슬롯을 읽어 각 항목이 어디에서 왔는지 기록하고, TokenSlotCount는 실제로 토큰이 들어 있는 슬롯이 몇 개인지 알려줍니다.
인증서 자체도 파서가 예전에 인식하던 일곱 개 속성 대신 담고 있는 모든 정보를 보고합니다. 우편 주소는 읽기 쉬운 줄로 디코딩되고, 모든 속성은 OID로 접근할 수 있습니다.
계속 검증할 수 있는 서명
PAdES에 프로필 두 개가 추가되었습니다. spPAdESBasicT는 폐기 정보 없이 내장 타임스탬프로 서명하고, spPAdESDocumentArchive는 장기 프로필 위에 아카이브 타임스탬프를 더해 폐기 정보를 포함한 문서 전체를 보호합니다. 덕분에 첫 번째 타임스탬프 자체의 유효 기간이 지난 뒤에도 파일을 계속 검증할 수 있습니다.
대부분의 적격 서명 카드에는 본인 인증서만 들어 있기 때문에, 발급 인증서를 찾는 일은 지금까지 사용자의 몫이었습니다. 새로운 GetIssuerCertificate와 GetCertificateChain 호출은 서명에 사용하는 인증서를 발급한 인증서와 그 위의 전체 경로를 찾아줍니다. 이름이 아니라 암호학적으로 일치를 확인하므로, 서명 키를 교체한 기관이 이전 기관과 혼동되지 않습니다. IssuerLookup은 검색 위치를 결정합니다. 기본값은 Windows 인증서 저장소이고, 함께 배포하는 PEM 또는 DER 파일이나 인증서 안에 들어 있는 주소를 쓸 수도 있으며, 마지막 항목은 기본적으로 꺼져 있습니다.
이제 타임스탬프 요청에 서명할 수 있습니다. 일부 적격 기관, 특히 폴란드 기관이 이를 요구합니다. RequestFormat을 trfCMS로 설정하고 키 공급자를 지정하면 되며, OnBeforeSendRequest와 OnAfterReceiveResponse가 실제로 보내고 받은 바이트를 그대로 전달합니다.
신뢰 앵커를 사용한 검증
이번 릴리스에서 가장 주의 깊게 읽어야 할 변경입니다. 지금까지 검증기는 검사 대상 문서에서 서명 인증서를 꺼내 그 키가 해당 문서에 서명했음을 확인했습니다. 이는 문서를 작성한 사람이 그 안의 서명도 작성했다는 사실만 증명할 뿐입니다.
새로운 TrustedCertificates와 TrustedCertificateStore 속성으로 신뢰하는 루트를 지정하고, RequireTrustedChain, CheckKeyUsage, RequireCompleteRevocationCheck로 결과의 엄격함을 정합니다. 앵커는 SHA-256 지문으로 확인하거나 앵커 자신의 키로 검증해 확인하며, 이름으로는 절대 확인하지 않습니다. 앵커를 지정하지 않은 검증기는 이전과 같은 판정을 반환하지만, ETSI TS 119 102-2 보고서는 앵커까지 체인이 연결되지 않은 서명에 대해 더 이상 total-passed로 표시하지 않습니다. 따라서 앵커 없이 생성해 보관 중인 보고서는 다시 생성해야 합니다.
Authenticode 서명은 이제 signtool /ac와 동일하게 추가 인증서를 포함할 수 있습니다. 덕분에 커널 모드 드라이버 서명이 교차 인증서를 거쳐 Microsoft Code Verification Root까지 체인을 연결할 수 있습니다.
프록시를 지원하는 단일 HTTP 전송 계층
이제 라이브러리가 보내는 모든 요청은 공유 HTTPOptions 속성을 가진 하나의 전송 계층을 거칩니다. 타임스탬프 클라이언트, OCSP 및 폐기 목록 클라이언트, EU 신뢰 목록 다운로드, 클라우드 키 공급자가 모두 여기에 해당합니다. 여기에는 프록시 설정이 담기는데, 시스템 프록시, 사용 안 함, 명시적 주소, 또는 주소별로 시스템이 결정하는 프록시 중에서 고를 수 있습니다. 그 밖에 자격 증명을 요구하는 프록시를 위한 인증 정보, 클라이언트 인증서, 허용하는 최소 TLS 버전, 사용자 에이전트도 함께 담깁니다. 모든 설정의 기본값은 이전에 해당 요청이 동작하던 방식과 같으며, 이 설정으로 표현할 수 없는 게이트웨이를 위해 새 OnHTTPRequest 이벤트가 전송 계층을 통째로 대체합니다.
서명 서버
API 키와 그 키를 만드는 사용자가 이제 프로젝트 단위로 분리됩니다. 따라서 프로젝트 관리자는 다른 사람의 키를 보지 않고 자기 프로젝트의 키만 관리합니다. 키는 한 방향으로 폐기하는 것만이 아니라 활성화하고 비활성화할 수 있고, 요청 제한과 일일 할당량은 생성 후에도 수정할 수 있으며, 감사 로그는 콘솔과 CSV 내보내기 양쪽에서 드디어 클라이언트 주소로 필터링할 수 있습니다.
Authenticode 서명은 이제 각각 다른 인증서를 사용하는 중첩 서명을 두 개 넘게 담을 수 있습니다. 만료를 앞둔 인증서와 그 후속 인증서로 서명한 파일 하나를 배포할 때 필요한 기능입니다. Windows 카탈로그 파일에도 서명할 수 있으며, 새 /api/v1/sign/raw 엔드포인트는 이미 계산해 둔 다이제스트에 서명하고 서명 값만 반환합니다. signtool이 /dlib 콜백으로 요구하는 것이 정확히 이것입니다. 전달받은 다이제스트라면 무엇이든 서명하므로 기본적으로 꺼져 있으며, 공급자 단위로 하나씩 켭니다.
서버 기본값 몇 가지가 충분한 이유가 있어 변경되었습니다. server.listen 설정은 이제 지정한 주소에 실제로 바인딩하고, 관리 작업에는 일회용 토큰을 담은 폼 전송이 필요하며, HTTPS로 전달되는 웹훅은 보내는 주소의 인증서를 검사합니다. 세 가지 모두 업그레이드 참고 사항에 실려 있습니다.
sgcIndy 2026.9.0
작은 릴리스이지만, 담긴 항목은 모두 챙겨둘 만한 수정입니다.
ALPN으로 합의한 프로토콜 이름이 OpenSSL이 길이를 저장하는 1바이트 공간에 4바이트로 기록되어, 프로토콜을 협상한 모든 핸드셰이크가 바로 옆 메모리를 덮어썼습니다. IOCP나 EPOLL 엔진의 TLS 서버는 상대방이 재협상을 요청하면 OpenSSL이 이미 준비해 둔 내용을 보내는 대신 쓰기를 계속 재시도하면서 스레드 하나의 CPU를 전부 소모했습니다. Linux에서는 쓰기 도중 상대방이 연결을 재설정하면 운영 체제가 TLS 애플리케이션을 종료시켰습니다. OpenSSL이 broken pipe 시그널을 억제해 달라고 시스템에 요청할 수 없는 방식으로 쓰기를 수행하기 때문입니다. FPC와 Lazarus에서의 동일한 문제도 수정되었으며, 여전히 노출되어 있던 macOS의 서버 수락 연결도 포함됩니다.
Community 설치본에서는 미리 컴파일된 Delphi 13 바이너리가 Delphi 12 프로젝트에서 만들어져, Delphi 13 설치 프로그램이 기대하는 370 이름 대신 290 이름을 달고 있었고 Windows ARM64EC는 아예 빌드되지 않았습니다. 이제 Delphi 13은 지원하는 모든 플랫폼에서 자체 프로젝트로 빌드합니다.
sgcOpenAPI 2026.9.0
파서가 더 이상 조용히 실패하지 않습니다. 이제 모든 문서는 Warnings 목록과 함께 반환되며, 여기에는 누락된 openapi나 info 멤버, JSON 타입이 잘못된 멤버, 생성하지 못한 오퍼레이션, 해석되지 않은 path item 참조, 그리고 읽기는 하지만 아직 적용되지 않는 JSON Schema 키워드가 담깁니다.
uses
sgcOpenAPI_Classes, sgcOpenAPI_Parser_Client_Pascal;
var
oParser: TsgcOpenAPI_Parser_Client_Pascal;
i: Integer;
begin
oParser := TsgcOpenAPI_Parser_Client_Pascal.Create;
Try
oParser.OpenAPIClassName := 'TPetStoreClient';
oParser.OutputFileName := 'PetStoreClient.pas';
oParser.ReadFromFile('petstore.json');
for i := 0 to oParser.Warnings.Count - 1 do
Memo1.Lines.Add('warning: ' + oParser.Warnings[i]);
oParser.SaveToFile('PetStoreClient.pas');
Finally
oParser.Free;
End;
end;
또한 어떤 버전의 명세를 읽고 있는지 알기 때문에 3.0 문서와 3.1 문서를 더 이상 같은 것으로 취급하지 않습니다. exclusiveMinimum과 exclusiveMaximum이 대표적인 경우입니다. OpenAPI 3.1의 webhooks, jsonSchemaDialect, components.pathItems, 라이선스 식별자, mutualTLS 보안 스킴, ["string","null"]처럼 배열로 선언된 타입, 불리언으로 선언된 스키마가 모두 지원되며, OpenAPI 3.2의 query 오퍼레이션과 additionalOperations 맵도 지원됩니다.
코드 생성은 예전에 포기하던 지점에서 좋아졌습니다. 인라인 object 스키마는 이제 문자열로 격하되지 않고 자체 클래스를 생성하고, items는 완전한 스키마로 읽히며, 생성된 클라이언트는 쿠키 파라미터와 matrix, label, simple, form, spaceDelimited, pipeDelimited, deepObject의 전체 파라미터 직렬화 규칙을 explode 및 allowReserved와 함께 지원합니다.
명령줄 도구를 드디어 빌드 스크립트에서 쓸 수 있습니다. 종료 코드를 설정하는데 성공하면 0, 실패 유형에 따라 1에서 7까지를 반환하며, 오류는 항상 표준 오류로 출력됩니다. 새 -r 스위치는 YAML 또는 Swagger 2.0 문서를 공개 변환기를 통해 변환하며, 기본적으로 꺼져 있습니다.
같은 OpenAPI 개선 사항이 sgcWebSockets에도 포함됩니다. 여기서는 서버 측 검증기가 ValidateHeaderParams, ValidateCookieParams, EnforceRequired로 헤더와 쿠키 파라미터까지 검사합니다.
업그레이드하기 전에
이번에는 모든 제품에 호환성 변경이 있습니다. 다음은 영향을 받을 가능성이 가장 높은 항목입니다.
- sgcWebSockets와 .NET에서 제거되었습니다. AppRTC, RTCMultiConnection, Flash 폴백이 사라졌습니다. 해당 항목이 들어 있는
.dfm에서는FallBack.Flash줄을 삭제하세요. 그러지 않으면 폼에서 속성이 존재하지 않는다는 오류가 발생합니다. 또한trpFlash이후의 모든TwsTransport멤버의 서수 값이 하나씩 밀렸다는 점에 유의하세요. WorkOpRoundRobin이 제거되었고WorkOpThreads는 더 이상 연결을 특정 스레드에 고정하지 않습니다. 데이터베이스 연결이나 스레드 로컬 캐시처럼 스레드 단위로 보관하던 것이 연결을 따라간다고 더는 가정할 수 없습니다.- 인증서 검증이 적용되지 않던 곳에서 이제 적용됩니다. OpenSSL 백엔드에서
TLSOptions.VerifyCertificate는 SChannel과 Apple이 이미 그랬던 것처럼 인증서를 호스트에 결합합니다. HTTP/3에서는 검사 결과가 더 이상 버려지지 않습니다.DTLSOptions.VerifyCertificate는 이제 검사 결과를 실제로 적용하며,DTLSOptions.RootCertFile은 이 엔드포인트 자신의 인증서가 아니라 신뢰 저장소입니다. 자신의 인증서는CertFile에 넣습니다. - 클라이언트의
WriteTimeout기본값이 무제한이 아니라 60초입니다. 또한 이전에는 Windows에서만 적용되었지만 이제 Linux, macOS, iOS, Android에서도 적용됩니다. 시간 제한을 두지 않으려면 음수로 설정하세요. - 재시도 범위가 좁아졌습니다. 기본적으로 GET, HEAD, OPTIONS만 재시도합니다. 서버가 이미 처리한 POST가 두 번 전송되어 주문이 한 번 더 들어갈 수 있기 때문입니다. 기존 동작에 의존하고 있었다면
RetryOptions.Methods에 POST를 추가하세요. - sgcSign에는 이제
TsgcX509Certificate가 하나뿐입니다. 라이브러리는 그 이름으로 클래스를 세 개 선언하고 있었습니다. 인증서를 나열하는 코드에는 uses 절에sgcSign_X509가, C++ Builder에서는 그에 해당하는.hppinclude가 필요합니다. - 이전 버전에서 만든 ASiC-E CAdES 컨테이너는 내부 문서와 암호학적으로 연결되어 있지 않습니다. 매니페스트의 모든 다이제스트가 빈 요소로 기록되었기 때문입니다. 이미 발급한 컨테이너는 다시 발급해야 하고, ASiC-E를 생성하는 코드는 서명 콜백을 받는 새
BuildCAdES오버로드로 옮겨야 합니다. - Object Inspector에 입력한 자격 증명은 더 이상
.dfm에 기록되지 않습니다. AWS 시크릿 키, Google Cloud 서비스 계정 JSON, PKCS#11 PIN을 비롯해 11개 sgcSign 유닛에 걸친 14개 속성이 저장하지 않음으로 표시되었습니다. 코드에서는 그대로 할당할 수 있고 기존.dfm도 계속 로드되지만, 다음에 폼을 저장할 때 값이 사라집니다. - sgcSign Server가 이제
server.listen을 실제로 바인딩합니다. 127.0.0.1로 설정했지만 사실은 네트워크 전체에서 접근할 수 있던 배포 환경은 접근이 차단됩니다. 설정이 원래 요구하던 동작입니다. - 생성된 OpenAPI 클라이언트가 서버 인증서를 검증합니다. 자체 서명 엔드포인트를 쓴다면
TLSOptions.VerifyCertificate를 False로 설정하세요. 요청 본문은 이제 UTF-8이고, 빈 문자열은"field": ""로 직렬화되며, 응답은 호출자가 제공한ResponseStream을 더 이상 해제하지 않습니다.
각 항목의 이유를 포함한 전체 목록은 각 제품의 변경 이력에 있습니다.
받는 방법
릴리스 2026.9.0은 지금 바로 이용할 수 있으며, 전체 소스 코드와 1년간의 업데이트가 포함됩니다. Delphi 7부터 Delphi 13 Florence까지, 그에 대응하는 C++ Builder 버전, 그리고 .NET을 지원합니다.
sgcWebSockets · sgcWebRTC · sgcCrypto · sgcHTML · sgcSign · sgcIndy · sgcOpenAPI
질문이나 의견이 있으신가요? 문의해 주세요. 코드를 직접 작성한 사람에게서 답변을 받으실 수 있습니다.
