graphql-yoga: create-react-app 명령어랑 비슷. GraphQL 프로젝트를 빠르게 시작할 수 있음
https://github.com/prisma-labs/graphql-yoga
easy installation
1. yarn init
2. make github repository
3. git init / git remote add / git pull origin master
graphql-yoga: 쉽게 설치하는데 중점을 둔 완전한 기능을 갖춘 GraphQL 서버
4. yarn add graphql-yoga <--- that's it!
<GraphQL이 해결하는 2가지 문제>
- over-fetching: 필요 이상의 정보를 받음.
- under-fetching: 어떤 하나를 완성하기 위해 그 아래 것들을 받는 것? - url 개념이 없어서 개 쿨해
3개의 api를 요청할 필요가 없는거지.
5. yarn global add nodemon
파일 수정할 때마다 서버 재시작
index.js 만들고 콘솔 찍어보기.
package.json에 "scripts" 추가
{
"name": "191204_movieql",
"version": "1.0.0",
"description": "Movie API with Graphql",
"main": "index.js", // nodemon은 얘를 주시할거임.
"repository": "https://github.com/daheeahn/191204_movieql",
"author": "daheeahn<deg9810@likelion.org>",
"license": "MIT",
"dependencies": {
"graphql-yoga": "^1.18.3"
},
"scripts": {
"start": "nodemon"
}
}
6. yarn start 하면 index.js 바뀔 때마다 콘솔 찍힘. 서버 재시작 된다는 것!
7. 이제 서버 만들거야. Quick Start (graphql-yoga 참고)
8. yarn add babel-node --dev
babel-node 좀 더 좋은 코드 작성하게 해줌. const graphqlYoga = require 이딴거 필요x. import 같은거 쓰게 해줘
const a = require 쓰기 싫고 import 쓰고 싶어서 깔았던데.
근데 이거 말고 babel-cli를 까는거야.. 흠 나는 이거 까는데 성공했어.
9. yarn global add babel-cli 이것도 깔아야하나봐
yarn global add babel-cli --ignore-engines ?? 7번 하더니 갑자기 error나서 이걸로 다시함. 근데 나는 위에거 했더니 에러 안남
10. package-json scripts를
"scripts": {
"start": "nodemon --exec babel-node index.js"
},
이렇게 변경!
그리고 yarn start 해봐~
SyntaxError: Unexpected token 나면 잘되고 있다는 뜻.
11. 이제 .babelrc 환경을 설정할거야 파일 저 이름으로 하나 만들어
babel을 위한 모든 환경설정을 넣을 수 있어!
{ // in .babelrc
"presets": ["env", "stage-3"] // for node
}
12. yarn add babel-cli babel-preset-env babel-preset-stage-3 --dev
언어 명세 다운
그리고 yarn start~
그럼 잘될거임
서버라는 새로운 변수 만들고, 새로운 서버 만들어서 환경설정만 넣으면 됨.
서버 시작하는게 넘 쉬운거야
13. schema: 사용자에게 보내거나 받을 data에 대한 설명.
위 설정하고 yarn start하면
no schema defined라고 뜬다.
이제 배울거여!
14. 아 근데 babel 설치해야해
15. 처음 발견한 에러가 No schema defined였지?
무엇을 받을지, 무엇을 줄 지에 대한 description
16. graphql 폴더 만들어서
그 안에 schema.graphql 파일 만들게
1) Query는 정보 받을 때만 쓰임
2) Mutation(변형): 정보를 바꿀 때
이제 우리가 GraphQL 서버에 할 건, 어떤 Mutations, 어떤 Query 들을 우리가 가졌는지 알려주는거야!
17. graphql/schema.graphql
type Query {
name: String!
}
! 는 required
18. graphql/resolvers.js 만들기
const resolvers = {
Query: {
name: () => "dahee"
}
}
export default resolvers
19. 그리고 index.js에서
import { GraphQLServer } from 'graphql-yoga'
import resolvers from './graphql/resolvers' // add this code
const server = new GraphQLServer({
typeDefs: "graphql/schema.graphql", // add this code
resolvers // add this code
})
server.start(() => console.log("GraphQL Server Running"))
그리고 yarn start하면 잘 돌아가고,
20. Graphql playground
localhost:4000 가면 있음 (graphql-yoga 깃헙 참고)
database 잘 테스트 되는지 보는거. Postman과 비슷해.
query {
name
}
타입도 int인데 string으로 하면 다 잡아줌
localhost:4000/graphql 하면 종점은 playground야 근데 이건 GET인데.. 암튼 안됨
그냥 localhost:4000 해야됨
이런건 다 POST다. 개발자 도구에서 네트워크 보면 알 수 있다.
21. 타입 정의
graphql/schema.graphql
type Person {
name: String!
age: Int!
gender: String!
}
type Query {
person: Person!
}
graphql/resolvers.js
const nicolas = {
name: 'Nicloas',
age: 18,
gender: 'female'
}
const resolvers = {
Query: {
person: () => nicolas
}
}
export default resolvers
playground
query {
person {
name
gender
}
}
22. 더 복잡한 Query
graphql/schema.graphql
type Person {
id: Int!
name: String!
age: Int!
gender: String!
}
type Query {
people: [Person]!
person(id: Int!): Person // ! 안넣었어. 해당하는 person을 못찾을 수도 있거든.
}
근데 여기서 Person! 이렇게 null을 반환하지 못하도록 하면 만약에 없는 id 요청했을 때 null 반환이 아니라, 에러를 뿜겠지!
graphql/resolvers.js
import { people } from './db'
const resolvers = {
Query: {
people: () => people,
}
}
export default resolvers
graphql/db.js
export const people = [
{
id: 1,
name: 'Dahee Ahn',
age: 23,
gender: 'female'
},
{
id: 2,
name: 'Sungah Oh',
age: 24,
gender: 'female'
},
{
id: 3,
name: 'Eunju Kim',
age: 25,
gender: 'female'
},
{
id: 4,
name: 'Sukyung Choi',
age: 26,
gender: 'female'
},
]
23. 유저가 우리에게 준 id는 어떻게 받을까?
GraphQL 서버가 쿼리나 뮤테이션의 정의를 발견하면, 리솔버를 찾고, 해당 함수를 실행할거야
people: (_, {}) => people,
=
people: () => people
오~
person: (_, args) => console.log(args)
해보자.
query {
person(id:2) { // id 꼭 써줘야 함.
name
id
}
}
이렇게!
근데 graphql 저장할 땐 nodemon 작동안해서 다시 yarn start 해야되는듯?
특별한 종류의 db backend가 필요없어
24. movie로 좀 바꿀거야
어ㄷ떠한. 그 어떠한 db도 다 가져다 쓸 수 있어.
mutation의 response를 조절할 수 있는건 참 멋진일이야.
request와 함께 response를 받을 수 있어!
Boolean 반환할 때는 굳이 값을 물어보지 않아도 돼.
addMovie(name: "name", score: 1) {
name
}
왜냐? addMovie(~): Movie! 이거든.
근데 deleteMovie(id: 0) {
없어도됨.
}
그냥 deleteMovie(id: 0) 만 해도 돼~
graphql/schema.graphql
type Movie {
id: Int!
name: String!
score: Int!
}
type Query {
movies: [Movie]!
movie(id: Int!): Movie
}
type Mutation {
addMovie(name: String!, score: Int!): Movie!
deleteMovie(id: Int!): Boolean!
}
graphql/resolvers.js
import { getMoives, getById, addMovie, deleteById } from './db'
const resolvers = {
Query: {
movies: (_, {}) => getMoives(),
movie: (_, { id }) => getById(id)
},
Mutation: {
addMovie: (_, { name, score }) => addMovie(name, score),
deleteMovie: (_, { id }) => deleteById(id)
}
}
export default resolvers
graphql/db.js
export let movies = [
{
id: 1,
name: '어바웃타임',
score: 100,
},
{
id: 2,
name: '업',
score: 200,
},
{
id: 3,
name: '코코',
score: 90,
},
{
id: 4,
name: '하트시그널2',
score: 1000,
},
]
export const getMoives = () => movies
export const getById = id => {
const foundMovie = movies.find(movie => id === movie.id) // FIXME: 이거 타입스크립트로 하면 타입정의는 어디애ㅔ서 이용하는거야:
return foundMovie
}
export const deleteById = id => {
const cleanedMovies = movies.filter(movie => movie.id !== id)
if (movies.length > cleanedMovies.length) {
movies = cleanedMovies
return true // 왜 boolean을 리턴해?
} else {
return false
}
}
export const addMovie = (name, score) => {
const newMovie = {
id: `${movies.length + 1}`,
name,
score
}
movies.push(newMovie)
return newMovie
}
이 graphql server를 가지고 REST API 를 이용할 수 있어.
사용자는 playground 콘솔과 상호작용 할거야.
25.
https://yts.mx/api/v2/list_movies.json?limit=50&minimum_rating=9https://yts.mx/api/v2/list_movies.json?limit=50
이제 db.js 이거로 싹 다 고칠거여~
26. yarn add node-fetch
nodejs에서 fetch할 때 필요해
https://github.com/node-fetch/node-fetch
여기 usage 보면 res.json() 해야되는 방법 있지~ 이게 아마 내가 일하면서 배운 그 response.json()이 아닌가 싶다!
뮤테이션은 db상태 변할 때!
원하는 만큼 정의 가능!
schema에게 타입만 정해주면 ㅎㅎ
id는 필요없어. db에의해 자동생성될거니까.
27. 영화API 정리
graphql/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]!
}
graphql/resolvers.js
import { getMovies } from './db'
const resolvers = {
Query: {
movies: (_, { limit, rating }) => getMovies(limit, rating),
},
}
export default resolvers
graphql/db.js
import fetch from 'node-fetch'
const API_URL = "https://yts.mx/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)
}
-----기타------
(_, {}) 에서 _ 주목!
parent, a, root 모든게 될 수 있어. _ 그래서 _ 얘도 되는거여
nodemon: js저장할 땐 재시작, graphql 저장할 땐 작동 안함
질문을 해결하는 함수를 만든다.
mutation: db 상태가 변할 때 사용하는 것,.
nodemon 땜에 동일 포트 사용중 에러 뜰 수도 ?
'Develop > React Native' 카테고리의 다른 글
[React] 실전형 React Hooks 10개 (0) | 2020.02.05 |
---|---|
[더들어야함] React Apollo (0) | 2020.02.05 |
TDD 개발 방법론 (0) | 2019.09.14 |
react-navigation (0) | 2019.07.07 |
[React/Inflearn] 리액트 처음이시라구요? React JS로 웹 서비스 만들기! (0) | 2019.06.24 |