← Back to list

[Swift] swift-openapi-generator 간단히 적용해보기

서버와 통신하는 iOS 앱을 만들다 보면, URLRequest를 직접 만들고 응답 모델을 붙이는 작업이 반복됩니다.

gaeng2y · 2026-04-09 14:20 · 0 claps · 8.7 min read
#swift #open-api #networking #data-transfer-object
Open on Medium ↗
Wiki topics: 📱 · Mobile Development

[Swift] swift-openapi-generator 간단히 적용해보기

Photo by Douglas Lopes on Unsplash

Photo by Douglas Lopes on Unsplash

서버와 통신하는 iOS 앱을 만들다 보면, URLRequest를 직접 만들고 응답 모델을 붙이는 작업이 반복됩니다.

이 과정을 줄이기 위해 Apple의 Swift OpenAPI Generator를 적용해봤습니다.

swift-openapi-generatorOpenAPI 문서(YAML/JSON) 를 기반으로 Swift의 API client / server 코드를 생성해주는 도구입니다. 빌드 시점에 코드를 생성하기 때문에, 스펙과 코드가 계속 동기화되도록 가져갈 수 있는 점이 특징입니다. (GitHub)

무엇이 좋은가

이 도구를 적용하면 대략 이런 이점이 있습니다.

  • OpenAPI 스펙 기반으로 타입 안전한 API 호출 코드를 만들 수 있다. (GitHub)
  • 요청/응답 모델을 직접 일일이 작성하는 보일러플레이트를 줄일 수 있다. (GitHub)
  • 빌드 타임에 생성되므로 스펙과 구현의 불일치를 줄이기 좋다. 생성 코드를 별도로 저장소에 커밋하지 않는 흐름도 가능하다. (GitHub)

iOS 클라이언트 기준으로는 보통 다음 조합을 사용합니다.

  • swift-openapi-generator : 코드 생성기
  • swift-openapi-runtime : 생성 코드가 사용하는 런타임
  • swift-openapi-urlsession : URLSession 기반 transport (GitHub)

기본 적용 흐름

전체 흐름은 단순합니다.

  1. OpenAPI 문서를 준비한다.
  2. Swift Package에 generator plugin과 runtime/transport를 추가한다.
  3. 빌드하면 Client 타입과 요청/응답 타입이 생성된다.
  4. 앱 코드에서는 생성된 Client를 사용해 API를 호출한다. (GitHub)

1. OpenAPI 문서 준비

예를 들어 openapi.yaml 파일이 있다고 가정합니다.

openapi: 3.1.0
info:
  title: GreetingService
  version: 1.0.0
servers:
  - url: https://example.com/api
paths:
  /greet:
    get:
      operationId: getGreeting
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                required:
                  - message

공식 README의 예시도 비슷한 형태로 operationId를 기준으로 Swift 메서드가 생성되는 구조를 보여줍니다. (GitHub)

2. 패키지 의존성 추가

Package.swift에 generator와 runtime, URLSession transport를 추가합니다.

// swift-tools-version: 6.0
import PackageDescription
let package = Package(
    name: "MyApp",
    platforms: [
        .iOS(.v16)
    ],
    dependencies: [
        .package(url: "https://github.com/apple/swift-openapi-generator", from: "1.0.0"),
        .package(url: "https://github.com/apple/swift-openapi-runtime", from: "1.0.0"),
        .package(url: "https://github.com/apple/swift-openapi-urlsession", from: "1.0.0")
    ],
    targets: [
        .target(
            name: "Networking",
            dependencies: [
                .product(name: "OpenAPIRuntime", package: "swift-openapi-runtime"),
                .product(name: "OpenAPIURLSession", package: "swift-openapi-urlsession")
            ],
            plugins: [
                .plugin(name: "OpenAPIGenerator", package: "swift-openapi-generator")
            ]
        )
    ]
)

핵심은 target에 plugin을 붙이는 것과, 생성 코드가 사용할 OpenAPIRuntime, 실제 HTTP 전송을 위한 OpenAPIURLSession을 함께 추가하는 것입니다. 공식 문서에서도 generator는 plugin/CLI 역할을 하고, URLSession transport는 별도 패키지로 분리되어 있습니다. (GitHub)

3. 설정 파일 추가

타깃 디렉터리 안에 보통 다음 파일들을 둡니다.

  • openapi.yaml
  • openapi-generator-config.yaml

예시:

generate:
  - types
  - client
accessModifier: public

이렇게 해두면 빌드 시 client와 관련 타입이 생성됩니다. 공식 README와 예제들은 build plugin 방식이 기본 사용 패턴이라고 안내합니다. (GitHub)

4. 생성된 Client 사용

이제 앱 코드에서는 직접 endpoint를 조립하기보다 생성된 Client를 사용합니다.

