본문 바로가기

모카 스터디/React

GraphQL로 영화 API 만들기

#1 [2022 UPDATE] INTRODUCTION

#1.0 Welcome (01:20)

이번 수업에서는, GraphQL이 뭔지 배워볼거야.
GraphQL이 왜 이렇게 멋진지 알아볼거고, GraphQL이 어떻게 동작하는지 알아볼거야.
그리고 우리는 GraphQL api를 어떻게 직접 만들 수 있는지 알아볼거야.
그리고 우리는 GraphQL의 어떤점이 특별한지를 이해해볼거야.
예를 들면, 깃헙 같은 기업들은 그들의 api를 만드는데 rest보다 GraphQL을 왜 선택했는지.

이 수업이 끝날 때 쯤엔, 우리는 GraphQL위에 구축된 혁신을 보게 될 거야.
우리는 예를들면 PostGraphile 같은 것들을 보게 될거야.
이건 아주아주 멋진 아이야. 얘는 GraphQL api를 얻을 수 있어.

postgres 데이터베이스를 갖고 있는 것 만으로도 말이야. 엄청 멋지지.
그리고 우리는 HASURA라는 아이도 봐볼거야.
HASURA는 너의 데이터베이스에서 즉각적으로 GraphQL api를 무료로 만들어주지.

 

#1.1 Requirements (02:17)

 

좋아 모두들, 그럼 이 수업은 누가 들으면 좋을까?
이 수업은 전에 한번 이상은 api를 설계해본 적이 있는 개발자가 들으면 좋아.
이전에 API를 구현하거나 설계한 적이 있다면 말야. rest api나 xml api 같은것들.

또는, 만약 너가 프론트엔드 개발자면, 그리고 백엔드에서 rest api로 개발해본적이 있다면.
그러면 넌 이번 수업에서 얻어가는 것들이 많을거야.
왜냐면 결국 너가 프론트엔드 개발자로서 사용하는 api가 GraphQL api로 변경될 수 있기 때문이야.

최신 용어가 무엇인지 알고 싶고, 그리고 REST api와 GraphQL api의 차이를 알고싶고, 
왜 깃헙은 GraphQL 을 그렇게 좋아하는지 알고싶다면,


GraphQL 이라는 언어 자체는, 그니까 쿼리언어는 똑같으니까.
그래서 오늘 너가 알게 될 모든 지식이나 오늘 배울 모든 것은  전혀 문제 없어. 너가 어떤 언어를 사용하든지말야.

 

#1.2 Software Requirements (02:05)

이번 수업은 파트별로 주제를 나눠볼거야.
첫 번째 파트로는, 우리는 많은 이론을 일단 먼저 해볼거야.

우리는 GraphQL과 rest API 를 비교해볼 거야. 그러기 위해선 우리는 rest API 가 무엇인지 다시 짚어봐야해.
API가 무슨 뜻인지도 다시 볼거고,왜 API 가 필요한건지.. 등등 그런 것들을 다시 봐볼거야.

우리는 GraphQL 언어를 살펴볼거야. GraphQL API 를 어떻게 사용할 수 있는지를 알아볼거야.

우리는 순서를 바꿔서 해볼거야.
보통, 사람들은 API 설계를 시작하고 그리고 API 구현이 끝났을 때, API 를 테스트하지.

우리는 거꾸로 할거야.

좋아, 우리는 GraphQL API 를 경험해볼거고,  사용했던 rest라는 것과 얼마나 다른지 봐볼거야.
알겠지? 그리고 GraphQL API 를 사용하는게 조금 편해지고, 그리고 GraphQL API 의 이점을 알게된 후에,
코딩하는 부분으로 넘어가도록 할게.

그래서 이 수업의 두번째 파트에서는, API 를 만들어보는거야!

GraphQL API 를 처음부터 구축해보는거야.

 

첫번째 파트에서는, 
브라우저만 깔려있으면 돼. 크롬이나 마이크로소프트 엣지, 네이버 웨일.. 너가 설치한 브라우저면 돼.


두번째 파트에서는, 컴퓨터에 vscode가 깔려있으면 돼.

API가 뭔지.
REST API가 무슨 의미인지 말야.
그리고 제일 중요한건, 왜 우리가 API 를 필요로 하는지도 말야.
그리고 API 가 무슨 일을 하는지도 볼거야.

#2 [2022 UPDATE] BEFORE GRAPHQ

#2.0 What is an API? (07:14)

일단 api가 대체 무슨 뜻일까? api는 Application Programming Interface라고 하지.

API가 REST api나 Graphql api만을 의미하는 api가 아니라는걸 이해하는데에 초점을 둬야해.
Web api 또한 있어. 브라우저 api도 있지. 또한, 트위터도 api가 있고, 아마존도 api가 있지.

api가 무엇인지 이해해야하는 이유는 graphql api와 REST api보다 더 광범위하기 때문이야
자 Interface라는 단어에 먼저 집중해보자.
좋 아. Interface는 너가 무언가와 상호작용하는 방식을 의미해.

예를 들면, 너의 텔레비전.
인터페이스를 가지고 있지.
텔레비전을 꺼주도록 해주는 버튼이 있잖아
그 버튼이 너가 텔레비전과 상호작용을 할 수 있도록 해주는 인터페이스야.

웹사이트도, 사용자 인터페이스를 가지고 있지. 
그건 사용자가 너의 웹사이트와 상호작용할 때 사용하는 거잖아.
인터페이스는 기본적으로 사용자에게 노출되어있는 버튼이고, 
그걸 통해 우리 어플리케이션이나 전자기기 등 무엇이든지 상호작용할 수 있지.

#2.1 What is REST? (09:34)

REST api 나 graphql api는 대체 무엇을 위해 사용되는지 말야.
정답은 의사소통을 하기 위해서야. 매우 간단하지.
너도 백엔드와 통신하고 싶을 때가 있을거야.

자, REST api와 Graphql api의 차이점은 이 버튼들이 어떻게 노출되어있는지에 있어.

REST의 경우는, 서로 다른 서버간의 통신이나 IOS 어플리케이션이 서버와 통신할 때
REST api를 사용한다면 그 통신은 URL로 이루어져.


만약 내가 REST api를 사용한다면, 이런식이 될거야. nomadmovies.co/movies 이런식으로 말야.
나는 이런 URL로 request를 만들거야. 이 URL은 JSON 배열을 줄거야.
이게 바로 REST API야.

리소스나 리소스 목록을 얻을 때, 이런 URL을 사용해. 이 경우엔 영화가 리소스고.
하지만 그러려면, nomadmovies 웹사이트가 이 URL을 공개적으로 노출시켜줘야겠지.
nomadmovies 웹사이트는 사람들이 이 URL을 요청하는 것을 허용시켜줘야해.

내가 보고싶은 어떤 영화가 있고, 그 영화에 대해 좀 더 자세히 찾아보고 싶다고 하자.
그러면 nomadmovies.co/api/movies/1 으로 접근할 수 있지.
알겠지? 그러면 api가 나에게 movieId가 1인 리소스를 줄거야.

또 내가 사람들에게 영화를 검색할 수 있도록 할거면, URL을 만들어서 노출시킬거야.
/api/search 라고 불리는 URL을 말야.

 그러면 사람들은 'rating=9' (평점이 9점인) 이런 것들을 붙여서 보낼 수 있어.
자, 내가 이 URL을 노출시키면, 내 백엔드에서는 이 부분을 보고, 영화를 필터링할거야.

이게 REST api에 대한 버튼들이 생긴 모습이고, 보다시피 버튼들은 그냥 URL이야.
그게 REST이고, 많은 사람들은 REST를 좋아하지. 왜냐면 조직화되어있고, 이해하기 쉽거든.
또 REST api를 이용한 작업은 정말 간단하고, 전세계의 거의 모든 디바이스들이 URL로 요청을 보낼 수 있어
URL을 요청하고, data를 받아오기만 하면 돼. 아주 간단하지.

브라우저도 이 api를 호출할 수 있어. IOS앱도, 안드로이드앱도 이 api를 호출 할 수 있어.
Reactjs도 이 api를 부를 수 있고, 일반 javascript도 부를 수 있어.



다음 영상에서는 HTTP를 사용하여 의도를 전달하는 방법을 볼거야.
예를 들어서, 난 영화를 받아오는게 아니라, 영화를 추가하고 싶어.영화를 삭제하고 싶어.영화를 업데이트하고) 싶어. 거야.

지금은 이것만 기억해. REST api와 Graphql api의 차이점은  이 둘은 둘 다 리모콘이지만, 버튼들이 생긴게 다른 것 뿐이야.

그리고 REST api의 버튼들을 누르는 방법은, 특정 URL로 요청하는 것이라는걸 배웠지.
이 URL들은 서버에 의해 노출되어있지.URL로 가서, 너가 원하는걸 찾아보면 돼.

 

 

#2.2 REST + HTTP (08:24)

이전 영상에서 REST api는 그저 버튼의 모양이 URL인 api라는 것을 보았어.
자, 이전 영상에서는 우리가 가진건 URL이라는 걸 봤을거야.

하지만 그렇다고 이 URL만으로 API의 모든걸 해야하는 건 아니야.
예를 들면, 새로운 영화를 만들고 싶다고하면, 너는 아마도 이렇게 생각할거야.
/movies/create
하지만 사실, API에 동사를 넣는 것은 좋은 방법이 아니야.

그 이유는, 어떤 사람들한테는 /movies/create으로 접근하는 것이 말이 된다고 느낄 수 있지만,
다른 사람들은 create를 사용하지 않을 수도 있어. add라는 동사를 쓸 수도 있어.
또다른 사람들은 upload라는 동사를 사용할 수도 있지.

그래서 항상 문서를 살펴봐야 하는 경우에는 REST API로 작업하기가 쉽지않아.
너는 그들이 어떤 단어를 쓰는지 찾아봐야겠지.


우리가 하는 일은 HTTP 메소드에 의존하는 거야.
알다시피, 너가 웹사이트에 요청을 보낼 때 너의 브라우저는 항상 get 요청을 보내. 
너가 nomadcoders.co를 입력하고 엔터를 치면, 너의 브라우저는 nomadcoders.co URL로 get 요청을 보내.

자동적으로 get 요청을 보내지.get 뜻은, 나에게 주다(give)라는 의미야.

너가 데이터를 보내고 싶을 때에는, 또는 form을 보내고 싶을 때에는, 우리는 POST라고 불리는 HTTP 메소드를 사용해.

사람들은 HTTP 메소드를 만들지 못해.
우리는 POST를 create, add, upload 등의 단어로 바꾸지 못해.
 못해. 우리는 HTTP의 표준 명세를 가지고 있고, 거기에 메소드 중 get, post가 있는거야.

delete, update, patch도 있고.

