팀에 API pipeline이 거짓말을 시작하는 순간을 일반적으로 발견할 수 있습니다. 스키마가 변경되면 생성된 타입이 불평하지 않고 PR이 초록색이 되고 somebody가 프론트 엔드에서 오래된 응답 형태를 읽는 것을 발견합니다. 그 것은 OpenAPI TypeScript 문제가 아니라 생성기가 인터페이스를 생성할 수 있는지 여부입니다.
문제를 해결하는 유용한 질문은 더 어려운 것입니다. 스키마, 전송 및 유효성 검사 간의 계약을 무엇으로 하고 빌드 시간에 빠르게 실패하는 부분은 런타임에 누출되는지 여부를 결정하는 것이어야 합니다. 한 번 프레임을 OpenAPI TypeScript __CAPGO_KEEP_0__를 선택하는 pipe line으로 하여, trade-off가 훨씬 명확해지고, 도구가 전체적인 해결책으로 위장하는 것을 멈추게 됩니다.
Table of Contents
- API가 안전한 것을 보장하지 않는 이유
- OpenAPI 스펙으로부터 TypeScript 타입을 생성하는 방법
- Pure 타입, Full 클라이언트, No codegen 사이의 선택
- Fetch나 Axios와 같은 Thin Typed 클라이언트를 연결하는 방법
- 런타임 검증을 추가하는 방법 (zod, ajv, io-ts 사용)
- CI에서 Generation, Validation, Contract 테스트를 넣어보세요
- 유지보수 가능한 Pipelines, 성능, 최종 체크리스트
생성된 타입이 안전한 API과 다르다는 이유
팀원 중 한 명이 옵션 응답 필드를 추가하는 PR를 병합합니다. 생성된 파일은 깨끗하게 업데이트되고 diff는 흉내가 나지 않으며, 모두 다음 단계로 넘어갑니다. 그런 다음 프론트엔드는 “일시적으로” cast된 수동으로 작성된 wrapper를 통해 더 오래된 형태를 계속 읽고, 프로덕션은 계약이 변경되지 않았다는 것처럼 행동합니다. as any생성된 타입에 대한 함정입니다.
TypeScript는 생성된 타입을 소비하는 __CAPGO_KEEP_0__만 보호할 수 있습니다 TypeScript can only protect the code that consumes the generated types생성된 __CAPGO_KEEP_0__ 연결에 대한 이해 discussion around understanding API connections __CAPGO_KEEP_0__은 여기서 유용합니다. 왜냐하면 대화가 단일 도구에서 시스템이 연결되는 방향으로 밀어내주기 때문입니다.
__CAPGO_KEEP_0__에서 실패하는 곳은 어디인가요.
가장 일반적인 브레이크 포인트는 재미있는 것이 아니라 지루한 것입니다. 스키마 드리프트는 OpenAPI 스펙과 실제로 배포된 서비스가 일치하지 않을 때 발생합니다. 부분적 커버지는 스펙이 단순히 행복한 경로만 모델링하는 반면 앱이 문서화되지 않은 에지 케이스에 의존할 때 나타납니다. 수첩으로 작성된 wrapper는 특히 누군가 “빠르게 움직이”고 loose response cast를 사용할 때 타입이 약화됩니다. any 실용적인 규칙은
wrapper가 거짓말할 수 있다면, 생성기는 당신을 구원할 수 없습니다. __CAPGO_KEEP_0__
There는 또한 런타임 간격이 있습니다. TypeScript 타입이 컴파일 후 사라지기 때문에, 잘못된 JSON이 네트워크를 통해 오면 거부할 수 없습니다. 네트워크는 편집기에서 추론한 내용에 관심이 없으며, 그 이유로 생성된 클라이언트는 더 안전한 API pipeline의 단일 층입니다.
보다 광범위한 운영 문제는 보안 및 계약 규율이며, 개발자 편의성만을 고려하는 것이 아닙니다. API 계약이 더 큰 앱 라이프 사이클에 어떻게 포함되는지 구조화된 시각을 원한다면 내부 가이드인 API 앱 스토어 준수성을 위한 보안 표준 이 가이드는 유용한 동반자입니다.
성숙한 방법으로 openapi typescript 을 생각하는 것입니다. strict schema-to-types bridge를 제공하여 훌륭하지만, 요청을 검증하지 않으며, 런타임 페이로드 형태를 강제하지도 않고, 느슨한 wrapper가 모든 것을 무너뜨리도록 하지도 않습니다. 생성기는 쉽게 20%를 제공하지만, pipeline 설계는 팀이 신뢰를 얻거나 거짓된 자신감을 쌓는 곳입니다.
OpenAPI 스펙으로부터 TypeScript 타입을 생성하는 방법

