sgcWebSockets Enterprise 에디션에는 새로운 컴포넌트인 TsgcWSAPIServer_OpenAPI가 포함되어 있으며, 이는 OpenAPI 3 설명을 Delphi 애플리케이션 내부에서 실행되는 REST 서버로 변환합니다. 폼에 드롭하고, HTTP 서버에 연결한 후, 사양을 전달하면 — 라우트, 요청 검증, 오류 응답 및 라이브 Swagger UI 문서가 자동으로 구성됩니다. 이 글에서는 컴포넌트의 작동 방식, 이를 사용하는 두 가지 방법(사양 우선 및 코드 우선), 중요한 구성 옵션, 그리고 새 프로젝트에 바로 붙여넣을 수 있는 완전한 Delphi 예제를 살펴봅니다.
컴포넌트의 기능
TsgcWSAPIServer_OpenAPI는 기존 API 서버 확장 지점을 통해 TsgcWebSocketHTTPServer에 연결되는 가벼운 API 서버입니다. 서버에 연결하고 OpenAPI 3.0 사양을 로드하면, 들어오는 모든 HTTP 요청에 대해 다음 네 가지 작업을 수행합니다:
- URL과 HTTP 메서드를 사양에 선언된 라우트(
{path}매개변수 포함)와 매칭합니다; - 요청을 검증합니다 — 필수 필드, 쿼리 매개변수, 경로 매개변수 및 요청 본문을 — 사양의 스키마에 따라 검증합니다;
- 해결된
operationId와 완전히 채워진 컨텍스트 객체를 포함하여OnRequest이벤트를 발생시키므로, 코드는 비즈니스 로직만 작성하면 됩니다; - 두 개의 내장 엔드포인트를 즉시 제공합니다 —
/openapi.json의 원시 사양과/docs의 대화형 Swagger UI — 모든 라우트에 대한 선택적 CORS 사전 요청도 함께 제공합니다.
결과적으로 사양이 단일 진실 공급원이 됩니다: JSON에서 경로, 매개변수 또는 응답 코드를 변경하고 재시작하면, Delphi 코드를 다시 컴파일하지 않고도 서버가 새 계약을 인식합니다.
사양 우선: 기존 OpenAPI 3 파일 로드
이미 OpenAPI 3 문서(예: API 디자이너에서 내보낸 petstore.json)가 있다면 연결은 기본적으로 세 줄입니다 — 컴포넌트 생성, 사양 로드, 서버 연결. 나머지는 모두 구성과 실제 응답을 생성하는 OnRequest 핸들러입니다.
uses
sgcWebSocket, sgcWebSocket_Classes,
sgcWebSocket_Server_API_OpenAPI,
sgcHTTP_OpenAPI_Server;
var
WSServer: TsgcWebSocketHTTPServer;
FOpenAPI: TsgcWSAPIServer_OpenAPI;
begin
WSServer := TsgcWebSocketHTTPServer.Create(nil);
WSServer.Port := 8080;
FOpenAPI := TsgcWSAPIServer_OpenAPI.Create(nil);
FOpenAPI.OnRequest := OnOpenAPIRequest;
FOpenAPI.OnBeforeRequest := OnOpenAPIBeforeRequest;
FOpenAPI.OnValidationError := OnOpenAPIValidationError;
// Configuration
FOpenAPI.OpenAPIOptions.Endpoint.ServeSpec := True;
FOpenAPI.OpenAPIOptions.Endpoint.ServeSwaggerUI := True;
FOpenAPI.OpenAPIOptions.CORS.Enabled := True;
FOpenAPI.OpenAPIOptions.Validation.ValidateRequest := True;
FOpenAPI.OpenAPIOptions.Validation.ValidateRequired := True;
FOpenAPI.OpenAPIOptions.Validation.ValidateRequestBody := True;
// Load spec and attach to server
FOpenAPI.LoadFromFile('petstore.json');
FOpenAPI.Server := WSServer;
WSServer.Active := True;
// Swagger UI: http://localhost:8080/docs
// Raw spec: http://localhost:8080/openapi.json
end;
OnRequest 이벤트는 operationId별로 디스패치됩니다 — YAML/JSON의 각 작업 옆에 작성한 문자열입니다. 작업별로 분기 하나를 작성하고, 컨텍스트에서 입력을 읽은 후 응답을 내보냅니다:
procedure TForm1.OnOpenAPIRequest(Sender: TObject;
const aOperationId: string; const aContext: TsgcOpenAPIServerContext;
var Handled: Boolean);
var
vId: Int64;
vLimit: Integer;
begin
Handled := True;
if aOperationId = 'listPets' then
begin
vLimit := aContext.QueryParamAsInteger('limit', 100);
aContext.RespondJSON(200, BuildPetsJSON(vLimit));
end
else if aOperationId = 'getPetById' then
begin
vId := aContext.PathParamAsInteger('petId');
if FindPet(vId) then
aContext.RespondJSON(200, PetAsJSON(vId))
else
aContext.RespondError(404, 'Not Found',
Format('Pet %d not found', [vId]));
end
else
Handled := False;
end;
TsgcOpenAPIServerContext 객체는 모든 핸들러의 핵심 도구입니다. 경로 및 쿼리 매개변수를 이름으로 노출하고(PathParamAsString, PathParamAsInteger, QueryParamAsString, QueryParamAsInteger, QueryParamAsBoolean), HeaderValue를 통한 헤더 조회, 본문을 문자열(BodyAsString) 또는 사전 파싱된 JSON(BodyAsJSON)으로 제공하며, 두 가지 응답 헬퍼도 포함합니다: 일반 페이로드용 RespondJSON(code, content)와 RespondError(code, title, detail). 후자는 RFC 7807 스타일의 application/problem+json 본문을 생성하므로 클라이언트는 항상 일관된 오류 형식을 받습니다.
코드 우선: Delphi 속성에서 사양 생성
두 번째 모드는 역방향 흐름입니다: 속성으로 데코레이션된 Delphi 클래스로 API를 선언하고, 스캐너에 런타임에 OpenAPI 문서를 생성하도록 요청한 다음, 해당 문서를 동일한 컴포넌트에 다시 입력합니다. JSON에서 손으로 작성할 것이 전혀 없습니다.
uses
sgcHTTP_OpenAPI_Server_CodeFirst;
type
[sgcServiceContract('Task Manager API',
'A simple task manager', '1.0.0')]
[sgcRoute('/api/v1')]
TTaskService = class
public
[sgcHttpGet]
[sgcRoute('/tasks')]
[sgcSummary('List all tasks')]
[sgcResponse(200, 'A list of tasks')]
procedure ListTasks([sgcFromQuery] const status: string); virtual;
[sgcHttpGet]
[sgcRoute('/tasks/{taskId}')]
[sgcSummary('Get a task by ID')]
[sgcResponse(200, 'The requested task')]
[sgcResponse(404, 'Task not found')]
procedure GetTask([sgcFromPath][sgcRequired]
const taskId: Integer); virtual;
[sgcHttpPost]
[sgcRoute('/tasks')]
[sgcSummary('Create a new task')]
[sgcResponse(201, 'Task created')]
procedure CreateTask([sgcFromBody] const body: string); virtual;
end;
클래스 자체에는 실제 본문이 필요하지 않습니다 — 스캐너가 RTTI를 통해 이를 읽으며, 실제 로직은 여전히 OnRequest 핸들러에 있습니다. 사양을 생성하고 서버를 시작하는 데는 몇 줄이면 됩니다:
var
oScanner: TsgcOpenAPICodeFirstScanner;
vSpec: string;
begin
oScanner := TsgcOpenAPICodeFirstScanner.Create;
try
vSpec := oScanner.GenerateSpec(TTaskService);
finally
oScanner.Free;
end;
FOpenAPI.LoadFromString(vSpec);
FOpenAPI.Server := WSServer;
WSServer.Active := True;
end;
속성 집합은 일반적인 경우를 다룹니다: 라우팅(sgcHttpGet, sgcHttpPost, sgcHttpPut, sgcHttpDelete, sgcHttpPatch, sgcRoute), 매개변수 바인딩(sgcFromPath, sgcFromQuery, sgcFromHeader, sgcFromBody), 검증(sgcRequired, sgcMinLength, sgcMaxLength, sgcRange, sgcPattern) 및 문서화(sgcSummary, sgcDescription, sgcTag, sgcResponse).
상세 구성
OpenAPIOptions는 세 가지 영구 하위 객체로 그룹화되어 있어 객체 인스펙터에서 모두 볼 수 있습니다:
Endpoint—BasePath는 모든 라우트와 내장/openapi.json및/docs엔드포인트에 접두사를 추가합니다;SpecFile은 디자인 타임에LoadFromFile의 대안으로 사용할 수 있습니다;ServeSpec및ServeSwaggerUI는 두 내장 엔드포인트를 토글합니다(기본적으로 모두 켜져 있음).Validation— 마스터 스위치는ValidateRequest입니다;ValidateRequired,ValidateQueryParams,ValidatePathParams및ValidateRequestBody를 사용하면 검사 범위를 좁힐 수 있습니다. 검증에 실패하면OnValidationError가 문제 목록과Continue플래그와 함께 발생합니다 —False로 설정하면 요청이 자동으로 거부됩니다.CORS—Enabled := True로 설정하면 서버는 모든 라우트에 대한 사전 요청OPTIONS에 응답하며,AllowOrigins,AllowHeaders및AllowMethods를 응답 정책으로 사용합니다.
OnRequest 외에도 네 가지 추가 이벤트를 통해 파이프라인에 접근할 수 있습니다: OnBeforeRequest(Accept := False로 설정하여 단축, 속도 제한이나 로깅에 유용함), OnAfterRequest(응답을 생성한 후의 사후 처리), OnAuthenticate(토큰이나 세션을 확인한 후 Authenticated := True로 설정), 그리고 OnException(프레임워크가 오류 본문을 쓰기 전에 HTTP 상태를 변경할 수 있는 포괄적 핸들러).
즉시 사용 가능한 Swagger UI
ServeSwaggerUI := True로 설정하면 서버는 BasePath + '/docs'에 Swagger UI 페이지를 게시하며, 이 페이지는 BasePath + '/openapi.json'에서 사양을 로드합니다. 브라우저에서 URL을 열면 자체 실행 중인 서버에서 제공되는 표준 try-it-out 환경이 표시됩니다 — 별도의 문서 빌드도, 정적 내보내기도 없습니다. CORS와 결합하면 백엔드를 프론트엔드 팀이나 API에 통합하는 파트너에게 전달하는 가장 빠른 방법입니다.
구하는 방법
이 컴포넌트는 sgcWebSockets의 Enterprise 에디션의 일부이며, SGC OpenAPI 팔레트 페이지에 등록되어 있습니다. 두 개의 완전한 데모 — 하나는 Petstore JSON을 사용한 사양 우선 방식, 다른 하나는 작업 관리자 서비스를 사용한 코드 우선 방식 — 가 Demos\23.OpenAPI에 포함되어 있습니다. sgcWebSockets 다운로드 페이지에서 최신 빌드를 다운로드하세요.
질문, 피드백 또는 기존 프로젝트에 통합하는 데 도움이 필요하신가요? 문의하기 — 코드를 작성한 사람들로부터 답변을 받게 됩니다.