핵심은 '메소드 + URL'이 API가 더 많은 일을 할 수 있도록 해준다는 거야!

그저 데이터를 줘! 줘! 줘! 라고 하는게 아니라,여기서 우리가 하고 있는 일이지.

우리는 데이터를 받고만있어.나에게 모든 영화들을 줘.

나에게 id가 1인 영화를 줘. 평점이 9점 이상인 영화를 나에게 줘, 알겠지?

여기서 너가 어떤 메소드를 사용하는지에 따라서,
백엔드 서버는 다른 일을 할거야. 너가 어떤 메소드를 사용하는지에 따라서말야.

 

이게 HTTP 메소드의 힘이야.
예를 들어, 이 URL로 너가 GET 요청을 보낸다면 너는 니꼬가 만든 모든 bookmarks를 받아오게 되겠지.
알겠지? 그런데 너가 이 URL로 POST 요청을 보내게되면,  너는 새로운 북마크를 만들게 될거야.
 
그냥 URL과 HTTP 메소드를 조합하면 되는거야. 넌 어떤 일이 일어날 지도 알 수 있고.
예를 들어, 우리가 api를 만들고있다면 이 URL의 GET 요청에는 모든 영화를 줄 수 있겠지
하지만 만약 POST 요청을 한다면 영화를 생성하게 될 거야.


URL에 동사를 넣지않는 등 좋은 관행을 따른 API 라면 말이야.
명사만 넣는다는거, 아주 기억하기 쉽지?
그리고, 너가 어떤 일을 할 것인지, 동사를 쓸 때에는, HTTP 메소드를 사용하는 거지.
POST, PUT, DELETE, GET.. HTTP 메소드는 더 있지만, 얘네들이 메인이야.

무언가를 만들고 싶다면, POST를 사용하면돼.
정보를 받아오고 싶다면, GET을 사용하면 되고.
무언가를 업데이트하고 싶다면, PUT을 사용하면되고.
무언가를 삭제하고 싶다면 DELETE 쓰고.

#3 [2022 UPDATE] WELCOME TO GRAPHQL

#3.0 What is GraphQL? (03:56)

 


graphql은 무엇이고 graphql의 이점은 무엇인지에 대해 배워볼거야
graphql은 누가 쓰는거고 누가 만들었고 왜 쓰는걸까?

우리의 경우에는 일반적인 rest API가 가지고 있는 문제점을 배워볼거야
그리고 graphql이 그걸 어떻게 해결하는지 볼거야

왜냐하면 graphql은 어떤 문제에 대한 해결책이거든

graphql을 정의하면서 시작해보자
graphql은 다운로드받거나 하는 게 아냐이 페이지에도 다운로드 버튼 같은 건 없지
graphql은 하나의 specification이야

 바로 graphql은 어떤 천재가 만들어낸 아이디어라는 거야 그냥 specification인거야
spcification은 아이디어를 설명해줘 아이디어가 어떻게 동작하는 지를 말야
아이디어의 모든 부분을 설명하는 거지 그럼 다른 사람들이 그 specification을 읽고
specification을 다룰 수 있는 코드를 짜는거야

그래서 예를들면 첫번째 graphql의 오픈소스 client는
여기에 있는 graphql-js였어
이건 최초로 만들어진 Javascript graphql 구현이야  여기에 있는 건 그냥 specification이고
그냥 specification이지

이건 그냥 누가 적어놓은 텍스트인거야 그리곤 누군가 그걸 읽고 그 아이디어를 Javascript로 구현한거지
그래서 내가 이 수업의 소개부분에서 말했는데 만약 graphql을 배운다면
Node.js, python, Java 등에 대한 지식은 넘어가도 된다는거야
왜냐하면 지금하려는 건 다른 환경에서 graphql을 써보려는 거거든
물론 graphql 아이디어는 똑같지 그냥 다른 환경에서 구현될 뿐이야

어떻게 validate하는지,Introspection이 무엇인지, 그냥 이것들이 어떻게 작동해야 하는지 설명해주는거야

그리고 진짜 대박인건 graphql server를 만들어줬다는 거야 graphql specification을 따르는 server를 말이지
좋아 이게 graphql이야 graphql은 domain-specific 언어야 사람들이 원하는 방식대로 구현하도록 하는 언어인거지
graphql은 정말 많은 사람들이 사용해

#3.1 Overfetching (04:23)

이 영상에선 어떤 문제들이 있는지 볼거야 graphql이 해결한 문제들 말이지
 graphql API는 rest API에 대한 직접적인 해결책이야

 rest API는 아주 큰 문제 두 가지를 갖고 있어

'필요한 걸 요청하고, 딱 그것만 받으세요'이걸 읽어보면
graphql이 over-fetching 문제점을 해결한다는 걸 알 수 있지

일단 이 movie API로 가보자 이건 JSON API야
난 엄청나게 긴 JSON을 받았어 보다시피 영화에 대한 정보야
이 API를 통해 받아왔지
여기서 문제는 우리가 over-fetching하고 있다는거야

over-fetching이란, 내가 데이터를 쓰던 말던 너무 많은 data를 받는다는 거야


만약 어플리케이션을 만든다고 생각해보자 내가 하고싶은 건 그냥 영화의 title을 보여주고
summary를 보여주고 image 정도만 보여주고 싶다고 생각해보자고
그런데도 이건 보다시피 내게 필요한 데이터 이상을 주고있어
난 title, year, summary, cover photo를 받고 싶을 뿐이야

필요한 것 보다 많은 data를 fetch하는거지이 경우에 over-fetching을 하고 있고
필요한 것 이상의 data를 받고 있지 이건 내 backend나 database가 일을 더 많이 해야한다는 거야
왜냐하면 database는 말 그대로 영화에 대한 모든 data를 줘야하니까

아게 graphql이 아주 잘 해결해준 한 가지 문제점이야 왜냐하면 graphql로는 url로 data를 즉시 받지 않아
대신에 graphql에서는 필요한 data를 요청하지 그냥 data를 받는게 아니라 필요한 것을 요청하는거지

그래서 이게 만약 graphql API라면 이렇게 말할 수 있을거야
헤이! name, year, summary, title, cover image를 줄 수 있겠니?

고마워~  그럼 끝이야

이게 바로 graphql이 해결해준거야 graphql query를 API에 보내면 정확히 요청한 것만 받아


그 다음 문제에 대해서 다룰거야 이건 under-fetching이라고 불리는데 역시 rest API가 가진 문제점이지

#3.2 Underfetching (05:58)

 under-fetching은 우리가 필요한 것 보다 덜 받는거야

좋아 화면을 보면, 영화 database를 볼 수가 있지

이건 영화나 TV 시리즈에 관한 정보를 가지고 있는 웹사이트인데
또, 이 웹사이트는 아주 멋진 API를 가지고 있어
이건 영화 database API야 그리고 이 영화 database API는 그냥 일반적인 rest API지
method가 정말 많아 companies, credits, keywords, lists등 많은 걸 받아올 수 있지
movies도 받아올 수 있네
또 movies에 대해선 엄청나게 많은 API method가 있고 말야 보다시피 그중 대부분은 GET request야

그래서 만약 이 now_playing이라는 movie API에 가보면
이런 걸 볼 수 있지 여기 보면 이미 over-fetching 문제가 있어
이미 너무 많은 정보를 받고 있고  그건 어쩌면 우리가 요청한 게 아닐 수도 있지

뿐만 아니라 이 API는 또 다른 문제점을 보여주는데 under-fetching이란 거야

내 생각에 모든 API가 over-fetching의 문제를 가지고 있고 그 중 몇몇은 under-fetching의 문제를 보여주고 있어
여기선 엄청나게 많은 data를 받고 있으니 over-fetching인거고 그리고 아마 우린 이 모든 data가 필요하진 않을거야

또 뿐만 아니라 여기에는 under-fetching이 있어 왜냐하면 만약에 이 영화를 화면에 보여줄 때
title을 보여주려 하고 overview를 보여주려 하고 또 사용자한테 이 영화가 액션 영화인지,
호러 영화인지, 아니면 코미디인지 뭐가 됐던지 간에
그 정보는 여기에 있어 근데 보다시피 정보를 얻지 못했어
genre의 id만 받았지 정보를 얻지 못했어

나는 여기  comedy, action, thriller같은 게 있었으면 좋겠는데
보다시피 그런 정보를 얻지 못했어
그래서 만약 이 영화가 어떤 영화인지 사용자한테 보여주고 싶다면,
코미디인지 액션인지, 뭐가 됐던 간에 그걸 말이지

두 개의 url에 request해야 해
첫번째로 now_playing url에서 영화에 대한 정보를 얻어야 하고
그리곤 또 다른 url에 request해야해
이 url은 movies의 genres에 대한 list를 알려줄거야
그래서 이 정보들을 한 화면에 보여주기 위해선 두 url에 request 해야 해

예를 들어 이 response를 받으면 우리는 찾아야 겠지 이 Moonfall은 Moonfall이 뭔지는 모르겠지만
근데 Moonfall은 28과 12래 찾아보자 28은 액션 영화라는군 그리곤 모험 영화래

이제 알겠네

그리고 genre가 878이라네
찾아보자 878은공상과학이래
 
그러니까 이게 under-fetching이라는 거야
만약 내가 영화에 대한 정보를 화면에 보여주고 싶은데 그 영화가 액션인지, 로맨스인지, 미스터리인지 알고싶다면
사용자에게 정보를 보여주기 전에 두 가지 request를 해야하는거야

보다시피 이 url을 fetch해서 영화에 대한 정보를 얻었지 하지만 그리곤 genres url을 fetch해야 해
genre의 정보를 얻기 위해서 말야보이는 것처럼  이방식은 좋지 않아
왜냐하면 어쩌면 필요한 data를 얻기 위해 3개의 request를 해야할 수도 있잖아

이건 실제로 rest API가 가진 문제야 때때로 하나의 url이 주는 것 보다 더 많은 data가 필요하단 거지
이 url은 이 data만 주고있고  이건 충분하지 않아 한 화면을 위해서 기본적으로 두 개의 request를 해야해

그건 로딩 시간이 더 걸릴 수 있단 거야 또 request중 하나는 실패할 수도 있단거지
이건 좋지 않아 이게 내가 원하는 것 보다 적게 fetch하는 under-fetching이야

그리고 그 결과로 어플리케이션은 많은 API request를 보내게 될 거야
여기 graphql 웹사이트를 보면 많은 resource들을 하나의 request에서 받을 수 있다고 하네
좋아 그럼 이게 무슨 말인지 보자 전형적인 rest API는 여러개의 url에서 로딩이 필요해

graphql API로는 필요한 모든 data를 받을 수 있지 단 하나의 request만으로 말야

