GraphQL + NodeJS 연습!

주형(Jureamer)·2022년 4월 15일
0
post-thumbnail

REST API와 비교가 많이 되는 GraphQL을 Node 위에서 연습 해보았다.

GraphQL을 사용하는 이유는 여러 가지가 있는데, 그 중에서도

Over Fetching(데이터를 필요 이상으로 많이 받는 것)과 Under Fetching(필요한 데이터를 받기 위해 1번 이상의 통신)이 주된 이유다.

GraphQL로는 원하는 데이터만 받을 수 있기에 위의 문제를 해결할 수 있고 그 외 장점과 단점도 물론 존재한다.

이 부분은 따로 포스팅을 해 볼 예정이다.

기본 설정

준비물은 기본 프로젝트에 먼저 graphql-yoga를 받아보자! (graphql 쉽게 셋업하게 해주는 패키지)

npm i graphql-yoga

그리고 노드 환경에서 ES6 문법을 위해 babel을 설치하고 package.json을 세팅 해준다.

npm i @babel/cli babel/core babel/node babel/preset-env -dev

--package.json--
"scripts": {
    "start": "nodemon --exec babel-node index.js"
  },

서버 생성

Query는 서버 또는 DB에서 값을 가져오는 REST API에서 GET의 기능을 한다.
typeDefs는 schema의 명세 기능을 담당하고
resolver는 데이터를 가져오기 위한 함수 기능을 담당한다.

import { createServer } from "@graphql-yoga/node";
const server = createServer({
  schema: {
    typeDefs: `
      type Query {
		greeting: String!
	  }	
    `,
    resolvers: {
      Query: {
        greeting: () => "Hello"
      }
    }
  }
})
server.start(() => console.log("GraphQL Server Start"))

Yoga를 사용하면 GraphiQL(PlayGround)이라는 곳에서 API를 테스트하고 확인할 수 있어서 매우 간편하다.

배열 생성 및 출력

schema, resolver 등의 기능을 별도의 파일로 분리하는 것이 유지보수 차원에서 좋다.

[db.js]

export const movies = [
  {
    id: 1,
    title: "Star Wars",
    rating: 8.5
  },
  {
    id: 2,
    title: "Avengers",
    rating: 9.3
  },
  {
    id: 3,
    title: "Lottos",
    rating: 7.0
  },
  {
    id: 4,
    title: "The Wars",
    rating: 6.4
  },
  {
    id: 5,
    title: "Bank",
    rating: 5.6
  },
]

Mutation은 서버, DB를 통해 데이터를 변경시키는 작업을 하며 REST API에서 Post, Update 등의 기능과 매칭된다.

import { createServer } from "@graphql-yoga/node";
import { movies } from "./graphql/db.js";
const server = createServer({
  schema: {
    typeDefs: `
      type Query {
        getMovies: [Movie]!,
        search(id: Int!): Movie
      }
	// schema Type 지정
      type Movie {
        id: Int!
        title: String!
        rating: Int!
      }
      type Mutation {
        addMovie(title: String!, rating: Float!): Boolean
      }
    `,
    resolvers: {
      Query: {
        getMovies: () => movies,
        search: (_, { id }) => movies.find((movie) => movie.id === id),
      },
      Mutation: {
        addMovie: (_, {title, rating}) => {
          const newMovie = {
            id: movies.length + 1,
            title,
            rating
          }
          const beforeLength = movies.length;
          movies.push(newMovie);
          const afterLength = movies.length
          if (beforeLength < afterLength) {
            return true
          } else {
            return false
          }
        },
      }
    }
  }
})

server.start(() => console.log("GraphQL Server Start"))

Resolver 함수의 경우 function(obj, args, context, info) {} 형태로, 두번 째 파라미터인 args는 인자 전달을 위해 사용하지만 예제처럼 사용하지 않을 때는 _로 명시하는 것이 좋다!

그럼 GraphiQL에서 정상작동 확인하자!

// 실행
mutation {
  addMovie(title: "Forest Gump",rating: 9.52)
}

// 결과

{
  "data": {
    "addMovie": true
  }
}
// 실행 
query {
  getMovies {
    id
    title
  }
}

// 결과
{
  "data": {
    "getMovies": [
      {
        "id": 1,
        "title": "Star Wars"
      },
      {
        "id": 2,
        "title": "Avengers"
      },
      {
        "id": 3,
        "title": "Lottos"
      },
      {
        "id": 4,
        "title": "The Wars"
      },
      {
        "id": 5,
        "title": "Bank"
      },
      {
        "id": 6,
        "title": "New Movie"
      },
      {
        "id": 7,
        "title": "Forest Gump"
      }
    ]
  }
}

잘 나온다!

다음엔 NestJS + TypeORM에 적용 시켜봐야겠다.

Reference

profile
작게라도 꾸준히 성장하는게 목표입니다.

0개의 댓글