API pipeline이 팀에 거짓말을 시작하는 순간을 일반적으로 찾을 수 있습니다. 스키마가 변경되면 생성된 타입이 불평 없이 업데이트되고 PR이 초록색으로 표시되고 somebody in the front end가 오래된 응답 형태를 계속 읽는 이유는 wrapper가 오류를 숨겼기 때문입니다. OpenAPI TypeScript 문제는 생성기가 인터페이스를 생성할 수 있는지 여부가 아니라며.
유용한 질문은 더 어려운 것입니다. 스키마, 전송 및 유효성 검사 간에 어떤 계약을 원하고 빌드 시간에 빠르게 실패하는 부분은 런타임에 누출되는지 여부를 결정하는 것이며. OpenAPI TypeScript pipeline 선택 항목으로서, 이익과 손실이 훨씬 분명해지고, 도구가 전체 해결책으로 위장하는 것을 멈추게 됩니다.
목차
- API가 안전한 것과 같은 Generated Types이 왜 다른 것인지
- OpenAPI 스펙에서 TypeScript 타입을 생성하는 방법
- Pure Types, Full Clients, 및 No Codegen 사이의 선택
- Fetch 또는 Axios를 둘러싸는 Thin Typed Client를 연결하는 방법
- zod, ajv, 또는 io-ts를 사용하여 런타임 검증을 추가하는 방법
- CI에서 생성, 검증 및 계약 테스트를 넣는 방법
- 유지 보수 가능한 PipeLine, 성능, 최종 체크리스트
생성된 타입과 안전한 API은 다릅니다
팀원 중 한 명이 옵션 응답 필드를 추가하는 PR를 병합합니다. 생성된 파일은 깨끗하게 업데이트되고, diff는 흥미롭지 않으며, 모든 팀원은 다음 단계로 넘어갑니다. 그런 다음 프론트 엔드에서는 이전 형태를 읽어오고, 손수 작성한 wrapper가 “임시로” cast된 것을 읽어오고, as any생산 환경은 계약이 변경되지 않았던 것처럼 동작합니다.
생성된 타입과 안전한 __CAPGO_KEEP_0__은 다릅니다. TypeScript는 생성된 타입을 소비하는 code만 보호할 수 있습니다만약 전송层가 계약을 다시 지우지 않는다면 discussion around understanding API connections __CAPGO_KEEP_0__는 여기서 유용합니다. 왜냐하면 대화가 단일 도구에서 시스템이 연결되는 방식으로 이동되기 때문입니다.
__CAPGO_KEEP_0__에서 실패하는 곳은 어디인가요.
가장 일반적인 브레이크 포인트는 재미있는 것이 아니라 지루한 것입니다. 스키마 드리프트는 OpenAPI 스펙과 실제로 배포된 서비스가 일치하지 않을 때 발생합니다. 부분적 커버지는 스펙이 단순한 경로만 모델링하는 반면 앱이 문서화되지 않은 에지 케이스를 의존하는 경우에 나타납니다. 수동으로 작성된 래퍼는 특히 alguien이 “빠르게 움직이”고 loose response cast를 사용할 때 타입이 약화되는 곳입니다. any 실용적인 규칙은
래퍼가 거짓말할 수 있다면 생성기는 당신을 구할 수 없습니다. __CAPGO_KEEP_0__
There’s also a runtime gap. TypeScript types disappear after compilation, so they can’t reject malformed JSON coming over the wire. The network does not care what your editor inferred, and that’s why a generated client is only one layer in a safer API pipeline.
더 광범위한 운영 문제는 보안과 계약 규칙이 아니라 개발자 편의성만을 위한 것이 아닙니다. 만약 API 계약이 더 큰 앱 라이프 사이클에 어떻게 포함되는지 구조화된 시각을 원한다면 이 내부 안내서에 API 앱 스토어 준수에 대한 보안 표준 은 유용한 동반자입니다.
성숙한 방법으로 생각하는 openapi typescript 은 이렇습니다. strict schema-to-types bridge를 제공하여 훌륭하지만, 요청을 검증하지 않으며, 런타임 페이로드 형태를 강제하지도 않고, 느슨한 wrapper가 모든 것을 무너뜨리도록 하지도 않습니다. 생성기는 쉽게 20%지만, pipeline 설계는 팀이 신뢰를 얻거나 거짓된 자신감을 쌓는 곳입니다.
OpenAPI Spec에서 TypeScript 타입을 생성하는 방법

