GraphQL + ApolloServer
1. GraphQL 타입 선언 (Schema 만들기)
1-1. Query 타입
Query 타입은 보통 fetch data를 하여 원하는 정보를 얻어올 때 쓰인다. schema.graphql을 만든 후 Schema에 Query 타입을 선언 하고 사용할 resolver들을 선언해준다. 상단에 #import를 이용하여 다른 graphql 파일로 부터 선언된 타입들을 불러올 수 있다. 전체 멤버를 불러오는 allMembers와 id를 이용하여 해당 멤버를 불러오는 getMemberById를 선언하였다.
#import Member from "member.graphql"
#import MemberResponse from "response.graphql"
type Query {
allMembers: MemberResponse!
getMemberById(user_id: String!) : MemberResponse!
}
MemberResponse라는 Response 타입을 선언하여 관리하였다. (아래는 response.graphql 파일의 코드다)
#import Member from "member.graphql"
interface Response {
res: Boolean!
msg: String!
}
type MemberResponse implements Response {
res: Boolean!
msg: String!
data: [Member]
}
1-2. Mutation 타입
type Query를 선언하고 그 아래에 type Mutation 을 선언하여 데이터를 변경하는 resolver들을 선언하였다. 같은 schema.graphql 파일에 선언한다. (추후 길어지면 분리해야할듯?)
type Mutation {
createMember(
user_id: String!
password: String!
member_type: String!
reg_date: String
reg_type: String!
reg_channel: String!
member_status: String!
info_period: String!
sms_receive: Boolean!
email_receive: Boolean!
) : MemberResponse!
updateMember(
user_id: String!
password: String
member_type: String
reg_date: String
reg_type: String
reg_channel: String
member_status: String
info_period: String
sms_receive: Boolean
email_receive: Boolean
) : MemberResponse!
deleteMember(user_id: String!) : MemberResponse!
}
2. Resolver 구현하기
2-1. Resolver 구현
Resolver 폴더 내에 Member.ts 파일을 만들고 그 안에 member 관련 resolver를 아래와 같이 작성한다.
import Member from "../controller/member";
import { MemberDto } from "../models/member.model";
const allMembers = async (_: void) => {
return await Member.getItems();
};
const getMemberById = async (_: void, {user_id}: MemberDto) => {
return await Member.getItemByUserId(user_id);
}
const createMember = async (_: void, args:any) => {
return await Member.insertItem(args);
};
const updateMember = async (_: void, args : any) => {
return await Member.updateItem(args.user_id, args);
};
const deleteMember = async (_: void, {user_id}: MemberDto) => {
return await Member.deleteItem(user_id);
}
export { allMembers, getMemberById, createMember, updateMember, deleteMember };
Member라는 모델을 만들어 해당 멤버관련 controller를 구현하여 호출하도록 만들었다. ORM으로 sequelize 를 사용하고 있으며 sequelize 관련해서는 다음 글에 포스팅 하겠다. 구현된 resolver들을 보면 root를 '_'로 void타입으로 받고 뒤에 argument를 받아 정보를 넘겨준다. 해당 argument는 graphql 쿼리로 부터 받은 정보와 일치한다.
2-2. resolverMap 작성하기
import { IResolvers } from "@graphql-tools/utils";
import { allMembers, getMemberById, createMember, updateMember, deleteMember } from "./Member";
const resolverMAP: IResolvers = {
Query: {
// Member
allMembers,
getMemberById,
},
Mutation: {
// Member
createMember,
updateMember,
deleteMember
}
};
export default resolverMAP;
@graphql-tools/utils 를 이용하여 생성된 여러가지 resolver들을 하나의 resolverMap으로 묶어준다.
3. GraphQLSchema 생성하기
1번에서 생성한 graphql 파일들로부터 Schema들을 로드하여 typeDefs로 만들어준다. 그리고 resolver 폴더에 선언된 resolverMap을 불러와 @graphql-tools/schema를 이용하여 하나의 GraphQLSchema로 생성한다.
import { loadSchema } from '@graphql-tools/load';
import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader';
import { makeExecutableSchema } from '@graphql-tools/schema';
import resolvers from './resolver';
import { GraphQLSchema } from 'graphql';
export default async function loadAllSchema() : Promise<GraphQLSchema> {
const typeDefs = await loadSchema('src/**/*.graphql', {
loaders: [new GraphQLFileLoader()]
});
const schema: GraphQLSchema = makeExecutableSchema({
typeDefs : typeDefs,
resolvers,
});
return schema;
}
4. ApolloServer 연동하기
Express + ApolloServer(Middleware) + GraphQL 조합으로 사용할 예정이라 위 작성된 Schema를 ApolloServer에 넣어 준 후 server를 실행시킨다. 그리고 endpoint path를 '/graphql'로 선언해준다.
import express from 'express';
import { ApolloServer } from 'apollo-server-express';
import depthLimit from 'graphql-depth-limit';
import { createServer } from 'http';
import compression from 'compression';
import cors from 'cors';
import loadAllSchema from './schema';
require("dotenv").config();
const app = express();
(async () => {
const schema = await loadAllSchema();
const server = new ApolloServer({
schema,
validationRules: [depthLimit(7)],
});
await server.start();
app.use('*', cors());
app.use(compression());
server.applyMiddleware({ app, path: '/graphql' });
const httpServer = createServer(app);
httpServer.listen(
{ port: 8000 },
(): void => console.log(`server Start`)
);
})();
https://studio.apollographql.com/
ApolloStudio를 이용하면 8000번 포트를 통해 graphql 쿼리를 post로 날려 response를 확인할 수 있다.
5. GraphQL Query작성 및 테스트
ApolloStudio도 좋지만 본인은 다른 rest api테스트도 필요해서 VSCode에 Thunder Client 를 설치하여 테스트해봤다.
테스트를 위해 작성한 query 를 첨부한다. GraphQL Query 작성에 대해선 다른 포스팅에서 만나보도록 하자 ㅎㅎ
왜 GraphQL을 사용하는지 알고싶다면 아래 글을 참조하기!
2022.09.21 - [개발 Study/Node, js, react] - [GraphQL] GraphQL과 REST
2022.09.29 - [개발 Study/Node, js, react] - [GraphQL] GraphQL 사용법 - (2) Sequelize + MSSQL 연동
'개발 Study > GraphQL' 카테고리의 다른 글
[GraphQL/Typescript] GraphQL로 이미지 파일 업로드하기 (1) | 2022.12.14 |
---|---|
[GraphQL] GraphQL 사용법 - (4) ThunderClient로 API 테스트하기 (0) | 2022.10.04 |
[GraphQL] GraphQL 사용법 - (3) Sequelize 사용하기(1:1, ForeignKey, Join) (1) | 2022.09.30 |
[GraphQL] GraphQL 사용법 - (2) Sequelize + MSSQL 연동 (1) | 2022.09.29 |
[GraphQL] GraphQL과 REST (2) | 2022.09.21 |
댓글