์์ฑ์ : ์ด๋ณ๋ฏผ
GraphQL
์ 2015๋
๋์ Facebook์์ ๋ฐํํ "๋ฐ์ดํฐ ์ง์์ด"์ด๋ค.
GraphQL
L์ Graph Query Language์ ์ฝ์๋ก QueryLanguage ๋ป์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋๋ ๋ฐ์ดํฐ ๊ด๋ฆฌ ์์คํ
์ ์ ๊ทผํ๊ธฐ ์ํ ์ธ์ด๋ก ServerAPI ์ ๋ณด๋ฅผ ์ฃผ๊ณ ๋ฐ๋ ๊ฒ์ ํนํ๋ QueryLanguage์ด๋ค.
GraphQL์ ํน์ ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ํน์ ํ ์คํ ๋ฆฌ์ง ์์ง๊ณผ ๊ด๊ณ๋์ด ์์ง ์์ผ๋ฉฐ ๊ธฐ์กด ์ฝ๋์ ๋ฐ์ดํฐ์ ์ํด ๋์ฒด๋๋ค.
GraphQL์ API๋ฅผ ์ํ ์ฟผ๋ฆฌ ์ธ์ด์ด๋ฉฐ ์ด๋ฏธ ์กด์ฌํ๋ ๋ฐ์ดํฐ๋ก ์ฟผ๋ฆฌ๋ฅผ ์ํํ๊ธฐ ์ํ ๋ฐํ์์ด๋ค.
GraphQL์ API์ ์๋ ๋ฐ์ดํฐ์ ๋ํ ์๋ฒฝํ๊ณ ์ดํดํ๊ธฐ ์ฌ์ด ์ค๋ช ์ ์ ๊ณตํ๊ณ ํด๋ผ์ด์ธํธ์๊ฒ ํ์ํ ๊ฒ์ ์ ํํ๊ฒ ์์ฒญํ ์ ์๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ฉฐ ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ API๋ฅผ ์ฝ๊ฒ ์งํ์ํค๊ณ ๊ฐ๋ ฅํ ๊ฐ๋ฐ์ ๋๊ตฌ๋ฅผ ์ง์ํ๋ค.
- ํ์ํ ๊ฒ์ ๊ตฌ์ฒด์ ์ผ๋ก ์์ฒญํ ์ ์์ผ๋ฉฐ ํญ์ ์์ธก ๊ฐ๋ฅํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ค.
- ๋จ์ผ ์์ฒญ์ผ๋ก ํ์ํ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ์ป์ ์ ์๋ค.
- ๊ฐ๋ ฅํ ๊ฐ๋ฐ์ ๋๊ตฌ๊ฐ ์๋ค. (์์ฒด์ ์ผ๋ก API ํ ์คํธ ๋๊ตฌ๊ฐ์๋ค.)
https://2020.stateofjs.com/ko-KR/technologies/datalayer/
โstate of JS 2020โ์ ์ค๋ฌธ์์ DataLayer ๋ถ๋ถ์์ ๊ด์ฌ๋์ ๋ง์กฑ๋ ๋น์จ 1์๋ฅผ ์ฐจ์ง ํ๋ค.
๋ํ ์ฌ์ฉํด๋ดค๊ณ ๋ค์ ์ฌ์ฉํ ๊ฒ์์ด 45%, ๋ค์ด๋ดค๊ณ ๋ฐฐ์ฐ๊ณ ์ถ์์ด 45%์ผ๋ก ๊ธ์ ๋๋ ๋งค์ฐ ๋๋ค.
GraphQL
์ ๋ค์๊ณผ ๊ฐ์ RESTAPI
์ ๋ฌธ์ ์ ์ ํด๊ฒฐ ํ ์ ์๋ค.
๋ค์์ ๊ฐ์ ์ฑ ์จ๋ผ์ธ ์ผํ๋ชฐ์์ ๋ณด์ฌ์ง๋ ๋ค๋ฅธ ํ์ด์ง์ ์ฑ ์ ๋ณด์ด๋ค.
์ฒซ๋ฒ์งธ ์ฌ์ง์๋ "์ ๋ชฉ", "์ง์์ด", "์ถํ์ฌ", "๊ฐ๊ฒฉ"์ธ์ "์ถํ์ผ"๊ณผ ๊ฐ์ด ์๋ ๋ถ๋ถ์ ์ ๋ณด์๋ ์๋ ์ ๋ณด๊ฐ ์๋ค.
๋ณดํต API๋ฅผ ๊ตฌ์ฑํ ๋ ๋ค์๊ณผ ๊ฐ์ด ์ฑ ์ ๋ํ ์ ๋ณด๋ฅผ ๊ตฌ์ฑํ๊ณ
{
"title": "์ปดํจํฐ๊ตฌ์กฐ๋ก (๊น์ข
ํ)",
"price": 28000,
"publisher": "์๋ฅ",
"author": "๊น์ข
ํ",
"publishedDate": "2019.02"
...
}
๊ฐ ํ์ด์ง์์ ํ์ํ ๋ฐ์ดํฐ๋ง ํ๋ฉด์ ๋ณด์ฌ ์ฃผ๊ฒ ๋๋ค.
์ฆ, ๋ถํ์ํ ๋ฐ์ดํฐ๊น์ง ๊ฐ์ด ์ ๋ฌ ๋ฐ๊ฒ ๋๋ค.
ํ์ํ ์ ๋ณด๋ณด๋ค ๋ ๋ง์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌ ๋ฐ์ ๋ถํ์ํ ๋ฆฌ์์ค ๋ญ๋น๊ฐ ๋ฐ์ํ๊ณ , ํ์ํ ์ ๋ณด๋ง ๊ณจ๋ผ๋ด๊ธฐ ์ํ ์์ ์ ์ถ๊ฐ๋ก ์งํํ์ฌ์ผํ๋ค.
โ ์ด๊ฒ์ Over-Fetching
์ด๋ผ ํ๋ค.
๋ค์ ๋ฌธ์ ์ ์ Under Fetcing์ด๋ค.
์ฌ์ดํธ๋ฅผ ๋ค์ด ๊ฐ๊ฒ ๋๋ฉด ์ํ์ ๋ํ ์ ๋ณด ๋ฟ๋ง ์๋๋ผ ์ค๊ฐ ์ค๊ฐ ๊ด๊ณ ๊ฐ ๋ณด์ด๋ ๋ถ๋ถ์ด ์๋ค.
์ฌ์ดํธ์ ๊ฒฝ์ฐ ๋จ ํ๋ฒ์ API๋ฅผ ํตํด์ ๋ฐ์ ์ค๋๊ฒ ์๋๋ผ ํ๋ก ํธ์๋์ ์์ญ๋ณ๋ก ํ์ด์ง์ ํ์ํ ๋ถ๋ถ์ ๊ฐ๊ธฐ ๋ค๋ฅธ API๋ก ๋ถํฐ ๊ฐ์ ๋ฐ์ ์ค๊ฒ ๋๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ํ ํ๋ฉด์์ ํ์๋กํ๋ ๋ฐ์ดํฐ๋ ํ๋์ endpoint๋ก์ ์์ฒญ์ผ๋ก๋ ์ถฉ๋ถํ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ง ๋ชปํ๊ณ ๊ทธ ์ด์์ endpoint์ ์์ฒญํด์ผํ๋ค.
ํ์ํ ๋ฐ์ดํฐ๋ฅผ ๋ง๋ค๊ธฐ ์ํด ์ฌ๋ฌ ๋ฒ์ ํธ์ถ์ด ํ์ํ์ฌ ์ถ๊ฐ์ ์ธ ๋ฆฌ์์ค ์์ฒญ์ด ๋ฐ์ํ๊ฒ ๋๊ณ , ์ฌ๋ฌ ์์ฒญ์ ํตํด ์ ๋ฌ ๋ฐ์ ์ ๋ณด๋ฅผ ์กฐํฉํ๋ ์ถ๊ฐ ์์ ์ด ๋ฐ์ํ๋ค.
โ ์ด๋ฌํ ๊ฒฝ์ฐ๋ฅผ Under-Fetching
์ด๋ผ๊ณ ํ๋ค.
Over-Fetching
๊ณผ Under-Fetching
์ด์ธ์๋ RESTAPI
๋ฅผ ์ฌ์ฉํ๋ฉด ์ผ์ผ์ด API์ URL๋ฅผ ์ง์ ํด ์ฃผ์ด์ผํ๋๋ฐ GraphQL
์์๋ ๋จ์ผ endpoint
๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ์ด๋ฌํ ๋ถํธํจ๋ ํด์ ํ ์ ์๋ค.
๋ํ API๋ฅผ ๊ฐ๋ฐํ๋ฉด์ ํ ์คํธ๋ฅผ ์งํํด์ผ ํ๋๋ฐ GraphQL์์๋ ์์ฒด์ ์ผ๋ก ๊ฐ๋ฐ ๋๊ตฌ๋ฅผ ์ง์ํ๋ค.
๋ค์๊ณผ ๊ฐ์ด ๋ฐ๋ก ํ ์คํธ ๋๊ตฌ๋ฅผ ๋ง๋ค๊ฑฐ๋ ์ฌ์ฉํ์ง ์๊ณ ๋ ์ฝ๊ฒ ํ ์คํธ๊ฐ ๊ฐ๋ฅํ๋ค.
RESTAPI
๋ฅผ ํ ์คํธํ ๋ ์ฌ์ฉํ๋Insomnia
์ ๊ฐ์ ๊ฐ๋ฐ ๋๊ตฌ ์ด๋ค.
-
query
์ฟผ๋ฆฌ๋ RESTAPI์์ ๋ณด๋ฉด CRUD์ค R์ด๋ผ๊ณ ๋ณด๋ฉด๋๋ค.
์ํ๋ ๋ฐ์ดํฐ๋ฅผ ์์ฑํด์ ์์ฒญํ๊ณ ๋ฐ์ ์ ์๋ค. -
mutation
๋ฎคํ ์ด์ ์ ์ฟผ๋ฆฌ์ ๋ค๋ฅธ ๊ฒ์ ์์ง๋ง RESTAPI์์ CRUD์ค CUD์ ํด๋นํ๋ค.
๋ฐ์ดํฐ์ ์ถ๊ฐ, ์์ , ์ญ์ ์์ฒญ์ ํ ์ ์๋ค. -
schema
๊ฐ์ฒด type์ ์ ์ํด ๋๋ ๋ถ๋ถ์ด๋ค.
type User { name: String! }
User
๋ GraphQL์ ํ๋๊ฐ ์๋ ๊ฐ์ฒด ํ์ ์ด๋ค.
name
์User
์ ํ์ ์ ํ๋ ์ด๊ณString
์ ์ค์นผ๋ผ ํ์ ์ค ํ๋์ด๋ฉฐ,!
๋ ์ด ํ๋๋ฅผ ์ฟผ๋ฆฌํ ๋ ํญ์ ๊ฐ์ ๋ฐํ ํ๋ ๊ฒ์ ์๋ฏธํ๋ค. -
resolver ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๊ตฌ์ฒด์ ์ธ ๊ตฌํ ๊ณผ์ ์ ๊ตฌํํ๋ ๋ถ๋ถ์ด๋ค.
์์ฒญํ๋ ๊ฐ์ ๋ฐ์ดํฐ์ ๊ตฌ์กฐ๋ฅผ ์ํ๋๋ฐ๋ก ๋ฐ๊พธ์ด์ ๋ฐํ ํ ์ ์๋ค.
GraphQL
์ ํ๋ ์์ํฌ๊ฐ์ ๊ฒ์ด ์๋ ์ง์์ด์ด๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์ฌ๋ฌ ํ๊ฒฝ์์ ์ ์ฉํ ์ ์๋ ์๋ฃจ์
์ด ์๋ค.
GraphQL์ ๋ฐฑ์๋ ๋ฟ๋ง์๋๋ผ ํ๋ก ํธ์๋์์ ์ฌ์ฉ ํ ์ ์๋ค.
๊ทธ์ค์์ ๋ํ์ ์ผ๋ก๋apollo
๊ฐ ์๋ค.
apollo
๋ apollo-server
์ apollo-client
๋ก ๋ฐฑ์๋, ํ๋ก ํธ ์๋๋ฅผ ๋ชจ๋ ์ ์ฉ ํ ์ ์์ผ๋ฉฐ,web
๋ฟ๋ง ์๋๋ผ ios
,android
์ ๊ฐ์ ๋ค๋ฅธ ํ๋ซํผ์๋ ์ ์ฉ ํ ์ ์์ด์ ์ธ๊ธฐ๊ฐ ๋ง๋ค.
GraphQL๋ฅผ ๊ฐ๋ฐํ Facebook์์ ์ง์ ๋ง๋ Relay๋ React๊ณ์ด๋ง ์ง์ํ๊ณ apollo๋ react,vue์ ๊ฐ์ ์น ํ๋ ์์ํฌ ๋ฟ๋ง ์๋๋ผ ios,android์ ๊ฐ์ app์๋ ์ ์ฉ ํ ์ ์์ด ์ธ๊ธฐ๊ฐ ๋๋ค.
์ค์น
- express
- graphql
- express-graphql
๋ค์ ์ฝ๋๋ GraphQL ๊ณต์ ํ์ด์ง์ ์์ ์ฝ๋ ์ด๋ค.
๋ค์ ๋ช
๋ น์ด๋ก ํจํค์ง ํ์ผ์ ์ค์นํ๊ณ ์ฌ์ฉ ํ ์ ์๋ค.
./test-express-graphql
$ npm install
๋ค์ ์ฝ๋๋ฅผ ํตํด ์ค์ตํ ์ ์๋ค.
./test-express-graphql/app1.js
var express = require("express");
var { graphqlHTTP } = require("express-graphql");
var { buildSchema } = require("graphql");
var app = express();
var schema = buildSchema(`
type Query {
hello: String
}
`);
var root = { hello: () => "Hello world!" };
app.use(
"/graphql",
graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
})
);
app.listen(4000, () => console.log("Now browse to localhost:4000/graphql"));
root
์ ์๋ hello๋ฅผ Query๋ก ๋ ๋ฆฌ๊ฒ ๋๋ฉด "Hello world!"๋ฅผ schema
์ ์ ์๋ Query์ ํ์
์ผ๋ก ๊ฐ์ ๋ฐํ ํด์ค๋ค.
graphQL์ ๋ฐํํ ๋ฐ์ดํฐ์ ๊ตฌ์กฐ๋ฅผ ๋ฏธ๋ฆฌ schema
์ type์ ์ ์๋ฅผ ํด์ฃผ์ด์ผ ํ๋ค.
app.use()
์ schema,root๋ฅผ ์ ์ํด ๋๊ณ graphiql: true
๋ฅผ ์ง์ ํ๊ฒ ๋๋ฉด ํด๋จ URL์ธ /graphql
๋ก ์ ์ํ๊ฒ ๋ ์ GraphQL playground๋ก ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฆด ์ ์๊ฒ ๋๊ณ ๊ฒฐ๊ณผ๋ฅผ ํ์ธ ํ ์ ์๋ค.
app.use(
"/graphql",
graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
})
);
-
์ํ๋ ๋ฐ์ดํฐ๋ง ๋ถ๋ฌ์ค๊ธฐ (Over-Fetching ํด๊ฒฐ)
./test-express-graphql/app2.js
var schema = buildSchema( ` type Query { users: [User] } type User{ index : Int name : String age : Int id : String } ` ); var root = { users: () => myData1 };
ํธ์ถํ๋ ค๊ณ ํ๋ ๋ฐ์ดํฐ
myData1
๋ฅผ ํธ์ถํ๊ธฐ ์ํด์๋ ๋ค์๊ณผ ๊ฐ์ดmyData1
์ ์๋ ๋ฐ์ดํฐ์ type์User
์ ์ ์ํ๊ณQuery
์users
๋ฅผ ํธ์ถํ ์User
๋ฐ์ดํฐ ํ์ ์ ๋ฐํํ๋ ์ฝ๋๋ฅผ ์ง๊ณroot
์์users
๋ฅผ ํธ์ถ์ ๋ฐํ ๋ฐ์ดํฐ๋กmyData1
๋ฅผ ์์ฑํ๋ฉด ๋๋ค.์ด๋ ์ ์ฒด ๋ฐ์ดํฐ๊ฐ ์๋ ์ํ๋ ๋ฐ์ดํฐ๋ง์ ํธ์ถํ์ฌ Over Fetching ๋ฌธ์ ๋ฅผ ํด๊ฒฐ ํ ์ ์๋ค.
-
์ฌ๋ฌ ๋ฐ์ดํฐ๋ฅผ ํ๋์ endpoint๋ก ๋ถ๋ฌ์ค๊ธฐ (Under-Fetching ํด๊ฒฐ)
app3.js
ํ์ผ์์๋ ๋๊ฐ์ง ๋ฐ์ดํฐmyData1
๊ณผmyData2
๋ฅผ ๋ถ๋ฌ์จ๋ค.app3.js
๋ฅผ ์คํ ์ํค๋ช ๋ค์๊ณผ ๊ฐ์ด ํ๋ฒ์ ๋ฐ์ดํฐ ๋ค์ ๋ฐ์ ์ ์๋ค../test-express-graphql/app3.js
app4.js
ํ์ผ์http://localhost:4000/
๊ฒฝ๋ก๋ก ์ ์์์ ์ํ๋ ๊ฐ๋งQuery
๋ก ๋ ๋ ค์ Ajax๋ฅผ ํตํด ๊ฐ์ ๋ฐ์์จ๋ค.ํ๋ก ํธ์์ ๋ค์๊ณผ ๊ฐ์ด ์ํ๋ ๊ฐ๋ง ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ ์ฌ์ฉ ํ ์ ์๋ค.
myData1
์์ "id","name"๊ฐ์myData2
์์ "password"์ "gender"๊ฐ์ ๊ฐ๊ฐ ํ๋ฒ์ ๋ฐ์ดํฐ๋ก ๋ฐ์์์ ํ๋ฉด์ ์ถ๋ ฅํ ๋ชจ์ต์ด๋ค../test-express-graphql/app4.js
-
์์ ์ค์ต
./test-apollo-server
$ npm install
-
์ง์ ์์ฑ
$ npm init $ npm install apollo-server
-
apollo-server ์ถ๊ฐํ๊ธฐ
import { ApolloServer, gql } from "apollo-server";
-
typeDefs ์์ฑ
GraphQL ๋ช ์ธ์์ ์ฌ์ฉ๋ ๋ฐ์ดํฐ, ์์ฒญ์ ํ์ ์ ์ง์ ํด์ ์คํค๋ง๋ฅผ gql(template literal tag)๋ก ์์ฑํ๋ค.
์ด๋ค ํ๋๋ฅผ ์ ํํ ์ ์๋์ง, ์ด๋ค ์ข ๋ฅ์ ๊ฐ์ฒด๋ฅผ ๋ฐํํ ์ ์๋์ง, ํ์ ๊ฐ์ฒด์์ ์ฌ์ฉํ ์ ์๋ ํ๋๋ ๋ฌด์์ธ์ง๋ฅผ ์ ์ํด๋๋ค.const typeDefs = gql` type Query { tests: [Test] } type Test { hello: String }
-
resolvers
์์ฒญ์ ๋ฐ๋ผ ๋ฐ์ดํฐ๋ฅผ ๋ฐํ, ์ ๋ ฅ, ์์ ์ญ์ ํ๋ค.
์ ์๋ ์คํค๋ง ํ๋์ ์ฌ์ฉ๋๋ ํจ์์ ์ค์ ํ๋์ ์ ์ํ๋ค.const resolvers = { Query: { tests: () => test, }, };
-
์คํ
ApolloServer๋ typeDefs์ resolvers๋ฅผ ์ธ์๋ก ๋ฐ์์ ์๋ฒ๋ฅผ ์์ฑํ๊ณ server.listen()๋ช ๋ น์ด๋ก ์๋ฒ๋ฅผ ์คํํ๋ค.
const server = new ApolloServer({ typeDefs, resolvers }); server.listen().then(({ url }) => { console.log(`๐ Server ready at ${url}`); });
์ค์ตํ๊ธฐ
-
์ํ๋ ๊ฐ๋ง ์์ฒญํ๊ธฐ
./test-apollo/index1.js
์์๋ก ์ฌ์ฉํ ๋ฐ์ดํฐ
./database/products.js
import ์ํค๊ธฐimport { products } from "./database/products.js";
์คํค๋ง ์ ์
./database/products.js
ํ์ผ์ ํ์ ์ ์ง์ ํฉ๋๋ค.const typeDefs = gql` type Query { products: [Product] } type Product { title: String price: Int salePer: String salePrice: String star: String starNum: String } `;
์ฟผ๋ฆฌ ํธ์ถ์ ๋ฐํํ ๋ฐ์ดํฐ ์ ์ํ๊ธฐ
const resolvers = { Query: { products: () => products, }, };
http://localhost:4000/graphql
๋ก ์ ์ํ์ฌ ์์ฒญ ๋ฐ๊ณ ์ถ์ ๊ฐ์ ์ ํํด์ ์์ฒญํ๊ธฐ -
ํ๋์ ์ฟผ๋ฆฌ๋ก ๋์์ ์ฌ๋ฌ ๋ฐ์ดํฐ ๋ฐ๊ธฐ
./test-apollo/index2.js
import { products } from "./database/products.js"; import { ho } from "./database/ho.js"; import { name } from "./database/name.js"; import { ApolloServer, gql } from "apollo-server"; const typeDefs = gql` type Query { products: [Product] hos: [Ho] names: [Name] } type Product { title: String price: Int salePer: String salePrice: String star: String starNum: String } type Ho { index: Int Ho: String } type Name { index: Int Name: String } `; const resolvers = { Query: { products: () => products, hos: () => ho, names: () => name, }, }; const server = new ApolloServer({ typeDefs, resolvers }); server.listen().then(({ url }) => { console.log(`๐ Server ready at ${url}`); });
index2.js
๋index1.js
์์ ๋ฐ์ดํฐHo
์Name
๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํ ๊ฒ์ ๋๋ค. -
์ํ๋ ๊ฐ๋ง ํํฐ๋งํด์ ๋ฐ๊ธฐ
resolvers
์ ๊ฐ์ ํํฐ๋งํด์ under fetching ๋ฌธ์ ๋ฅผ ํด๊ฒฐ ํ ์ ์๋ค../test-apollo/index3.js
type Query { product(price: Int): [Product] }
๋ค์๊ณผ ๊ฐ์ด
Query
๋ถ๋ถ์ ๊ธฐ์กด์ ์๋products: [Product]
์ ์ ๋ ฅ๊ฐ์ ๋ฐ์ผ๋ ค๊ณ ๊ฐ์product(price: Int): [Product]
๋ก ์ ์ํด์ค๋ค.const resolvers = { Query: { // products.price์ด ์์ฒญ ์ฟผ๋ฆฌ ๊ฐ๋ณด๋ค ํด ๊ฒฝ์ฐ๋ง ์ถ๋ ฅ product: (parent, args, context, info) => products.filter((product) => { return product.price >= args.price; }), }, };
๊ทธ๋ฆฌ๊ณ ๋์
resolvers
์์ ์ํ๋ ์ฝ๋๋ฅผ ์ง์ ํด์ค๋ค.๋ง์ฝ ์์ฒญ๊ฐ๋ณด๋ค ๋์ ๊ฐ์ ๋ฐ๋๋ค๊ณ ํ๋ฉด ์ด๋ ์์ฒญ์ธ์๋ก๋
args
๋ฅผ ๋ฐ๋๋ค.
filter
๋ก ์์ฒญํ ์ธ์์ธargs.price
๋ณด๋ค ํฐ ๊ฐ๋ง ๋์ค๊ฒ ํ๋ฉด ์์ฒญ๋ฐ์ ์ธ์๋ณด๋ค ํฐ๊ฐ๋ง ๋์ค๊ฒ ๋๋ค.price
๊ฐ 8000๋ณด๋ค ํฐ ๊ฐ ์ถ๋ ฅํ๊ธฐ -
์ํ๋ ๊ฐ๋ง ํํฐ๋งํ๊ธฐ2
index2.js
ํ์ผ์์ ์คํํ์๋ ๋ณด๋ฉด"data":{ "A":[ { "a": "value", }, ], "B":[ { "b": "value", }, ] }
ํ๋์ endpoint๋ก
data
์์ ๊ฐ์ ์์ง๋ง ๊ฐ๊ฐ A, B๋ก ๋๋์ด์ ธ ์จ๋ค.type Ho { index: Int Ho: String names: [Name] } type Name { index: Int Name: String }
Ho
์์Name
์ ๋ฃ์ด์Ho
๋ฅผ ํธ์ถํ ๋Name
์ ๊ฐ์ด ํธ์ถํ๋๋ก ๋ฃ์ด์ฃผ๋ฉด๋๋ค.๊ทธ๋ฆฌ๊ณ resolvers๋ฅผ ์ง์ ํด์ฃผ์ด์ผํ๋ค.
์ง์ ํ์ง ์๊ณ ๊ทธ๋ฅ ํธ์ถํ๋ฉดHo.names
์์ ๋ชจ๋names
๊ฐ ๋์ค๊ฒ ๋๋ค.๊ทธ๋ฆฌ๊ณ resolvers์ ๋ค์๊ณผ ๊ฐ์ด
filter
๋ก index๋ฒํธ๊ฐ ์ผ์นํ๋ ๊ฐ์ 1:1๊ด๊ณ๋ก ํธ์ถ๋๊ฒ ํด์ค๋ค.hos: () => ho.map((ho) => { ho.names = name.filter((v) => { return ho.index == v.index; }); return ho; }),
-
HTML๊ณผ ์ฐ๋ํ๊ธฐ
index5.js
์ :4000 ํฌํธ ์คํ์ํจ ํindex.html
๋ฅผ LiveServer๋ก :5050 ํฌํธ๋ก ์คํ ์ํจ๋ค.A B C ./test-apollo/index5.html
./test-apollo/index5.js
์์ ์ฝ๋๋ ๋ด์ฉ์ ๊ฒ์ํ ๊ฐ ์ด์์ ๊ฐ์ ๊ฐ์ ธ์จ๋ค. ๋ผ๋์ค๋ฐ์ค์ ์๋ ๊ฐ์ ์ ํํ ๊ฐ๋ง ์์ฒญํด์ ๊ฐ์ ธ์จ๋ค. (Over Fetching)
"B"๋ ํ ์ธ์จ ์ ํ ํ์๋ ๊ฒฐ๊ณผ์ด๊ณ "C"๋ ํ ์ธ์จ, ํ ์ธ๊ฐ ๋ชจ๋๋ฅผ ์์ฒญํ ๊ฒฐ๊ณผ์ด๋ค.์์ฒญํ์ง ์์ ๊ฒฐ๊ณผ๊ฐ์ ๋ํด์๋
undefined
๊ฐ ๋จ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.