기초적인 graphql과 nodesjs 다루기
#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]!
}