[정리] graphQL code generator

2021. 3. 8. 15:55프로그래밍-Web/GraphQL

graphql-code-generator.com/

 

GraphQL Code Generator | GraphQL Code Generator

And more! You can generate your resolvers' signatures, dump schemas, model types, query builders, React Hooks, Angular Services, and much more!

graphql-code-generator.com

Typescript와 graphQL을 함께 이용하면, type이라는 용어탓에 헷갈리는 경우가 생긴다.

리졸버, MongoDB 모델, graphQL의 타입정의들이 자주 중복되기 때문이다.

이러한 문제때문에 graphQL을 빌드한 산출물에 대한 모든 type이 적절하게 generate되도록 code generator라는 라이브러리를 사용한다

code generator를 설치하고 적절한 스크립트를 작성하여 graphQL의 스키마를 근거로 한 타입들이 자동산출되도록 해준다.

 

1) code generator의 설치 및 실행

 

yarn을 통해 @graphql-codegen/typescript를 설치하고, yarn generate로 실행한다

 

2) args, query, mutation, resolvers에 대한 타입 정의

 

@graphql-codegen/typescript@graphql-codtypescriㅇp

code generator의 스크립트는 크게 schema와 generates로 나뉜다.

schema는 소스코드를 컴파일했을때 사용되는 graphQL 스키마 파일들의 위치를 의미한다

이렇게 graphQL 스키마만 정의해주어도 resolver와 그 input들에 대한 정의는 끝난다.

이것들은 모두 graphQL 스키마 안에 정의되어있기 때문이다.

wbs.graphql
wbs리졸버

다음과 같은 리졸버를 예시로 들어보자

해당 리졸버는 graphql 스키마 파일에 args를 정의해두었다

따라서 별다른 설정을 해주지 않아도, 컴파일하는 시점에서 getActivityListbyCompany라는 리졸버의 타입이 정해지고, 그 args들의 타입도 정해지는 것이다.

 

getActivityListbyCompany의 쿼리타입
getActivityListbyCompany의 args타입
getActivityListbyCompany의 리졸버타입

이 정의들은 모두 graphql.d.ts에 생긴다.

따라서 args와 쿼리타입, 리졸버타입을 따로 정의해주지않아도, 정해진 타입이 생기는것이다.

 

단 리졸버의 경우 추가적인 플러그인을 추가 사용해야 한다.

mutation의 경우도 모두 동일하다

 

 

3) MongoDB 모델의 타입 정의

 

이 시점까지 문제가 되는 부분은 리턴값이다.

리졸버와 리졸버에서 사용하는 input값들에 대한 타입 제한을 하더라도, output에 대한 타입설정이 빠져있다.

 

이를 위해 스크립트에 추가 플러그인 사용을 정의하는 config문을 작성한다.

해당 설명에 대해선 mapper안에 모두 정의한다.

 

 

 

이렇게 번거로운 과정이 필요한 근본적인 이유는, graphQL 스키마의 output값과 실제 모델에서 주는 output값이 다르기 때문이다.

graphQL의 타입은 client및 개발자의 편의대로 정의한 것이지만, 실제로는 model을 통해 db로부터 데이터를 전달받는다.

이를 위해 model에 interface(타입스크립트 적용을 위해 정의한)를 통해 실제 받는 데이터들을 정의해두는데, 리졸버의 리턴값도 그와 같을 것이므로 모델에서 정의한 데이터들을 사용하도록 하는것이다.

이렇게 설정해야 리턴값들이 타입스크립트 정의를 따른다

 

실제로 code generator를 사용하기 전에는 아폴로가 제공하는 makeExecutableSchema를 통해 typeDefs와 resolvers를 만들어줬다. 

그러나 이는 실제로 받아오는 데이터인 mongoDB 모델의 정의는 포함하지 못했다.

 

code generator는 graph-tools의 merge가 내부적으로 모두 동작하고, 

더불어 mapper를 통해 Mongoose(MongoDB)모델과의 type SYNC도 맞출 수 있다.

 

 

4) Context, Scalar의 타입 정의

 

Context에 대한 정의도 플러그인을 이용한다.

context.ts파일에 공유가 필요한 ctx들을 정의한 후 타입을 설정하면, 모든 리졸버에서 사용하는 ctx의 타입이 정해진다.

 

graphQL 스키마에 사용자가 필요한대로 타입을 정의하는 scalar의 경우는 따로 add 커맨드를 정의해주어야 한다.

upload의 경우 타입스크립트에 없는 정의이므로, 별도의 라이브러리를 받아 각각 자료형으 정의한다.