- graphql์ด Rest API ์ Over-fetching / Under-fetching์ ์ผ๋ง๋ ์ ๋์ํ๋์ง๋ฅผ ๋ณด์ฌ์ฃผ๊ธฐ ์ํด์.
๊ฐ์ ธ์จ ์ ๋ณด์์ ํ์ํ ์ ๋ณด๋ ํ์ ์ ์ผ ์๋ ์๋ค. ํ์ง๋ง Rest API๋ก ํธ์ถ์ ํ๊ฒ๋๋ฉด, ๋ถํ์ํ ์ ๋ณด๊น์ง ๊ฐ์ง๊ณ ์ค๋ ๊ฒฝ์ฐ๊ฐ ์๋ค ์ด๋ฅผ Over-fetching
์ด๋ผ๊ณ ํ๋ค.
์๋ฒ์ ์์์ด ๋ญ๋น๊ฐ ๋จ.
ํ๋ก ํธ์๋์ ํ๋์ ํ์ด์ง๋ฅผ ๊ตฌ์ฑํ๊ธฐ ์ํด์ ํ๋กํ ์ ๋ณด, ๊ฒ์๋ฌผ ์ ๋ณด, ๋๊ธ ์ ๋ณด๋ฑ ๋ง์ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์์ผํ์ง๋ง, Rest api์์๋ ์ด๋ฌํ ๊ฒ์ ๊ฐ ๋ถ๋ถ์ ๋ฐ๋ผ ์์ฒญํด์ผํ๋ค. ํ์ํ ์ ๋ณด๋ฅผ ํ๋ฒ์ ๊ฐ์ ธ์ค์ง ๋ชปํ๋ ๊ฒ์ Under-fetching
์ด๋ผ๊ณ ํ๋ค.
์๋ฒ์ ์์ฒญ๋์ด ์ฆ๊ฐํ๊ฒ ๋จ.
์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์, ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ์ ํ์ํ ๊ฒ์ ์ต์ ํํ์ฌ ํ๋ฒ์ ์์ฒญ์ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ์ค๋ ๊ฒ์ ์ฃผ ๋ชฉํ๋ก ํ์ฌ ๋ง๋ค์ด์ก๋ค.
GraphQL
๊ณผ SQL
์ ๊ฐ์ Query Language์ด๋ค. ๊ฐ๋จํ ๋งํด์ ์ง์ํ์ผ๋ก ์์ฒญํ์ฌ ํ์์ ๋ฐ๋ฅธ ์๋ต์ ๋ฐ์ ์ ์๋ ๊ฒ์ด๋ค.
import express, { Application } from "express";
import { ApolloServer } from "@apollo/server";
import { expressMiddleware } from "@apollo/server/express4";
const typeDefs = `#graphql
type Query {
hello: String
}
`;
const resolvers = {
Query: {
hello: () => "world",
},
};
export default async function createApp(): Promise<Application> {
const app = express();
const server = new ApolloServer({
typeDefs,
resolvers,
});
await server.start();
app.use("/graphql", express.json(), expressMiddleware(server));
return app;
}
์์ ๊ฐ์ด ์ฝ๋๋ฅผ ๊ตฌ์ฑํ์๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก express๋ฅผ ์ฌ์ฉํ์ง์๊ณ graphQL๋ฅผ ์ ์ํ ์ ์์ง๋ง, express์ ํจ๊ป ์ ์ฐํ๊ฒ ๋์ํ๋ graphQL์ ์ฌ์ฉํ๋๋ก ํ๋ ๊ฒ์ ๋ชฉํ๋ก ํ๋ค.
express์ ๋ฏธ๋ค์จ์ด๋ฅผ ํตํด์ resolver์ ์ ๊ทผํ์ฌ Query๋ฅผ ํ์ธ ํ ๋ต์ ์ค ์ ์๋ ๊ฒ์ด๋ค.
ํ์ฌ ์ฑํฐ์์ npm test
๋ฅผ ํตํด์ ํ
์คํธ๋ฅผ ์งํํด๋ณด์.
query : "query { hello }"
๋ผ๋ ํ์์ ์ฟผ๋ฆฌ๋ฅผ json ํ์์ผ๋ก ๋ณด๋ด๊ฒ ๋๋ฉด, ์ผ๋ฐ Rest API์ ๊ฐ์ JSONํํ๋ก ์๋ต์ ๋ฐ์ ์ ์๊ฒ ๋๋ค. ํด๋น ํ ์คํธ๋ ์ด์ ๋ํ ๋ถ๋ถ์ ์ง๊ด์ ์ผ๋ก ํ์ธํ ์ ์๋๋ก ๊ตฌ์ฑํ๋ค..
์ด๊ธฐ ์ฑํฐ์์๋ database๋ฅผ ์ฌ์ฉํ์ง์๊ณ practice์ ๋ํด์ ์๊ฐํ๋ ค๊ณ ํ๋ค.
ํ๋กํ ์ ๋ณด, ๊ฒ์๋ฌผ, ๋๊ธ์ ํ๋ก ํธ์์ ์์ฒญ์ด ํ์๋ก ํ ๋:
- REST API : ํ๋กํ ์ ๋ณด, ๊ฒ์๋ฌผ, ๋๊ธ์ ๋ํ ์์ฒญ์ ๋ฐ๋ก ๊ตฌ์ฑํ๋ค.
- GraphQL : Query ๊ธฐ๋ฐ์ผ๋ก ํ๋ฒ์ ์์ฒญ์ผ๋ก ๊ฐ๋ฅํ๊ฒ ํ ์ ์๋ค.
/api/profile
/api/board/:id
/api/comment
๋ก ๊ตฌ์ฑํ ๊ฒ์ด๋ค. ํ์ฌ๋ ์ธ์ฆํ๋ ๊ฒ์ด ๋ชฉ์ ์ด ์๋๊ธฐ ๋๋ฌธ์, ์ธ์ฆ๋ถ ์์ด ๋ฌด์กฐ๊ฑด์ ์ผ๋ก 1๋ฒuser์ profile์ ์ฃผ๋๋ก ํ๊ฒ ๋ค.
query {
userProfile(id: 1) {
id
name
email
age
phone
}
getBoard(id:1){
postId
userId
title
content
timestamp
}
getComment(boardId:1){
commentId
postId
userId
content
timestamp
}
}
ํด๋น ์ฟผ๋ฆฌ๋ฅผ ํตํด ํ๋ฒ์ ์ ๊ทผ ๊ฐ๋ฅ, ํด๋น ๋ถ๋ถ์์๋ ์ค๋ช ์ ๋ถํ์ํ ๋ด์ฉ์ ์ ์ธํ์ฌ ์งํํ๋ค.
Rest API
๋ ์๋ฒ๊ฐ ๊ตฌ์ฑํ๊ณ ์๋ ํํ๋ฅผ ํด๋ผ์ด์ธํธ์ ํ์์ ๋ฐ๋ผ ๋ณ๊ฒฝํ๋ ค๋ฉด ์๋ก์ด api ๋ฅผ ๊ตฌ์ฑํด์ผํ๋ ๋ฒ๊ฑฐ๋ฌ์์ด ์กด์ฌํ ์ ์๋ค.
ํ์ง๋ง, GraphQL
์ ๊ฒฝ์ฐ์๋ ๊ทธ ๋ ๊ทธ๋ ํ์ํ ์ธ์๋ง์ ๋ฐ์ ์ ์๊ธฐ ๋๋ฌธ์, ์๋ต์ ๋ฐ๋ ๊ฒ์ ์์ ๋กญ๋ค.
Rest API
์ GraphQL
์์ ์์ฒญ์ ๋ฐ๋ฅธ ์๋ ์ฐจ์ด๊ฐ ๋ํ๋ ์๋ ์๋ค๊ณ ํ๋๋ฐ, ์ ๋ง์ธ์ง ํ์ธํ๊ธฐ ์ํด์ ๋์ผ ์๋ฒ ์คํ์์ ์ด 5๋ฒ์ ํ
์คํธ๋ฅผ ์งํํด๋ดค๋ค.
npm test perform
์ ํตํด์ ์ด๋ฅผ ํ์ธํ ์ ์๋ค!
perform์ ๋ํ test๋ฅผ ์งํํ ๊ฒฐ๊ณผ 1.3 ~ 1.7 ๋ฐฐ ๋ ๋น ๋ฅธ ๊ฒ์ผ๋ก ์ธก์ ๋์๋ค. ์ด๋ ๊ฒ ํ ๋ฒ์ ๋ง์ ์์ฒญ๋์ด client๊ฐ ํ์๋ก ํ๋ค๊ณ ์๊ฐํ๋ฉด ํธํ ๊ฒ์ด๋ค.
๋ง์ ํด๋ผ์ด์ธํธ๋ ํ๋์ ํ์ด์ง ๋จ์์ ์ฌ๋ฌ ๋ฐ์ดํฐ๋ฅผ ์ป๊ธฐ ์ํ ์๋ก ๋ค๋ฅธ api์์ฒญ์ ๋ฐ๋ณตํ๋ค.
GraphQL์ด Rest API์ Under-Fetching๊ณผ Over-Fetching ๊ฐ์ ์ํฉ์ ์ผ๋ง๋ ์ ๊ทน๋ณตํ๋์ง์ ๋ํด์ ์๊ฐํ๋ ค๊ณ ํ๋ค.
Under-Fetching
๋ ์์ ์์ ์ ๋น์ทํ๋ค.
๋จผ์ REST ๊ตฌ์กฐ๋ฅผ ์์์ผ๋ก GraphQL๊น์ง ์์ฑํด๋ณด์.
์ฌํ ๋ฆฌ๋ทฐ ์น์ฌ์ดํธ์์ ์ฌ์ฉ์์ ํ๋กํ ์ ๋ณด๋ฅผ ํฌํจํ ํน์ ์ฌ์ฉ์์ ์์ฑํ ๋ฆฌ๋ทฐ ๋ชฉ๋ก์ ํด๋ผ์ด์ธํธ์์ ์์ฒญํ๋ ์ํฉ์ ๊ณ ๋ คํด๋ณด์. ์ฌ์ฉ์๋ ์ฌ๋ฌ ๋ฆฌ๋ทฐ๋ฅผ ์์ฑํ ์ ์์ผ๋ฉฐ, ๊ฐ ๋ฆฌ๋ทฐ์๋ ์์ฑ์์ ์ ๋ณด๊ฐ ํฌํจ๋์ด ์๋ค.
ํ์ฌ ์น์์ ์ฌ์ฉ์์ ๋ํ ๊ธฐ๋ณธ ์ ๋ณด (์ด๋ฆ๊ณผ ์ด๋ฉ์ผ)๋ง์ ๋ณด์ฌ์ฃผ๋ ค๊ณ ํ๋ค. ํด๋น ์ฌํญ์ ๊ณ ๋ คํด๋ณด์.
์ฌ๊ธฐ์ ํ์ํ ๋ถ๋ถ์ ์ถ์ถํด๋ณด๋ฉด ์๋์ ๊ฐ๋ค.
-
RestAPI
- ์ ์ ์ ์ฒด ์ ๋ณด -
/api/user
- ์ ์ ํ๋กํ ์ ๋ณด -
/api/user/:userId
- ์ฌ์ฉ์ ๋ฆฌ๋ทฐ ๋ชฉ๋ก -
/api/user/:userId/review
- ๋ฆฌ๋ทฐ ์์ธ ์ ๋ณด -
/api/review/:reviewId
- ์ ์ ์ ์ฒด ์ ๋ณด -
-
GraphQL
-
typeDef Schema
export default `#graphql type User { id: Int! name: String! email: String! reviews: [Review] } type Review { reviewId: Int! content: String! score: Int! timestamp: String! author: User } type Query { user(id: Int): User users: [User] userReviews(userId: Int!): [Review] review(id: Int!): Review } `;
- ์ด๋ฌํ Schema ๊ตฌ์กฐ๋ก ์ด๋ ํ ๋ฐ์ดํฐ๋ฅผ ์ํธ๊ตํํ ์ง ํ๊ธฐํจ.
reviews:[Review]
์ ๊ฐ์ Recursiveํ ๊ตฌ์กฐ ๋ํ ๊ฐ๋ฅ
-
์์ ๊ฐ์ ํํ๋ก ๊ตฌ๋ถ์ด ๊ฐ๋ฅํ๋ค. ๋ณธ ์ฑํฐ๋ถํฐ ์์ ๋ ๊ฐ๋ ์ฑ์ ์ํด ๋ชจ๋ํ๋ฅผ ์งํํ๋ฉด์ ๊ตฌ์กฐํ๋ฅผ ํ๋๋ก ํ๊ฒ ๋ค.
- graphql
- loader
- express.ts
- graphql.ts
- index.ts
- schema
- resolver.ts
- typeDefs.ts
- app.ts
- loader
- restapi
- api
- routes
- review.ts
- user.ts
- index.ts
- routes
- loaders
- index.ts
- app.ts
- api
-
Under-Fetching
Test Description REST API Performance (ms) GraphQL API Performance (ms) Measure Performance 38.17 14.33 Image Data -
Over-Fetching
Test Description REST API Performance (ms) GraphQL API Performance (ms) Measure Performance 9.13 20.4 Image Data
npm test perform
์ ํตํด ์ฑ๋ฅ์ ์ธก์ ํด๋ณผ ์ ์์ ๊ฒ์ด๋ค.
๊ฐ๋จํ๊ฒ ์์๋ฅผ ๋ค์ด์ฃผ๊ฒ ๋ค. ์ด ๊ฒ์ ๋ง์น Buffering ๊ฐ๋
๊ณผ ๋น์ทํ๋ค. ๊ณ๋์ ๊ฐ์ง๊ณ ์ฌ ๋, ๋ฐ๊ตฌ๋๋ฅผ ๊ฐ์ง๊ณ ํ๋ฒ์ ๊ฐ์ ธ์ค๋ ๊ฒ
๊ณผ 1๊ฐ์ฉ ์๋ค๊ฐ๋ค ํ๋ฉด์ ๊ฐ์ ธ ์ค๋ ๊ฒ
๋ฑ GraphQL๊ณผ Rest API๋ ํด๋น ์์์ ๊ฐ์ ์ฐจ์ด๊ฐ ๋๋ค.
Under-Fetching์ ๊ฒฝ์ฐ ๋ REST API ์์ ํ์๋ก ํ๋ ๋ฐ์ดํฐ๋ฅผ ์ป๊ธฐ ์ํด์๋ ์ฌ๋ฌ๋ฒ์ ์์ฒญ์ด ํ์ํ ๊ฒ์ด๋ค. ๊ฒฐ๊ตญ ๋์ผํ ๋ฐ์ดํฐ๋ฅผ ์ป๋๋ค๊ณ ๊ฐ์ ํ๋ฉด ์๋ค ๊ฐ๋ค๊ฑฐ๋ฆฌ๋ ์๊ณ
๋ง ๋ ์ถ๊ฐ ๋ ๊ฒ์ด๋ค.
์ด ๊ฒ์ด ๊ฐ๋จํ ๋งํด ์ฑ๋ฅ์ฐจ์ด์ ํฐ ์์ธ์ด ๋ ๊ฒ์ด๋ค.
์ด๋ ๊ฒ ๋งํ๋ฉด graphql ๋งน์ ๋ก ์์ ๊ฐ์ด ๋๊ปด์ง ์๋ ์์ง๋ง, ๊ทธ๋ ์ง๋ ์๋ค. ์ฟผ๋ฆฌ ๊ตฌ์กฐ๊ฐ ์์ง๊น์ง ๋จ์ํด์ ๊ด์ฐฎ์ง๋ง, ์์ recursive ํ ๊ตฌ์กฐ๋ฅผ ํ์ฉ
ํ๋ค๋ ๋ง์ ๋ดค๋ค๋ฉด ์์ํ๊ฒ ์ง๋ง, ์ฟผ๋ฆฌ ๊ตฌ์กฐ๊ฐ ๋ณต์กํด์ง ์๋ก graphql ์์์ ์ค๋ฒํค๋๊ฐ ๋ฐ์ํ ์ ์๋ค๋ ์ ๋ ์ผ๋ํด๋๋ฉด ์ข์ ๊ฒ ๊ฐ๋ค.
๊ทธ๋ฌํ ์ค๋ฒํค๋๋ฅผ ์ ์ธํ๋ฉด ๋ง์ ์ด์ ๋ค์ด ์กด์ฌํ๋ค.
- ๋ณต์ ์์ฒญ์ ๊ฐ์
- ์ ํํ ๋ฐ์ดํฐ ์์ฒญ (ํ์ํ ๋ฐ์ดํฐ๋ง ๊ฐ๋ฅ)
- ๋คํธ์ํฌ ํธ๋ํฝ ๊ฐ์(๋จ์ผ ์์ฒญ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ป์ ์ ์๊ธฐ ๋๋ฌธ์)
์ด๋ฌํ, ์ด ์ ์ ์คํ๋ ค ๋ค์ํ ์๋น์ค๋ฅผ ๋ง๋๋๋ฐ ํฐ ๋์์ ์ค ๊ฒ์ด๋ผ ํ์ ํ๋ค.
Over-Fetching ์์ ์ ๊ฒฝ์ฐ๋ graphql์์ ์ค๋ฒํค๋
๊ฐ ๋ฐ์ํ๋ ์ข์ ์ฌ๋ก๋ผ๊ณ ์๊ฐํ๋ค.
๋ค๋ฅธ ์ฌ๋๋ค: ๋ฐฉ๊ธ๊น์ง๋งํด๋ GraphQl์ด ์ข๋ค๊ณ ํ์์์!
๋ฌผ๋ก ์ด๋ค. ํ์ง๋ง ์ค๋ฒํค๋๋ฅผ ๊ณ ๋ คํด์ผํ๋ค.
์ฌ๊ธฐ์ ์ ๊น ์ฃผ๋ชฉํ๋ฉด ์ข์ ์ ์ Response Size์ด๋ค. GraphQL์ด Rest API ๋ณด๋ค ํจ์ฌ ์ ๋ค. ํ์ฌ ์คํ ์์ฒด๋ Local์์ ์งํํ์ง๋ง, ์ฌ๋ฌ remote ํต์ ์ด ์์ ๋ Response Size๊ฐ ๋ฎ์ ์ฆ, "๋์ญํญ"์ด ๋ฎ์ GraphQL์ด ์ ๋ฆฌํด์ง ์ ์๋ค.
GraphQL์์ ์ค๋ฒํค๋๊ฐ ๋ฐ์ํ๋ ์ด์ ๋ ์ฟผ๋ฆฌ๋ฅผ ํตํ ์ง์๋ ์๊ตฌ์ ๋ง๊ฒ ๋ฐ์ดํฐ ํด์๊ณผ์ ์ ๊ฑฐ์น๊ธฐ ๋๋ฌธ์ ์๋ตํ ๋ฐ์ดํฐ๋ฅผ ๋ง๋ค์ด๋ด๋๋ฐ๊น์ง ์๊ฐ์ด ์ค๋๊ฑธ๋ฆฌ๋ ๊ฒ์ด๋ค.
์ด๋ฅผ ์ฟผ๋ฆฌ ์ต์ ํ, Resolver ์ต์ ํ ๋ฑ๊ณผ ๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก ํด์ํ ์ ์๋ค. ์ด๋ ์ถํ ์ฑํฐ์์ ์๊ฐํ ์์ ์ด๋ค.
์ง๊ธ๊น์ง์ ๋ด์ฉ์ผ๋ก ์์์ผ๋ฉด ์ข๊ฒ ๋ ์ ์ ์๋ก๊ฐ์ ํธ๋ ์ด๋ ์คํ๊ฐ ๋ถ๋ช ์กด์ฌํ๋ค๋ ๊ฒ์ด๋ค.