sgcWebSockets 2026.10

· 릴리스
sgcWebSockets 2026.10

sgcWebSockets 2026.10이 출시되었습니다. 이번 버전에는 세 가지 흐름이 있습니다. sgcHTML은 비즈니스 웹 애플리케이션에 필요한 부분들을 갖추어 더 이상 손으로 작성하지 않아도 되게 했고, 암호화는 외부 라이브러리를 단 하나도 추가하지 않고 포스트 퀘텀으로 전환했으며, 새로운 Enterprise 인증 컴포넌트들이 로그인 화면을 맡습니다.

웹 애플리케이션: 지루한 부분, 끝냈습니다

세션, 로그인, CSRF. 새로운 TsgcHTMLAuth 컴포넌트와 그 세션 저장소는 쿠키를 유지하고, 로그인과 로그아웃 요청에 응답하고, 유휴 세션을 종료하고, 실패한 로그인 시도를 제한합니다. CSRF 토큰은 meta 태그에 담겨 전달되고, htmx가 모든 요청에 알아서 이를 추가하며, 서버는 이를 가지고 있지 않은 post 요청을 거부합니다.

FAuth := TsgcHTMLAuth.Create(Self);
FAuth.SessionStore := TsgcHTMLSessionStore_Memory.Create(Self);
FAuth.CookieName := 'app_session';
FEngine.Auth := FAuth;

라우트처럼 읽히는 라우트. 경로 매개변수, 메서드 필터, 그리고 헤더, 쿠키, 본문에 대한 접근:

with FRouter.Routes.Add do
begin
  Path := '/customers/{id}/edit';
  Methods := [hrmGet, hrmPost];
  RequireLogin := True;
  RequireRoles := 'admin,sales';
end;

테스트할 수 있는 페이지. DispatchDirect는 뒤에 소켓이 전혀 없어도 요청에 응답하며, 새로운 유닛이 생성된 HTML을 읽어 id, 클래스, 태그, 속성으로 요소를 찾고 페이지를 저장된 사본과 비교하므로, 마크업의 의도치 않은 변경을 고객이 아니라 테스트가 알아차립니다.

애플리케이션처럼 느껴지는 내비게이션. 페이지는 전체 새로고침 없이 전환되며 스크롤 위치와 사용자가 입력하던 내용을 유지하고, 로딩 바, 연결이 끊겼을 때의 대화상자, 요청이 실패했을 때의 메시지를 제공합니다. 이 모든 것은 기본적으로 꺼져 있습니다.

네 가지 핵심 기능

이들 각각에는 별도의 글이 있고 마지막에 링크되어 있으니, 여기서는 그것이 무엇인지만 소개합니다:

Push, 두 가지 방식

Server sent events는 이제 WebSocket 대신 업데이트를 전달할 수 있으며, 연결이 끊긴 동안 놓친 내용을 다시 재생해주고, 일반 HTTP 서버에서도 동작합니다. Web Push는 닫혀 있는 브라우저에도 도달합니다. 여기에는 알림 수신함과 환경설정 테이블이 함께 제공되며, 알림 컴포넌트가 특정 사용자가 어떤 채널을 받을지 결정합니다.

Delphi를 위한 EventSource 클라이언트

새로운 TsgcSSEClient는 어떤 Server-Sent Events 스트림이든 수신하며 모든 에디션에 포함됩니다. 스스로 재연결하며 Last-Event-ID를 전송하므로, 서버는 스트림이 멈춘 지점에서 재개합니다. 서버가 보내는 retry: 필드가 존중되고, OnEvent가 이벤트 타입과 데이터, id를 전달하며, ReconnectOptions가 백오프와 지터를 더합니다. TLS, 프록시, 인증은 OnBeforeConnect에서 설정하며, 여기서 컴포넌트가 사용하는 HTTP 클라이언트를 전달받습니다.