가장 가벼운 유용한 설정은 일반적으로 실제 리포지토리 churn을 견딜 수 있는 설정입니다. OpenAPI 스펙을 동일한 리포지토리에 유지하고, 커밋된 타입 파일을 생성하고, CI에서 드리프트를 표시하는 대신, someone이 refresh 단계를 기억하는 것을 의존하지 않도록 합니다. 명령어 npx openapi-typescript ./openapi.yaml -o ./src/types/api.d.ts 는 deterministc output 파일을 생성하여 리뷰어들이 다른 소스 변경과 같이 검토할 수 있도록 합니다.
실질적으로 중요하는 플래그
The -o 출력 플래그는 생성된 아티팩트가 명확해지도록 만드는 데 중요합니다. --immutable is useful when you want the generated types to preserve readonly intent in the output, and --alphabetize diffs가 schema 순서 변경 시 의미 없는 변경이 발생하지 않도록 유지할 때 유용합니다. --enum matters when your team prefers enums in the generated surface instead of unions.
The project’s own documentation is clear about the scope, it is a 타입 생성기, not a client runtime or request layer, and that limitation helps when you want a lightweight, type-first setup. Its repository also shows the maintenance model behind the tool, which is part of why open source tooling can hold up in production when the docs and releases stay active, as discussed in open source 유지 보수에 대한 사례 repository and GitHub repository and CLI documentation.
Wire generation into package.json 이 명령어는 빌드 스크립트와 함께 존재하고, 스펙이 변경될 때마다 실행합니다. CI에서 파일을 재생성하고, 변경이 없으면 실패합니다. git diff 드라이프트가 보입니다. 이는 계약 변경을 가시적인 검토 작업으로 바꾸고, 런타임 시 무시되는 위험을 피합니다.
스키마 쪽도 명령어 라인과 마찬가지로 중요합니다. 프로젝트에서는 compilerOptions.noUncheckedIndexedAccess 이러한 additionalProperties 되도록 하세요. 이는 호출 사이트에서 더 안전한 인덱싱을 강제합니다. 또한 T | undefined혼합하지 말고 단독으로 사용하는 것을 추천하며, oneOf 루트에 위치시키는 것을 추천합니다. 위치가 모호할 때, 잘못된 정의가 생성된 출력에서 사라질 수 있기 때문입니다. 한 가지 더 많은 세부 사항은 나중에 시간을 절약할 수 있습니다. $defs 는 결코 openapi-typescript 생성되므로, 미흡한 스키마 세부 사항이 허용적인 타입 아래에 숨겨지지 않고 일찍 노출됩니다. any스펙을 명확하게 유지하거나, 생성기는 다시 그 불명확성을 노출해 줄 것입니다.
지속적인 워크플로는 간단합니다. 스펙을 버전 관리 하에 두고, 빌드 시 재생성하고, 생성된 파일을 커밋하고, 타입 체커가 불일치 시 불평하는 것을 허용합니다. 그럼으로써, 나머지 pipeline의 안정적인 계약 경계를 얻을 수 있습니다.
The workflow that lasts is straightforward. Put the spec under version control, regenerate on build, commit the generated file, and let the type checker complain before anyone merges a mismatch. That gives you a stable contract boundary for the rest of the pipeline.
Pure 타입, 풀 클라이언트, 및 코드 생성을 위한 선택
| 패턴 | 빌드 시간 | 출력 파일 | 배포 중량 | 최적 |
|---|---|---|---|---|
| Pure 타입에 얇은 wrapper | 빠름 | 적음 | 저함 | 코드 생성을 원하는 팀 및 작은 런타임 표면 |
| 풀 클라이언트 코드 생성 | 느린 | 많은 | 높은 | 빠른 전달과 자동화된 작업을 원하는 팀 |
| 코드 생성 요청 빌더가 없는 | 빠르다 | __CAPGO_KEEP_0__가 보는 churn이 거의 없거나 최소화된 | 작은 코드베이스 앱이 수동으로 전송 로직을 선호하는 | 도구가 이기면 안된다. 그것은 __CAPGO_KEEP_0__가 보는 pipeline 형태가 저장소, 팀, 그리고 churn의 얼마나 많은 변화를 맞는지를 결정한다. |
The choice isn’t really “which tool wins”. It’s which pipeline shape fits your repo, your team, and how much churn the API sees. In a 2025 benchmark around a large OpenAPI spec of about 약 1,200개의 연산과 75,000개의 라인, 2MB의 큰 OpenAPI 스펙을 기준으로, openapi-typescript 약 1,200개의 연산과 75,000개의 라인, 2MB의 큰 OpenAPI 스펙을 기준으로 1.5 초 __CAPGO_KEEP_0__ 보다 평균적으로 약 8.0 초 에서 @hey-api/openapi-ts, 5.5 초 에서 Orval, 18.1 초 에서 Kubb, 16 한 개의 출력 파일을 생성하는 동안 hey-api, 2,719 에서 Orval및 3,877 위해 Kubb (성능 비교 정보).
순수 타입은 제어를 선호합니다
순수 타입 설정은 수동으로 요청 레이어와 pair가 잘 작동하는 것을 의미합니다. 런타임이 작고 API 표면이 단순하고 평범해야 합니다. 이는 번들러에 민감한 프론트 엔드와 앱에서 중요합니다. 앱의 소유권이 한 팀에만 있는 경우, 개발자 경험은 단순한 구문만이 아닙니다. 개발자 경험의 중요성을 다시 한번 생각해 볼 필요가 있을 때 개발자 경험의 관점 클라이언트 code가 짧고 명확하며 검토 가능한 경우, 개발자 경험을 판단하는 것이 더 쉬워집니다.
전체 클라이언트는 전달 속도에 중점을 둡니다
openapi-generator, hey-api, Orval및 Kubb 모두 타입보다 더 많은 것을 시도합니다. 요청 메서드, 모델, 플러밍을 함께 생성하는 것이 유용할 수 있습니다. 특히 백엔드와 프론트 엔드 팀 간의 큰 전달이 필요할 때. 성능 비교에서 드러난 비용은 명확합니다. 더 많은 생성된 파일, 더 큰 런타임 표면, 그리고 스펙이 커질수록 빌드 충돌의 여지가 있습니다.
코드 생성이 없는 경우 지역 리팩터링을 favor합니다
타입된 요청 빌더 및 fetch wrappers는 한 코드베이스가 모양의 양쪽 끝을 소유하고 API 변경이 밀접하게 조정될 때 잘 작동합니다. 단점은 유지 보수 규율입니다. 생산자와 소비자 사이에 팀과 저장소가 많을수록, 수동으로 요청层가 드리프트하는 경우가 많습니다. 따라서 contract 테스트를 적극적으로 강제해야 합니다.
core 의사 결정 지점은 이념적이지 않습니다. 배포 예산이 협소한 경우, 순수 타입이 매력적입니다. 팀이 최소한의 설정 시간을 원하고 출력을 흡수할 수 있다면, 전체 클라이언트는 설정 시간을 단축할 수 있습니다. contract를 가까이 유지하고 최소한의 움직이는 부분을 원한다면, no-codegen 요청 빌더가 올바른 내부 거래일 수 있습니다.
Fetch 또는 Axios와 Thin Typed Client를 연결하는 방법

