graphql/graphql+nodejs(노마드코더)

기초적인 graphql과 nodesjs 다루기

김마드 2020. 2. 28. 18:23

#1 설치

 

1. 프로젝트 폴더 하나 생성후 npm init 입력 (관련 정보들 입력)

2. npm install graphql-yoga 설치

 

#2 Problems solved by GraphQL

 

1. 기존 restAPI의 단점은 over-fetching과 under-fetching 이 있었다. 하지만 graphql에서는 필요한 정보만 백엔드서버에서(DB)에서 요청 하여 가지고 올 수 있다. 좋네~!

 

#3 Creating a GraphQL Server with GraphQL Yoga

 

1. npm install -g nodemon 설치 (파일을 수정 및 저장 할 때마다, 서버를 재시작하게 해줌 // index.js를 확인함)

2. npm install -g babel-cli 설치(Babel은 ES6/ES7 코드를 ES5 코드로 변환해주는 도구이다. ES6/ES7으로 개발하기 위해서 babel-cli를 설치한다.)

3. npm install babel-preset-env babel-preset-stage-3 --dev (바벨에 필요한 추가 모듈 설치)

4. package.json 부분에 아래 내용 추가

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

5. index.js 에 아래 내용 추가. 여기서 npm start를 하면 아직은 scheme가 없다고 출력 될 것이다. 

import { GraphQLServer } from "graphql-yoga";

const server = new GraphQLServer({});

server.start(() => console.log("Graphql Server Running"));

 

#4 Creating the first Query and Resolver ~  #5 Extending the Schema

Query에 대한 type을 정의해 주어야 한다. graphql(신규 생성) / schema.graphql 파일 생성 후 그 안에

아래와 같이 입력하자. name은 요청 값이고, 응답값 유형은 string이다. 이 때 ! 는 필수값(required)이라는 의미이다.

type Query {
    name: String!
}

 그리고, graphql/resolvers.js 파일 생성 후, 아래와 같이 입력하자. 이때 name 값은 위 Query에 정의한 이름과 같아야 한다.

const resolvers = {
  Query: {
    name: () => "JeHyung"
  }
};

export default resolvers;

 그 후, index.js파일에 아래와 같이 내용을 추가해주자. 아래 내용을 모두 입력 후 npm start를 하면 localhost:4000에 접속 할 수 있고, graphql-yoga 모듈에서 제공해주는 Graphql Playground화면이 뜬다.

import { GraphQLServer } from "graphql-yoga";
import resolvers from "./graphql/resolvers";

const server = new GraphQLServer({
  typeDefs: "graphql/schema.graphql",
  resolvers
});

server.start(() => console.log("Graphql Server Running"));

 query{

    name

이와 같이 요청하면 resolvers에 정의한 내용이 출력된다.

 

-Graphql Playground화면

이를 함수를 활용하여 아래와 같이 할 수 있다.

 

schema.graphql파일

 

person값에 Victor라는 값을 연동시켜, 해당 객체의 값을 가지고 올 수 있다. (코드 재활용성 및 가독성 증가) 

type Victor {
  name: String!
  age: Int!
  gender: String!
}

type Query {
  person: Victor!
}

 

resolvers.js파일

 

위 schema.graphql 파일과 마찬가지로, bangviet이라는 함수에 구체적인 값 명시 (나중에 이 값들이 db에 들어갈듯 하다?)

const bangviet = {
  name: "jehyung",
  age: 20,
  gender: "female"
};

const resolvers = {
  Query: {
    person: () => bangviet
  }
};

export default resolvers;

 # 전체 코드 분석

schema에서는 각 필드 데이터의 유형을 정해놓은 곳이다.

 

Mutaion은 database의 값을 변경될 때 쓰는 단어이다. (추가,삭제 등)

인자 값도 참고

 

-schema.graphql

type Movie {
  id: Int!
  name: String!
  score: Int!
}

type Query {
  movies: [Movie]!
  movie(id: Int!): Movie
}

type Mutation {
  addMovie(score: Int!, name: String!): Movie!
  deleteMovie(id: Int!): Boolean!
}

 

앞 서, schema에서 정의한 내용을 실행하는 부분이다. db에 어떤 인자를 넘겨 해당 db의 data들을 다양한 방법으로 가지고 올 수 있는 단계.

 

-resolvers.js

import { getMovies, getById, addMovie, deleteMovie } from "./db";

const resolvers = {
  Query: {
    movies: () => getMovies(),
    movie: (_, { id }) => getById(id)
  },
  Mutation: {
    addMovie: (_, { name, score }) => addMovie(name, score),
    deleteMovie: (_, { id }) => deleteMovie(id)
  }
};

export default resolvers;

 

db.js에는 크게 1)db 고유 데이터 2)resolvers에서 받아온 인자를 활용하여, db 고유 데이터를 어떤식으로 활용할지에 대한 구체적 함수가 포함 되어 있다. 구체적인 내용들은 아래 코드를 보면 쉽게 이해 할 수 있다.

 

-db.js

let movies = [
  {
    id: 0,
    name: "Star Wars - The new one",
    score: 1
  },
  {
    id: 1,
    name: "Avengers - The new one",
    score: 8
  },
  {
    id: 2,
    name: "The Godfather I",
    score: 99
  },
  {
    id: 3,
    name: "Logan",
    score: 2
  }
];

export const getMovies = () => movies;

export const getById = id => {
  const filteredMovies = movies.filter(movie => movie.id === id);
  return filteredMovies[0];
};

export const deleteMovie = id => {
  const cleanedMovies = movies.filter(movie => movie.id !== id);
  if (movies.length > cleanedMovies.length) {
    movies = cleanedMovies;
    return true;
  } else {
    return false;
  }
};

export const addMovie = (name, score) => {
  const newMovie = {
    id: `${movies.length + 1}`,
    name,
    score
  };
  movies.push(newMovie);
  return newMovie;
}

 

 # REST API와의 통합

 1. npm install node-fetch 설치 (axios의 fetch 기능과 동일함)

 

2. 기존 yts라는 곳에서 제공하는 rest api 데이터를 가지고와 어떻게 graphql에서 사용 할 수 있는지 보자.

 

 

 

-db.js

아래 내용을 보면, fetch를 사용하였지만, 향 후 axios로 다시 재설정 할 예정이다. 눈으로 그 흐름을 따라가 보자.

import fetch from "node-fetch";

const API_URL = "https://yts.am/api/v2/list_movies.json?";

export const getMovies = (limit, rating) => {
  let REQUEST_URL = API_URL;
  if (limit > 0) {
    REQUEST_URL += `limit=${limit}`;
  }
  if (rating > 0) {
    REQUEST_URL += `&minimum_rating=${rating}`;
  }
  return fetch(REQUEST_URL)
    .then(res => res.json())
    .then(json => json.data.movies);
};

 

 

-resolvers.js

import { getMovies } from "./db";

const resolvers = {
  Query: {
    movies: (_, { limit, rating }) => getMovies(limit, rating)
  }
};

export default resolvers;

 

-schema.graphql

type Movie {
  id: Int!
  title: String!
  rating: Float!
  summary: String!
  language: String!
  medium_cover_image: String!
}

type Query {
  movies(limit: Int, rating: Float): [Movie]!
}