graphql-compose는 node.js에서 복잡한 graphql 스키마를 구성할 수 있도록 도와주는 라이브러리입니다.
스키마를 구성할 수 있도록 여러가지 리졸버(resolver), 타입 스키마를 제공합니다.
graphql-compose에서 제공하는 리졸버가 아닌, 유저가 직접 구성해서 작성한 리졸버로, 리턴되는 타입을 지정해줘야만 합니다.
커스텀 리졸버를 통해 제작되어있는 모델 타입 정보가 아닌, 일부 정보만 리턴하고자 할 때 타입을 지정하는 것이 어려웠고, type을 JSON으로 명시해주었을 경우, playground 등에서 원하는 정보만 얻기 어려웠다는 단점이 있었습니다.
해당 단점을 보완하고자 여러가지 리서치를 진행했고, createObjectTC 문서를 통해 해답을 얻을 수 있었습니다.
import { UserProductModel, UserTicketModel } from '~'; // 모델 스키마가 정의되어 있는 파일 루트
import { ProductModelTC } from '~'; // TC 가 정의되어 있는 파일 루트
const name = 'resolverName';
// args에는 해당 리졸버 쿼리를 보낼 때 함께 보내는 argument의 key 네임과 값의 타입을 지정해줍니다.
ProductModelTC.addResolver({
args: {
id: 'String',
},
name,
resolve: async ({ args }: { args: { id?: string } }) => {
const item = await Model.findOne({
uid: args.id,
});
if (!item) {
throw new Error('올바르지 않은 상품 정보입니다. 다시 시도해주세요.');
}
const userTickets = await UserTicketModel.find({
parentPackage: userProductPackage._id,
});
const userProducts = await UserProductModel.find({
parentPackage: userProductPackage._id,
});
return {
userPackage: userProductPackage,
userTickets: userTickets,
userProducts: userProducts,
};
},
type: 'JSON',
});
해당 리졸버는 Model을 통해 원하는 데이터를 받아 수정, 가공 된 타입의 데이터를 리턴하고 있습니다.
초기에는 타입을 지정해주지 못 해 JSON타입으로 값을 리턴하였고, playground 등에서 테스트를 진행할 때 따라오는 데이터 중 원하는 정보만 받아올 수 없었습니다.
import { UserProductModel, UserTicketModel } from '~'; // 모델 스키마가 정의되어 있는 파일 루트
import { ProductModelTC } from '~'; // TC 가 정의되어 있는 파일 루트
import { schemaComposer } from 'graphql-compose';
const name = 'resolverName';
// 리턴될 데이터의 타입을 미리 지정해서, objectTC로 제작합니다.
// userTickets, userProducts의 경우 단일 데이터가 아닌 배열 데이터로 리턴되어 배열([])로 감싸주었습니다.
// 해당 방식으로 데이터의 타입을 지정해 줄 경우, UserTickets의 _id만 받거나, 원하는 일부 데이터만 받아오는 것이 가능해집니다.
const ReturnType = schemaComposer.createObjectTC({
name: 'returnType',
fields: {
userPackage: 'UserProduct',
userTickets: '[UserTicket]',
userProducts: '[UserProduct]',
},
});
ProductModelTC.addResolver({
args: {
id: 'String',
},
name,
resolve: async ({ args }: { args: { id?: string } }) => {
const item = await Model.findOne({
uid: args.id,
});
if (!item) {
throw new Error('올바르지 않은 상품 정보입니다. 다시 시도해주세요.');
}
const userTickets = await UserTicketModel.find({
parentPackage: userProductPackage._id,
});
const userProducts = await UserProductModel.find({
parentPackage: userProductPackage._id,
});
return {
userPackage: userProductPackage,
userTickets: userTickets,
userProducts: userProducts,
};
},
type: ReturnType,
});
createObjectTC를 통해 리턴될 값의 스키마를 제작하고, 해당 스키마를 type에 작성해주었습니다.
타입을 JSON으로 지정해주었을 때와 다르게 query에 리턴되는 데이터 중 일부의 값만 받아올 수 있도록 하는 것이 가능해집니다.