thin wrapper는 생성기가 멈추고 애플리케이션 code이 시작되는 지점입니다. wrapper는 하나의 함수를 노출하고, 타입된 매개 변수와 쿼리 객체를 받으며, 호출을 전달하여 fetch 또는 주입된 axios 인스턴스에 전달하여, 너무 똑똑하지 않도록 하세요. 대부분의 프로덕션 설정에서, 그层는 30–60 줄 그 이유는 생성된 타입이 이미 대부분의 모양을 가지고 있기 때문입니다. 생산에 대한 정신 모델이 유지됩니다:
경로 매개 변수는 타입이 유지되므로
- __CAPGO_KEEP_0__ __CAPGO_KEEP_0__
/users/{id}이러한 함수를 호출하기 위해서는 반드시 __CAPGO_KEEP_0__가 필요합니다.id. - 쿼리 객체는 타입이 유지됩니다. 따라서 옵션 필터가 문자열로 변하지 않습니다.
- 응답 본문은 타입이 유지됩니다. 따라서 code를 파싱할 때도 타입이 좁은 형태를 기대할 수 있습니다.
그런 wrapper는 의도적으로 재미없습니다. 그것은 재시도, 변환, 또는 인증 정책을 만드는 것이 아니라, 타입이 지정된 연산에서 요청을 운반层로 옮겨 타입이 지정된 결과를 다시 올려주는 것입니다.
wrapper를 재미없고 의존성 적으로 가볍게 유지하거나, 향후의 코드 생성 변경이 앱에 전파되지 않도록 하세요.
팀이 Axios를 선호하는 경우 패턴은 동일하지만, 운반 구현만 변경됩니다. 팀이 더 단순한 브라우저 측 __CAPGO_KEEP_0__를 원하는 경우, as any 가끔 충분합니다. 중요한 것은 요청 함수가 생성된 경로 타입을 받아 타입이 지정된 응답을 반환하고, 나중에 변형되는 loosely 형태의 객체가 아닌 것입니다.
For teams that prefer Axios, the pattern is the same, only the transport implementation changes. For teams that want simpler browser-side code, fetch 이러한 접합부를 잘 사용한다면,
이러한 접합부를 잘 사용한다면, openapi typescript 개발자와의 협업을 위한 깨끗한 노동 분배를 제공합니다. 스키마는 스펙에, 전송은 wrapper에, 그리고 앱은 타입이 지정된 연산 대신 ad hoc 요청 code를 보게 됩니다.
zod, ajv, 또는 io-ts를 사용한 런타임 검증 추가
타입스크립트 타입은 런타임에 사라지며, 네트워크는 편집기의 자신감에 관심이 없습니다. 따라서 안전한 패턴은 '타입을 생성하고 희망'이 아니라 '타입을 생성하고 edge에서 데이터가 앱에 들어오는 곳에서 검증'입니다. 생성된 스키마는 진실의 원천이며, 라이브러리들인 zod, ajv및 io-ts 컴파일 타임 타입이 할 수 없는 경계 검사를 처리합니다.
데이터가 앱에 들어오는 곳에서 검증하세요
React 앱의 경우, 요청이 해결되고 페이로드가 상태에 들어가기 전에 edge는 일반적으로 위치합니다. 서버의 경우, 페이로드가 데이터베이스에 기록되거나 비즈니스 규칙에 전달되기 전에 edge는 위치합니다. 규칙은 간단합니다. 검증을 경계 근처에 유지하고 기능 code를 통해 수동 검사를 퍼뜨리지 마세요.
A zod 스키마가 생성된 응답 형태를 반영할 수 있습니다.
import { z } from "zod";
const WeatherForecastSchema = z.object({
date: z.string(),
temperatureC: z.number(),
summary: z.string().nullable(),
temperatureF: z.number().optional(),
});
예제는 스키마가 optional로 표시한 field를 검증하고, 런타임 검증을 생성된 것과 일치시킵니다. ajv 는 서버에서 높은 처리량 JSON 스키마 검증을 원할 때 강력한 선택입니다. io-ts still fits 팀이 이미 존재하는 스타일의 구성에 적합합니다. fp-ts 형식의 구성.
대상이 앱으로 들어가기 전에 payload를 검증하는 것을 너무 늦게 하려는 것은 큰 실수입니다. 만약 payload가 앱으로 들어가기 전에 타입 시스템이 이미 무시되고 버그가 숨을 수 있는 장소를 만들면 안됩니다. JavaScript의 단위 테스트에 대한 짧은 안내서 이 마음가짐과 잘 어울립니다. 단위 테스트와 경계 검증 모두 잘못된 가정에 대한 오류를 일찍 잡아내서 가장 잘 작동합니다.
깨끗한 계층 구조는 예측 가능합니다. OpenAPI TypeScript 계약을 생성하고, 검증기를 사용하여 런타임 payload를 검증하고, 앱은 code에서만 살아남은 데이터만 볼 수 있습니다. 이것은 정적 타입이 불신하는 응답을 경찰하는 것보다 훨씬 더 좋은 경계입니다.
CI에서 생성, 검증 및 계약 테스트를 넣는 방법