가장 가벼운 유용한 설정은 일반적으로 실제 리포지토리 churn에 견디는 설정입니다. OpenAPI spec을 같은 리포지토리에 유지하고, 생성된 타입 파일을 커밋하고, CI에서 드리프트를 표시하는 대신, 누군가가 리프레시 단계를 기억하도록 의존하지 말고, npx openapi-typescript ./openapi.yaml -o ./src/types/api.d.ts 는 리뷰어들이 다른 소스 변경과 같이 검토할 수 있는 결정적인 출력 파일을 제공합니다.
실질적으로 중요하는 플래그
출력 플래그는 생성된 아티팩트가 명확해지도록 만드는 데 중요합니다. -o 생성된 타입이 readonly 의도(intent)를 보존하고 싶을 때 유용합니다. --immutable 스키마 순서가 의미 없는 변경으로 인해 diff가 안정적이게 유지되도록 합니다. --alphabetize 생성된 표면에서 enum 대신 union을 사용하는 팀이 선호할 때 중요합니다. --enum 프로젝트의 문서는 범위가 명확합니다. 그것은
타입 생성기 클라이언트 런타임이나 요청 레이어가 아닌타입 최우선 설정을 위해 가볍게 유지하기 위해 도움이 됩니다. 도구의 유지 관리 모델은 도구의 저장소에서 보여집니다.활발한 문서와 릴리스가 유지되는 경우 오픈 소스 도구가 프로덕션에서 유지될 수 있는 이유입니다. GitHub repository and CLI documentation.
__CAPGO_KEEP_1__ 문서 package.json 이 명령어는 빌드 스크립트와 함께 존재하고, 스펙이 변경될 때마다 실행합니다. CI에서 파일을 재생성하고, 변경이 없으면 실패합니다. git diff 변화가 드러나도록 contract 변경을 visible review 작업으로 바꾸고, silent runtime risk를 피합니다.
schema 측면도 명령어 라인과 마찬가지로 중요합니다. 프로젝트에서는 compilerOptions.noUncheckedIndexedAccess 이러한 방법을 추천합니다. additionalProperties become T | undefined, safer indexing을 강제하고, call site에서 safer indexing을 강제합니다. 또한 oneOf 혼합하지 말고, extra composition과 함께 사용하지 말고, 사용합니다. 또한 $defs root에 위치시키고, placement이 모호할 때는 root에 위치시키고, misplaced definitions가 generated output에서 사라지지 않도록 합니다. 한 가지 더 자세한 정보가 시간을 절약합니다. openapi-typescript never produce any, missing schema detail이 hidden되지 않고, early로 surface됩니다.
spec을 explicit하게 유지하거나, generator가 ambiguity를 expose하지 않도록 합니다.
지속적인 워크플로는 간단합니다. spec을 버전 관리하에 두고, 빌드 시 재생성하고, generated 파일을 커밋하고, type checker가 mismatch를 complain하기 전에 anyone이 merge합니다. 그럼, pipeline의 나머지 부분에 대해 stable contract boundary를 제공합니다.
Pure Types, Full Clients, 그리고 No Codegen을 선택하는 방법
| Pattern | 빌드 시간 | 출력 파일 | Bundle 크기 | Best fit |
|---|---|---|---|---|
| Thin Wrapper와 함께 Pure Types | 빠르다 | 적다 | Low | 제어를 원하는 팀과 작은 런타임 표면 |
| Full-client Codegen | 속도 저하 | 많은 | 높은 | 빠른 전달 및 자동화된 작업을 원하는 팀 |
| 코드 생성 요청 빌더가 없음 | 빠름 | 없음 또는 최소 | 저 | 한 개의 코드베이스 앱이 수동으로 전송 논리를 선호하는 팀 |
선택은 정말로 “어떤 도구가 승리하는가”가 아니라 “어떤 PIPELINE 형태가 저장소, 팀, 그리고 API가 겪는 변동성에 적합한가”입니다. 2025년 대규모 OpenAPI 스펙(약 75,000 라인, 2MB, 약 1,200 작업)에 대한 벤치마크에서 75,000 라인, 2MB, 약 1,200 작업, openapi-typescript 자동 생성된 출력에 대해 약 1.5 초 대략적인 것과 비교하여 8.0 초 에서 @hey-api/openapi-ts, 5.5 초 에서 Orval, 그리고 18.1 초 에서 Kubb, 또한 단일 출력 파일을 생성하는 동안 16 에서 hey-api, 2,719 에서 Orval및 3,877 위한 Kubb (성능 비교 상세 정보).
순수 타입은 제어를 선호합니다
순수 타입 설정은 수동 요청 레이어와 잘 어울립니다. 런타임이 작고 API 표면이 단순하고 검토할 수 있기 때문입니다. 이게 프론트 엔드에서 번들러에 민감한 경우와, 하나의 팀이 스펙과 소비자 모두를 관리하는 앱의 경우에 중요합니다. 개발자 경험은 단순한 구문만이 아니라는 것을 기억해 주고 싶다면, 개발자 경험 관점 클라이언트 code가 짧고 명확하며 검토할 수 있을 때 더 쉽게 판단할 수 있습니다.
전체 클라이언트는 전달 속도에 주목합니다
openapi-generator, hey-api, Orval, 및 Kubb 모두 타입보다 더 많은 것을 시도합니다. 요청 메서드, 모델, 및 플러밍을 함께 생성하는 것이 유용할 수 있습니다. 특히 백엔드와 프론트 엔드 팀 간의 큰 전달에서 유용합니다. 하지만 성능 비교에서 드러나는 비용은 명확합니다. 더 많은 생성된 파일, 더 큰 런타임 표면, 및 스펙이 커질 때 빌드 충돌의 여지가 있습니다.
코드 생성이 없는 경우 지역 리팩터링을 favor합니다
타입된 요청 빌더 및 fetch wrappers는 한 코드베이스가 모양의 양쪽 끝을 소유하고 API 변경이 밀접하게 조정되는 경우 잘 작동합니다. 단점은 유지 보수 규율입니다. 생산자와 소비자 사이에 팀과 저장소가 많아질수록, 수동으로 요청 레이어가 드리프트하는 경우가 많습니다. 이 경우에는 강력하게 계약 테스트를 강제해야 합니다.
핵심 결정 지점은 이념적이지 않습니다. 배포 예산이 협소한 경우, 순수 타입이 매력적입니다. 팀이 최대한의 프레임워크를 원하고 출력을 흡수할 수 있다면, 전체 클라이언트는 설정 시간을 줄입니다. 계약을 가까이 유지하고 최소한의 움직이는 부분을 원한다면, no-codegen 요청 빌더가 올바른 내부 거래일 수 있습니다.
Fetch 또는 Axios를 둘러싸는 Thin Typed Client를 연결하는 방법

