sgcOpenAPI 2026.6 — 독립형 OpenAPI 서버, Spec-First 또는 Code-First

· 릴리스

sgcOpenAPI의 차기 릴리스 — 6월에 출시 예정인 2026.6 버전 — 은 완전히 새로운 컴포넌트 TsgcHTTPServer_OpenAPI를 제공합니다. 이것은 임베디드 HTTP 서버로 OpenAPI 3.0 서비스를 호스팅하는 단일 독립형 Delphi 컴포넌트입니다. 폼에 드롭하고, 스펙을 지정하거나(또는 RTTI 속성으로 Delphi 클래스에서 생성), Active := True를 설정하면 자동으로 제공되는 Swagger UI가 포함된 문서화된 REST API를 갖게 됩니다.

핵심 변경 사항은 sgcOpenAPI가 더 이상 HTTP 서버를 호스팅하기 위해 sgcWebSockets를 필요로 하지 않는다는 것입니다. 새 컴포넌트는 전적으로 sgcOpenAPI에서 제공, 패키징 및 설치됩니다. 이미 sgcWebSockets를 사용하고 있다면 이전 TsgcWSServer_API_OpenAPI 컴포넌트는 변경 없이 계속 작동합니다 — 둘 다 내부적으로 동일한 엔진을 공유합니다.

하나의 컴포넌트로 얻을 수 있는 것

TsgcHTTPServer_OpenAPI는 세 가지를 번들로 제공합니다:

빠른 시작 — 최소 예제

Swagger UI가 포함된 작동하는 OpenAPI 서버를 호스팅하는 데 필요한 모든 것:

uses
  sgcHTTPServer_OpenAPI;

var
  oServer: TsgcHTTPServer_OpenAPI;
begin
  oServer := TsgcHTTPServer_OpenAPI.Create(nil);
  try
    oServer.Bindings.Add.Port := 8080;
    oServer.LoadFromFile('petstore.json');
    oServer.OnRequest := MyOnRequest;
    oServer.Active := True;
    Readln;
  finally
    oServer.Free;
  end;
end;

Swagger UI는 http://localhost:8080/docs로, 스펙은 http://localhost:8080/openapi.json로 접속하세요. 스펙에 정의된 모든 작업은 해결된 operationId와 완전히 구성된 요청 컨텍스트와 함께 MyOnRequest 핸들러로 라우팅됩니다.

Spec-First — 기존 OpenAPI 3.0 파일 로드

이미 OpenAPI 3.0 JSON 또는 YAML 파일(Petstore, 내부 API 계약, 모킹하려는 공용 스키마)이 있다면 spec-first가 이를 제공하는 가장 빠른 방법입니다. LoadFromFile은 스펙을 읽고 파싱하며, paths 섹션에서 라우트 테이블을 구성하고, 들어오는 모든 요청을 이에 대해 매칭합니다.

각 라우트의 operationId는 디스패치 키입니다. OnRequest 내에서 각 작업을 차례로 처리합니다:

uses
  sgcHTTP_OpenAPI_Server, sgcHTTP_OpenAPI_Server_Engine,
  sgcHTTPServer_OpenAPI;

procedure TForm1.OnOpenAPIRequest(Sender: TObject;
  const aOperationId: string; const aContext: TsgcOpenAPIServerContext;
  var Handled: Boolean);
begin
  Handled := True;
  if aOperationId = 'listPets' then
    HandleListPets(aContext)
  else if aOperationId = 'getPetById' then
    HandleGetPetById(aContext)
  else if aOperationId = 'createPet' then
    HandleCreatePet(aContext)
  else
    Handled := False;
end;

procedure TForm1.HandleGetPetById(const aContext: TsgcOpenAPIServerContext);
var
  vId, vPetJSON: string;
begin
  vId := aContext.PathParamAsString('petId');
  vPetJSON := FPets.Values[vId];
  if vPetJSON <> '' then
    aContext.RespondJSON(200, vPetJSON)
  else
    aContext.RespondError(404, 'Not Found', 'Pet ' + vId + ' not found');