지속적인 pipeline은 계약을 게이트로 바꾸고, 드리프트를 실패시키고, 생성자 버전을 고정하고, merge 전에 mock 또는 계약 도구와 __CAPGO_KEEP_0__ 형태를 실행하는 것을 의미합니다. tsc --noEmit, and exercise the API shape against a mock or contract tool before merge. If you pin the generator version in package.json동일한 스펙으로 두 명의 엔지니어가 의도하지 않은 결과를 만들 수 없습니다.
A simple GitHub Actions shape
A 실제적인 워크플로우는 다음과 같습니다.
- 리포지토리나 생성된 소스에서 스펙을 Pull합니다.
- 타입을 재생성합니다.
- __CAPGO_KEEP_0__이 변경된 경우 실패합니다.
git diff변경 사항을 보여줍니다. - 실행
tsc --noEmit. - Mock 서버를 사용하여 Spectral-backed 체크나 Prism과 같은 서버를 실행합니다.
계약 테스트와 스냅샷 테스트의 주요 차이점은 범위입니다. 스냅샷은 파일이 변경된다는 것을 알려줍니다. 계약 테스트는 스펙에 따라 스펙이 어떻게 행동해야 하는지 여부를 알려줍니다.
Mock 서버는 시간이나 팀 경계에 의해 백엔드와 프론트엔드 작업이 분리된 경우 특히 유용합니다. Mock 서버는 실제 계약을 대신하여 고정된 fixture를 사용하는 대신 소비자 code에게 예측 가능한 API 표면을 제공합니다. 연속적 통합 설정 가이드 __CAPGO_KEEP_0__을 검토하는 것만으로도 충분합니다.
로컬에서 생성기 버전을 업그레이드한 개발자가 다른 개발자가 업그레이드하지 않은 경우, 생성된 파일은 신호 대신 랜덤한 잡음이 됩니다. CI는 그럴 수 없습니다.
결과는 스키마 변경, 타입 생성, 컴파일러 검사 및 계약 테스트가 모두 서로를 강화하는 pipe라인입니다. 그것이 workflow가 진실되게 만드는 것입니다.
유지보수 가능한 Pipe라인, 성능, 최종 체크리스트