예를 들어 graphql을 사용한 앱은 모바일로 연결하더라도 빠를 수 있다고 하네
다시 말하지만, 많은 API에 여러개의 request를 보낼 필요가 없기 때문이야
하나의 API에 request를 보내고거기서 필요한 모든 data를 받는거지

좋아 지금까지 under-fetching이었어
under-fetching은 너의 API request가  너가 필요한 data를 다 주지 않는거야
rest API request는 너에게 필요한 data를 다 주지 않아 그럼 넌 다른 곳에 또 request를 해야겠지

 

#3.3 Try GraphQL (09:45)


안녕

 

 

 

 

#4 [2022 UPDATE] YOUR GRAPHQL API

#4.0 Setup (05:21)

우리의 첫 graphql API를 만들어 볼거고 Apollo server라는 걸 써서 해볼거야
여기 보다시피 Apollo server는 오픈소스야
spec-compliant GraphQL server라고 쓰여있는데

이게 무슨 뜻이냐면 Apollo server는 node.js server 같은건데 graphql을 이해하는 서버야
왜냐하면 이건 graphql specification을 구현하고 있거든
전에 말했던 것처럼 graphql은 specification일 뿐이고 그걸 구현하기 위해서는 실제 코드를 써야하지

그게 바로 Apollo server인거야

그리고 실제로 정말 좋아 왜냐하면 Apollo server는 그 자체로 실행할 수 있거든
Apollo server만 있어도 node.js server처럼 작동한다구
만약 express, fastify, hapi, coap 등
가지고 있는 어떤 node.js backend라도
Apollo server를 최상단에 추가할 수 있어

예를 들어 express로 만들어진 rest API가 있다고 해보자
근데 그 API를 graphql API로 바꿔주고 싶다면
server를 그렇게 많이 수정하지 않아도 돼 middleware만 추가시켜주면 되거든

좋아 그럼 먼저 폴더를 만들어주자 Apollo server를 설치 및 설정할거고
 API 만들기를 시작해볼거야 먼저 Documents 폴더로 이동해서
tweetql이라는 폴더를 만들어줄거야  말했듯이, twitter API같은 걸 만들어보고 싶거든
하지만 graphql Twitter API인거지

이제 tweetql폴더를 VSCode에서 열어주자고 그리고 여기서 npm init -y라고 써줄거야
그럼 node respository를 초기화할거야 그리고 또 설치해줄 게 몇 개 있어

설치해줘야 할 게 뭐냐면

npm install  apollo-server와 graphql을 설치해주자
좋아 그리고 그냥 더 나은 개발경험을 위해서 nodemon이라는 것도 설치해줄거야
그러니까 nodemon을 -D(devDependencies)로 설치해줄거야

그리고 server.js라는 새 파일을 만들어주자고
또 .gitignore라는 파일도 만들어줄거야
그리곤 .gitignore에 와서 node_modules을 추가하고

그리고 새 git 레포지토리를 초기화해줄거야 
이제 package.json에 와서 이 script를 dev로 고쳐주고 아니면 start나 너가 원하는 거로 바꿔주고

그리고 여기에서는 nodemon server.js 명령어를 적어줄거야

 이것의 type이 module이라고 해주는거야


그리고 server.js로 가면

ApolloServer, gql을 apollo-server로부터 import 할 수 있을거야

type을 module이라고 해야하는 이유는

그렇게 하지 않으면 import문이 아닌 다른 문법을 써야했기 때문이야 require를 쓰는건데 의미는 같은거야
 하지만 난 이 방식을 더 좋아해 너도 첫번째가 더 괜찮으면 이걸("type":"module") package.json에 넣어줘야 해

먼저 npm run dev 명령어가 작동하는지 보자고
nodemon은 작동중이야
내가 server.js를 저장할 때마다 nodemon이 서버를 재시작 시키는거야

그럼 우리 서버를 만들어주자

(위와 같이 작성) 그리고 server.listen()이라고 해줄건데
여기 보이는 것처럼 listen()은 Promise야 그래서 .then()이라고 해주고 onfulfilled argument가 있는데
이건 value를 줄 거고 value의 type은 ServerInfo인거야 그리고 serverInfo에는 이 property들이 있는데
우리는 url을 쓸거야 그래서 여기로 와서  url을 받아와서 console.log해주자

console을 열고 무슨 일이 일어났는지 봐봐 지금 발생해야 하는 건 이 error야


Apollo server는 존재하는 schema나 modules 또는 typeDefs를 가져야 한다네

이건 다음 영상에서 고쳐볼거야 그냥 이 error를 봤다는 걸 기억해
이 error가 떴다면  모든 게 순조롭게 되고 있는거야 좋아 다음 영상에서 만나자고

이 error를 고쳐볼건데 이 error로 뭔가를 배워볼거야 포인트는 error를 고치는 게 아니라 공부하는거야

우리는 실수를 하고 실수로부터 배우려는거지 예를들면 typeDefs라고 하는 게 왜 필요한지 말야

 

 

#4.1 Query Type (08:50)

 

지금 여기서 보고있는 error인 'Apollo Server는 존재하는 schema, modules 혹은 typeDefs를 필요로 합니다.'

이게 뜨는 이유는 graphql이 data의 shape을 미리 알고있어야 하기 때문이야

rest의 세상에서는 rest API는 많은 url들의 집합이야, 맞지?

엄청나게 많은 url들이 있고 또 규칙들이 있지 어떤 것들은 GET을 허용해주고
어떤 것들은 POST, 어떤 것들은 PUT이나 DELETE를 허용해주지 그래도 그냥 많은 url들의 집합인거야

graphql의 경우, graphql API는 많은 type들의 집합이야
graphql server한테 서버에 있는 data의 type을 설명해주어야 하지 return하려 하는 data라던지
또, 사용자가 보낼 수 있는 data라던지  사용자가 쓸 수 있는 query 등 말이야

이건 server가 실행하기 전에 graphql한테 설명해주어야 하는 것들이야
 보다시피 이 server는 실행되지 않을거야 우리가 앞으로 쓸 data의 shape에 대해 설명해주지 않는다면 말이지

왜냐하면 우리는 그걸 Apollo server에 설명해야 하거든
이게 Star Wars API에서 GraphQL schema 하면서 어쩌구 저쩌구가 있는 이유야
여기있는 schema는 mongodb의 mongoose schema랑 비슷한거야

만약 mongoose와 mongodb를 node.js에서 쓰고 있다면 model의 shape을 설명해줘야 하지 graphql에도 똑같은거야
하지만 이것 덕분에 우리는 아주 멋진 documentation 쓸 수 있어

그걸 보면 우리가 API로 할 수 있는 작업들을 볼 수 있지 또 이게 return하는 값이 뭔지 볼 수 있고
어떤 건 number고 film이란 type은 뭐고 film안에는 어떤 property가 있고 등등
이 모든 걸 받을 수 있지 왜냐하면 이 Star Wars graphql API를 만든 사람이
graphql한테 모든 data의 shape을 설명해줬거든
그러니까 누군가가 graphql한테 설명을 해준거야

이 graphql API는 Film이란 걸 return할거라고 말이지
그리고, Film은 String인 title을 가지고 있고, integer인 episodeID를 가지고, String인 openingCrawl,
또 director를 가진 다는 것 등등
누군가 이 모든 걸 graphql에 설명을 한거야

이것 덕분에 멋진 자동완성이 있는거고
봐봐, 만약 이렇게 해보려고 하면 자동완성이 되잖아 다시 말하지만, graphql이 film안에 뭐가 있는지 알고 있기 때문이야
film이 가질 수 있는 property나 field들의 정보를 말이야

우리 data의 shape을 graphql한테 설명해줘야한다는 거지 그러기 위해서

여기에 새 상수를 만들어줄거고 graphql function을 사용할거야

 

그리고 모든 건 ``안에 있어야 해 이 안에 작성해야 하는 건

graphql의 schema definition language이야 SDL
그러니 여기서 graphql한테 data의 shape을 설명해줄거야 이걸(``) 쓰는 건 매우 중요해 

 graphql의 Schema definition language를 쓸거야 우리 data의 type에 대해
graphql한테 설명해주기 위해서 말야 여기에 있는 건실제 graphql인데 graphql Query language라고 하지
graphql API한테 우리가 사용할 data의 shape을 설명해주기 위해서  graphql SDL을 쓸건데
이건 Schema definition language라는 거지

query data에 대해서도 하나의 언어를 쓰고 data의 shape을 설명하는 데에도 같은 언어를 쓴다는 거야
좋아 그럼 여기로 와서 typeDef를 넣어주자고 
 그러면 이제 또 error를 볼 수 있을거야 또 다른 error말이지
이 error는 예상치 못한 EOF(end of file)라네

왜냐하면 이 경우엔 보다시피 type이 없잖아 그러면 무슨 type을 써야할까?
어떤 type을 써야하나 우리가 써야만 하는 건 의무적으로 말이지 그러니까 꼭 해야하는 건

의무적으로 Query라는 type을 작성해야 해  이걸 안쓰면 어떻게 되는지 보여줄게
만약 Tweet이라는 type을 만들면 좋아 Tweet은 text를 가질거고text는 String이라고 할거야
이렇게 한다면, 난 type을 만든거지

맞아, 그러니까 무언가를 graphql한테 설명하고 있는거지

하지만 여기 error를 보면 Query type은 제공되어야 한다고 하네 이건 필수라는 거지
모든 graphql API는 Query를 가져야 해

Query type없이는 서버가 시작하지 않을거야 Query type은 아주 아주 강력해
너가 Query type에 뭘 넣던지 간에 그것들은 모두 사용자가 request할 수 있는 게 돼

 

한번 rest API의 세상에서 생각해보자 여기 Query type에 무엇을 넣던지 간에
여기에 뭘 넣고 여기에 어떤 field를 넣던지 간에

예를 들면 /text 같은 식으로 GET url을 만드는 거와 같아

만약 String을 return하는 hello를 이렇게 만들면
내가 hello를 Query안에 넣었기 때문에,
rest API에서 /hello url을 만든 것 과 같아

그러니까 Query type안에 무엇을 넣던지
그건 rest API에서 GET request url을 노출시키는 거와 같은거야

graphql Star Wars API를 생각해봐
그 API에서 request할 수 있는 모든 걸 볼 수 있었지
allFilms, film(id), allPeople, person 등 
여기에서 볼 수 있는 모든 것들은  너가 request할 수 있는 거야

 


왜냐하면 누군가 이걸 작성한 거거든 누군가 이 모든 것들을 Query type안에 넣어둔거야

그래서 Query type을 만드는 건 무진장 중요하고, 또 필수적인거야
그리고 또 중요한 건 Query type안에 있는 모든 것들은 마치 GET url을 만드는 거랑 같다는 거야

그러니까 여기에서 allFilms를 Query안에 넣는거는 이렇게 하는 거랑 비슷한거지/allFilms 

 rest API에서의 이거랑 똑같은거야 그래서 graphql에서 이렇게 하는건 rest API에서 이렇게 하는 거라는 거지