end;

TsgcOpenAPIServerContext는 요청의 모든 것에 대한 타입 지정된 접근자를 제공합니다: 템플릿화된 세그먼트를 위한 PathParamAsString / PathParamAsInteger, 기본값이 있는 QueryParamAsString / QueryParamAsInteger / QueryParamAsBoolean, 요청 본문을 위한 BodyAsString / BodyAsJSON, 그리고 들어오는 헤더를 위한 HeaderValue. 응답하려면 헬퍼인 RespondJSON(code, content)RespondError(code, title, detail)를 사용하거나, 완전한 제어를 위해 Response.Code, Response.ContentType, Response.Content를 직접 설정하세요.

Code-First — Delphi 클래스에서 스펙 생성

API 계약을 Delphi로 작성하고 스펙을 생성하도록 하려면, RTTI 속성으로 클래스를 데코레이트하세요. TsgcOpenAPICodeFirstScanner가 클래스를 순회하여 완전한 OpenAPI 3.0 JSON 문서를 구성하며, LoadFromString으로 이를 서버에 로드합니다. 이 기능은 Delphi XE7 이상이 필요합니다(확장 RTTI용).

uses
  sgcHTTP_OpenAPI_Server_CodeFirst;

type
  [sgcServiceContract('Task Manager API',
    'A simple task management demo', '1.0.0')]
  [sgcRoute('/api/v1')]
  TTaskManagerService = class
  public
    [sgcHttpGet]
    [sgcRoute('/tasks')]
    [sgcSummary('List all tasks')]
    [sgcTag('Tasks')]
    [sgcResponse(200, 'A list of tasks')]
    procedure ListTasks([sgcFromQuery] const status: string); virtual;

    [sgcHttpPost]
    [sgcRoute('/tasks')]
    [sgcSummary('Create a new task')]
    [sgcTag('Tasks')]
    [sgcResponse(201, 'Task created successfully')]
    procedure CreateTask([sgcFromBody] const body: string); virtual;

    [sgcHttpGet]
    [sgcRoute('/tasks/{taskId}')]
    [sgcSummary('Get a task by ID')]
    [sgcTag('Tasks')]
    [sgcResponse(200, 'The requested task')]
    [sgcResponse(404, 'Task not found')]
    procedure GetTask([sgcFromPath][sgcRequired]
      const taskId: Integer); virtual;
  end;

메서드 본문은 스텁입니다 — 컴파일러가 이들에 대해 RTTI를 방출하도록 하기 위해서만 존재합니다. 실제 작업은 OnRequest에서 일어나며, 스캐너가 각 메서드 이름(ListTasks, CreateTask, GetTask…)에서 파생한 operationId에 의해 디스패치됩니다.

시작 시 클래스를 스캐너에 전달하고 생성된 스펙을 서버에 로드합니다:

uses
  sgcHTTP_OpenAPI_Server_CodeFirst, sgcHTTPServer_OpenAPI;

var
  oScanner: TsgcOpenAPICodeFirstScanner;
  oServer: TsgcHTTPServer_OpenAPI;
  vSpec: string;
begin
  oScanner := TsgcOpenAPICodeFirstScanner.Create;
  try
    vSpec := oScanner.GenerateSpec(TTaskManagerService);
  finally
    oScanner.Free;
  end;

  oServer := TsgcHTTPServer_OpenAPI.Create(nil);
  oServer.LoadFromString(vSpec);
  oServer.Bindings.Add.Port := 8081;
  oServer.OnRequest := MyOnRequest;
  oServer.Active := True;
end;

속성은 일반적인 메타데이터를 다룹니다: sgcServiceContract는 OpenAPI info 블록을 채우고, sgcRoute는 클래스 또는 메서드 수준에서 경로를 설정하며, sgcHttpGet / Post / Put / Delete / Patch / Head / Options는 동사를 선택하고, sgcSummarysgcDescription은 작업을 문서화하며, sgcTag는 Swagger UI에서 그룹화하고, sgcResponse(code, description)는 각 응답을 선언하며, sgcFromPath / FromQuery / FromBody / FromHeadersgcRequired와 함께 각 매개변수를 설명합니다.

