sgcOpenAPI vs Swagger Codegen — Delphi 클라이언트를 더 빠르게 생성

· 리뷰

문제: 대부분의 최신 API는 Delphi SDK가 아닌 OpenAPI 사양을 제공해요

Delphi에서 최신 REST API를 통합해 본 적이 있다면 워크플로는 아마 다음과 같았을 거예요: 문서 읽기, TIdHTTP 또는 TNetHTTPClient 주변에 래퍼 손으로 작성, 요청 본문을 문자열 리터럴에 붙여넣기, TJSONObject로 응답 파싱, TDateTime 직렬화와 싸우기, 모든 엔드포인트에 대해 반복. 작동하지만 확장되지 않아요. API에는 80개의 엔드포인트가 있고, 8개를 래핑하고, 공급업체가 다음 달에 10개를 더 추가하면 래퍼가 썩어요.

OpenAPI(이전 Swagger)의 약속은 공급업체가 기계 판독 가능한 설명 — 하나의 YAML 또는 JSON 파일 — 을 게시하고 생성기가 이를 선택한 언어로 타입이 지정된 클라이언트로 변환한다는 것이에요. 대부분의 언어에서 이것은 매우 잘 작동해요: openapi-generatorswagger-codegen은 Python, TypeScript, Go, Java, C#, Rust 및 기타 여러 언어에 대해 관용적인 클라이언트를 생성해요.

Delphi의 경우 이야기는 역사적으로 덜 매끄러웠어요. 이 게시물은 2026년 기준 두 가지 주요 옵션 — 오랫동안 존재한 오픈 소스 swagger-codegen Delphi 생성기와 eSeGeCe의 네이티브 상용 sgcOpenAPI — 을 비교하고 동일한 입력 사양에서 각각이 생성하는 것을 보여줘요.

swagger-codegen 및 openapi-generator에 대해

이제 SmartBear 산하의 Swagger 프로젝트는 swagger-codegen을 제공해요. 2018년 커뮤니티 포크 후 병렬 프로젝트인 openapi-generator가 많은 언어의 사실상 표준이 되었어요. 두 도구 모두 Mustache 템플릿을 통해 긴 대상 언어 목록을 지원해요. Delphi 생성기(swagger-codegen의 delphi와 커뮤니티 템플릿)가 있지만 항상 가끔씩 자원 봉사자가 유지 관리하는 2계층 대상이었어요.

작성 시점에 openapi-generator의 Delphi 템플릿은 이전 Delphi 버전에서 컴파일되는 코드를 생성하지만 최신 Delphi(D11/D12/D13)에서는 알려진 문제가 있어요: nullable 필드의 잘못된 처리, 최신 RTL에 대한 {$IFDEF} 가드 누락, OpenAPI 3.1 지원 없음, 스트리밍 응답 지원 없음, 특정 HTTP 클라이언트 라이브러리 버전에 의존하는 런타임. Delphi 생성기에 대한 여러 오래된 GitHub 이슈가 수년간 열려 있어요. 사양에 따라 결과가 달라질 거예요.

sgcOpenAPI에 대해

sgcOpenAPI는 eSeGeCe의 네이티브 Delphi 도구예요. OpenAPI 3.0(이제 3.1) 사양을 파싱하고 sgc 명명 규칙을 따르는 Delphi 유닛을 내보내요: 클라이언트의 경우 Tsgc[Api]Client, 각 스키마 객체의 경우 Tsgc[Api]_[Model], 그리고 작업당 하나의 메서드. 생성된 코드는 sgcWebSockets의 TsgcHTTPComponentClient를 전송으로 사용하므로 인증, 재시도, TLS 및 HTTP/2가 무료로 상속돼요.

생성기 자체가 Delphi로 작성되었기 때문에 Delphi 도구에 임베드하거나, 명령줄에서 실행하거나, 빌드 스크립트에서 호출할 수 있어요. 출력은 sgcWebSockets 외에는 런타임 종속성이 없는 일반 .pas 파일이에요 — JVM 없음, Node 없음, Python 없음, 템플릿 엔진 없음.

기능 비교

기능swagger-codegen / openapi-generator (Delphi 대상)sgcOpenAPI
OpenAPI 2.0 (Swagger)
OpenAPI 3.0예 (openapi-generator)
OpenAPI 3.1작성 시점 제한적
런타임 요구 사항생성기 실행을 위한 Java 11+없음 (네이티브 Delphi exe)
대상 Delphi 버전D10.x에서 최선의 노력, 작성 시점 D11+에서 종종 깨짐D7부터 D13까지
HTTP 백엔드현재 Delphi 템플릿에서 기본적으로 IndysgcHTTPComponentClient (Indy / ICS / SChannel, HTTP/2 포함)
비동기 / 스트리밍 응답제한적
OAuth2 / API 키 / 베어러 인증부분적예, 네이티브 컴포넌트
다형성 (oneOf, allOf, discriminator)제한적
Nullable 필드일관성 없음예 (TsgcNullable<T>)
파일 업로드 / multipart부분적
서버 스텁 생성예 (대부분 다른 언어)예 (sgcWebSocketHTTPServer가 있는 Delphi 서버 스텁)
라이선스오픈 소스 (Apache 2.0)상용