사용자가 request할 수 있도록 하고 싶은 모든 건 뭐든지 type Query안에 있어야 해
사용자가 뭔가를 request하게 하도록 하려면 type Query안에 넣어줘야해

사용자가 너한테 data를 보내면 어떻게 되는지에 대해 얘기해볼거야

tweet을 게시하거나 사진을 업로드하거나 하는 것들 말야

 

#4.2 Scalar and Root Types (10:06)

여기 보이는 것 처럼 너가 서버를 시작하면 '당신의 graph를 explore할 준비가 되었나요?' 라는 페이지를 볼 수 있을거야
이건 Apollo가 자체적인 studio를 가지고있기 때문인데


이건 polar studio라고 불려 요점은 이게 graphql api를 explore 할 수 있게 해준다는 거지
이건 graphql API와 상호작용하는 graphiQL 비슷한건데  버튼도 더 많고 다크모드 등등을 지원하지

그럼 Query your server 버튼을 눌러보자 
우리는 localhost:4000과 소통해볼게,

그리고 여기, documentation 안에서  Root에 있는 Query type을 볼 수 있지

 


우리가 만든 query말야 그리고 여기 보면 Query는 text랑 hello를 가지고 있지, 좋아



play버튼만 누르면 우리 server에 말을 걸거야 버튼을 누르면이렇게 server에 말을 걸지
똑같은 작업이 Explorer에서도 될거야 여기에 Query를 작성할 수 있는데, text랑 hello를 요청해 볼게
그리고 Run을 누르면, 여기 보이는 것 처럼 null이라고 하네
우리는 이게 왜 아직 null이라고 하는지 몰라 null이라고 해서는 안되는데 말야

왜냐하면 우리가 여기 적은 것 처럼 얘는 String을 return 해야하기 때문이지
근데 여기 보면, 지금 String을 return하고 있지 않아 null을 return하고 있지

자 첫번째로, 왜 error가 안뜰까?
두번째로, 왜 null이고 누가 null이라고 하는걸까?
그리고 이걸 어떻게 바꿀 수 있을까

그게 바로 퍼즐의 두 번째 조각이야
첫번째로 해야할 건 우리 API가 생긴 모양을 graphql에 설명해줘야 해
그리고 나서 사용자가 원하는 data를 만들어낼 수 있도록 실제 코드를 작성해야 해
좋아, 일단은 우리 API의 shape을 설명하는 거에 집중해보자

우선 Query에 하나의 field를 가지게 하고 싶어
사용자가 allTweets라고 하는 request를 할 수 있도록 하고 싶어
좋아, 여기서 scalar type, non-scalar type 혹은 root type에 관해 공부해볼거야

 

Scalar type은 graphql에 built-in, 내장되어있는 거야
예를 들면, String이라는 type, Int라는 type 그리고 Boolean이라는 type을 가지고 있지

우리는 또한 ID를 가지고 있는데 이것도 type이야

 


우리의 API는 allTweets를 줘야해 모든 트윗을 말이야
이러한 경우에 나는 여기에 Scalar type을 쓸 수 없어

왜냐하면 allTweets을 요청 받으면 database에 있는 모든 트윗을 유저에게 전달하고 싶거든
그러니까 String으로는 작동하지 않겠네  Boolean, Int, 그리고 ID도 작동하지 않을거야

그래서 우리가 해야하는 건 우리만의 type을 만드는거야
여기에 와서
 type Tweet Tweet은 ID type의 id를 가질거고 또 String type의 text를 가질거야
일단은 이게 다야, 지금은 이것들이 Tweet이 가져야 할 것들이야



그래서 누군가 allTweets을 request하면  allTweets field가 Tweet의 list type을 return하도록 하는거야

여기에 너는 어떤 type이라도 정의할 수 있고 또 너가 원하는대로 연결할 수 있어
일단 이 코드를 저장하고 studio로 돌아가보자 그럼 여기 보는 것처럼 이게 업데이트되었어

 

 


Studio는 우리가 Query 안에서 allTweets라는 field를 request할 수 있단 걸 알아

그럼 allTweets는 Tweet의 list를 주겠지 Tweet은 id와 text를 가지고 있고

그럼 여기서 request를 해보자 allTweets라고 쓰면 멋진 자동완성이군!
Tweet은 id랑 text를 가지고 있고~      그럼 실행해보자  여전히 null이라고 하긴 하지만 걱정하지마


이제 여기 있는 것들과 우리가 만든 게 비슷하다는걸 알 수 있을거야


더 많은 type들을 만들어보자
이제 Tweet type이 user에 의해 만들어졌다고 해보자 User type을 만들어볼게

 User는 id를 가질거고 또, String type의 username을 가질거야

그리고 Tweet이 User에 의해 만들어졌다고 할거야


author라고 하고 type은 User가 될거야
이것처럼 Tweet의 list로 [Tweet]을 쓰는 것과

 그냥 User 하나를 쓰는 건 엄청나게 다른거야

 

 

 

이건 database에서의 관계에 따라 결정돼
여기서 말하는 건 Tweet이 하나의 author를 갖는다는 말이고
그리고 allTweets는 여러개의 Tweet을 준다는 거지

 

 

 

너도 볼 수 있듯 이러한 Schema definition language는 엄청 이해하기 쉬워


너는 너가 원하는 어떤 type도 만들 수 있고 String, ID, Boolean, Integer 처럼 몇몇 type들은 이미 만들어져 있지
그리고 넌 더 큰 type들을 설계하는데 이것들을 쓸 수 있는거지  또 원한다면 type들을 연결해줄 수 있어

이제 이걸 저장하고 Explorer로 돌아가면 
Query의 allTweets를 보면 Tweet의 list를 받을 수 있는게 보여

Tweet은 id를 가지고 있고 text와 author도 가지고 있어

그리고 또 author는 id와 username을 가지고 있지

 

 

 

 

 



이건 그냥 우리가 graphql에게 무언가를 설명하는 방식이야
다른 거 하나 더 만들어보자
좋아 내가 하려 하는 건 그냥 하나의 Tweet을 보여주는 거야
그러니까 모든 Tweet들을 받아오는 거 대신에 하나의 Tweet만 받아오려고 해


문제는 user가 말하는 Tweet이 어떤 건지 모른다는 거야
내가 하려하는 건 rest API의 세상에서의 /api/v1/tweets/:id 같은 거야

이런 건 rest API의 세상에 있는 거지 나는 Tweet의 id를 받고 싶어 이걸 하기 위해선 argument를 사용하면 돼
이 부분은 약간 javascript나 typescript의 function처럼 생겼지 이 보라색 부분들이 query의 argument인거야

하나의 film을 request하는 사람은 우리가 database에서 찾을 수 있도록 id를 말해줄거야
우리의 경우에서는 하나의 tweet을 request하는 사람은  이렇게 Tweet의 id를 말해줄거야

이제 우리는 이 request를 받는데,  tweet의 id를 함께 받을거야 그러니,

우리는 그저 그 tweet을 찾으면 되지

다시 우리의 Explorer로 돌아가서 보면 Argument라는 게 있지

그러니까 만약 하나의 tweet을 받고 싶으면  tweet의 id가 뭔지 말해줘야 해
1, 2, 3, 4, 5와 같이 말야



 

 

#4.3 Mutation Type (09:22)

이전 강의에서, 우리는 Query type에 무엇을 넣더라도,
다시말해   Query에 넣은 모든 field들은 user에 의해 request될 수 있다는 걸 배웠어

user가 그것들을 요청 할 수 있는거지
즉 Query 안에 allTweets를 넣는 건  rest API 세상에서 GET request를 받는 url을 만드는 것과 같아

이런 거 말야똑같은 거야 Query에 allTweets를 넣는 건

 url을 만들고 노출시켜서 GET request를 할 수 있도록
그러니까 user가 무언가를 GET할 수 있도록 하는것과 같아

그리고 tweet도 마찬가지야 user가 하나의 tweet을 볼 수 있도록
/api/v1/tweet 과 같은 GET url을 만드는 거랑 같아
그리고 user가 보고싶어하는 tweet의 id를 받아오지 graphql에는 url이 없으니까 이런식으로 하지 않고
대신에 우리가 하는 건 이 query가 argument를 받게 하는거지 그리고 여기서 argument는 id지


graphql 세상에서 query는 rest API의 세상에서 GET request를 만드는 것과 같아
그리고 이것처럼 rest API 세상에 URL variable이 있다면 graphql 세상엔 argument가 있는거야

 

만약 이 두가지 모두에 대한 query를 작성하고 싶으면

첫번째로 모든 tweet을 받아오도록 allTweets를 쓰고 또 allTweets은 text를 가지지
그러니까 우리는 모든 tweet의 text를 받아오고 싶은거야
그리고 tweet을 받아올거고 tweet의 author와 author의 username을 받아올거야
그리고 여기 tweet은 id를 필요로 하지 id는 이런식으로 써주면 되고 일단은 1을 입력할거야


여기서 엔터만 눌러서 자동완성 시켜볼게 지금 보이는 건

studio가 날 도와준거야
query를 만들어준거야 우리는 여기에서 variable만 바꿔주면 돼

그러면 studio는 이 값을 여기에 넣어줘

그리고 또 여기에다가 넣어주지, 이게 studio가 도와주고 있는 것들이야
꼭 이렇게 해야할 필요는 없어

 

 

 

 

 

그전반전은 graphql에 type들을 설명해주는 거고
후반전은 data를 만들어내기 위해 실제로 코드를 작성하는거지


이제 mutation에 대해 얘기하려고 해
좋아, 내가 말했던 것처럼 너가 query type에 무얼 넣던지 이건 rest API의 세상에서 GET url과 같은 거야
rest API의 세상에서 user가 tweet을 만들 수 있게 하려면 이런 식으로 하겠지

user가 GET request랑 POST request를 보낼 수 있도록 하겠지
graphql의 세상에서는 POST request 같은 모든 것들을 Mutation type에 넣어줄거야
이건 특별한 type인데  user가 보낸 data로 mutate하는 동작들을 모두 넣는 거야, 
backend를 mutate하는 것들을 말이야. 예를들어 database가 있지
user가 너한테 data를 보내고, 그 data로 mutation이 발생한다면 data, database, cache, server 등등 에서말야
그렇다면 그건 Mutation type에 있어야 해


그러니까 여기서 하려는 건 user가 tweet을 post할 수 있게 해주는 거야
user가 tweet을 post하려 하려면, tweet의 내용을 줘야 해

그러니까 user는 우리한테 String 하나를 보내야 하지 text말야
그리고 이 mutation이 끝나면 user한테 새로운 tweet을 줄거야
일단 지금은 authentication이 없기 때문에 user한테 userId를 받아와서 tweet을 만들거야

 