생성기가 멈추고 애플리케이션 code이 시작되는 thin wrapper입니다. wrapper는 하나의 함수를 노출하고, 타입이 지정된 매개 변수와 쿼리 객체를 받으며, 호출을 전달하여 fetch 또는 주입된 axios 인스턴스에 대한 호출을 전달하여, 너무 똑똑하지 않도록 시도하지 마십시오. 대부분의 프로덕션 설정에서, 이 레이어는 30–60 줄 정도로 남아 있습니다. 이미 생성된 타입이 모양의 대부분을 이미 포함하고 있기 때문입니다. 이러한 정신 모델이 유지됩니다:
경로 매개 변수는 타입이 지정되어 있으므로
- 이러한 정신 모델이 유지됩니다: 경로 매개 변수는 타입이 지정되어 있으므로
/users/{id}이러한 함수를 호출하기 위해서는 반드시 __CAPGO_KEEP_0__id. - 쿼리 객체는 타입이 유지됩니다. 따라서 옵션 필터가 문자열로 변하지 않습니다.
- 응답 본문은 타입이 유지됩니다. 따라서 code을 파싱할 때도 타입이 좁은 형태를 기대할 수 있습니다.
그런 wrapper는 의도적으로 재미없습니다. 그것은 재시도, 변형, 또는 인증 정책을 만드는 것이 아니라, 타입이 지정된 연산에서 요청을 전송층으로 옮기고, 그 후에 타입이 지정된 결과를 다시 상위로 넘겨주는 것입니다.
wrapper를 재미없고 의존성-light로 유지하거나, 향후의 코드 생성 변경이 모든 앱에 영향을 미치지 않도록 하세요.
팀이 Axios를 선호하는 경우, 패턴은 동일하지만, Transport 구현이 변경됩니다. 팀이 더 단순한 브라우저 측 __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 API
SDK openapi typescript 개발 labor를 분리하는 깨끗한 구분을 제공합니다. 스키마는 스펙에, 전송은 wrapper에, 그리고 앱은 타입이 지정된 연산을 대신하여 ad hoc 요청 code를 받습니다.
zod, ajv, 또는 io-ts와 함께 Runtime Validation 추가
TypeScript 타입은 런타임에서 사라지고 네트워크는 편집기 의견에 대한 신뢰를 고려하지 않습니다. 따라서 안전한 패턴은 '타입을 생성하고 기대'가 아니라 '타입을 생성하고 edge에서 데이터가 앱에 들어오는 곳에서 검증'입니다. 생성된 스키마는 진실의 원천이며, 라이브러리들 zod, ajv및 io-ts 컴파일 타임 타입이 처리할 수 없는 경계 검사를 처리합니다.
데이터가 들어오는 곳에서 검증하세요
React 앱의 경우, 요청이 해결되고 페이로드가 상태에 들어가기 전에 일반적으로 edge입니다. 서버의 경우, 페이로드가 데이터베이스에 기록되거나 비즈니스 규칙에 전달되기 전에 edge입니다. 규칙은 간단합니다. 검증을 경계 근처에 유지하고 기능 code를 통해 산발적으로 수동 검사를 분산하지 마세요.
A zod shape은 생성된 응답 shape을 반영할 수 있습니다. 그러나 그것을 대체하지는 않습니다:
import { z } from "zod";
const WeatherForecastSchema = z.object({
date: z.string(),
temperatureC: z.number(),
summary: z.string().nullable(),
temperatureF: z.number().optional(),
});
예제는 스키마가 optional 필드를 표시했을 때 필드를 검증하고 런타임 검사를 생성된 것과 일치시킵니다. ajv strong한 선택입니다. 서버에서 높은 처리량 JSON 스키마 검증을 원할 때 io-ts still fits 팀이 이미 존재하는 스타일의 구성에 적합합니다. fp-ts 형식의 구성.
큰 실수는 너무 늦게 유효성을 검사하는 것입니다. 데이터가 앱으로 들어가기 전에 타입 시스템이 이미 무시되고 버그가 숨을 곳을 찾았습니다. JavaScript의 단위 테스트에 대한 짧은 안내서 이 마음가짐과 잘 어울립니다. 단위 테스트와 경계 유효성 검사는 모두 잘못된 가정에 대한 오류를 빨리 잡아내서 가장 잘 작동합니다.
깨끗한 층별 구조는 예측 가능합니다. OpenAPI TypeScript 계약을 생성하고, 유효성 검사기는 런타임 데이터를 검사하고, 앱은 code에 의해만 데이터가 유효성 검사를 통과한 데이터만 볼 수 있습니다. 이것은 정적 타입이 불신하는 응답을 경찰하는 것보다 훨씬 더 좋은 경계입니다.
CI에서 생성, 유효성 검사, 계약 테스트를 넣는 방법