워크플로 비교

swagger-codegen 워크플로

  1. Java 11 이상 설치.
  2. openapi-generator-cli JAR 다운로드.
  3. java -jar openapi-generator-cli.jar generate -i spec.yaml -g delphi -o ./out 실행.
  4. IDE에서 생성된 .pas 파일 열기. Indy 런타임 경로 추가. Delphi 버전에 대한 컴파일 문제 수정. Nullable 처리 패치. 모든 사양 변경 후 다시 실행.
  5. 생성된 클라이언트는 템플릿이 제공하는 별도의 런타임 지원 유닛에 의존해요. 그 유닛을 프로젝트와 함께 배포해요.

sgcOpenAPI 워크플로

  1. sgcOpenAPI IDE를 열거나 CLI를 호출: sgcOpenAPI.exe -i spec.yaml -o ./out.
  2. IDE에서 생성된 유닛 열기. sgcWebSockets를 사용한다면 이미 가지고 있는 TsgcHTTPComponentClient를 사용해요.
  3. 생성된 클라이언트 컴포넌트를 폼에 드롭하고, 기본 URL과 자격 증명을 설정하고, 타입이 지정된 메서드를 호출하세요.

나란히 비교: 생성된 GET /users/{id} 메서드

동일한 OpenAPI 조각, 두 도구, 동일한 작업. 헬퍼의 이름과 정확한 형식은 명확성을 위해 약간 양식화되었지만 접근 방식의 차이는 실재해요.

swagger-codegen (Delphi 대상, 단순화)

function TUsersApi.GetUserById(const Id: Int64): TUser;
var
  HttpRequest: TIdHTTP;
  Path, Response: string;
  JsonValue: TJSONValue;
begin
  Path := StringReplace(BasePath + '/users/{id}', '{id}', IntToStr(Id), [rfReplaceAll]);
  HttpRequest := TIdHTTP.Create(nil);
  try
    HttpRequest.Request.CustomHeaders.AddValue('Authorization', 'Bearer ' + FApiKey);
    Response := HttpRequest.Get(Path);
  finally
    HttpRequest.Free;
  end;
  JsonValue := TJSONObject.ParseJSONValue(Response);
  try
    Result := TUser.Create;
    Result.Id := (JsonValue as TJSONObject).GetValue<Int64>('id');
    Result.Name := (JsonValue as TJSONObject).GetValue<string>('name');
    // ... nullable fields handled inconsistently ...
  finally
    JsonValue.Free;
  end;
end;

sgcOpenAPI

function TsgcUsersApiClient.GetUserById(const aId: Int64): TsgcUser;
var
  vResponse: TsgcAPIResponse;
begin
  Result := nil;
  vResponse := DoGet(Format('/users/%d', [aId]));
  Try
    if vResponse.StatusCode = 200 then
      Result := TsgcUser.FromJSON(vResponse.Content);
  Finally
    vResponse.Free;
  End;
end;

// TsgcUser is generated with typed nullable fields:
//   property Id: Int64 read FId write FId;
//   property Name: string read FName write FName;
//   property Email: TsgcNullable<string> read FEmail write FEmail;
//   property CreatedAt: TDateTime read FCreatedAt write FCreatedAt;
//
// Authentication, retry, HTTP/2, TLS are configured on the
// underlying TsgcHTTPComponentClient once, not per-method.

주목할 만한 차이점:

서버 스텁

두 도구 모두 서버 측 코드를 생성할 수 있지만 openapi-generator의 Delphi 서버 템플릿은 작성 시점 최소한이에요. sgcOpenAPI는 작업당 하나의 가상 메서드, 요청 검증, 응답 형성 및 내장 OpenAPI 탐색기 엔드포인트가 있는 TsgcWebSocketHTTPServer 기반 핸들러를 생성해요. 단일 Delphi 프로젝트가 API를 노출하고 Delphi 클라이언트가 소비하는 내부 서비스의 경우 왕복이 매우 짧아요.

swagger-codegen이 여전히 올바른 선택인 경우

sgcOpenAPI가 실제 시간을 절약하는 경우

맺음말

OpenAPI에서의 코드 생성은 프로젝트의 수명 동안 누적되는 생산성 승리 중 하나예요 — 생성기가 사양과 Delphi 버전에 발맞춰 진행되는 경우. swagger-codegen / openapi-generator는 우수한 다중 언어 도구이지만 Delphi 대상은 역사적으로 최선의 노력으로 취급되었어요. sgcOpenAPI는 Java 종속성 없이 그리고 수동 패치 주기 없이 컴파일 가능하고 관용적이며 전체 기능 OpenAPI 3.0 / 3.1 클라이언트(및 서버 스텁)를 제공하는 집중적인 네이티브 Delphi 대안이에요. 이미 REST API를 통합하는 대부분의 Delphi 팀의 경우 공급업체가 사양을 업데이트하는 첫 번째 시점에 그 비용을 회수해요.