추후 백엔드에서 GraphQL API를 사용할지 REST API를 사용할지 아직 확정이 나지 않은 상태여서 각각의 차이에 대해 알아보고 Apollo Client 를 테스트하기 위해 간단하게 Apollo Server를 만들어보았다. Apollo Server에서 원하는 데이터를 받아오기 위해 서버를 만든 후, 임시 json 데이터를 넣어주었다.
1. 작업 폴더 생성 후 package.json setup
우선, sever만 따로 작업할 폴더를 만들어주었고, 이 안에서 npm을 사용할 수 있도록 기초적인 셋팅을 해주었다.
# 폴더생성 및 package.json setting
mkdir server
cd server
npm init -y
2. apollo-server, graphql, nodemon 설치
apollo server를 만들어주기 위해 graphql과 apollo server를 설치하고, node 서버의 코드 변경을 감지하여 변경시마다 명령을 실행시켜주는 node.js 패키지 nodemon까지 설치해주었다. nodemon을 설치하면 자바스크립트 코드의 변경 결과를 바로바로 확인할 수 있어 원하는대로 수정, 반영할 수 있다는 장점이 있다.
npm i @apollo/server graphql
npm i nodemon -D
3. Server.js 파일 생성 및 package.json 수정
Server.js 파일 생성 후, apollo server 공식 문서에서 확인한 스크립트를 복붙해준다. 우선 간단하게 실행이 되는지만 테스트를 해보려고 공식문서에 있는 것을 그대로 가져왔는데, books라는 배열 데이터를 임시로 넣어주었다. 기본적으로 Apollo server 는 typeDefs와 resolvers를 인자로 전달받아 생성되는데, 각각이 의미하는 것은 아래와 같다.
typeDefs
- 자료요청에 사용될 쿼리들을 정의해놓은 곳
- 쿼리 명령문마다 반환될 데이터 형태를 지정해놓음
resolvers
- resolver안에는 Query, Mutation 등이 들어가는데 Query는 object의 항목들로 데이터를 반환하는 함수를 선언한다. 실제 프로젝트에서 보통 데이터를 조회하는 용으로 사용된다.
- Mutation은 삭제, 수정, 추가 등의 요청을 할 때 사용된다.
// server.js 기본 셋팅
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
// 임시 데이터
const books = [
{
title: 'The Awakening',
author: 'Kate Chopin',
},
{
title: 'City of Glass',
author: 'Paul Auster',
},
];
// Schema
const typeDefs = `#graphql
type Book {
title: String
author: String
}
type Query {
books: [Book]
}
`;
// 데이터 반환 함수
const resolvers = {
Query: {
books: () => books,
},
};
// server 생성
const server = new ApolloServer({
typeDefs,
resolvers,
});
const { url } = await startStandaloneServer(server, {
listen: { port: 4000 },
});
console.log(`🚀 Server ready at: ${url}`);
// package.json 파일 수정
"scripts": {
"dev": "nodemon server.js"
},
"type": "module"
4. Server 실행 및 데이터 확인
package.json의 scripts 부분을 nodemon server.js로 수정해주었기 때문에 아래와 같이 npm run dev를 실행하면 노드몬으로 스크립트 파일이 실행된다. 정상적으로 실행이 되었다면 아래와 같이 console에 local 주소가 찍힐 것이다. 나는 포트 번호를 4000으로 해주었기 때문에 localhost:4000으로 서버를 실행시켰다. 이 부분은 알아서 설정 가능!
$ npm run dev
> server@1.0.0 dev
> nodemon server.js
[nodemon] 2.0.20
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node server.js`
🚀 Server ready at: http://localhost:4000/
기본적으로 Apollo Server가 제데로 실행된건지 확인하기 위해 playground를 열어서 query를 날려보았다. 내가 띄운 로컬 서버 주소로 접속하면 playground가 잘 실행되는 것을 확인할 수 있다. 이 창을 열어 query를 날렸을 때 응답이 제대로 오는지를 확인해볼 수 있다.
Apollo Server에 쿼리를 날릴때는 클라이언트 쪽에서 필요한 데이터를 직접 뽑아올 수 있다고 한다. 그래서 임시로 만들어주었던 books라는 배열 안에서 필요한 데이터 요청을 어떻게 하면 되는지를 알아보았다.
// book data
const books = [
{
title: 'The Awakening',
author: 'Kate Chopin',
},
{
title: 'City of Glass',
author: 'Paul Auster',
},
];
먼저 안에 들어있는 데이터를 다 받아오고 싶어 books 안에 있는 title과 author을 모두 요청했다. 그 결과 아래와 같이 json 데이터가 넘어온 것을 볼 수 있었다.
// request
query ExampleQuery {
books {
title
author
}
}
// response
{
"data": {
"books": [
{
"title": "The Awakening",
"author": "Kate Chopin"
},
{
"title": "City of Glass",
"author": "Paul Auster"
}
]
}
}
두번째로는 books 안에있는 title값만 불러올 수 있도록 query를 날려보았다. 내가 딱 요청한 것만 담아 보내주니 신기했다. axios로 요청을 보내는 것이 아니라 query를 날려 데이터를 요청하는 것 또한 처음 해본 것이었는데 REST API와는 다르게 하나의 endpoint에 내가 원하는 데이터를 요청할 수 있어 편했다.
// request
query ExampleQuery {
books {
title
}
}
// response
{
"data": {
"books": [
{
"title": "The Awakening"
},
{
"title": "City of Glass"
}
]
}
}