Prologue

이번에 무려 $300를 결제해서 노마드코더에서 인스타그램 클론이라는 클래스를 들었다. 프로젝트의 이름은 Prisma로 만드는 인스타그램이라는 뜻의 Prismagram 이었다. 클래스의 내용은 알찼다. 하지만 막상 만들어놓고보니, "음..? 내가 어떻게 만들었더라..?" 라는 생각이 문득 들었다. 어릴 때는 계속 두뇌를 개발하면 언젠가 천재가 되지 않을까 꿈꿨지만 터무니 없는 이야기였다. 인간의 뇌는 not-perfect 하며 volatile 하다. 그래서, 우리는 항상 우리가 배웠던 것을 organization 해야 한다는 결론에 이르렀다!

Organization은 매우 귀찮은 작업이지만 내 스스로 찾아보기 좋은 레퍼런스를 만들기 위해서는 필수다!
한번 내가 배웠던 것들을 정리해보자!

[WIL from prismagram #2] GraphQL 서버 추가 세팅하기

[WIL from prismagram #2] GraphQL 서버 추가 세팅하기

1. Logger 세팅하기

Logger란 서버에서 무슨 일이 일어나는지 알려주는 녀석을 말합니다. Logger가 없는 경우 어디에서 에러가 났는지 찾거나 서버가 지금 어떤 일을 하고 있는지 알기 매우 어렵습니다. 이를테면 우리가 덧셈을 하는 프로그램을 짰을 때, print문이 없으면 우리는 프로그램이 메모리에 어떤 값을 갖고 있는지 알 수 없습니다. Node.js 로 구성한 서버에서는 주로 morgan 이라는 모듈을 많이 사용합니다.

yarn add morgan 명령어를 이용하여 morgan 모듈을 설치할 수 있습니다.

Screen Shot 2019-08-04 at 10.26.47 PM.png

위와 같이 import logger from 'morgan' 코드로 morgan 모듈을 추가해주고,
server.express.use(logger('dev')) 코드를 통해 서버에서 morgan을 사용할 수 있습니다.

우리가 만든 GraphQLServer 오브젝트 내부에는 express가 포함되어 있어 위와 같은 코드를 사용할 수 있습니다.

결과적으로, 이 과정을 마치면 다음과 같은 로깅을 확인할 수 있습니다.

Screen Shot 2019-08-04 at 10.24.50 PM.png

이 로깅은 GraphQL서버에서 라이브 기능을 제공하기 위해 자체적으로 계속 요청을 하는 것으로 보입니다. 이 외에 우리가 또 서버로 요청을 보낼 시에 우리가 보낸 요청에 대한 서버의 응답도 물론 로그로 볼 수 있습니다.

2. GraphQL 파일 작성하기

이전 게시물에서 테스트를 위하여

typeDefs = `
type Query {
  test: String!
}
`

query = {
  Query: {
    test: () => "hello world"
  }
}

와 같은 방식으로 코딩했지만, 이렇게 계속 코딩하면 보기에 좋지 않습니다. 파일로 나누는 편이 보기 좋겠지요.

위의 내용을 보면 알 수 있듯이, 우리는 어떠한 GraphQL API를 사용하기 위해서, 그 API가 반환할 타입을 지정해주고

// 타입 정의
type Query {
  *query-name*: *type*
}

그 쿼리가 정확히 어떤 내용을 리턴하는지 지정해주면 됐습니다.

// 리졸버 정의
Query : {
  *method*: () => *do something*
}

이제 이 내용을 파일로 정의하기 위해서 먼저, 메인 디렉토리에 api디렉토리를 만들어주고 schema.js 파일을 만들어줍니다.

api 폴더 내부에는 graphql파일들과 resolver파일들이 들어가고 그것을 schema.js에서 합쳐줄 것입니다. schema 파일은 typeDefs와 resolvers를 모두 가질 것입니다.

이런 구조로 동작시키기 위해서 다음과 같은 의존성을 추가해줍시다.

yarn add graphql-tools merge-graphql-schemas

의존성을 추가해주고

schema.js에 다음과 같은 내용을 작성합니다.

import path from 'path';
import { makeExecutableSchema } from 'graphql-tools';
import { fileLoader, mergeResolvers, mergeTypes } from 'merge-graphql-schemas';

// __dirname은 이 프로젝트의 메인 디렉토리의 이름(src)까지의 경로를 의미
// allResolvers는 api 밑의 모든 js를 가져오기 때문에 절대 Resolver의 역할이 아닌 js를 두면 안됨

const allTypes = fileLoader(path.join(__dirname, '/api/**/*.graphql'));
const allResolvers = fileLoader(path.join(__dirname, '/api/**/*.js'));

const schema = makeExecutableSchema({
  typeDefs: mergeTypes(allTypes),
  resolvers: mergeResolvers(allResolvers)
});

export default schema;

그리고 api 디렉토리 밑에 우리가 사용할 GraphQL의 TypeDefs(.graphql)와 Resolver(.js)를 정의해줍시다.

api/Hello/sayHello/sayHello.graphql 을 다음과 같이 작성합니다.

type Query{
  sayHello: String!
}
export default {
  Query {
    sayHello: () => "Hello"
  }
}

마지막으로 메인에 있는 server.js의 내용을 다음과 같이 바꿔줍니다.

require('dotenv').config();
import { GraphQLServer } from 'graphql-yoga';
import logger from 'morgan';
import schema from './schema';

const PORT = process.env.PORT || 4000;

const server = new GraphQLServer({ schema });
server.express.use(logger('dev'));

server.start({ port: PORT }, () =>
  console.log(`Server is running on  http://localhost:${PORT}`)
);

이제 다시 서버를 실행시켜봅시다.

yarn dev

Screen Shot 2019-08-10 at 6.49.33 PM.png

다음과 같은 내용이 나오면 성공입니다.