import Foundation
import OpenAPIURLSession
final class GreetingAPI {
    private let client: Client
    init() {
        self.client = Client(
            serverURL: URL(string: "https://example.com/api")!,
            transport: URLSessionTransport()
        )
    }
    func fetchGreeting() async throws -> String {
        let response = try await client.getGreeting()
        switch response {
        case .ok(let okResponse):
            return try okResponse.body.json.message
        default:
            throw URLError(.badServerResponse)
        }
    }
}

이 패턴은 공식 README에 있는 generated client 사용 예시와 같은 방향입니다. Client를 만들고, operation별 메서드를 async/await로 호출하는 형태입니다. (GitHub)

실제로 써보면서 느낀 점

1) API 스펙이 기준이 된다는 점이 좋다

보통 앱 코드에서 API 호출부가 먼저 생기고 문서는 뒤늦게 맞추는 경우가 많은데, 이 방식은 반대로 OpenAPI 문서가 기준이 됩니다. 결과적으로 서버와 클라이언트가 같은 계약을 보고 작업하기 쉬워집니다. 이건 생성기가 OpenAPI 문서로부터 코드를 만드는 구조 자체에서 오는 장점입니다. (GitHub)

2) 네트워킹 레이어의 반복 코드가 줄어든다

path, method, request body, response model을 각각 손으로 관리하던 부담이 줄어듭니다. 특히 규모가 커질수록 직접 작성하는 DTO/endpoint 코드보다 생성 기반 접근이 유지보수에 유리해 보였습니다. 이 점은 공식 예제들이 client/server, middleware, 다양한 content type까지 확장해 보여주는 이유이기도 합니다. (GitHub)

3) 완전히 “아무 설정 없이” 되는 도구는 아니다

OpenAPI 문서 품질이 낮으면 생성 결과도 애매해질 수 있습니다. 또 공식 이슈 기준으로 외부 파일로 분리된 JSON references 지원은 아직 제한적이라, 큰 스펙을 여러 파일로 나누어 관리하는 경우에는 제약을 확인하는 편이 좋습니다. (GitHub)

Swift 프로젝트에서는 어디에 두면 좋을까

개인적으로는 Networking 또는 API 모듈을 따로 두고, 그 안에 아래처럼 두는 구성이 깔끔해 보입니다.

Networking/
 ┣ Sources/
 ┃ ┣ Generated/
 ┃ ┣ OpenAPI/
 ┃ ┃ ┣ openapi.yaml
 ┃ ┃ ┗ openapi-generator-config.yaml
 ┃ ┗ APIClient.swift

실제로 앱 전반에서 생성 타입을 직접 퍼뜨리기보다는, 생성된 client를 내부 구현으로 감추고, 바깥에는 프로젝트에서 쓰는 Repository / Service 인터페이스를 노출하는 방식이 더 안정적입니다. 공식 예제에도 generated API를 감싸는 curated client library 예제가 따로 있습니다. (GitHub)

마무리

swift-openapi-generator는 Swift 프로젝트에서 OpenAPI 스펙을 기준으로 네트워킹 코드를 관리하고 싶을 때 꽤 매력적인 선택지였습니다.

특히 이런 경우에 잘 맞습니다.

  • 서버가 이미 OpenAPI 문서를 제공하는 경우
  • 앱에서 타입 안전한 API 호출 구조를 원할 때
  • 스펙과 클라이언트 코드의 동기화를 자동화하고 싶을 때 (GitHub)

반대로, 작은 프로젝트이거나 OpenAPI 문서 관리가 전혀 안 되는 팀이라면 초기 세팅 비용이 더 크게 느껴질 수도 있습니다.

그래도 “문서를 기준으로 Swift API 코드를 생성한다” 는 흐름 자체는 꽤 깔끔했고, 규모가 있는 프로젝트일수록 도입 가치가 있어 보였습니다. (GitHub)

참고

[embed]GitHub - apple/swift-openapi-generator: Generate Swift client and server code from an OpenAPI… Generate Swift client and server code from an OpenAPI document. - apple/swift-openapi-generatorgithub.com

[embed]OpenAPI Initiative - The OpenAPI Initiative provides an open source, technical community, within… This allows people to understand how an API works, how a sequence of APIs work together, generate client code, create…www.openapis.org


메타데이터
post_id
bace3d00c866
slug
swift-swift-openapi-generator-간단히-적용해보기-bace3d00c866
url
https://medium.com/@gaeng2y/swift-swift-openapi-generator-%EA%B0%84%EB%8B%A8%ED%9E%88-%EC%A0%81%EC%9A%A9%ED%95%B4%EB%B3%B4%EA%B8%B0-bace3d00c866
canonical_url
https://medium.com/@gaeng2y/swift-swift-openapi-generator-%EA%B0%84%EB%8B%A8%ED%9E%88-%EC%A0%81%EC%9A%A9%ED%95%B4%EB%B3%B4%EA%B8%B0-bace3d00c866
author_url
https://medium.com/@gaeng2y
status
ok
fetched_at
2026-06-09 15:37:30