끊임없이 진화하는 웹 개발 환경에서 GraphQL은 기존 REST API의 강력한 대안으로 떠올랐으며, 클라이언트가 필요한 데이터를 정확하게 요청할 수 있는 기능을 제공합니다. 하지만 이러한 유연성은 특히 프런트엔드와 백엔드 간의 타입 안정성을 유지하는 데 있어 새로운 과제를 야기할 수 있습니다. 바로 이 지점에서 graphql-codegen
이 등장합니다. 이 혁신적인 도구는 GraphQL 스키마로부터 타입이 지정된 코드를 자동으로 생성하여 개발 워크플로우를 대폭 개선하고 런타임 오류의 상당 부분을 제거합니다.
이 글은 graphql-codegen
을 이해하고 숙달하기 위한 가이드 역할을 할 것입니다. 기본적인 개념부터 시작하여 도구를 설정하고 구성하는 실용적인 단계별 예제를 살펴보고, 프로젝트에 통합하기 위한 모범 사례를 탐색할 것입니다. 이 가이드를 마치면 graphql-codegen
을 활용하여 더욱 견고하고 유지보수하기 쉬우며 타입 안전성이 높은 애플리케이션을 구축할 수 있게 될 것입니다.
최대 생산성으로 개발팀이 함께 작업할 수 있는 통합된 올인원 플랫폼을 원하시나요?
Apidog는 귀하의 모든 요구 사항을 충족하며, 훨씬 저렴한 가격으로 Postman을 대체합니다!
graphql-codegen
이란 무엇이며 왜 필요한가요?
본질적으로 graphql-codegen
은 GraphQL 스키마와 GraphQL 오퍼레이션(쿼리, 뮤테이션, 서브스크립션)을 인트로스펙트하고 다양한 언어로 코드를 생성하는 명령줄 도구입니다. 이 초보자 가이드에서는 가장 일반적인 사용 사례인 프런트엔드 애플리케이션을 위한 TypeScript 타입 및 훅 생성에 초점을 맞출 것입니다.
graphql-codegen
이 해결하는 주요 문제는 GraphQL API의 데이터 구조와 쿼리 결과에 대한 TypeScript 인터페이스를 수동으로 작성하는 지루하고 오류가 발생하기 쉬운 과정입니다. 이 도구가 없으면 개발자는 타입이 지정되지 않은 데이터로 작업하거나(TypeScript의 이점을 잃게 됨) API가 발전함에 따라 쉽게 구식이 될 수 있는 타입을 생성하고 유지 관리하는 데 상당한 시간을 소비해야 합니다.
graphql-codegen
을 도입하면 다음과 같은 여러 이점을 얻을 수 있습니다:
- 엔드 투 엔드 타입 안정성: 스키마에서 직접 타입을 생성함으로써
graphql-codegen
은 프런트엔드 코드가 백엔드의 데이터 모델과 항상 동기화되도록 보장합니다. 즉, 타입 관련 오류를 사용자가 접하기 훨씬 전에 컴파일 시점에 잡아낼 수 있습니다. - 향상된 개발 경험: 생성된 타입을 사용하면 코드 편집기에서 자동 완성 및 지능적인 제안과 같은 기능을 활용하여 개발 속도를 높이고 효율성을 높일 수 있습니다. 더 이상 API 응답의 형태를 추측할 필요가 없습니다!
- 상용구 감소:
graphql-codegen
은 타입뿐만 아니라 Apollo Client 및 React Query와 같은 인기 있는 GraphQL 클라이언트를 위한 바로 사용할 수 있는 훅도 생성할 수 있습니다. 이를 통해 반복적인 데이터 가져오기 로직을 작성할 필요가 없습니다. - 향상된 유지보수성: API 스키마가 변경될 때, 간단한 명령만으로 타입을 다시 생성할 수 있습니다. 이를 통해 시간이 지남에 따라 코드베이스를 훨씬 쉽게 유지 관리하고 리팩토링할 수 있습니다.
이 접근 방식은 GraphQL 스키마가 API의 단일 정보 소스 역할을 하는 "스키마 우선(schema-first)" 개발 철학과 완벽하게 일치합니다.
시작하기: 첫 번째 graphql-codegen
설정
graphql-codegen
사용의 실질적인 측면을 살펴보겠습니다. 이 튜토리얼에서는 GraphQL, TypeScript에 대한 기본적인 이해가 있고 Node.js와 패키지 관리자(npm 또는 yarn 등)가 설치되어 있다고 가정합니다.
우리의 목표는 간단한 React 애플리케이션에서 graphql-codegen
을 설정하여 블로그 게시물 목록을 표시하는 것입니다.
1단계: 프로젝트 초기화 및 종속성 설치
먼저 TypeScript로 새 React 프로젝트를 생성하고 필요한 종속성을 설치해 보겠습니다.Bash
npx create-react-app my-blog --template typescript
cd my-blog
npm install @apollo/client graphql
npm install -D @graphql-codegen/cli @graphql-codegen/client-preset typescript
설치한 종속성에 대한 설명은 다음과 같습니다:
@apollo/client
: React를 위한 인기 있는 GraphQL 클라이언트입니다.graphql
: Apollo Client와graphql-codegen
모두에 필요한 피어 종속성입니다.@graphql-codegen/cli
:graphql-codegen
의 명령줄 인터페이스입니다.@graphql-codegen/client-preset
: 클라이언트 측 애플리케이션 구성을 간소화하는 현대적이고 간소화된 프리셋입니다.typescript
: TypeScript 컴파일러입니다.
2단계: graphql-codegen
초기화 마법사
graphql-codegen
을 시작하는 가장 쉬운 방법은 초기화 마법사를 사용하는 것입니다. 프로젝트의 루트 디렉토리에서 다음 명령을 실행합니다:Bash
npx graphql-codegen init
마법사는 프로젝트 구성을 돕기 위해 일련의 질문을 할 것입니다. 블로그 애플리케이션 시나리오에 대한 일반적인 답변 세트는 다음과 같습니다:
- 어떤 유형의 애플리케이션을 구축하고 있습니까?
Application built with React
- 스키마는 어디에 있습니까? GraphQL API 엔드포인트의 URL을 제공합니다. 이 튜토리얼에서는 공개적으로 사용 가능한 예제 API를 사용할 수 있습니다:
https://swapi-graphql.netlify.app/.netlify/functions/index
- 오퍼레이션과 프래그먼트는 어디에 있습니까?
src/**/*.tsx
(이는graphql-codegen
에게src
디렉토리 내의 모든.tsx
파일에서 GraphQL 쿼리를 찾도록 지시합니다.) - 플러그인 선택: 마법사가 플러그인 세트를 제안할 것입니다.
typescript
,typescript-operations
,typescript-react-apollo
를 포함한 기본값은 훌륭한 시작점입니다. - 출력을 어디에 작성합니까?
src/gql/
(이는 생성된 파일을 저장할 새 디렉토리src/gql
를 생성합니다.) - 인트로스펙션 파일을 생성하시겠습니까?
Yes
(이는 로컬 개발 및 IDE 확장에 유용할 수 있습니다.) - 구성 파일 이름을 어떻게 지정하시겠습니까?
codegen.ts
- package.json에서 codegen을 실행할 스크립트는 무엇입니까?
codegen
이 질문들에 답하면 마법사는 프로젝트 루트에 codegen.ts
파일을 생성하고 package.json
에 codegen
스크립트를 추가합니다.
3단계: 구성 파일(codegen.ts
) 이해하기
codegen.ts
파일은 graphql-codegen
설정의 핵심입니다. 마법사가 생성하는 간소화된 버전을 살펴보겠습니다:TypeScript
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
overwrite: true,
schema: "https://swapi-graphql.netlify.app/.netlify/functions/index",
documents: "src/**/*.tsx",
generates: {
"src/gql/": {
preset: "client",
plugins: []
}
}
};
export default config;
주요 구성 옵션을 분석해 보겠습니다:
overwrite: true
: 이 옵션은 명령을 실행할 때마다 기존 생성 파일이 덮어쓰여지도록 보장합니다.schema
: GraphQL 스키마의 소스를 가리킵니다. 라이브 엔드포인트의 URL, 로컬.graphql
또는.json
파일일 수 있습니다.documents
:graphql-codegen
에게 GraphQL 오퍼레이션(쿼리, 뮤테이션, 프래그먼트)을 찾을 위치를 알려주는 glob 패턴입니다.generates
: 구성에서 가장 중요한 부분입니다. 각 키는 출력 파일 또는 디렉토리를 나타내고, 값은 무엇을 생성할지 정의합니다.preset: "client"
:client-preset
은 프런트엔드 애플리케이션을 위해graphql-codegen
을 구성하는 강력하고 권장되는 방법입니다. 여러 플러그인을 번들로 제공하고 간소화된 경험을 제공합니다. 쿼리를 작성하는 데 사용할graphql
함수를 생성합니다.
4단계: 첫 번째 GraphQL 쿼리 작성
이제 graphql-codegen
이 구성되었으므로 블로그 게시물을 가져올 GraphQL 쿼리를 작성해 보겠습니다. 새 파일 src/components/Posts.tsx
를 생성합니다:TypeScript
import { gql } from '../gql/gql';
import { useQuery } from '@apollo/client';
const GET_POSTS = gql(`
query GetPosts {
allFilms {
films {
id
title
director
releaseDate
}
}
}
`);
const Posts = () => {
const { loading, error, data } = useQuery(GET_POSTS);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error :(</p>;
return (
<div>
{data?.allFilms?.films?.map((film) => (
<div key={film?.id}>
<h2>{film?.title}</h2>
<p>Director: {film?.director}</p>
<p>Release Date: {film?.releaseDate}</p>
</div>
))}
</div>
);
};
export default Posts;
생성된 src/gql/gql.ts
파일에서 gql
함수를 가져오는 것을 확인하세요. 이것은 client-preset
에서 제공하는 gql
함수이며, 타입 추론의 마법을 가능하게 하는 것입니다.
5단계: graphql-codegen
실행 및 마법 확인
이제 package.json
에서 codegen
스크립트를 실행합니다:Bash
npm run codegen
이 명령은 스키마를 인트로스펙트하고, GET_POSTS
쿼리를 찾아, 해당 TypeScript 타입을 src/gql
디렉토리에 생성합니다.
이제 Posts.tsx
의 useQuery
훅에서 반환된 data
객체를 검사하면 완전히 타입이 지정된 것을 볼 수 있습니다! IDE는 data.allFilms.films
에 대한 자동 완성을 제공하고, 쿼리에 존재하지 않는 필드에 액세스하려고 하면 TypeScript가 경고할 것입니다.
심층 탐구: 실용적인 블로그 프런트엔드 예제
이해를 굳히기 위해 예제를 확장해 보겠습니다. 블로그가 다음과 같은 더 전통적인 스키마를 가지고 있다고 상상해 보세요:GraphQL
type Author {
id: ID!
name: String!
}
type Post {
id: ID!
title: String!
content: String!
author: Author!
}
type Query {
posts: [Post!]!
post(id: ID!): Post
}
type Mutation {
createPost(title: String!, content: String!, authorId: ID!): Post!
}
이 스키마가 http://localhost:4000/graphql
에서 실행되고 있다고 가정해 보겠습니다. 그에 따라 codegen.ts
를 업데이트할 것입니다:TypeScript
// codegen.ts
// ...
schema: "http://localhost:4000/graphql",
// ...
이제 단일 게시물을 표시하는 컴포넌트와 새 게시물을 생성하는 컴포넌트를 만들어 보겠습니다.
단일 게시물 가져오기TypeScript
// src/components/Post.tsx
import { gql } from '../gql/gql';
import { useQuery } from '@apollo/client';
import { useParams } from 'react-router-dom';
const GET_POST = gql(`
query GetPost($id: ID!) {
post(id: $id) {
id
title
content
author {
id
name
}
}
}
`);
const Post = () => {
const { id } = useParams<{ id: string }>();
const { loading, error, data } = useQuery(GET_POST, {
variables: { id },
});
if (loading) return <p>Loading...</p>;
if (error) return <p>Error :(</p>;
return (
<div>
<h2>{data?.post?.title}</h2>
<p>By {data?.post?.author?.name}</p>
<p>{data?.post?.content}</p>
</div>
);
};
export default Post;
npm run codegen
을 실행하면 GetPostQuery
및 해당 변수에 대한 타입이 생성되어 useQuery
훅 및 그 결과에 대한 타입 안전성을 제공합니다.
새 게시물 생성TypeScript
// src/components/CreatePost.tsx
import { gql } from '../gql/gql';
import { useMutation } from '@apollo/client';
import { useState } from 'react';
const CREATE_POST = gql(`
mutation CreatePost($title: String!, $content: String!, $authorId: ID!) {
createPost(title: $title, content: $content, authorId: $authorId) {
id
}
}
`);
const CreatePost = () => {
const [title, setTitle] = useState('');
const [content, setContent] = useState('');
const [createPost, { data, loading, error }] = useMutation(CREATE_POST);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
createPost({ variables: { title, content, authorId: '1' } }); // Assuming authorId '1' for simplicity
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="Title"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<textarea
placeholder="Content"
value={content}
onChange={(e) => setContent(e.target.value)}
/>
<button type="submit" disabled={loading}>
{loading ? 'Creating...' : 'Create Post'}
</button>
{error && <p>Error creating post: {error.message}</p>}
{data && <p>Post created with ID: {data.createPost.id}</p>}
</form>
);
};
export default CreatePost;
여기서 graphql-codegen
은 CreatePostMutation
및 해당 변수에 대한 타입을 생성합니다. 이를 통해 createPost
함수를 호출할 때 title
, content
, authorId
에 대해 올바른 타입을 전달하도록 보장합니다.
고급 개념 및 모범 사례
graphql-codegen
에 익숙해지면 더 많은 고급 기능과 모범 사례를 접하게 될 것입니다:
- 프래그먼트:
graphql-codegen
은 GraphQL 프래그먼트에 대한 뛰어난 지원을 제공합니다..tsx
파일에 프래그먼트를 정의할 수 있으며,graphql-codegen
은 타입을 올바르게 처리하여 컴포넌트에 대한 재사용 가능하고 공동 배치된 데이터 종속성을 촉진합니다. .graphql
파일 사용: 관심사 분리를 위해 GraphQL 쿼리, 뮤테이션, 프래그먼트를 전용.graphql
파일에 작성할 수 있습니다.codegen.ts
의documents
배열을 업데이트하여 이 파일 확장자를 포함시키기만 하면 됩니다:documents: ["src/**/*.tsx", "src/**/*.graphql"]
.- 커스텀 스칼라: GraphQL 스키마가 커스텀 스칼라(예:
Date
,JSON
)를 사용하는 경우, 타입 안전성을 유지하기 위해codegen.ts
파일에서 해당 TypeScript 타입에 매핑할 수 있습니다. - Watch 모드: 원활한 개발 경험을 위해
graphql-codegen
을 watch 모드로 실행할 수 있습니다. 이렇게 하면 GraphQL 오퍼레이션을 포함하는 파일을 저장할 때마다 타입이 자동으로 다시 생성됩니다.package.json
의codegen
스크립트에--watch
플래그를 추가하기만 하면 됩니다:"codegen": "graphql-codegen --watch"
.
일반적인 문제 해결
graphql-codegen
은 강력한 도구이지만, 초보자는 몇 가지 일반적인 문제에 직면할 수 있습니다:
- "Unable to find schema": 이 오류는 일반적으로
codegen.ts
의schema
경로가 잘못되었거나 GraphQL 서버가 지정된 주소에서 실행되고 있지 않음을 의미합니다. - 플러그인 구성 오류: 필요한 모든 플러그인이 설치되어 있고
codegen.ts
의 구성이 올바른지 확인하십시오. graphql
피어 종속성 문제: 프로젝트에graphql
이 직접 종속성으로 설치되어 있는지 확인하십시오.
결론: 타입 안전성의 미래를 받아들이세요
graphql-codegen
은 단순한 코드 생성 도구 그 이상입니다. GraphQL로 애플리케이션을 구축하는 방식에 대한 패러다임 전환입니다. 자동화를 수용하고 스키마의 힘을 활용함으로써 더 견고하고 유지보수하기 쉬우며 작업하기 즐거운 코드베이스를 만들 수 있습니다.
이 튜토리얼은 graphql-codegen
시작을 위한 견고한 기반을 제공했습니다. 핵심 개념을 다루고, 실용적인 예제를 살펴보고, 모범 사례를 언급했습니다. 여정은 여기서 끝나지 않습니다. graphql-codegen
생태계는 방대하며, 다양한 프레임워크 및 사용 사례를 충족하는 풍부한 플러그인 컬렉션을 가지고 있습니다. 공식 문서를 탐색하고, 다양한 플러그인을 실험하며, graphql-codegen
이 GraphQL 개발 워크플로우를 어떻게 혁신할 수 있는지 발견해 보시기 바랍니다. 즐거운 코딩 되세요!
최대 생산성으로 개발팀이 함께 작업할 수 있는 통합된 올인원 플랫폼을 원하시나요?
Apidog는 귀하의 모든 요구 사항을 충족하며, 훨씬 저렴한 가격으로 Postman을 대체합니다!