만약 user가 backend를 mutate하게 하고 싶거나 user가 data를 보내게 해서 그걸 backend에 업로드 하고 싶거나
database를 수정하고 cache를 지우고 logout 기능을 작동하게 만들고 싶다면
그게 mutation이라면 Mutation에 넣어줘야해

만약 user가 그냥 data를 받게 하고 싶은거라면 그건 Query type안에 있어야지
만약 user가 data를 보내고 그게 backend를 mutate 한다면 그건 mutation이야

Query type에 field를 만드는 것은  rest API의 세상에서 GET HTTP method로 url을 만들고 노출시키는 것과 같지
그리고 Mutation type에 field를 추가하는 건 url을 노출시키고 POST HTTP method로 그걸 관리하는 것과 같아


그럼 studio로 돌아가 보자
 이제 studio가 mutation을 가지고 있어 새로운 mutation이 있고 이 mutation은 postTweet이라고 하지

postTweet이 뭘 가지고 있는지 보자 postTweet은 argument를 가지고 있지
 다시말해 postTweet을 호출할 때 text와 userId를 보내야 한다는 뜻이야 그럼 id와 text, author를 받을거고
좋아 그리고 이제 여길 보면 어디에도 query라는 단어가 없다는 걸 알 수 있지


물론 우리는 그렇게 할 순 있어, 이렇게 하고 실행해도 똑같아 하지만 그렇게 하지 않아 왜냐하면 default로 이건 query거든
하지만 너가 mutation을 호출하고 싶다면  이렇게 여기에다가 mutation이라고 써줘야 해

 

이제 우리가 가지고 있는 하나의 mutation인 postTweet을 쓸거야  postTweet은 우리한테 새 tweet의 text를 줄거야
또한, postTweet은 argument를 필요로 하지 이걸 올린 user의 userId는 1로 해두자
!

다시 복습 하자면

mutation은 그냥 url에 POST request를 쓸 수 있도록 해주는거야 하지만 실제로는 그것보다는 더 많은 일을 해
생각해봐 rest API에서 만약 무언가를 삭제하고 싶다면 DELETE request를 보내야겠지
무언가 업데이트 하고 싶다면 PUT request를 보내고, 맞지?
PUT이라는 HTTP method를 사용하겠지 graphql에서는 그런 식으로 하지 않아
graphql은 Query이거나 Mutation이지

그러니까 한 tweet을 지우려고 한다면 그건 mutation안에 있어야 해
만약 tweet을 수정하고 싶다고 해도 그건 mutation안에 있어야 하지
지금은 삭제하거나 업데이트하는 건 없어 POST, PUT, DELETE는 모두 mutation안에 있는거야

말이 되지, 왜냐하면 무언가를 지우는 건 database를 mutate한다는 거니까
무언가를 업데이트 하는 것도 database를 mutate하는거고
 무언가를 포스팅 하거나 생성하는 것도 database를 mutate하는거지
그럼 하나 더 만들어보자

deleteTweet이라고 하는 걸 만들어볼게
deteteTweet은 id가 필요하지 우리는 id를 받지만 Tweet을 return하진 않을거야 왜냐하면 그 Tweet은 삭제됐을테니까
그래서 Boolean을 return해줄거야

tweet을 삭제하려고 할 때 그 tweet을 찾았다면 true, 못 찾았다면 false를 return 할거야
이것으로 우리의 API의 형태를 graphql에 설명하는 부분은 끝났어
또한 데이터에 일어날 수 있는 작업들을 설명하는 부분도 끝났지

user가 너한테서 data를 받도록 하고 싶다면 그건 Query type안에 있어야해
또 만약 user가 너한테 data를 보내서 그 data가 database로 가거나 무언가를 지우거나, 업데이트를 하거나 하면
그건 mutation이 되어야해

 

 마지막 복습을 해볼게
이제 퍼즐의 후반전을 치를 때라서 말야
여기 봐봐, 난 null을 보는 게 이제 너무 지겨워
정확히 어디에다 data를 만드는 코드를 작성해야 하는지 알아볼거야

#4.4 Non Nullable Fields (07:25)

이번 영상에서는 여기 있는 느낌표에 대해서 배워볼거야 그리고 왜 이게 우리가 만들어 놓은 걸 고장낸건지 말야

느낌표만 추가했을 뿐인데 왜 error가 뜨냐는 거지

우선 Query에 tweet을 예시로 쓰려고 하는데

여기 느낌표를 지워줄거야 이게 없으면 전처럼 정상 작동 할 거야

query를 작성해보자 그리고 argument로 id를 줘야하지
일단 id는 이렇게 쓸게 뭐든 상관 없어

그리고 Run을 누르면 보이는 것 처럼 error가 없지
 error가 뜨지 않는 이유는 여기에 있는 이 Tweet은 Nullable field이기 때문이야

type을 요런 식으로 작성하면 graphql에게는 이게 Tweet이 될 수도 있고 null도 될 수 있는거야

만약 너가 type을 Tweet이라고 쓰거나  예를 들면 뭐.. String이거나
아니면 이렇게 Boolean이라고 쓴다면 graphql은 이걸 보고 '이 query는 Boolean이나 null을 주는군'이라고 생각해

이건 기본값이야

 그리고 이건 nullable field라고 부르는데 null이 될 수 있는 field인거지
모든 건 기본적으로 null이 될 수 있어
그래서 이렇게 쓰더라도 graphql이 뭐라고 하지 않는거야
이게 여기에 아무 error도 없는 이유야

왜냐하면 null을 return하고 있고 graphql은 괜찮다고 하는거지
모든 field는 기본적으로 nullable이니까

이건 Tweet이 될 수도, null이 될 수도 있다는 뜻이야 Boolean이 될 수도 있고 null이 될 수도 있지
좋아, 이 경우에 이건 ID가 될 수도 있고 null이 될 수도 있어

 

 


여기 tweet Query를 예를 들면 이건 항상 Tweet을 return해야해
항상   그러니 이렇게 해보자 여기 이 query는 항상 하나의 tweet을 return할거라는 걸 알지

항상, 이건 항상 tweet을 return할거야 이거에 대해서 확신한다면, 여기에 느낌표를 써주면 돼
좋아, 우린 이게 절대로 null을 return하지 않는다고 확실히하는거야

이건 내가 모든 곳에 느낌표를 붙인 이유야
모든 user는 id를 갖고 있을거라 확신하기 때문이지. 그러니까 required 이고
모든 user는 username을 갖고 있을거야. 이것도 required지


그래서 예를들어, 만약 여기에 firstName이란 걸 추가한다면

우리는 모든 user가 firstName을 가지는지 아닌지에 대해 선택해야해
가지고 있는지 아닌지를 말야 너가 선택해야 해, 만약 모두가 firstName을 가져야 한다면
이렇게 하면 돼 (느낌표 추가) 이렇게 하지 않는 다면 (느낌표 제거)

graphql한테 이건 String이 될 수도, null이 될 수도 있다고 말하는 거야


만약 id가 9071인 tweet을 원한다고 하면 어떨까 database에 존재하지 않는 tweet인거야
즉 되돌려 줄 tweet을 가지고 있지 않은거야 그래서 이렇게 해줄거야 (느낌표 제거)


좋아 이제 선택할 수 있어 graphql한테 어떤 건 항상 존재하고 어떤 건 null이 될 수 있는지를 말해줄 수 있어


allTweets라는 query가

 

우선, 항상 하나의 list를 무조건 준다는거고,
이 list는 항상 tweet로 채워진 list일거야

 

 

 

 

만약 이렇게 한다면 (느낌표 제거)

이게 말하는 건 allTweets가 항상 list를 줄거라는 건데
이 list는 Tweet, null, 그리고 다시 Tweet 이런식으로도 들어갈 수 있다는거야

이건 내가 원하는 게 아냐
내가 말하고 싶은 건 이 list는 오직 Tweet만 가질거라고 알려주는거야


이제 너는 뭐가 required고 뭐가 required가 아닌지 구분할 수 있을거야


error 메세지를 보면, 이해가 돼 non-nullable field에 null을 return할 수 없습니다
allTweets는 non-nullable이지  allTweets는 절대로 null이 되어선 안돼
그리고 지금 우리 API는 모든 것에 null을 return하고 있지

다음번엔 모든 요청에 null을 주지 않도록 response를 만들어 내는 코드를 직접 작성해 볼거야

 

#4.5 Recap (07:02)

#4.6 Query Resolvers (11:36)

 

이제 우리의 API가 최소 50%는 완성 됐다고 생각해도 좋아 왜냐하면 지금까지 한 것으로,
GraphQL은 뭐가 나올지 알고 있어
GraphQL은 어떤 쿼리들을 요청 받을지 알고
GraphQL은 이 쿼리들의 arguments들이 무엇인지 알고 
GraphQL은 어떤 것이 required하고 어떤 것이 required가 아닌지 알아
그리고 return types(반환 타입들)도 똑같아 

GraphQL은 이 tweet이 우리에게 tweet type이나 null을 줄 걸 알아 
그리고 deleteTweet mutation은 boolean을 줄 거라는 것도 알아 
항상 true이거나 항상 false야! null은 절대 없어 

이제 우리는 후반전을 진행할거야 실제로 코드를 쓰는거지 
이 data를 만들어낼 코드를 말야  그러니까 ... 우리는 많은 JavaScript를 할거야
왜냐하면 이건 Node.js 서버거든

여기서 우리가 본 건 GraphQL Schema 정의 언어였어
네가 만드는 그 어떤 서버에도 이건 사용할 수 있지
모든 GraphQL 실행에서 이 언어를 이해할 거야
하지만 니가 어떤 프로그래밍 언어를 사용하느냐에 따라서 이 다음에 우리가 할 작업은 조금 달라질거야
당연히 로직은 같을거야 그 로직은 resolvers라고 불리는 거야. 우리가 지금부터 작성해야하지
알겠지? resolvers들은 하나의 객체가 될거야 

이 객체는 우리의 타입 정의와 같은 형태를 가져야 해 
예를 들어, 쿼리라고 써볼게 query 똑같아야 해 


예를 들어, tweet 이라고 써볼게 좋아 이 tweet 은 function이 될거고 null을 return할거야
그럼 GraphQL Studio에서의 결과는 같겠지 하지만 우리는 여기서 console log를 할거야  그리고 '호출됐음' 이라고 해볼게

 

 

우리가 tweet query를 받는다면 이 console.log가 우리 console에서 작동할거야
그래서 나는 지금 그 resolvers를 여기  그리고 다시 한 번 중요한거. 이름은 꼭 같아야 해 
알겠지? 왜냐하면 이게 GraphQL, 즉 Apollo의 동작과 관련이 있거든 
만약 Apollo가 누군가 query의 tweet을 요청하는 것을 본다면 
Apollo는 resolvers의 query로 갈 거고 이 function을 실행시킬거야
그리고 여기서 return 되는것은 여기서 return하는 것과 같은거야