pipeline이 지속되면 계약을 게이트로 바꾸고, 제네레이터 버전을 고정하고, 드리프트가 발생하면 실패하고, __CAPGO_KEEP_0__의 모양을 mock 또는 계약 도구와 연동하여 머지하기 전에 실행하세요. 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합니다.
- 타입을 Regenerate합니다.
- Fail the job if
git diff변경 사항을 보여줍니다. - Run
tsc --noEmit. - 백엔드와 프론트엔드가 시간이나 팀 경계로 분리되어 있는 경우 Mock 서버가 특히 유용합니다. Mock 서버는 실제 계약 대신 고정된 fixture를 사용하는 대신 실제 계약을 확인하면서도 소비자 __CAPGO_KEEP_0__에게 예측 가능한 __CAPGO_KEEP_1__ 표면을 제공합니다.
계약 테스트와 스냅샷 테스트의 주요 차이점은 범위입니다. 스냅샷은 파일이 변경되었다는 것을 알려줍니다. 계약 테스트는 스펙이 파일이 어떻게 행동해야 하는지에 대해 말합니다.
A mock server is especially useful when backend and frontend work are separated by time or team boundaries. It gives consumer code a predictable API surface while still checking the actual contract rather than a hard-coded fixture. The A practical workflow looks like this: Pull the spec from the repo or generated source. Regenerate the types. Fail the job if shows changes. Run Execute a contract test against a mock server such as Prism or a Spectral-backed check. The key difference between contract tests and snapshot tests is scope. Snapshots often tell you the file changed. Contract tests tell you whether the shape still behaves like the spec says it should. A mock server is especially useful when backend and frontend work are separated by time or team boundaries. It gives consumer __CAPGO_KEEP_0__ a predictable __CAPGO_KEEP_1__ surface while still checking the actual contract rather than a hard-coded fixture. The __CAPGO_KEEP_0__
CI baseline이 깨끗하고 반복 가능할 때 팀이 여전히 필요로하는 유용한 참고 자료입니다.
로컬 개발자만 코드 생성기 버전을 업그레이드하고 다른 개발자가 업그레이드하지 않으면, 생성된 파일은 신호 대신 랜덤한 잡음이 됩니다. CI는 그럴 수 없도록 해야 합니다.
스키마 변경, 타입 생성, 컴파일러 검사 및 계약 테스트가 모두 서로를 강화하는 pipe라인이 결과입니다. 그것이 워크플로우가 진실함을 의미합니다.

