본문 바로가기
개발 Study/GraphQL

[GraphQL] GraphQL 사용법 - (1) Schema 생성 후 ApolloServer 연동하기

by jiyoon_92 2022. 9. 27.
반응형

GraphQL + ApolloServer

GraphQL

 

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/

 

Apollo Studio

Studio is a hub for creating, evolving, and consuming your graph for all members of your team.

studio.apollographql.com

ApolloStudio를 이용하면 8000번 포트를 통해 graphql 쿼리를 post로 날려 response를 확인할 수 있다.


5. GraphQL Query작성 및 테스트

ApolloStudio도 좋지만 본인은 다른 rest api테스트도 필요해서 VSCode에 Thunder Client 를 설치하여 테스트해봤다.

ThunderClient + graphQL 테스트
member API.json
0.00MB

테스트를 위해 작성한 query 를 첨부한다. GraphQL Query 작성에 대해선 다른 포스팅에서 만나보도록 하자 ㅎㅎ

왜 GraphQL을 사용하는지 알고싶다면 아래 글을 참조하기!

2022.09.21 - [개발 Study/Node, js, react] - [GraphQL] GraphQL과 REST

 

[GraphQL] GraphQL과 REST

GraphQL을 사용하는 이유 1. GraphQL이란? GraphQL은 2012년도에 페이스북에 의해 고안된 API용 쿼리 언어이자 쿼리를 수행하기 위한 런타임이다. 2015년에 오픈소스로 공개되었다. GraphQL은 REST 및 웹서비

chuun92.tistory.com

2022.09.29 - [개발 Study/Node, js, react] - [GraphQL] GraphQL 사용법 - (2) Sequelize + MSSQL 연동

 

[GraphQL] GraphQL 사용법 - (2) Sequelize + MSSQL 연동

Sequelize + MSSQL 1. Sequelize란? Node 에서 자주 사용되는 ORM 라이브러리다. ORM(Object-Relational Mapping)이란 관계형 데이터베이스와 자바스크립트 객체를 서로 연결해주는 도구로 좀 더 DB작업을 쉽게..

chuun92.tistory.com

2022.09.30 - [개발 Study/Node, js, react] - [GraphQL] GraphQL 사용법 - (3) sequelize 사용하기(1:1, ForeignKey, Join)

 

[GraphQL] GraphQL 사용법 - (3) sequelize 사용하기(1:1, ForeignKey, Join)

Sequelize 테이블 연결 및 외래키 사용 1. Sequelize 테이블 관계 테이블 관계는 1:1, 1:N, M:N 이 있는데 foreignkey를 이용하여 서로 관계를 맺으며 join을 통해 연결된 테이블의 정보까지 불러올 수 있다. 참

chuun92.tistory.com

 

 

반응형

댓글