여기서 아무 에러도 나서는 안돼 왜냐하면 이 경우 Tweet은 nullable이기 때문이야 
여기 보이는 것처럼 required가 아니니까 nullable이지 

여기 보이 듯 null이 나왔어 

 

맞아 하지만 여길보면.. '호출됐음'이 나왔네. 끝이야! 


이게 퍼즐의 두번째 파트야. 누군가 field를 요청했을 때 실제로 호출될 함수인 것이지.
알겠지? 누군가 query type안에 있는 tweet field를 요청하면 
apollo server는 resolvers의 query type의 tweet function으로 가서 이 function을 호출 할거야

 

 

그럼 이제 이 작업들을 시행할 우리의 가짜 데이터베이스를 만들 차례야
좋아 그럼 allTweets filed의 resolver를 만드는 것부터 시작할게 
이런 단어를 외우는 게 진짜 중요해 

우리가 사용해야하는 단어들은 이것들이야 type query는 안에 allTweets라는 field를 가지고 있고,
우리가 이제 allTweets를 위한 resolver를 쓸 거야  그래서 여기 이걸 resolver라고 한거고
좋아 그럼 allTweets field의 resolver를 구현해볼게

그리고 이걸 위해서 우린 list가 필요해 물론 tweets의 list지 
그럼 가짜 DB를 빨리 만들어보자

그리고 여기서는 GraphQL에 우리가 알려줬던 형태를 따라야 해
tweet엔 ID, text, author가 있지

Tweet은 ID를 가지고 있고


 

 

 

 


나중에 relationships을 어떻게 하는지 보여줄게 아주 멋지거든 
당연히 이런걸 계속 다루지는 않을거고 실제로 네 데이터베이스나 다른 것들을 다뤄볼거야
알겠지? 좋아 그럼 해보자  allTweets resolver를 구현해볼게

좋아 여기선 tweets를 return 할거야 

여기로 와서 query allTweets를 실행해보자. 모든 text와 id를 가져와볼게 

 

 

 

 

 


가자 3, 2, 1..   붐!  여기 나왔네  좋아 첫번째 resolver 끝났어 완벽해 

 


이제 두번째 것, tweet(id) 를 시행해보자 여기서 우리는 arguments에 대해 알아볼거야
왜냐하면 우리는 user에게 그들이 요청한 id의 tweet을 return 해야 하잖아.
그럼 이 resolver도 만들어 보자 여기 tweet 이라고 할게
좋아 이제 여기에 올 argument에 대해 알아보자
 사실 Apollo 서버가 resolver function을 부를 때 function에게 어떤 argument를 주거든 

첫 번째 건 root argument라고 해 
두번째 건 네가 원하는 바로 이 argument야

 



우리는 이 args (arguments) 만 console.log만 할거야 
좋아 그럼 console.log(args) 일단 null을 return할게
기억해 tweet resolver는 null을 return해도 괜찮아. non-nullable이 아니거든



이제 tweet을 id 1로 쿼리해볼게  tweet을 id 1과 적고.. text를 받아오자. 실행!
보이듯이 null이야 

우리의 resolver가 했던거지  아무 문제 없어  하지만 console을 보면, 이것 봐  우리를 위해 자동으로 수행되는 작업이야
user가 arguments를 보낼 때 그 arguments들은 항상 너의 resolver function의 두번 째 argument가 돼 

항상! 이 규칙은 GraphQL의 명세야
argument들이 있고, 그 argument들이 따라야 하는 순서가 있지


그러니까 네 server가, 만약 Java GraphQL server이든 Python GraphQL server이든 Node.JS GraphQL server이든
어떤 서버이든  항상 root를 너의 resolver funtion의 첫 번째 argument로 줄거야 root는 나중에 다시 얘기할게 

그리고 두번째는 query나 mutation에서 유저가 보낸 argument가 될 거야


그럼 이제 유저가 'helloooo' 라는 걸 보냈다고 했을 때, 좋아 만약 유저가 hello라는 argument를 보내면 
우리는 hello가 여기 나타날 걸 알아. args 안에서 말이야 그리고 id라는 이름으로 말이지
id라는 이름은 여기 tweet(id) 에서 온 거고 모두 널 위해 수행되는 작업이지
그럼 이걸 풀어서 id를 갖고올게  그럼 이제 JavaScript로 Tweets 배열 안에 있는 Tweet을 찾아볼게

이건 그냥 JavaScript 동작이야

id가 우리가 받은 id와 같은 tweet을 찾는거지.. 끝!
다시 말하지만 이게 네가 할 진짜 작업은 아냐
아마 나중엔 여기서 데이터베이스에 접근해서 어떤 SQL 코드를 실행시킬거야

내가 helloooo 라는 id의 tweet을 찾으려하면 무슨 일이 일어날까?

아무 일도 안 일어났어 

완벽해 

 만약 내가 id 1로 찾으려 하면.. 짠     보이지? 찾았어! 멋져 


아주 아주 잘 돼 

첫 번째 argument는 root argument이고  이게 뭘 의미하는지는 나중에 볼거야 
몇몇 다른 튜토리얼을 보면 사람들이 '_' 이렇게 쓰는걸 볼 수 있는데 이건 이 arugment를 무시하기 위한거야 
넌 여기 무언가를 넣어야만 해  만약 아무것도 넣지 않으면 root로 부터 id를 가져오려고 하게 되는거지
왜냐하면 이건 첫 번째 argument니까. 첫 번째 건 무시해야 해 
그래서 어떤 사람들은 이렇게 쓰기도 하고 어떤 사람들은 _을 두 번 써. 원하면 root를 써도 되고

#4.7 Mutation Resolvers (09:11)

 

좋아, 우선  query resolver의 로직을 따라가보자
만약 mutation type에 대한 resolver를 만들고 싶다면 그냥 여기로 와서 이렇게

Mutation 이라고 쓰기만 하면 돼 그리고   올바른  field를 가져와야 한다는 걸 잊지마


즉, 이 상황에서 우리는 postTweet mutaion의 resolver를 실행하려해

여기에 postTweet이라 쓰고 첫번째 argument로 root를 받아올 건데
그리고 우리가 원하는 두 가지를 받아오기 위해 여기 중괄호를 열어줄게
text와 userId를 받아오자  그럼 복사하고 여기에 붙여넣기할게
다시, 우리가 필요한 건 text와 userId야 좋아, 여기에서 우리는 무언가를 할거야


 이 mutation에서 하려고 하는건 새 tweet을 만드는 일이야
그리고 newTweet은 id, text, author가 필요하단 걸 잊지마
id는 현재 tweets의 길이에 1을 더한 값이 될거야
text는 그냥 넣어주면 되고

 이제, 우리의 database인 tweets에 newTweet을 push 시키자
기억해, postTweet mutation은 항상 우리가 만든 새 tweet을 줘야해
그래서 newTweet을 return 해줄거야

 


좋아, 그럼 작동하는지 보자
여기로 와서 mutation을 만들어보자 이 mutation은 postTweet을 호출할거야
그리고 이 mutation은 text를 가져야 하고 text는 "I'm new" 라고 해보자
또, userId를 가져야 하지 일단은 1로 할거야  userId는 지금은 상관없어
여기로 와서 3, 2, 1, 붐 여기 보이는 것 처럼 우리는 새 tweet을 받았어
id는 3이고 text는 i'm new지  I'm more new로 한 번 더 해보자
3, 2, 1, 붐  id는 4야

 

다음 비디오에선 tweet과 author의 관계를 create하고 resolve할거야
왜냐하면 지금은 우리 tweet이 author를 가지고 있지 않거든
그래서 만약 지금 author를 요청한다면 error가 뜰거야

그리고 또, 여기에 있는 모든 field에 대한 resolver를 만드는 법을 배울거야
 우리는 지금 Query의 allTweets, tweet이라는 field와
Mutaition의 postTweet, deleteTweet의 resolver를 만들어밨어
근데, 만약 예를 들어 user 내부의 field에 resolver를 만든다면 어떨까

멋있을 것 같네
다음 영상에서는 너가 가지고 있는 모든 type에 대한 resolver를 만드는 법을 배울거야
Mutation, Query, tweet, 그리고 심지어는 user까지도 말이야

#4.8 Type Resolvers (08:51)

이번 영상에서는 어떤 type 내부의 어떤 field든 resolver function을 만드는 법을 보여주려해
즉 Query나 Mutation안에 있는 field만 얘기하는 게 아닌거지

 

일단 user database를 만들면서 시작하자 그리고 user는 id, firstName, lastName을

가지지 이게 다야 여기로 와서 id는 1 firstName는 nico, lastName은 las

이제 새로운 Query를 하나 만들어볼게
allUsers라고 할거고 이건 non-nullable list를 줄거고
non-nullable User를 줄거야

allUsers는 그냥 users를 return 하도록 할거야

 

 

이제 allUsers를 써보자  보이는 것 처럼 id, firstName, lastName을 받아올 수 있군


내가 말했던 것 처럼 원한다면, 어떤 field에 있는 어떤 type에도 resolver function을 만들 수 있어
이건 정말 정말 유용하게 쓸 수 있어 이번엔 dynamic field를 다뤄보려고 해

지금 id, firstName, lastName은 database로부터 오는거지
그러니까 기본적으로 Apollo server와 graphql은 내가 return하는 object안에 lastName이 있을 거란 걸 알고 있어

여기서 여러개의 object들이 들어있는 list를 return하고 있지 graphql은 알고있는거야
이 object안에는 id, firstName, lastName이 있을 거란 걸 말이지


그게 우리가 여기서 data를 볼 수 있는 이유야 그런데 만약 user가 fullName이라는 field를 가지게 하면 어떻게 될까?
그리고 이건 non-nullable String 이라고 해볼게
좋아, 그럼 내가 여기서 fullName을 요청해볼게

이건 작동하지 않아

왜냐하면 우리의 data안에는 fullName field가 존재하지 않거든
이제 fullName의 resolver를 만들어야 할 때가 온거야
fullName은 dynamic field가 될 거 거든

 

 

 

 

 

우리가 이전에 배운 로직를 따라가보면예를 들어 만약에 우리가 type Query를 가지고 있고
거기에 allUsers라는 field가 있다면 또 resolvers object의 Query 내부에 allUsers라는 function을 가지고 있다면
Apollo server가 이 function을 실행할 거란 걸 알아

누군가가 Query에 allUsers를 호출한다면 말이지 우리는 이 이름들이 같아야 한다는 걸 알아

만약 type Query가 allUsers를 가지고 있다고 작성했다면 allUsers에 대한 resolver의 이름도 allUsers라고 해야하고
Query 안에 있어야 하지