생존하는 pipe라인은 모두가 지루한 관리를 받는 pipe라인입니다. 스펙 버전을 관리하고 스키마 변경을 code과 같이 검토하고 생성기를 고정하고, 깨진 변경 사항이 승인되는 방법을 문서화합니다. 만약 프로세스가 흐트러지면, 사람들은 그 주변을 돌아가고, 그 후 생성된 타입은 강제가 아닌 장식이 됩니다.
몇 가지 성능 조절자가 실제로 중요합니다.
모노레포에서 스펙이 자주 변경되지만 하나의 패키지만 사용하는 경우 incremental generation이 도움이 됩니다. tsc --incremental 반복적인 컴파일러 작업을 줄일 수 있고, 프로덕션 빌드에서 필요하지 않은 출력 플래그를 비활성화하여 생성된 표면을 작게 유지할 수 있습니다. 실제로 가장 큰 이익은 여전히 사회적이지요, 기술적이지요, 예측할 수 있는 pipe라인이 더 자주 실행됩니다.
아래의 체크리스트는 기억해야 할 것입니다:
- 버전 고정: 생성기를 고정하여
openapi-typescript버전 정보package.json이러한 문제를 해결하기 위해, __CAPGO_KEEP_0__은 여러 기기에서 출력이 드리프트되지 않도록 합니다. - 스키마 검토: 스펙 변경을 계약 변경으로 대우하고, 하우스키핑으로 대우하지 않도록 하세요.
- 드리프트 감지: CI에서 다시 생성하고 diff가 발생하면 실패하세요.
- 에지 검증: 앱 상태 또는 영속성에 도달하기 전에 신뢰되지 않은 페이로드를 파싱하세요.
- 계약 테스트: Run a mock-backed check that proves consumer code still matches the schema.
- 브레이킹-변경 정책: 형태 변경을 승인하는 사람과 클라이언트에게 알리기 위한 방법을 기록하세요.
A pipeline that includes those gates doesn’t just generate types, it makes the contract visible. That visibility is what keeps teams from trusting a file that only looks safe.
If you’re shipping Capacitor or Electron apps and you want your update pipeline to behave with the same discipline, Capgo gives you a practical way to move JavaScript, CSS, copy, config, and asset fixes quickly without waiting on app store review. Visit Capgo to see how its signed bundles, rollback protection, and release controls fit into a release process that needs speed without losing control.