GraphQL + Node Express + Apollo Server 구현

Jeongkuk Seo
sjk5766
Published in
9 min readMay 29, 2019

처음에 GraphQL을 접한 뒤, 음.. facebook에서 만들었고,, REST와는 다른 방법론이고 음.. 그래.. Schema를 정의하고, Query와 Resolver를 만들고..그런데 구현을 어떻게 하지? 라는 의문을 해결하기 위해 한참을 검색했네요.

GraphQL 튜토리얼 사이트에서 제공하는 방법대로 하나하나 쫓아가도록 하겠습니다. 우선 Node는 설치가 되어 있다는 가정하에 작업을 수행할 디렉토리를 생성합니다. 제 경우 GraphQL 디렉토리를 생성했습니다. 그 다음 package.json 파일에 다음과 같은 데이터를 저장합니다.

{
"name": "graphql",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "nodemon --ignore data/ server.js"
},

"dependencies": {
"apollo-server-express": "^1.4.0",
"body-parser": "^1.18.3",
"cors": "^2.8.4",
"express": "^4.16.3",
"graphql": "^0.13.2",
"graphql-tools": "^3.1.1",
"notarealdb": "^0.2.2"
},

"devDependencies": {
"nodemon": "1.17.1"
}
}

그 다음 npm install 명령어로 필요한 모듈을 설치합니다.

npm install

data 디렉토리를 만들고 내부에 students.json과 colleges.json 파일을 생성합니다. 두 파일에 저장된 데이터는 DB에서 불러온 데이터 역할을 하게 됩니다. colleges.json 파일의 내용은 아래와 같습니다.

[
{
"id": "col-101",
"name": "AMU",
"location": "Uttar Pradesh",
"rating":5.0
},

{
"id": "col-102",
"name": "CUSAT",
"location": "Kerala",
"rating":4.5
}
]

students.json 파일의 내용은 아래와 같습니다.

[
{
"id": "S1001",
"firstName":"Mohtashim",
"lastName":"Mohammad",
"email": "mohtashim.mohammad@tutorialpoint.org",
"password": "pass123",
"collegeId": "col-102"
},
{
"id": "S1002",
"email": "kannan.sudhakaran@tutorialpoint.org",
"firstName":"Kannan",
"lastName":"Sudhakaran",
"password": "pass123",
"collegeId": "col-101"
},
{
"id": "S1003",
"email": "kiran.panigrahi@tutorialpoint.org",
"firstName":"Kiran",
"lastName":"Panigrahi",
"password": "pass123",
"collegeId": "col-101"
}
]

data 디렉토리와 동일한 레벨로 나온 후, json 데이터를 처리 할 db.js 파일을 만듭니다.

const { DataStore } = require('notarealdb');

const store = new DataStore('./data');

module.exports = {
students:store.collection('students'),
colleges:store.collection('colleges')
};

Schema를 정의하기 위해 schema.graphql 파일에 다음 내용을 입력합니다.

type Query  {
test: String
}

resolver.js 파일을 만들어 아래 내용을 입력합니다. GraphQL로 test라는 쿼리가 들어올 경우, Test Success, GraphQL server is up & running !! 이라는 문자열이 응답갈 것을 예상해 볼 수 있습니다.

const Query = {
test: () => 'Test Success, GraphQL server is up & running !!'
}
module.exports = {Query}

최종적으로 서버를 띄울 server.js 를 만듭니다.

const bodyParser = require('body-parser');
const express = require('express');
const db = require('./db');

const port = process.env.PORT || 9000;
const app = express();

const fs = require('fs')
const typeDefs = fs.readFileSync('./schema.graphql',{encoding:'utf-8'})
const resolvers = require('./resolvers')
// schema와 resolver를 makeExecutableSchema 함수의 인자로 전달한다.
const {makeExecutableSchema} = require('graphql-tools')
const schema = makeExecutableSchema({typeDefs, resolvers})

app.use(bodyParser.json());
// apollo server express의 모듈을 각 API에 맵핑.
const {graphiqlExpress,graphqlExpress} = require('apollo-server-express')
app.use('/graphql',graphqlExpress({schema}))
app.use('/graphiql',graphiqlExpress({endpointURL:'/graphql'}))

app.listen(
port, () => console.info(
`Server started on port ${port}`
)
);

위에까지 정상적으로 했을 떄 디렉토리 구조는 아래와 같습니다.

├── data
│ ├── colleges.json
│ └── students.json
├── db.js
├── node_modules
├── package.json
├── package-lock.json
├── resolvers.js
├── schema.graphql
└── server.js

port를 9000번으로 listen 하였기 때문에 npm start 명령 후, 9000번으로 접속해보면 아래와 같은 화면을 확인 할 수 있습니다. 9000 포트에 graphiql을 잊지말고 전달해야 확인할 수 있습니다.

위에서 test 쿼리가 들어왔을 때, 고정된 문자열을 전달하도록 우리가 schema와 resolver를 정의 했습니다. 그렇다면 위에서 students.json에 저장해 놓은 데이터를 전달하도록 조금 소스를 변경하겠습니다.

우리가 추가하려는 작업은 GraphQL에 student가 들어왔을 때 필요한 컬럼에 맞는 데이터를 응답하려는 것입니다. 우선 schema.graphql 파일을 다음과 같이 변경합니다.

type Query {
test: String
student: [Student]
}
type Student {
id: String
firstName: String
lastName: String
email: String
password: String
collegeId: String
}

Student 라는 스키마가 추가되었고, 각 컬럼에 대한 type이 정의되어 있습니다. Query 에는 student에 대한 타입으로 Student 타입을 리스트로 정의했습니다. 이제 Schema가 끝났으니 resolver.js 파일을 다음과 같이 수정합니다.

const { students, colleges } = require(‘./db’);const Query = {
test: () => ‘Test Success, GraphQL server is up & running !!’,
student: () => students.list()
}
module.exports = {Query}

resolver.js에서 Query로 student가 들어올 경우, db.js로 부터 import 받은 students를 list 형태로 응답할 것을 명시하고 있습니다. 이 상태로 저장한 뒤 다시 서버를 동작시키면 아래와 같이 응답이 오는 것을 확인할 수 있습니다.

추가적인 컬럼을 요청할 경우

이제 위 상태에서 Mutation 작업과, 실제 DB로 바꿔 보는 등의 작업을 수행하면서 GraphQL을 더 탐구해 보도록 하겠습니다.

참고 사이트

https://www.tutorialspoint.com/graphql/graphql_example.htm

--

--