이 로직에 의해 나type User의 fullName에 대한 resolver를 만들 수 있다는 거야
그리고 User는 fullName이란 걸 가지고 있고
hello!를 return 할거야

 

보이겠지만 아주 잘 작동해! 좋아, 무슨 일이 일어나고 있는거지?

 fullName은 우리가 return할 data에는 없잖아 data에는 없었지 하지만, graphql이 작동하는 방식에 따라
fullName의 resolver가 발견된거야 그래서 fullName의 resolver가 호출된거고
우리는 resolver의 결과값을 받았지 

 

 

 

둘 중에 어떤 게 먼저 출력되는지 확인해 보자구 좋아, 해보자  3, 2, 1  붐!

보다시피 allUsers가 먼저 호출됐어 일단 graphql이 allUsers resolver에 먼저 갔다는 뜻이고
거기있는 모든 data를 가지고 왔겠지 그리곤 graphql은 allUsers가 return하는 data에 fullName field가 없다는 걸 알아차린거지


그런데 우리는 여기서 fullName을 request하고 있고 그럼 이제 graphql은 resolver를 찾으려 할 거야
type User의 field 이름이 fullName인 것을 찾을거야 그리고 graphql은 이 resolver를 실행하는거지

이제 이 resolvers의 root argument 안을 봐보자 여기엔 무엇이 있을 거냐면,

fullName을 호출하는 User object가 있을거야 resolver의 첫번째 argument에서는 root query를 찾을 수 있어

여기서 root를 가져오면, fullName을 호출하는 User를 보게 될 거야 그러니까 무슨 뜻이냐면
여기 root 안에는 이 User가 있는거야 왜냐하면 이게 바로 fullName을 호출하는 User니까 말야


다른 User를 하나 더 만들거야
 id는 2고 firstName은 Elon lastName은 Mask

좋아 이제 root를 console.log해볼거야
console에 어떻게 나올 지 한번 보자

보다시피 두 명의 user가 있고 둘이 같은 fullName을 가지고 있지 그럼 console을 한번 보자


콘솔을 열어보면 allUsers가 호출되었대 하지만 fullName은 두 번 호출되었어
그 이유는 바로 graphql이 찾으려고 했기 때문이야

이 user의 fullName과 여기 이 user의 fullName을 말이지! 이게 무슨 말이냐면, 여기 root argument를 보면
이 resolver가 처음 호출됐을 때는 id가 1인 걸 받아왔어 그리고 두번째로 fullName이 호출되었을 때는 id가 2인 걸 받았어

아주 간단해 먼저 Query에 allUsers에 갔지 바로 여기서 호출 한 거지
그리곤 return 해야 하는 두 개의 User가 있으니까
graphql은 첫번째 User의 fullName을 호출했고 그 다음 두번째 User의 fullName을 호출했지
fullName을 호출하는 User는 resolver function의 첫번째 argument에 있어

 

그럼 이걸 이렇게 열어서 firstName과 lastName만 받아올 수 있지
그리고 여기서 하나의 String을 return 할게

붐, 보다시피 아주 잘 작동해

fullName의 resolver function이 호출되고 있고 이 User data가 argument로 주어진 거야
그러니 우린 result data를 만들어 낼 수 있는거지
다음 영상에서도 이 개념을 더 연습 해볼거니까

이제 users와 tweets를 연결해주어야 하거든 여기로 와서 tweet에다가 author를 쓰거나 하진 않을거야
귀찮으니 이렇게 하진 않을거야  이렇게 하고 싶지 않아

물론 이렇게 할 수는 있겠지만 근데 그렇게 하기 싫어
type 정의에서는 이걸 다 써줘야하지만, database를 다룰 때는 그렇게 쓸 수 없어

실제 database, 적어도 SQL database는 그렇게 작동하지 않아 우린 두 개의 table을 가질거야
Tweet을 위한 거 하나, User를 위한 거 하나
다음 영상에선 방금 여기서 배운걸 이용해서 이걸 어떻게 만드는지 보여줄거야

바로 어떤 root type이라도 될 수 있는 resolver field로 말이야

 

#4.9 Relationships (07:23)

이번 영상에서는 Users와 Tweets를 연결해볼거야  저번 비디오에서 애기했던 type resolver말야

보이는 것 처럼, 우리는 User가 fullName을 가질거라고 GraphQL에게 얘기했어
하지만 fullName은 실제 data에 있지는 않아

대신에fullName은 data에 기반해서 도출되는 거지
우린 GraphQL이 아주 똑똑해서 fullName이 resolver인 것을 알 수 있다는 것도 배웠어

그래서 그게 만약 resolver라면  그 resolver를 호출할거고 resolver가 무엇을 return하든지  우리의 API에 보일거야

이 부분에 있는 이 root는 그저 Query에 대한 정보를 줬기 때문이야
그리고 이 경우에 우리는 Query에 대해서는 신경쓰지 않지
하지만 type resolver의 첫번째 argument는

return되고 있는 object의 data를 줄거야

 

 

 

 

 

 

 이제 이 좋은 걸 활용해서 tweet들과 user들을 연결하려 해
그래서 내가 하려는건 tweet한테 userId를 주는거야

여기에 userId라고 써주고

그리고 이 tweet은 id가 2인 user가 만들었다고 하는거지 그리고 이 tweet은 id가 1인 user가 만들었다고 하는거야
이건 SQL database가 저장하는 방식이랑 비슷해  실제로 foriegn key를 저장하고 join을 하지
그래서 join 비슷한 걸 해보려고 하는데 type resolver를 이용해서 해볼게
좋아 그럼 Tweet이라는 새로운 type resolver를 만들어보자

 

기억해야할 건 field의 이름이야 field의 이름은 author네

 

 

 

 

함수로 만들어주고 다시 말하지만 author resolver의 첫번째 argument는 Tweet이 될거야

 

 

Tweet obejct는 먼저 이게 될거고 그 다음엔 이게 되겠지

 

 

좋아 이제 하려는 건 userId를 가져오는거야 좋아,

여기로 와서 userId를 받아오고
이제 해야할 건 찾아서 return해주는거야!
tweet의 userId를 가진 user를 말야

 

 




예를 들어 만약 이 tweet이 호출된다면id가 2인 user를 이 database에서 찾으려고 하겠지
이걸 하는 방법은 Array.find를 이용하는거야


작동하는지 보자고  3, 2, 1, 붐    보이는 것 처럼 아주 잘 작동하네


멋지지 않아? 정말 멋져   처음으로 호출된 건 allTweets야 맞지?


그러니까 allTweets는 Query로서 먼저 호출되었어
그러곤 많은 tweet들의 list를 return해줬지
그건 여기에 있는 이 type이야

 

 

 

 

 


이 Tweet type을 return하려고 하는거야

그럼 graphql이 여기로 오겠지

 


만약 author를 request 한다면

 

 

 

 

 


graphql은 우리의 tweets의 data는

author라고 하는 게 없다는 걸 알아차리고

 

 

 


graphql은 어딘가에 author resolver가 

있어야한다는걸 알게 될 거야

 

 

 

그리고 여기  author resolver가 있어  graphql은 resolver의 첫번째 argument로
이 모든 data를 줄거야  그리고 여기 userId까지 말이지
기본적으로는 우리가 return하는 data인거고 그리곤
우린 type User를 return하고 있고  graphql은 type User가 뭔지 알아

여기에 있으니까

 

그리고 우린 type User의 fullName을 request하고있어
그래서 다시 말하자면 graphql은 여기로 와서 보곤

 

 


우리 user에게는 fullName이란 게 없단 걸 알거야
그래서 graphql은 resolver로 가서
그리고 User에 fullName resolver라는 게 있다는 걸 알아차리지

 

 

 

 

그래서 graphql은 이 User data를 fullName resolver한테 주는거야
그리고 fullName가 산출되는거지

 

 

 

 

 

 

 

 

 


보다시피 우린 author와 fullName이라는 산출된 field를 두개 가지고 있어
이것들은 database에는 없지 보다시피 존재하지 않아 우리가 그때그때 산출해낸거야

예를 들어 Instagram을 만든다고 생각해보자
그리고 user가 한 사진을 request한거야

이건 user가 그 사진에 이미 좋아요를 했는지 안했는지를 그때그때 산출해 내는거랑 비슷해




이제 우린 명확히해야해
 만약 유저가 tweet을 생성한다면 userId를 추가하여 tweet을 만들어야 한다고



#4.10 Documentation (04:51)

 

좋아 모두들
너가 localhost:4000으로 이동하면 graphql studio로 오게 될 거야
operation 등 여러가지를 볼 수 있는 이 화면이 보이겠지

너가 원한다면 여기서 Schema도 볼 수 있어

 

 

Schema에는 네 API의 documentation이 있고
무엇을를return하는지 등등 모든것들이 있지
예를 들면 어떤 argument들이 있는지,
만약 postTweet을 한다면 그 결과는 뭐가 될지,
Object도 볼 수 있고.. Field도 있고.. 

 

 

 

 

 

 

 

schema를 explore할 수 있게 해줄거야 근데 여기서 schema를 상세히 설명 할 수도 있어
각 field들에 대한 설명을 추가할 수 있는거지 


어떤 type을 클릭할 때 마다 이 API에 있는 요것들이 대체 무엇인지에 대한 정보들이 있지
이건 정말정말 유용해 만약 프론트엔드 개발자와 팀에서 함께 일하고 있다면
Schema에 대한 설명이 필요 할 거야
왜냐하면 프론트엔드 개발자들은 GraphiQL, Apollo GraphQL Studio,
또는 GraphQL playground나 GraphQL Client인 Altair를 쓸테니까 무엇을 쓰던지
어떤 client를 쓰던, 이런 documentation을 볼 수 있어 여기 보는 것 처럼
Query type에 대한 설명이 있고 Mutation type에 대한 설명도 있지
하지만 예를들어 Tweet에 대한 설명을 보려하면 설명이 안되어있지
그러니 Tweet Object에 설명을 추가해주자 여기로 와서


