손쉽게 백엔드와 데이터베이스, 스토리지를 해결해주는 firebase를 이용하면서 편리함을 얻었지만 편리한 만큼 단점도 보였다.
필요한 정보만 쏙쏙 받아오고 싶은데 전체 데이터를 호출한다는 점 (Over-fetching), 그리고 한 번의 요청으로 모든 데이터를 받아오지 못해 여러 번의 요청을 해야 한다는 점이다.
예를 들어, 인스타그램의 메인 페이지에서 다른 유저의 스토리, 게시글, 친구 추천을 불러올 때 이러한 정보들은 GET /users/{id}/story, GET /users/{id}/posts처럼 여러 번의 요청이 필요하다. 이런 여러 호출이 자원 낭비와 느린 로딩 속도를 발생한다는 점이다. (Under-fetching)
이 불편함을 해결하기 위해 방법을 찾다가 graphQL과 이를 구현 시켜줄 Apollo를 찾게 되었다.
rest api는 관리해야 할 EndPoint의 증가로 발생하는 문제점이 있다. (특정 기능을 위해 여러 번 API가 호출 된다는 점, 유지보수의 어려움 등..)
GraphQL의 특징
1.EndPoint가 하나라는 점
Rest API는 정보를 얻기 위해 여러 번 네트워크를 호출하거나, 다양한 API를 호출해야 했는데, GraphQL은 단 하나의 EndPoint를 제공하며, 한 번의 요청으로 모든 정보를 가져올 수 있는 엄청난 장점이 있다.
2.Over-fetching, Under-fetching 방지
위에서 적었듯 필요한 정보를 얻기 위해 전체 데이터를 가져오는 것은 속도도 느려질뿐더러 자원을 낭비한다. GraphQL은 고정된 endpoint로 요청을 보내기 때문에 정해진 데이터를 받아올 수 있다.
GraphQL은 하나의 명세일 뿐이기에 이를 구현할 방법이 필요한데 그 중 하나가 Apollo다. GraphQL 사용을 도와주는 라이브러리인 것이다.
GraphQL은 객체에 대한 필드를 요청하는 것이 간편하다. 쿼리와 결과가 동일한 형태인 것을 알 수 있는데 이는 서버에서 클라이언트가 요청하는 필드를 알고 있기 때문이다. 필드는 객체를 참조할 수 있다.
hero {
name
friends {
name
}
}
}
아래의 예는 friends 필드가 배열을 반환한다.
{
"data": {
"hero": {
"name": "R2-D2",
"friends": [
{
"name": "Luke Skywalker"
},
{
"name": "Han Solo"
},
{
"name": "Leia Organa"
}
]
}
}
}
GraphQL은 필드에 인자를 전달할 수 있다. Rest API는 단일의 인자들만 전달할 수 있지만, GraphQL에서는 모든 필드와 중첩된 객체가 인자를 가질 수 있기에 한 번의 요청으로 처리가 가능하다.
요청
{
human(id: "1000") {
name
height(unit: FOOT)
}
}
응답
{
"data": {
"human": {
"name": "Luke Skywalker",
"height": 5.6430448
}
}
}
정보를 요청해 데이터를 가져올 때 사용한다. (Get)
query {
teams {
id
manager
office
extension_number
mascot
cleaning_duty
project
}
}
GET 요청을 제외한 나머지 요청들을 말한다. 해당 정보를 추가하고 삭제하고 변경할 때 사용한다.
추가
mutation {
postTeam (input: {
manager: "John Smith"
office: "104B"
extension_number: "#9982"
mascot: "Dragon"
cleaning_duty: "Monday"
project: "Lordaeron"
}) {
manager
office
extension_number
mascot
cleaning_duty
project
}
}
수정
mutation {
editTeam(id: 2, input: {
manager: "Maruchi Han"
office: "105A"
extension_number: "2315"
mascot: "Direwolf"
cleaning_duty: "Wednesday"
project: "Haemosu"
}) {
id,
manager,
office,
extension_number,
mascot,
cleaning_duty,
project
}
}
삭제
mutation {
deleteTeam(id: 3) {
id,
manager,
office,
extension_number,
mascot,
cleaning_duty,
project
}
}
GraphQL은 하나의 명세일 뿐이기에 이를 구현할 방법이 필요한데 그 중 하나가 Apollo다. 아래는 React에서 Apollo를 사용하는 방법이다.
Apollo Client 설치
npm install @apollo/client graphql
or
yarn add @apollo/client graphql
설치가 끝났다면 ApolloClient 인스턴스를 초기화 한다.
index.js
import {
ApolloClient,
InMemoryCache,
ApolloProvider,
useQuery,
gql
} from "@apollo/client";
초기화를 끝냈다면 index.js에서 uri 및 캐시 필드가 있는 구성 개체를 전달한다.
index.js
const client = new ApolloClient({
uri: 'https://48p1r2roz4.sse.codesandbox.io',
cache: new InMemoryCache()
});
uri : graphQL의 서버 URL
cache: cache는 InMemoryCache의 인자이며 불필요한 query 요청을 방지해준다.
Apollo Client 와 React의 연결
위의 과정을 거쳐 ApolloProvider를 앱을 감싸 react에서 활용할 수 있게 연결한다.
import React from 'react';
import { render } from 'react-dom';
import {
ApolloClient,
InMemoryCache,
ApolloProvider,
useQuery,
gql
} from "@apollo/client";
const client = new ApolloClient({
uri: 'https://48p1r2roz4.sse.codesandbox.io',
cache: new InMemoryCache()
});
function App() {
return (
<div>
<h2>My first Apollo app 🚀</h2>
</div>
);
}
render(
<ApolloProvider client={client}>
<App />
</ApolloProvider>,
document.getElementById('root'),
);