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는 세 가지를 번들로 제공합니다:
- 일반적인
Bindings,Port및Active속성을 가진 임베디드 HTTP 서버(Indy 기반). - OpenAPI 엔진: 스펙 파싱,
{paramName}세그먼트를 사용한 경로 템플릿 라우팅, JSON-Schema 검증, CORS, 예외 처리. - 두 개의 자동 제공 엔드포인트:
/openapi.json의 스펙과/docs의 Swagger UI. 둘 다 기본적으로 활성화되어 있으며OpenAPIOptions.Endpoint에서 토글할 수 있습니다.
빠른 시작 — 최소 예제
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는 동사를 선택하고, sgcSummary와 sgcDescription은 작업을 문서화하며, sgcTag는 Swagger UI에서 그룹화하고, sgcResponse(code, description)는 각 응답을 선언하며, sgcFromPath / FromQuery / FromBody / FromHeader는 sgcRequired와 함께 각 매개변수를 설명합니다.
구성 — 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 설치가 필요하지 않습니다:
- Demos/30.Server/01.CodeFirst — Delphi 클래스의 속성만으로 정의된 Task Manager API.
- Demos/30.Server/02.SpecFirst —
petstore.json에서 제공되는 클래식 Petstore 예제.
업그레이드
현재 sgcWebSockets와 함께 TsgcWSServer_API_OpenAPI를 사용하고 있다면 아무것도 변경되지 않습니다 — 클래스, 속성 및 이벤트가 모두 보존되며, 구현은 이제 새 독립형 컴포넌트를 구동하는 동일한 공유 엔진에 위임됩니다. 기존 코드를 그대로 유지하거나, sgcWebSockets 의존성을 제거하기 위해 한 번에 한 폼씩 TsgcHTTPServer_OpenAPI로 마이그레이션할 수 있습니다.
sgcOpenAPI 2026.6은 6월에 다운로드 페이지에서 제공될 예정입니다.
질문, 피드백 또는 마이그레이션 도움이 필요하신가요? 문의하기 — 코드를 작성한 사람들로부터 답변을 받으실 수 있습니다.