""" 을 두 번 써주고 (화면 참조)
보여주기 위한 거라서 그냥 대충 쓰고있어

 

 

 

 

이제 여기 나타나고있어

 

 Tweet object ~ 어쩌구 저쩌구
원한다면 모든 field에 똑같이 할 수 있어

예를 들면 User의 fullName에 대한 설명을 추가 할 수 있겠지
좋아 User에 가서fullName에 대해 설명을 적자

 

그리고 Mutation에도 써볼게

deleteTweet에다가 (위와 같이 작성) 



Schema 문서를 아주 쉽게 작성할 수 있도록 해주잖아 이전에 REST API에 대한 documentation을 작성할 때는
조금 어려웠어 하지만 GraphQL에서는 빌트인 마냥 이미 존재하고 있어

여러 client들이 방식은 조금 다를 수 있지만 모두가 documentation을 보여줘
이건 Altair라고 하는 다운받을 수 있는 다른 GraphQL client인데
이것으로 어떤 GraphQL API도 explore할 수 있어  다운로드 받거나 browser에 설치할 수도 있는데
나는 일단 웹 버전을 써볼게 여기에서 해야할 건
localhost:4000와 같은 지금 실행중인 서버를 복사 붙여넣기로 입력해두고 send request를 클릭해

그럼 error를 보게 될 거야 하지만 적어도 이건 GraphQL의 error야

즉 GraphQL과 잘 연결 되었다는 뜻이지  그리고 여기 Docs를 클릭하면
Docs에서 Query와 Mutation을 볼 수 잇지 좋아 tweet을 눌러보자
그러면 보다시피 documentation이 여기 있네 'Tweet object는 Tweet에 대한 resource를 나타냅니다'
이건 우리가 이전에 써둔거잖아 Mutation도 똑같아

'Tweet을 찾으면 삭제하고 찾지 못하면 false를 return한다'
보다시피 엄청나게 유용해 그리고 Altair도 사용하고 싶다면 추천할게. 정말 멋진 툴이야

 디자인만 다르고 Apollo Studio가 제공하는 건 똑같이 다 제공해줘
하지만 studio.graphql.com 처럼 웹 사이트가 아니지 실제로 설치해서 offline으로 쓸 수 있어
보다시피 documentation을 제공하고 있구 


한 언어 안에 documentation 기능이 빌트인되어 있다니.. 정말 멋져
다음 영상에선 마지막 개념에 대해 배울거야
바로 바로.. REST API를 GraphQL API로 감싸는 방법이지

 왜냐하면 실제로, 너가 이미 아는지 모르겠지만   Star Wars GraphQL API는 사실 Star Wars REST API를 감싸고 있는거야

 

#4.11 Migrating from REST to GraphQL (09:58)  

이번 비디오에서는 어떻게 REST API를 GraphQL API로 감쌀 수 있는지 보여줄거야

front-end에서는 GraphQL을 쓰고 싶은데 back-end에서는 REST API를 쓰고 싶을 수도 있고
이럴 때 할 수 있는 건, 아주 작은 graphql 서버를 만들거나  아니면 express server 최상단에 apollo를 두고
REST API를 GraphQL API로 바꾸는 작업을 할 수 있어.

 

 

내가 보여줄게 자 처음으로 해야 하는 건
이 field들의 type을 GraphQL schema로 서술하는거야

 

우클릭 하고 inspect(검사)를 누르고 좋아 여기서 뭔가 해볼게 붙여넣기 할게 좋아. 그리고 이렇게 해보자
==>데이터들의 key값들 찾기

그리고 schema에 Movie라는 새로운 type을 만들고
여기에 붙여넣기를 하면 돼

모든 ,를 선택하고 지우고 엔터

좋아 그리고 이쪽에 모든 따옴표를 선택하고 삭제하자
이쪽 따옴표도 마찬가지지

다시 말하지만 이건 그냥 type을 서술하는 작업이야
가지고 있는 REST API가 무엇을 주는 지에 대해서는 알아야되는 거야

 

 


ID는 Number가 될거야 String! 은 복붙해야겠는걸
genres는 String의 Array가 될 거야 rating은 삭제하자


좋아 이제 Movie type을 갖게 됐어
이제 첫 단계를 끝낸거지


다음 단계는 resolver를 만드는 거야 그러니 allMovies라는 resolver를 만들어보자

allMovies는 Movie list를 return할 거야
여기로 와서 Query에 allMovies라고 써주자

자 여기서 확실히 해야하는 건 Movie type의 list를 return 하는 거야
우리가 해야하는 건 이게 다야 data가 어디에서 오는지 중요하지 않아
내가 말했듯이 그건 가짜 database에서 올 수도 있고 실제 database에서 올 수도 있고
아니면 다른 API에서 올 수도 있지 난 이 url을 fetch 해볼게 여기 이 url을 fetch 할 거야
response의 json을 받아서 그리고 그 json을 가지고 json.data.movies를 return해주자고

 


이걸 return 하면 되겠지   테스트 ㄱㄱ
아 fetch is not defined라고 하네
물론 그렇겠지, 왜냐하면 우리는 지금 NodeJS 환경이니까
그러니 아주 빠르게  여기로 와서 npm install node-fetch로 설치할게

잘 작동 하는군~!
그러니까 내 server가 다른 서버로 request를 보내고
그 server가 답을 하면 내 server가 graphql Query에 답을 주는거지
그리고 보다시피  graphql이 Movie의 type을 아니까
내가 원하는 data로 응답하고 있어


다시 schema sandbox studio에 오면 보이는 것처럼 allMovies라는 Query가 하나 더 생겼다
그럼 이 Query를 실행해보자  documentation은 닫고 여기에서 allMovies를 해주자고

보다시피 다른 API에 요청을 보내야하니 시간은 더 걸려
하지만 봐봐 rest API를 graphql API로 바꿨어
이렇게 genres도 요청 할 수 있고  이게 맞다면 String의 list를 주겠지

이게 rest API를 graphql API로 변환하는 방법이야
보다시피 grqphql은 data를 어디서 가져 올 지 선택하게 해줘 원하는대로 할 수 있지
graphql의 좋은 점은 바로 data를 request 하는 방식이야


내가 이걸 왜 보여주고 싶었냐면, 이 다음 수업으로
 front-end 개발자를 위한 graphql 수업을 만들거거든
예를 들면 어떻게 graphql을 front-end에서 쓸 수 있을지에 대한거지
ReactJS와 apollo client를 함께 말이야 이게 내가 allMovie resolver를 만들었던 이유야
여기 resolver를 하나 더 추가하고 싶은데 id를 통해 하나의  Movie를 받는 걸로 말이야
왜냐하면 이 API도 id로 Movie를 찾을 수 있게 해주거든

 

바로 여기에 resolver를 작성해보자 

 Query로 와서 movie를 만들어주자

 

 

 

movie는 String인 id를 받아와서 그리고 Movie를 return할거야


movie에 대한 resolver도 만들어주자 좋아 root는 무시해주고
id를 받아오고 여기 위에 한 것과 똑같은 걸 할건데, url이 달라지겠지
movie_id는 우리의 argument에서 가져온 id가 되겠지 좋아 그럼 결과는 data.data.movie가 되겠군


만약 너가 back-end 개발자인데  팀의 front-end 개발자가 와서 '제발 graphql로 바꿔주세요'라고 부탁하면
넌 이제 어떻게 하는지 알고있어 아무것도 수정할 필요가 없지
그냥 API에 request하고 그들이 원하는 걸 graphql에 주면 돼
아주 멋지게 documentation 작업을 할 수 있다는 것도 잊지말아줘!

 

#4.12 GraphQL and Beyond (03:18)

좋아 모두들, 이 강의를 끝냈어! 봐줘서 정말 정말 고맙고
관심 가져줘서 고마워  나와 함께 GraphQL 공부한 게 즐거웠다면 좋겠고
추후에 너가 GraphQL을 사용해봤으면 좋겠어 GraphQL의 장점들을 알게되었길 바래

너의 backend가 얼마나 좋아질 수 있을지를 보고 이게 네 팀에 얼마나 도움을 줄 수 있을지를 느꼈으면 좋겠어

예를 들면 Subscription type같은거야 여기에는 Query type과 Mutation type밖에 없지
Subscription type은 예약된 type같은 건데 너의 API에 바뀐 게 있을 때 리얼타임으로 업데이트를 받는거야

말도 안되게 멋진 거야 상상해봐 리얼타임으로 알림을 받을 수 있다고

누가 tweet을 추가하거나 삭제할 때 말야 이건 진짜로 멋져. 이게 바로 Subscription type 이라는 거야
type Query와 type Mutation과 같이 type Subscription을 만들 수 있어 물론 구현하는 건 조금 더 복잡하지만

만약 좀 더 자세히 알고 싶다면 부탁하건데 이 Uber Eats 강의를 들어봐

이 수업에선 typescript로  NestJS의 GraphQL API를 만들거든
Subscription으로 실시간 동작까지 말이야 GraphQL을 사용하는게 얼마나 강력한지 볼 수 있는 멋진 코스라구

Subscription을 만들어보는 거 정말 좋은거야

또 이 수업에서는 schema를 만들기 위해서 typescript와 NestJS를 사용할거야
그래서 이 수업에서는 실제로 schema를 이렇게 쓸 필요가 없는데
왜냐하면 생각해봐, 여기보면 반복이 너무 많잖아 우리는 type Query 그리고 allMovies라고 써야하고

그리고 또 여기와서 Query 그리고 allMovies라고 해야해
이건 되게 반복적이고 만약 resolver에서 뭔갈 바꾼다면 schema에서도 바꿔야하지


Uber Eats에서는 typescript로 schema를 만들어볼거야 엄청 놀라울 거야
 아주 멋있고 대단하지 그러니까 너가 typescript로 쓰기만 하면
너의 schema와 type들이 만들어지고 Validation도 있을거고

그러니까 이 수업을 들어봐줬으면 좋겠고 또한, 만약 GraphQL을 ReactJS의 UI에서 더 공부해보고 싶다면
인스타그램 클론코딩 수업을 확인해봐 왜냐하면 여기에서는 웹사이트, ios와 andriod의 어플리케이션을 만들어보거든
 
GraphQL을 사용해서 말이지 또 GraphQL Subscription을 사용해서 프라이빗 메시지나
이런 것들을 아이폰에서 만들어볼 수 있어
그러니 이것도 확인해보구 또 만약 이미 database가 있다면 hasura를 확인해봐
나는 hasura를 너무 좋아해! 진짜 좋은 어플리케이션이야
돈 받은 거 아니고 광고 아니야 그래도 hasura는 아주 멋져

너의 database를 hasura의 server에 연결할 수 있게 해주거든 그리고 그것만 하면 네 data의 GraphQL API를 만들어줄거야
이런 걸 받는다고 생각해봐 네 database에 대한 Mutation들과 Query들의 묶음을 '즉시'말이야

예를 들면 여기서 했던 것들을 할 필요가 없는거지 이런 작업을 할 필요 없을거야

예를 들면 여기 이런거 너가 해야할 건 hasura에 database를 연결하는 거 밖에 없고
그러면 hasura는 너의 database의 모든 table에 대해 GraphQL API를 만들어줄거야


그러니까 너가 database를 가지고 있고 server를 migrate하거나 하고 싶지 않다면그냥 hasura에 연결하면
그럼 프론트엔드 개발자는 data를 hasura에 request할 수 있고 그리고 hasura는 GraphQL API를 주는거지

내가 말했듯이 Uber Eats, Instagram Clone, Hasura도 한번 봐줘