[GraphQL] Schema 등록하기

koline·2023년 11월 17일
0

GraphQL

목록 보기
4/8

Schema


apollo-server-express 서버를 생성했으면 서버에 resolvertypeDef를 포함한 schema를 등록해야 한다. resolvertypeDef에 대한 설명은 GraphQL이란? 포스팅 참조.




TypeDef와 Resolver 작성


GraphQL이란? 포스팅에서 설명했으므로 설명은 생략하고 아래와 같이 TypeDefResolver를 작성해준다.

// \resolver\character\character.typeDefs.ts
import { gql } from "apollo-server-express";

export default gql`
  type Query {
	  """
  	  단일 Character 조회
  	  """
      character(id: Int!): Character

	  """
  	  모든 Character 목록 조회
  	  """
      allCharacters: [Character]
  }

  type Mutation {
	  """
  	  Character 생성
  	  """
      createCharacter(name: String!, appearsIn: [ID!]!): Character
  }
  
  """
  등장인물 Type
  """
  type Character {
	  """
	  등장인물 식별번호
	  """
	  id: ID!

	  """
	  등장인물 이름
	  """
  	  name: String!

	  """
	  등장인물 등장 회차정보
	  """
      appearsIn: [Episode]!
  }
`;

TypeDef를 작성할 때는 apollo-server-expressgql을 import 해서 백틱(`) 안에 작성해야한다. 즉 string이라는 건데 VSCode를 사용한다면 Apollo GraphQL extension을 설치하면 일반 코드처럼 자동완성이나 색깔 구분도 되고 오류도 잡아준다.

이제 Resolver도 작성해 주는데 나는 querymutation을 나눠서 작성했다.

// \resolver\character\character.queries.ts
import { GraphQLError } from "graphql";
// prisma-client
import client from "../../client";

export default {
  Query: {
    /**
     * 단일 Character 조회
     * @param {ID} id: 등장인물 식별번호
     * @returns 등장인물 정보
     */
    character: (_, { id }) => {
      return client.Character.findFirst({
          where: {
            id,
          },
      });
    },
    allCharacters: () => {
      return client.Character.findMany();
    },
  },
};


// \resolver\character\character.mutations.ts
import { GraphQLError } from "graphql";
// prisma-client
import client from "../../client";

export default {
  Mutation: {
    /**
     * Character 생성
     * @param {string} : 등장인물 식별번호
     * @param {number[]} appearsIn: 등장인물 식별번호
     * @returns 생성된 등장인물 정보
     */
    createCharacter: (_, { name, appearsIn }) => {
      return client.Character.create({
          data: {
            name,
            appearsIn: { connect: appearsIn.map(id => ({ id })) }
          },
      });
    },
  },
};

참고로 GraphQL은 Query는 여러 query가 하나의 operation으로 올 경우 동시에 쿼리를 실행하고 Mutation은 순차대로 진행한다. 즉, 비동기 처리가 어느정도 자동으로 되서 return 정보를 async/await 처리 해주지 않아도 된다. (그러나 메소드 내에서의 비동기 처리는 해줘야 한다. Promise 객체가 return될 때만 자동으로 비동기처리를 해준다는 뜻.)




Schema 생성


이제 위에 작성해준 ResolverTypeDefs를 합쳐서 하나의 Schema로 만들어 준다.

// 원하는 디렉토리에 schema.ts 생성
const { makeExecutableSchema } = require('@graphql-tools/schema');
const { mergeTypeDefs, mergeResolvers } = require('@graphql-tools/merge');
const { loadFilesSync } = require('@graphql-tools/load-files');


const loadedTypes = loadFilesSync(`${__dirname}/**/*.typeDefs.ts`);

const loadedResolvers = loadFilesSync(
    [
        `${__dirname}/**/*/*.{queries,mutations}.ts`
    ]
);

const typeDefs = mergeTypeDefs(loadedTypes);

const resolvers = mergeResolvers(loadedResolvers);

const schema = makeExecutableSchema({ 
    typeDefs,
    resolvers
});

export default schema;

참고로 __dirname은 현재 파일의 절대 경로를 출력하는 변수로 경로가 다를 경우 각자 경로에 맞게 변경해주면 된다.




Server에 Schema 적용


마지막으로 작성한 Schemaapollo-server-express에 적용해준다

const express = require('express');
const { ApolloServer, gql } = require('apollo-server-express');
const schema = require('./schema').default;

const app = express();

/**
 * Apollo server 생성 
 */
const server = new ApolloServer({
  // 작성한 스키마 적용
  schema,
  playground: true,
  context: ({ req, res }) => {
    return { req, res };
  },
  formatError: (err) => {
    console.log(err);
    return err;
  }
});

/**
 * Express app에 Apollo 연결 
 */
const con = async() => {
  await server.start();
  server.applyMiddleware({ app, path: "/graphql" });
}
con();

/**
 * application 실행 확인 
 */
app.listen({port: 4000}, () => {
	console.log('Now browse to http://localhost:4000' + server.graphqlPath)
})

이제 서버를 실행시킨후 http://localhost:4000/graphql로 요청을 보내면 응답이 올 것이다.

Playground에 들어가보면 작성된 typeDefresolver를 자동으로 인식해서 클릭 몇번이면 테스트를 해볼 수 있다.

profile
개발공부를해보자

0개의 댓글

관련 채용 정보