openapi code generator ์ฌ์ฉํด๋ณด๊ธฐ
FEConf 2024๋ฅผ ๋ค๋ ์ ๋ฐํด ๋์ ๋ก์ผ ๋ง๋ค๊ธฐ ๋ฐํ๋ฅผ ๋ฃ๊ณ openapi code generator๋ฅผ ํ์ตํด๋ณด๊ณ ์ค๋ฌด์ ์ ์ฉํ ์ ์๋๋ก ํ๊ธฐ์ํด ํ์ต์ ํ๋ ๊ณผ์ ์ ๊ธฐ๋กํ๋ค.
ํ์ตํด๋ณด๊ณ ์ ์ฉํด๋ณด๊ณ ์ถ์ ์ฃผ์ ๋ 14๋ถ 30์ด ์ ๋๋ถํฐ ์์ํ๋ ์๋ฒ API ์ฃผ์ ๋ฐํ์ธ๋ฐ, ์ผ๋ฐ์ ์ธ api ์ฐ๋ ๊ณผ์ ์ธ ์คํ๋ฌธ์ ํ์ธ
-> ์ฝ๋ ์ด๊ด
-> data fetcher ์์ฑ
-> ์ฝ๋ ์์
์ ๊ณผ์ ์ ํจ์จํ ํ๋ ๋ด์ฉ์ด์๋ค.
OpenAPI Generator๋ก API์ ์์ ํ Model๊ณผ ์ ํํ๋ ๊ตฌํ์ฝ๋ ์๋์์ฑํ๊ธฐ ๋ธ๋ก๊ทธ ๊ธ์ ์ฐธ๊ณ ํ๋ค.
openapi-generator ์ค์น
์ฐ์ openapi-generator๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด openapi-generator๋ฅผ ์ค์นํด์ผ ํ๋ค. ๋๋ macos๋ฅผ ์ฌ์ฉ์ค์ด์ฌ์ ๊ณต์๋ฌธ์์์ ์ ๊ณตํ๋ ๋ฐฉ๋ฒ ์ค homebrew๋ฅผ ํตํด ์ค์นํ๋ค.
์ค์น ํ ํฐ๋ฏธ๋์ openapi-generator
๋ฅผ ์
๋ ฅํด๋ดค๋ค.
The most commonly used openapi-generator-cli commands are:
author Utilities for authoring generators or customizing templates.
batch Generate code in batch via external configs.
config-help Config help for chosen lang
generate Generate code with the specified generator.
help Display help information about openapi-generator
list Lists the available generators
meta MetaGenerator. Generator for creating a new template set and configuration for Codegen. The output will be based on the language you specify, and includes default templates to include.
validate Validate specification
version Show version information used in tooling
See 'openapi-generator-cli help <command>' for more information on a specific
๋ค์์ผ๋ก ์ ๋์๋ง ์ค ๋๋ ์์ฑ๋ฐฉ๋ฒ์ ๋ํด ๊ถ๊ธํด์ openapi-generator help generate
๋ฅผ ์
๋ ฅํด๋ดค๋ค.
OPTIONS
...
-c <configuration file>, --config <configuration file>
Path to configuration file. It can be JSON or YAML. If file is JSON,
the content should have the format {"optionKey":"optionValue",
"optionKey1":"optionValue1"...}. If file is YAML, the content should
have the format optionKey: optionValue. Supported options can be
different for each language. Run config-help -g {generator name}
command for language-specific config options.
-e <templating engine>, --engine <templating engine>
templating engine: "mustache" (default) or "handlebars" (beta)
-g <generator name>, --generator-name <generator name>
generator to use (see list command for list)
-i <spec file>, --input-spec <spec file>
location of the OpenAPI spec, as URL or file (required if not loaded
via config using -c)
-o <output directory>, --output <output directory>
where to write the generated files (current dir by default)
...
๋ง์ ์ต์ ์ด ๋์๋๋ฐ, ๊ทธ ์ค์์ ๋ช ๊ฐ๋ง ์ถ๋ ค๋ดค๋ค.
์ฐ์ ์ ํ ์คํธ๋ฅผ ์ํด config ์ค์ ์์ด ์ต์ ์คํฌ๋ฆฝํธ๋ฅผ ์คํํด๋ณด๊ธฐ๋ก ํ๋ค. ๋๋ generator๋ก typescript-fetch๋ฅผ, input์ผ๋ก๋ swagger ์์ ์ ๊ณตํ๋ ์์ ๋ฅผ ์ฌ์ฉํ๊ธฐ๋ก ํ๋ค.
swagger api์์ ์ ๊ณตํ๋ json, yaml ํ์ผ๊ฒฝ๋ก๋ฅผ i ์ต์ ์ผ๋ก ์ค์ ํ๋ฉด ๋๋ค.
๋๋ ๊ฐ๋จํ๊ฒ ์์ ํ๊ธฐ ์ํด script๋ก ๋ฑ๋กํ๋ค.
// package.json
"scripts": {
"generate": "openapi-generator generate -g typescript-fetch -i https://petstore3.swagger.io/api/v3/openapi.json"
},
// command line
pnpm generate
์คํฌ๋ฆฝํธ๋ฅผ ์คํํ๋ ๋ค์๊ณผ ๊ฐ์ ๋๋ ํ ๋ฆฌ์ ํ์ผ์ด ์์ฑ๋๋ค.
orval
์ค๋ฌด์์ ์ ์ฉํ๊ธฐ ์ํด ์ถ๊ฐ ๋ฆฌ์์น๋ฅผ ํ๋ค. ํ์ฌ ์ค๋ฌด์์ httpClient๋ก๋ fetch
, ์ํ๊ด๋ฆฌ๋ react-query
์ ํจ์ฑ ๊ฒ์ฌ๋ zod
๋ฅผ ์ฌ์ฉํ๊ณ ์๋๋ฐ ์ฌ์ฉ์ค์ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํตํฉ์ด ๊ฐ๋ฅํด์ผํ๋ ์กฐ๊ฑด์ด ์์๋ค.
์ฌ๋ฌ openapi generator ์ค์์ ์กฐ๊ฑด์ ์ ํฉํ generator๋ก Orval์ ์ฑํํ๋ค.
์ฐ์ orval๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ ์ค์น๊ฐ ํ์ํ๋ค
pnpm add orval -D
petstore ์์ ๋ฅผ ๋ฐ๋ผ config๋ฅผ ์์ฑํ๊ณ ์คํํ๋ ๋ถ๋ถ์ ํฐ ์ด๋ ค์์ ์์๋ค. orval.config.ts๋ฅผ ์์ฑํ๊ณ config๋ฅผ ์์ฑํ ๋ค์ pnpm orval
์ ํด์ฃผ๋ฉด ๋๋๋ค.
๋ด๊ฐ ์ฌ์ฉํด์ผ ํ๋ ํ๊ฒฝ์ ๋ง๋๋ก client, httpClient, zod ์ค์ ์ ์์ฑํ๋ค.
์์ธํ config๋ ๊ณต์๋ฌธ์์์ ํ์ธํ ์ ์๋ค.
import { defineConfig } from 'orval';
export default defineConfig({
petstore: {
output: {
mode: 'tags-split', // ํ์ผ ์์ฑ๋ฐฉ๋ฒ // ๋จ์ผ๋ก ๋ง๋ค๊ฑด์ง ๋ถ๊ธฐํ ๊ฑด์ง ๋ฑ
target: 'src/petstore.ts', // ํ์ผ ์์ฑ์์น
schemas: 'src/model', // ๋ชจ๋ธ ์์ฑ์์น
mock: true, // mocks ์์ฑ ์ฌ๋ถ (๊ธฐ๋ณธ generator๋ MSW)
// baseUrl: "/api/v2",
baseUrl: 'https://petstore3.swagger.io/api/v3',
client: 'react-query', // ํด๋ผ์ด์ธํธ
httpClient: 'fetch', // http ํด๋ผ์ด์ธํธ
override: {
query: {
useQuery: true,
useInfinite: true,
useInfiniteQueryParam: 'nextId',
options: {
staleTime: 60_000,
},
},
},
},
input: {
target: 'https://petstore3.swagger.io/api/v3/openapi.json',
},
},
petstoreZod: {
output: {
mode: 'tags-split',
client: 'zod',
target: 'src/gen/endpoints',
fileExtension: '.zod.ts',
},
input: {
target: 'https://petstore3.swagger.io/api/v3/openapi.json',
},
},
});
์๋ ์ด๋ฏธ์ง์ ๊ฐ์ ์ฝ๋๊ฐ ์์ฑ๋๋ค.
ํ๊ธฐ
๋๋ต์ ์ธ ๋ฐฉ๋ฒ์ ์๊ฒ๋๋ค. ํ ์คํธ ํด๋ณธ ๊ฒ ์ฒ๋ผ ํ๊ฒฝ๋ง ๊ฐ์ถฐ์ง๊ณ ์ปจ๋ฒค์ ๋ง ์ ํด๋๋ฉด ํจ์จ์ ์ธ ์์ ์ด ๊ฐ๋ฅํ ๊ฒ ๊ฐ๋ค. ์ด์ ํ์ฌ์์ ๋๋ฃ ๊ฐ๋ฐ์๋ถ๋ค๊ณผ ์ปจ์ผ์์ค๋ฅผ ๋ง์ถ๊ณ ํ๊ฒฝ์ ๋ง๊ฒ ์ปค์คํ ์ ํด๋ด์ผ ํ๋ค.
orval๊น์ง ์ฌ์ฉํ๊ณ ๋๋ orval config ์ค์ ๋ฐฉ๋ฒ์ ๋ํด ๋ ๊น๊ฒ ํ์ตํด์ผ ํ ๊ฒ ๊ฐ์๊ณ , pet store ์์ ์ฒ๋ผ ์์ฑ๋์ด์์ง ์์ ์ค๋ฌด์ฝ๋์ ์ ์ฉํ๋ ค๋ฉด ๋๋ฃ ๊ฐ๋ฐ์๋ค๊ณผ swagger json ๊ด๋ จ ์ปจ๋ฒค์ ๋ ๋ ผ์๊ฐ ํ์ํ๋ค.
์ฐ์ ์ค๋ฌด์์ ์ ์ฉํด๋ณด๊ณ ์ถ๊ฐ ํฌ์คํธ๋ฅผ ์์ฑํด์ผ๊ฒ ๋ค.