구성 — OpenAPIOptions

모든 서버측 구성은 OpenAPIOptions 아래에 있으며, 세 가지 하위 옵션으로 그룹화됩니다:

oServer.OpenAPIOptions.Endpoint.BasePath        := '/api';
oServer.OpenAPIOptions.Endpoint.ServeSpec       := True;   // /openapi.json
oServer.OpenAPIOptions.Endpoint.ServeSwaggerUI  := True;   // /docs

oServer.OpenAPIOptions.CORS.Enabled             := True;
oServer.OpenAPIOptions.CORS.AllowOrigins        := '*';
oServer.OpenAPIOptions.CORS.AllowHeaders        := 'Content-Type, Authorization';
oServer.OpenAPIOptions.CORS.AllowMethods        := 'GET, POST, PUT, DELETE, PATCH, OPTIONS';

oServer.OpenAPIOptions.Validation.ValidateRequest     := True;
oServer.OpenAPIOptions.Validation.ValidateRequestBody := True;
oServer.OpenAPIOptions.Validation.ValidateQueryParams := True;
oServer.OpenAPIOptions.Validation.ValidatePathParams  := True;
oServer.OpenAPIOptions.Validation.ValidateRequired    := True;

검증이 활성화되면, 들어오는 모든 요청은 핸들러에 도달하기 전에 스펙에 선언된 JSON Schema에 대해 확인됩니다 — 필수 필드, 타입, 형식, 열거형, 범위. 실패하면 오류 목록과 요청을 수락하거나 거부하는 플래그와 함께 OnValidationError 이벤트가 발생합니다.

이벤트

이 컴포넌트는 요청 수명 주기를 위한 여섯 가지 이벤트를 노출합니다:

OnBeforeRequest: 디스패치 전에 발생합니다. Accept := False를 설정하면 403 Forbidden으로 거부합니다. 속도 제한, 로깅 또는 라우트별 게이트에 유용합니다.

OnAuthenticate: 메인 핸들러 전에 발생합니다. Authenticated := False를 설정하면 401 Unauthorized로 거부합니다. 헤더, 쿠키 또는 쿼리 매개변수를 검사하여 결정합니다.

OnValidationError: 검증이 실패하면 발생하며 오류 목록을 받습니다. Continue := False를 설정하면 400 Bad Request로 거부합니다.

OnRequest: 메인 디스패치 이벤트. aOperationId를 보고, aContext.Response에 응답을 작성하고, Handled := True를 설정합니다.

OnAfterRequest: 핸들러가 반환된 후 발생합니다 — 메트릭이나 감사 로깅에 이상적입니다.

OnException: 처리되지 않은 예외가 핸들러에서 발생하면 호출됩니다. 500 Internal Server Error 외의 다른 것을 원하면 aResponseCode를 조정하세요.

데모

sgcOpenAPI 2026.6에는 두 개의 완전한 데모가 함께 제공되며, 둘 다 새 독립형 컴포넌트만 사용합니다 — sgcWebSockets 설치가 필요하지 않습니다:

업그레이드

현재 sgcWebSockets와 함께 TsgcWSServer_API_OpenAPI를 사용하고 있다면 아무것도 변경되지 않습니다 — 클래스, 속성 및 이벤트가 모두 보존되며, 구현은 이제 새 독립형 컴포넌트를 구동하는 동일한 공유 엔진에 위임됩니다. 기존 코드를 그대로 유지하거나, sgcWebSockets 의존성을 제거하기 위해 한 번에 한 폼씩 TsgcHTTPServer_OpenAPI로 마이그레이션할 수 있습니다.

sgcOpenAPI 2026.6은 6월에 다운로드 페이지에서 제공될 예정입니다.

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