GraphQL#2 - Apollo Server Setting + Query

이강원·2020년 2월 27일
0

GraphQL

목록 보기
2/4
post-thumbnail

GraphQl과 Apollo server를 연동해보기.

지난 포스트에 이어 이번에는 Express로 Apollo server를 구현해보고 GraphQL을 연동해보자.

install

npm module부터 설치.
EslintTypescript, Babel 같은 모듈은 설명 제외했습니다.

// npm
npm i apollo-server-express
// yarn
yarn add apollo-server-express

teamData.json

Test 용도로 Dummy Data용 json을 일단 하나 만들어보자. 예시로 나는 아래와 같은 teamData.json 파일을 하나 만들었다.

[
  {
    "name": "팀원1",
    "email": "팀원1@gmail.com"
  },
  {
    "name": "팀원2",
    "email": "팀원2@gmail.com"
  },
  {
    "name": "팀원3",
    "email": "팀원3@gmail.com"
  }
]

index.ts

이제 apollo server를 구동할 index 파일을 생성하고 필요한 모듈들을 import 하자.

import express from 'express';
import { ApolloServer, gql } from 'apollo-server-express';
import teamData from './mockup/teamData.json';
  • typescript 사용 중 json 파일을 import 시킬때 error가 난다면 tsconfig파일에서 resolveJsonModule: true를 추가해주면 된다.
  • express 모듈은 apollo-server-express안에 built in 되있기 때문에 따로 설치가 필요없다.

typeDefs

typeDefstype definitions의 약자로서 Apollo server를 구동시킬때 type 정의에 관한 typeDefs를 argument로 넘기게 된다.

const typeDefs = gql`
  type Member {
    name: String
    email: String
  }

  type Query {
    members: [Member!]!
  }
`;

위의 Dummy Data를 기준으로 Member Type schema 정의를 먼저 선언 해두고 Query Type의 members라는 키값은 Member Type으로 이루어진 배열이라는 의미이다. 이전 포스트에서 적어놨듯이 !(느낌표)는 field의 기대값으로 null을 허용하지 않겠다는 의미(non-nullable)이다. 직관적으로 얘기하자면 필수값으로 정의하겠다 라는 의미이다.

resolver

resolverschema에서 정의된 동일한 유형의 Data 또는 해당 Data에 관한 promise를 반환하는 함수이다. 그러나 field값이 primitive(숫자형) Type이거나 Scalar Type이라면 resolver는 break된다.
resolver 역시 Apollo server를 구동시킬때 필요한 설정이다.

const resolver = {
  Query: {
    members: () => teamData,
  }
}

resolver는 4개의 인자를 받을 수 있다.

fieldName: (parent, args, context, info) => data;

  • parent: 부모 resolver에서 반환된 객체
  • args: field에 전달해야 될 인수를 포함한 객체
  • context: GraphQL에서 모든 Resolver가 공유하고 있는 객체, 주로 middleware를 통해 입력받은 값들을 담고 있거나 로그인/인증정보와 같은 요청 별 상태를 포함하고 Data에 접근하기 위한 context
  • info: 음 이건 암만 설명을 봐도 잘 모르겠다..schema 정보와 특정 필드의 정보를 가지고있다는데 이건 나중에 다시한번 봐야겠다.

Apollo Server Setting

Apollo server의 Endpoint는 단 1개이다. 그리고 Apollo server를 구성하는 가장 큰 2가지 요소. 바로 위의 typeDefsresolvers이다. 그리고 추가를 하자면 Apollo 에서 자체적으로 제공하고 있는 Query IDE인 Playground가 있다.

const server = new ApolloServer({
  typeDefs,
  resolvers: resolver,
  playground: true,
});

키값이 resolvers s가 붙어있는 단수가 아닌 복수이다. resolver들의 모음 이라고 보면 금방 이해가 될듯하다. 한가지의 resolver가 아닌 각 field드 마다 그에 상응하는 각각의 resolver함수들의 모임을 Apollo server에 resolvers설정을 해주면 된다 라고 보자.

express middleware 연동

const app = express();

server.applyMiddleware({ 
  app,
  path: '/graphql',
});

app.listen( { port:7077 }, () => {
  console.log('server 7077 port start');
})

Apollo Server의 Middleware에 Express를 연동시키고 Endpoint는 localhost:7077/graphql 이라는 단일 EndPoint로 설정 해주면 기본적인 Apollo Server Setting이 끝이 나게 된다.

전체소스

import express from 'express';
import { ApolloServer, gql } from 'apollo-server-express';
import teamData from './mockup/teamData.json';

const typeDefs = gql`
  type Member {
    name: String
    email: String
  }
  type Query {
    members: [Member]
  }
`;

const resolver = {
  Query: {
    members: () => teamData,
  }
}

const server = new ApolloServer({
  typeDefs,
  resolvers: resolver,
  playground: true,
});

const app = express();

server.applyMiddleware({ 
  app,
  path: '/graphql',
});

app.listen( { port:7077 }, () => {
  console.log('server 7077 port start');
})

PlayGround

Apollo에서 제공해주는 Query IDE툴이다. 상단에서 보듯이 Apollo server setting에 playground:true라고 설정을 한 후, localhost:7077/graphql 로 접속하게 되면 Playground가 활성화 되고. 직접 Query / Mutation Test를 할수 있다.

위의 소스 예시테스트

introspection

Introspection이란 Playground 안에서 실시간으로 제공해주는 API 명세서 라고 보면 된다. 기존의 API 공유를 위해 Swagger처럼 명세서를 따로 만들어서 관리하는 것도 은근 공수가 들고 번거롭다. 그런 번거로움을 덜기 위해 Introspection은 서버 자체에서 현재 서버에 정의된 스키마의 실시간 정보를 공유하기 때문에 따로 API 명세서를 요구 및 공유 하지 않아도 된다.

Introspection 예시

마치며

Apollo server setting에 대해 알아보는 시간이었다. 아직까지는 굉장히 기초적인 세팅 내용이긴 하지만, 오랫만에 정리 해보면서 다시 한번 되새김 해보는 시간이였다. 다음 포스트는 Mutation예시 또는 SchemaResolver 함수 Module화에 대해 한번 정리를 해볼까 한다.

profile
양산현 포스트를 쓰고싶진 않다. 공식예제를 그대로 가져다 붙이기도 싫다.그냥 내가 경험했던걸 토대로 기록하고자 한다. 내 글의 헤비 커스토머는 내 자신이다.

0개의 댓글