GraphQL

Graph QL

graphQL

GraphQL 영상출처

이 예제에서는 영화관 API를 Graph QL을 가지고 만드는 예제이다.

여기서는 graphql- yoga 를 사용하여 더 쉽게 Graph QL을 사용하였다.

Graphql을 사용하면 기존의 Rest API를 사용하던 단점인 Over-fetching, Under-fetching을 극복할 수 있다.

Over-fetching

내가 요청한 영역의 정보보다, 많은 정보를 서버에서 받는 경우.

  • Rest API는 값을 불러올때 전체의 값을 불러온 후 골라서 사용하였다면 Graphql은 원하는 값들만 골라서 가져올 수 있다.
1
2
// Rest API
/users/1/GET
1
2
3
4
5
6
7
8
// Graph QL
query {
users {
name
age
}
}

Under-fetching

하나를 완성하려고 많은 소스를 요청하는 경우이다.

  • 여러 혼합된 정보가 필요하면 여러개의 API를 조합해서 가져와야했지만 Graphql은 아니다.
1
2
3
4
5
// Rest API

/feed/
/noti/
/users/1/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Graph QL
query{
feed {
comments
likeNumber
}
noti {
isRead
}
user {
username
profilePic
}
}

내가 접근한 GraphQL 구현방법.

schema.graphql에 Query, Mutation을 구현하고 이 파일을 index.js typeDefs에 연결을 한다.
그 다음 db.js 에서 원하는 값을 만들고 원하는 동작을 resolver.js에 정의한 후 함수로 생성한다.
resolver.js에 구현할때 함수명은 schema.graphql에서 정의한 명으로 사용하고 각각의 함수들을 db.js에서 구현한 함수들을 통하여 구현한다.

정보를 조회할경우 Query를 정보의 변경시 Mutation을 사용한다.

schema.graphql

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# url 이라고 생각하면 편하다.
type Movie {
id: Int!
name: String!
score: Int!
}

type Query {
# 왼쪽은 이름, 오른쪽은 return할 값.
movies: [Movie]!
movie(id: Int!): Movie
}

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

index.js

1
2
3
4
5
6
7
8
9
10
11
import { GraphQLServer } from "graphql-yoga";
import resolvers from "./qraphql/resolver"

const server = new GraphQLServer({
typeDefs: "qraphql/schema.graphql",
resolvers
// resolvers: resolvers 로도 표현이 가능하지만
// 최신 자바스크립트는 resolvers 만 써도 같은 의미이다.
})

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

db.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
let movies = [
{
id: 0,
name: "해리포터",
score: 99
},
{
id: 1,
name: "어벤져스",
score: 4
},
{
id: 2,
name: "목격자",
score: 8
},
{
id: 3,
name: "웜바디스",
score: 100
}
];

export const getMovies = () => movies;

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

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

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


resolver.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

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

// resolvers는 함수로 구현한다.
const resolvers = {
Query: {
movies: () => getMovies(),
movie: (_, { id }) => getById(id)
},
Mutation: {
addMovie: (_, {name, score}) => addMovie(name, score),
deleteMovie: (_, { id }) => deleteMovie(id)
}
};

export default resolvers;

Share