FSSE := TsgcSSEClient.Create(Self);
FSSE.URL := 'https://example.com/events';
FSSE.ReconnectOptions.Backoff := True;
FSSE.ReconnectOptions.MaxInterval := 30000;
FSSE.ReconnectOptions.Jitter := 0.2;
FSSE.OnEvent := DoSSEEvent;
FSSE.Open;

procedure TForm1.DoSSEEvent(Sender: TObject; const aEvent: TsgcSSEEvent);
begin
  Memo1.Lines.Add(aEvent.EventType + ': ' + aEvent.Data);
end;

그 뒤에서 동작하는 파서인 TsgcSSEParser는 공개되어 있습니다. 어떤 text/event-stream이든 그 바이트를 임의 크기의 청크로 넘겨주기만 하면 되며, 이는 바로 LLM 스트리밍 응답이나 MCP Streamable HTTP 응답이 동작하는 방식 그대로입니다.

FParser := TsgcSSEParser.Create;
FParser.OnEvent := DoSSEEvent;
FParser.Feed('event: delta' + #10 + 'data: {"text":"Hel"}' + #10#10);

새 데모 Demos\20.HTTP_Protocol\17.SSE_Client_Component가 전체 과정을 처음부터 끝까지 보여줍니다.

AI: 곧바로 활용할 수 있는 답변

TsgcAIChat은 새로운 ChatJSON 메서드를 통해 OpenAI, Anthropic, Gemini, DeepSeek, Ollama, Grok, Mistral에서 사용자가 제공한 스키마를 따르는 JSON을 요청할 수 있으며, 이 메서드는 응답을 파싱하고 읽을 수 없을 경우 파싱 오류를 첨부해 다시 한 번 묻습니다. 채팅 컴포넌트는 이제 이미지도 주고받으며, BaseUrl은 이제 Ollama뿐 아니라 모든 제공자에서 지원되어, 어느 것이든 프록시나 로컬 게이트웨이로 지정할 수 있습니다.

문서 추출: PDF에서 검증된 JSON까지

새로운 TsgcAIDocumentExtractor는 PDF나 이미지와 JSON 스키마를 받아, 그 스키마에 맞춰 검증된 JSON을 반환합니다. OpenAI, Anthropic, Gemini는 PDF를 직접 읽고, 나머지 비전 모델은 이미지를 읽습니다. 내장 프리셋은 인보이스, 영수증, 신분증(dpInvoice, dpReceipt, dpIDCard)을 다루며, 모든 필드에 신뢰도가 함께 제공되므로 OnLowConfidence는 MinConfidence보다 낮은 값 중 다시 확인해야 할 항목을 알려 줍니다. 답변이 검증을 통과하지 못하면 컴포넌트는 오류를 첨부해 한 번 더 요청합니다(ValidationRetries).

FExtractor := TsgcAIDocumentExtractor.Create(Self);
FExtractor.AIChat := AIChat1;
FExtractor.Preset := dpInvoice;
FExtractor.MinConfidence := 0.8;
FExtractor.OnLowConfidence := DoLowConfidence;

Memo1.Lines.Text := FExtractor.ExtractFile('invoice.pdf');
if FExtractor.LastResult.FieldConfidence('total') < 0.8 then
  ShowMessage('Check the total by hand');

TsgcAIOCRTesseract나, 설치할 것 없이 Windows 10 이상에 내장된 OCR을 사용하는 TsgcAIOCRWindows를 연결하고 OCRMode를 domFallback이나 domAlways로 설정하면 텍스트를 먼저 로컬에서 인식하므로, Ollama에서 실행되는 텍스트 전용 모델로도 추출할 수 있습니다. 직접 프롬프트를 작성하려면 TsgcAIChat에 새로 추가된 ChatWithDocument, ChatWithDocumentBase64, ChatWithAttachments, ChatJSONWithAttachments를 사용하세요. 이들은 TsgcAIChatAttachments 목록에 담긴 파일 하나 또는 여러 개를 메시지와 함께 전송합니다.

듣고, 대답하고, 도구를 호출하는 음성 에이전트

새로운 TsgcAIVoiceAgent는 듣고, 사용자가 발화를 마쳤는지 감지하고, 자신의 목소리로 대답하며, OpenAI Realtime 또는 Gemini Live를 통해 사용자의 도구를 호출하는 단일 컴포넌트입니다. WebSocket으로 통신하거나 OpenAI와는 WebRTC로 통신하며, Windows, Android, iOS에서 동작합니다. 턴은 서버 VAD, 시맨틱 VAD, 클라이언트 측 VAD 또는 수동 방식으로 감지됩니다(vtdServerVAD, vtdSemanticVAD, vtdClientVAD, vtdManual). BargeIn을 사용하면 사용자가 끼어들 수 있고, 에이전트는 말을 멈추고 중단된 지점에서 응답을 잘라냅니다. OnTranscript는 사용자와 에이전트 양쪽의 실시간 전사를 전달합니다.

FAgent := TsgcAIVoiceAgent.Create(Self);
FAgent.Provider := vapOpenAI;
FAgent.OpenAIOptions.ApiKey := 'sk-...';
FAgent.Instructions := 'You are the shop assistant. Keep answers short.';
FAgent.TurnDetection.Mode := vtdSemanticVAD;
FAgent.BargeIn := True;

oTool := FAgent.Tools.Add;
oTool.Name := 'find_product';
oTool.Description := 'Looks up a product by name';
oTool.Parameters :=
  '{"type":"object","properties":{"name":{"type":"string"}}}';

FAgent.OnTranscript := DoTranscript;
FAgent.OnToolCall := DoToolCall;
FAgent.Start;

procedure TForm1.DoToolCall(Sender: TObject; const aCallId, aName,
  aArguments: string; var aResult: string; var aHandled: Boolean);
begin
  if aName = 'find_product' then
  begin
    aResult := FindProduct(aArguments);
    aHandled := True;
  end;
end;

도구는 OnToolCall에서 제공되며, TsgcWSAPI_Client_MCP가 MCPClient에 할당되면 해당 MCP 서버의 도구가 모델에 자동으로 제공됩니다. 전화 통신을 위해 Audio.Format은 8kHz의 G.711 mu-law 또는 A-law로 전환됩니다(vafG711ULaw, vafG711ALaw). 음성 에이전트는 Delphi 7부터 Delphi 13까지, 그리고 .NET에서 사용할 수 있으며, 새로운 데모는 이를 TDataSet 기반의 음성 매장 도우미로 바꿔 줍니다.

암호화: Object Pascal로 구현한 포스트 퀀텀

ML-KEM(FIPS 203), ML-DSA(FIPS 204), SLH-DSA(FIPS 205), X-Wing 하이브리드 키 캡슐화, 포스트 퀀텀 X.509 인증서와 인증 기관, 그리고 ML-DSA로 서명된 JWT. 이 모든 것이 외부 라이브러리 없이 sgcCrypto 패키지 안에서 Object Pascal로 작성되었으며, NIST의 알려진 응답 벡터에 대해 검증되었습니다.

그 위에는 역시 순수 Pascal로 작성된 네이티브 TLS 1.3 및 TLS 1.2 엔진이 있습니다. 클라이언트나 서버는 OpenSSL도 SChannel도 없이 TLS로 통신하며, RFC 10024의 하이브리드 포스트 퀀텀 그룹을 협상하고, ALPN, S N I, 클라이언트 인증서, 그리고 운영체제 신뢰 저장소의 선택적 사용을 지원합니다. TLS 1.2는 아직 TLS 1.3을 지원하지 않는 상대를 위한 것으로, 기본으로 순방향 비밀성을 갖는 AES-GCM과 ChaCha20-Poly1305 스위트를 제공하며, 확장 마스터 시크릿과 다운그레이드 방지를 포함하고, TLSOptions.Version이 허용되는 최저 버전을 지정합니다. 하이브리드 그룹은 TLS 1.3에만 남아 있습니다.

고전 암호화 쪽도 같은 작업에서 강화되었습니다: 블라인딩된 상수 시간 RSA, 상수 시간 타원곡선 스칼라 곱셈과 Ed25519, 테이블을 쓰지 않는 AES와 GHASH, 가져온 개인 키를 공개 키 절반과 대조해 검증하는 절차, 그리고 최소 형태가 아닌 DER 서명의 거부.

인증: 모두가 요구하는 로그인

새로운 인증 컴포넌트들이 로그인 화면에 대해 모든 고객이 묻는 질문에 답합니다. Enterprise와 All-Access 에디션, 그리고 sgcAuth 팩에 포함되며, 같은 컴포넌트가 sgcWebSockets .NET에도 있습니다.

언급할 만한 수정 사항

.NET

.NET 라이브러리도 보조를 맞춥니다: ASP.NET Core를 위한 ClaimsPrincipal 브리지가 포함된 인증과 세션, 라우터, 테스트 도우미, SPA 내비게이션, 네이티브 엔드포인트를 갖춘 SSE 전송, 구조화된 출력, 두 OCR 엔진을 모두 갖춘 문서 추출, 실시간 음성 에이전트, AI Data Pack, Web Push, MCP Apps, 어댑터가 포함된 CRUD 컴포넌트, 그리고 새로운 TsgcSSEClient까지, 모두 Delphi와 동일한 API 이름을 사용합니다.

ASP.NET Core용 Razor Tag Helpers. 이제 sgcHTML은 Telerik UI와 DevExpress처럼 MVC 또는 Razor Pages 애플리케이션에 자연스럽게 들어맞습니다. <sgc-grid>, <sgc-form>, <sgc-autocomplete>, <sgc-dialog>, <sgc-chart> 같은 Tag Helper와 Html.Sgc() 아래의 대응하는 fluent API는 서버에서 Bootstrap 5를 렌더링하고 htmx로 컨트롤러와 통신하며, JavaScript 프레임워크가 필요 없습니다. 그리드는 IQueryable에서 페이징, 정렬, 필터, 검색, XLSX와 PDF 내보내기를 처리하므로 EF Core가 이 모든 것을 SQL로 실행합니다.

<sgc-grid name="orders" key="Id" items="Model"
          asp-action="Read" asp-export-action="Export" export="xlsx,pdf"
          page-size="15" sortable="true" filterable="true"
          searchable="true" push-url="true">
    <sgc-column field="Reference" searchable="true" />
    <sgc-column field="Customer" searchable="true" />
    <sgc-column field="OrderDate" title="Date" format="{0:yyyy-MM-dd}" filter="range" />
    <sgc-column field="Total" format="{0:N2}" align="right" filter="range" />
</sgc-grid>

// OrdersController
public IActionResult Read(SgcDataRequest request) => this.SgcGrid(request, Rows());

입력은 asp-for로 바인딩되어 ModelState 오류를 표시하며, this.SgcCloseDialog("edit-order", refresh: "orders")는 편집 대화 상자를 닫고 그리드를 다시 불러옵니다. 다른 제품에 없는 부분은 서버 푸시입니다. live="true"인 차트는 백그라운드 서비스가 hub.BroadcastChartAsync(...)를 호출할 때 열려 있는 모든 브라우저에서 다시 그려지며, sgcHTML WebSocket을 통해 이루어지고 SignalR 코드는 필요 없습니다. esegece.sgcHTML.AspNetCore NuGet 패키지에 포함되며 Community 에디션에서도 사용할 수 있고, 22.RazorMvc 데모는 익숙한 주문 샘플을 이것으로 다시 만든 것입니다.

업그레이드

새로운 것은 모두 추가적이며 기본적으로 꺼져 있습니다. 새 유닛을 넣고 패키지를 다시 빌드하면, 기존 애플리케이션은 이전과 정확히 똑같이 동작합니다.

전체 버전

영상으로 보기

이에 관한 짧은 영상이 eSeGeCe 채널에 있습니다.

질문, 피드백, 마이그레이션 도움이 필요하신가요? 문의하기 — 코드를 작성한 사람들에게서 직접 답변을 받으실 수 있습니다.