The pipelines that survive are the ones with boring governance. Version the spec, review schema changes like code, pin the generator, and document how breaking changes get approved. If the process is fuzzy, people will route around it, and then the generated types become decoration instead of enforcement.
생존하는 pipe라인은 모두가 지루한 관리를 받는 pipe라인입니다. 스펙 버전을 관리하고, 스키마 변경을 __CAPGO_KEEP_0__와 같이 검토하고, 생성기 버전을 고정하고, 깨진 변경 사항이 승인되는 방법을 문서화합니다. 만약 프로세스가 흐트러지면, 사람들은 그 주변을 돌아가고, 생성된 타입은 강제가 아닌 장식으로 변하게 됩니다.
실제로 몇 가지 성능 조절 장치가 중요합니다. tsc --incremental 모노레포에서 스펙이 자주 변경되지만 한 패키지만 소비하는 경우 incremental generation이 도움이 됩니다.
반복적인 컴파일러 작업을 줄이고, 프로덕션 빌드에서 필요하지 않은 출력 플래그를 비활성화하여 생성된 표면을 작게 유지할 수 있습니다. 실제로 가장 큰 이익은 여전히 사회적이지요, 기술적이지요. 예측 가능한 pipe라인이 더 자주 실행되기 때문입니다.
- 아래의 체크리스트는 기억해야 할 것입니다. 버전 고정:
openapi-typescript__CAPGO_KEEP_0__package.json__CAPGO_KEEP_0__ - 스키마 검토: 변경 사항을 계약 변경으로 대우하지 말고 일반 유지보수로 대우한다.
- __CAPGO_KEEP_0__ 감지: CI에서 재생성하고 diff가 있으면 실패한다.
- 에지 검증: 미신뢰할 수 있는 데이터를 앱 상태나 영속성에 도달하기 전에 파싱한다.
- 계약 테스트: code가 스키마와 일치하는지 mock-backed로 검증한다.
- __CAPGO_KEEP_0__ 정책: 변경 사항이 shape을 변경하는 경우 승인자와 클라이언트에게 알리는 방법을 기록한다.
pipeline이 포함하는 게이트가 없는 것은 단지 타입을 생성하는 것만 아니라, 계약을 보이게 만든다. 이 보이는 것은 팀이 파일이 안전해 보이기만 해도 신뢰하지 않도록 하는 것이다.
Capacitor 또는 Electron 앱을 배포하고자 하시고 업데이트 PIPELINE이 동일한 discipline로 동작하길 원하신다면, Capgo은 JavaScript, CSS, 복사본, 설정, 및 자산 수정을 빠르게 업데이트할 수 있도록 해줍니다. 앱 스토어 리뷰를 기다리지 않고. Capgo 에서 signed bundles, rollback 보호, 및 릴리즈 컨트롤이 릴리즈 프로세스에 속하는 것을 확인하실 수 있습니다. 속도와 제어를 잃지 않고.