Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/knu-k/graphql-ts-practica

To address the issues of over-fetching and under-fetching that commonly occur in REST APIs, we will configure GraphQL and then conduct performance analysis on it.
https://github.com/knu-k/graphql-ts-practica

apollo apollo-server backend es6 express graphql nodejs restapi typescript

Last synced: 3 months ago
JSON representation

To address the issues of over-fetching and under-fetching that commonly occur in REST APIs, we will configure GraphQL and then conduct performance analysis on it.

Awesome Lists containing this project

README

        

## ๐Ÿ—’๏ธ ์™œ ํ•ด๋‹น ์ฃผ์ œ์— ๋Œ€ํ•œ ์˜ˆ์ œ๋ฅผ ์ œ์ž‘ํ•˜๋Š”๊ฐ€?

- graphql์ด Rest API ์˜ Over-fetching / Under-fetching์— ์–ผ๋งˆ๋‚˜ ์ž˜ ๋Œ€์‘ํ•˜๋Š”์ง€๋ฅผ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด์„œ.

### Over-fetching์ด๋ž€

๊ฐ€์ ธ์˜จ ์ •๋ณด์—์„œ ํ•„์š”ํ•œ ์ •๋ณด๋Š” ํ•œ์ •์ ์ผ ์ˆ˜๋„ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ Rest API๋กœ ํ˜ธ์ถœ์„ ํ•˜๊ฒŒ๋˜๋ฉด, ๋ถˆํ•„์š”ํ•œ ์ •๋ณด๊นŒ์ง€ ๊ฐ€์ง€๊ณ  ์˜ค๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค ์ด๋ฅผ `Over-fetching` ์ด๋ผ๊ณ  ํ•œ๋‹ค.

> ์„œ๋ฒ„์˜ ์ž์›์ด ๋‚ญ๋น„๊ฐ€ ๋จ.

### Under-fetching์ด๋ž€?

ํ”„๋ก ํŠธ์—”๋“œ์˜ ํ•˜๋‚˜์˜ ํŽ˜์ด์ง€๋ฅผ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด์„œ ํ”„๋กœํ•„ ์ •๋ณด, ๊ฒŒ์‹œ๋ฌผ ์ •๋ณด, ๋Œ“๊ธ€ ์ •๋ณด๋“ฑ ๋งŽ์€ ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์™€์•ผํ•˜์ง€๋งŒ, Rest api์—์„œ๋Š” ์ด๋Ÿฌํ•œ ๊ฒƒ์„ ๊ฐ ๋ถ€๋ถ„์— ๋”ฐ๋ผ ์š”์ฒญํ•ด์•ผํ•œ๋‹ค. ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ํ•œ๋ฒˆ์— ๊ฐ€์ ธ์˜ค์ง€ ๋ชปํ•˜๋Š” ๊ฒƒ์„ `Under-fetching` ์ด๋ผ๊ณ  ํ•œ๋‹ค.

> ์„œ๋ฒ„์— ์š”์ฒญ๋Ÿ‰์ด ์ฆ๊ฐ€ํ•˜๊ฒŒ ๋จ.

### GraphQL์˜ ๋“ฑ์žฅ

์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ, ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์— ํ•„์š”ํ•œ ๊ฒƒ์„ ์ตœ์ ํ™”ํ•˜์—ฌ ํ•œ๋ฒˆ์˜ ์š”์ฒญ์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์˜ค๋Š” ๊ฒƒ์„ ์ฃผ ๋ชฉํ‘œ๋กœ ํ•˜์—ฌ ๋งŒ๋“ค์–ด์กŒ๋‹ค.

`GraphQL`๊ณผ `SQL`์€ ๊ฐ™์€ Query Language์ด๋‹ค. ๊ฐ„๋‹จํžˆ ๋งํ•ด์„œ ์งˆ์˜ํ˜•์œผ๋กœ ์š”์ฒญํ•˜์—ฌ ํ•„์š”์— ๋”ฐ๋ฅธ ์‘๋‹ต์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

## ๐Ÿ˜Š ch1. Query๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ

### hello world๋ฅผ ํ•ด๋ณด์ž

```tsx
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 {
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`๋ฅผ ํ†ตํ•ด์„œ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•ด๋ณด์ž.

```json
query : "query { hello }"
```

๋ผ๋Š” ํ˜•์‹์˜ ์ฟผ๋ฆฌ๋ฅผ json ํ˜•์‹์œผ๋กœ ๋ณด๋‚ด๊ฒŒ ๋˜๋ฉด, ์ผ๋ฐ˜ Rest API์™€ ๊ฐ™์€ JSONํ˜•ํƒœ๋กœ ์‘๋‹ต์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค. ํ•ด๋‹น ํ…Œ์ŠคํŠธ๋Š” ์ด์— ๋Œ€ํ•œ ๋ถ€๋ถ„์„ ์ง๊ด€์ ์œผ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌ์„ฑํ–ˆ๋‹ค..

## ๐Ÿ˜Š ch2. ๊ฐ„๋‹จํ•˜๊ฒŒ RestAPI ์™€ GraphQL ๊ฐ„์˜ ๋น„๊ต

์ดˆ๊ธฐ ์ฑ•ํ„ฐ์—์„œ๋Š” database๋ฅผ ์‚ฌ์šฉํ•˜์ง€์•Š๊ณ  practice์— ๋Œ€ํ•ด์„œ ์†Œ๊ฐœํ•˜๋ ค๊ณ  ํ•œ๋‹ค.

### ๐Ÿšฉ์ดˆ๊ธฐ ์‹œ๋‚˜๋ฆฌ์˜ค ๊ตฌ์„ฑ

ํ”„๋กœํ•„ ์ •๋ณด, ๊ฒŒ์‹œ๋ฌผ, ๋Œ“๊ธ€์„ ํ”„๋ก ํŠธ์—์„œ ์š”์ฒญ์ด ํ•„์š”๋กœ ํ•  ๋•Œ:

- REST API : ํ”„๋กœํ•„ ์ •๋ณด, ๊ฒŒ์‹œ๋ฌผ, ๋Œ“๊ธ€์— ๋Œ€ํ•œ ์š”์ฒญ์„ ๋”ฐ๋กœ ๊ตฌ์„ฑํ•œ๋‹ค.
- GraphQL : Query ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ๋ฒˆ์— ์š”์ฒญ์œผ๋กœ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค.

### ๐ŸดREST API๋กœ ๊ตฌ์„ฑ

`/api/profile`
`/api/board/:id`
`/api/comment`
๋กœ ๊ตฌ์„ฑํ•  ๊ฒƒ์ด๋‹ค. ํ˜„์žฌ๋Š” ์ธ์ฆํ•˜๋Š” ๊ฒƒ์ด ๋ชฉ์ ์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์—, ์ธ์ฆ๋ถ€ ์—†์ด ๋ฌด์กฐ๊ฑด์ ์œผ๋กœ 1๋ฒˆuser์˜ profile์„ ์ฃผ๋„๋ก ํ•˜๊ฒ ๋‹ค.

### ๐Ÿณ๏ธGraphQL๋กœ ๊ตฌ์„ฑ

```graphQL
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
}
}
```

ํ•ด๋‹น ์ฟผ๋ฆฌ๋ฅผ ํ†ตํ•ด ํ•œ๋ฒˆ์— ์ ‘๊ทผ ๊ฐ€๋Šฅ, ํ•ด๋‹น ๋ถ€๋ถ„์—์„œ๋„ ์„ค๋ช…์— ๋ถˆํ•„์š”ํ•œ ๋‚ด์šฉ์€ ์ œ์™ธํ•˜์—ฌ ์ง„ํ–‰ํ–ˆ๋‹ค.

### โœ… ๊ฐ„๋‹จํ•œ ๋น„๊ต ๋ถ„์„

#### : ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์›ํ•˜๋Š” ์‘๋‹ต์„ ์ค€๋น„ํ•  ์ˆ˜ ์žˆ๋Š” graphQL

`Rest API` ๋Š” ์„œ๋ฒ„๊ฐ€ ๊ตฌ์„ฑํ•˜๊ณ  ์žˆ๋Š” ํ˜•ํƒœ๋ฅผ ํด๋ผ์ด์–ธํŠธ์— ํ•„์š”์— ๋”ฐ๋ผ ๋ณ€๊ฒฝํ•˜๋ ค๋ฉด ์ƒˆ๋กœ์šด api ๋ฅผ ๊ตฌ์„ฑํ•ด์•ผํ•˜๋Š” ๋ฒˆ๊ฑฐ๋Ÿฌ์›€์ด ์กด์žฌํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ, `GraphQL`์˜ ๊ฒฝ์šฐ์—๋Š” ๊ทธ ๋•Œ ๊ทธ๋•Œ ํ•„์š”ํ•œ ์ธ์ž๋งŒ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์‘๋‹ต์„ ๋ฐ›๋Š” ๊ฒƒ์— ์ž์œ ๋กญ๋‹ค.

#### : ๊ณผ์—ฐ ์‘๋‹ต ์†๋„๊ฐ€ ์ •๋ง ๋น ๋ฅผ๊นŒ? ์‹ค์ œ ์‹คํ—˜์„ ํ•ด๋ณด์ž

`Rest API` ์™€ `GraphQL`์—์„œ ์š”์ฒญ์— ๋”ฐ๋ฅธ ์†๋„ ์ฐจ์ด๊ฐ€ ๋‚˜ํƒ€๋‚  ์ˆ˜๋„ ์žˆ๋‹ค๊ณ  ํ–ˆ๋Š”๋ฐ, ์ •๋ง์ธ์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋™์ผ ์„œ๋ฒ„ ์ŠคํŽ™์—์„œ ์ด 5๋ฒˆ์˜ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•ด๋ดค๋‹ค.

`npm test perform`์„ ํ†ตํ•ด์„œ ์ด๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค!

nop

perform์— ๋Œ€ํ•œ test๋ฅผ ์ง„ํ–‰ํ•œ ๊ฒฐ๊ณผ 1.3 ~ 1.7 ๋ฐฐ ๋” ๋น ๋ฅธ ๊ฒƒ์œผ๋กœ ์ธก์ •๋˜์—ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•œ ๋ฒˆ์— ๋งŽ์€ ์š”์ฒญ๋Ÿ‰์ด client๊ฐ€ ํ•„์š”๋กœ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ํŽธํ•  ๊ฒƒ์ด๋‹ค.

> ๋งŽ์€ ํด๋ผ์ด์–ธํŠธ๋Š” ํ•˜๋‚˜์˜ ํŽ˜์ด์ง€ ๋‹จ์œ„์— ์—ฌ๋Ÿฌ ๋ฐ์ดํ„ฐ๋ฅผ ์–ป๊ธฐ ์œ„ํ•œ ์„œ๋กœ ๋‹ค๋ฅธ api์š”์ฒญ์„ ๋ฐ˜๋ณตํ•œ๋‹ค.

## ๐Ÿ˜Š ch3. Under-Fetching๊ณผ Over-Fetching์— ๋Œ€ํ•œ ์‚ฌ๋ก€์™€ GraphQL์„ ํ†ตํ•œ ๊ทน๋ณต

### โฌ‡๏ธ Under-Fetching & ๐Ÿ“ˆ Over-Fetching

GraphQL์ด Rest API์˜ Under-Fetching๊ณผ Over-Fetching ๊ฐ™์€ ์ƒํ™ฉ์„ ์–ผ๋งˆ๋‚˜ ์ž˜ ๊ทน๋ณตํ•˜๋Š”์ง€์— ๋Œ€ํ•ด์„œ ์†Œ๊ฐœํ•˜๋ ค๊ณ  ํ•œ๋‹ค.

`Under-Fetching`๋Š” ์œ„์˜ ์˜ˆ์ œ์™€ ๋น„์Šทํ•˜๋‹ค.

๋จผ์ € REST ๊ตฌ์กฐ๋ฅผ ์‹œ์ž‘์œผ๋กœ GraphQL๊นŒ์ง€ ์ž‘์„ฑํ•ด๋ณด์ž.

#### ๐ŸšฉUnder-Fetching ์‹œ๋‚˜๋ฆฌ์˜ค

์—ฌํ–‰ ๋ฆฌ๋ทฐ ์›น์‚ฌ์ดํŠธ์—์„œ ์‚ฌ์šฉ์ž์˜ ํ”„๋กœํ•„ ์ •๋ณด๋ฅผ ํฌํ•จํ•œ ํŠน์ • ์‚ฌ์šฉ์ž์˜ ์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ ๋ชฉ๋ก์„ ํด๋ผ์ด์–ธํŠธ์—์„œ ์š”์ฒญํ•˜๋Š” ์ƒํ™ฉ์„ ๊ณ ๋ คํ•ด๋ณด์ž. ์‚ฌ์šฉ์ž๋Š” ์—ฌ๋Ÿฌ ๋ฆฌ๋ทฐ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ฐ ๋ฆฌ๋ทฐ์—๋Š” ์ž‘์„ฑ์ž์˜ ์ •๋ณด๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋‹ค.

#### ๐ŸšฉOver-Fetching ์‹œ๋‚˜๋ฆฌ์˜ค

ํ˜„์žฌ ์›น์—์„œ ์‚ฌ์šฉ์ž์— ๋Œ€ํ•œ ๊ธฐ๋ณธ ์ •๋ณด (์ด๋ฆ„๊ณผ ์ด๋ฉ”์ผ)๋งŒ์„ ๋ณด์—ฌ์ฃผ๋ ค๊ณ  ํ•œ๋‹ค. ํ•ด๋‹น ์‚ฌํ•ญ์„ ๊ณ ๋ คํ•ด๋ณด์ž.

#### ๐Ÿ—‚๏ธ ์š”๊ตฌ์‚ฌํ•ญ์— ๋”ฐ๋ฅธ ํ•„์š” ์š”์†Œ ์ถ”์ถœ

์—ฌ๊ธฐ์„œ ํ•„์š”ํ•œ ๋ถ€๋ถ„์„ ์ถ”์ถœํ•ด๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

- RestAPI
- ์œ ์ € ์ „์ฒด ์ •๋ณด - `/api/user`
- ์œ ์ € ํ”„๋กœํ•„ ์ •๋ณด - `/api/user/:userId`
- ์‚ฌ์šฉ์ž ๋ฆฌ๋ทฐ ๋ชฉ๋ก - `/api/user/:userId/review`
- ๋ฆฌ๋ทฐ ์ƒ์„ธ ์ •๋ณด - `/api/review/:reviewId`
- GraphQL

- typeDef Schema

```tsx
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
- restapi
- api
- routes
- review.ts
- user.ts
- index.ts
- loaders
- index.ts
- app.ts

#### ๐Ÿ’ซperformance

- Under-Fetching

| Test Description | REST API Performance (ms) | GraphQL API Performance (ms) |
| ------------------- | ------------------------------------------ | ------------------------------------------- |
| Measure Performance | 38.17 | 14.33 |
| Image Data | ![alt text](./images/ch3-rest-perform.png) | ![alt text](./images/ch3-graph-perform.png) |

- Over-Fetching

| Test Description | REST API Performance (ms) | GraphQL API Performance (ms) |
| ------------------- | ------------------------------------------- | -------------------------------------------- |
| Measure Performance | 9.13 | 20.4 |
| Image Data | ![alt text](./images/ch3-rest-perform2.png) | ![alt text](./images/ch3-graph-perform2.png) |

`npm test perform`์„ ํ†ตํ•ด ์„ฑ๋Šฅ์„ ์ธก์ •ํ•ด๋ณผ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

#### ๐Ÿ’ซ์„ฑ๋Šฅ์— ๋Œ€ํ•œ ์ฐจ์ด๊ฐ€ ์กด์žฌํ•˜๋Š” ์ด์œ 

๊ฐ„๋‹จํ•˜๊ฒŒ ์˜ˆ์‹œ๋ฅผ ๋“ค์–ด์ฃผ๊ฒ ๋‹ค. ์ด ๊ฒƒ์€ ๋งˆ์น˜ Buffering ๊ฐœ๋…๊ณผ ๋น„์Šทํ•˜๋‹ค. ๊ณ„๋ž€์„ ๊ฐ€์ง€๊ณ  ์˜ฌ ๋•Œ, `๋ฐ”๊ตฌ๋‹ˆ๋ฅผ ๊ฐ€์ง€๊ณ  ํ•œ๋ฒˆ์— ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ`๊ณผ `1๊ฐœ์”ฉ ์™”๋‹ค๊ฐ”๋‹ค ํ•˜๋ฉด์„œ ๊ฐ€์ ธ ์˜ค๋Š” ๊ฒƒ` ๋”ฑ GraphQL๊ณผ Rest API๋Š” ํ•ด๋‹น ์˜ˆ์‹œ์™€ ๊ฐ™์€ ์ฐจ์ด๊ฐ€ ๋‚œ๋‹ค.

**_Under-Fetching์˜ ๊ฒฝ์šฐ_** ๋Š” REST API ์—์„œ ํ•„์š”๋กœ ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด์„œ๋Š” ์—ฌ๋Ÿฌ๋ฒˆ์˜ ์š”์ฒญ์ด ํ•„์š”ํ•œ ๊ฒƒ์ด๋‹ค. ๊ฒฐ๊ตญ ๋™์ผํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์–ป๋Š”๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋ฉด `์™”๋‹ค ๊ฐ”๋‹ค๊ฑฐ๋ฆฌ๋Š” ์ˆ˜๊ณ `๋งŒ ๋” ์ถ”๊ฐ€ ๋œ ๊ฒƒ์ด๋‹ค.

์ด ๊ฒƒ์ด ๊ฐ„๋‹จํžˆ ๋งํ•ด ์„ฑ๋Šฅ์ฐจ์ด์— ํฐ ์š”์ธ์ด ๋œ ๊ฒƒ์ด๋‹ค.

์ด๋ ‡๊ฒŒ ๋งํ•˜๋ฉด graphql ๋งน์‹ ๋ก ์ž์™€ ๊ฐ™์ด ๋Š๊ปด์งˆ ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ๊ทธ๋ ‡์ง€๋Š” ์•Š๋‹ค. ์ฟผ๋ฆฌ ๊ตฌ์กฐ๊ฐ€ ์•„์ง๊นŒ์ง„ ๋‹จ์ˆœํ•ด์„œ ๊ดœ์ฐฎ์ง€๋งŒ, ์œ„์— `recursive ํ•œ ๊ตฌ์กฐ๋ฅผ ํ—ˆ์šฉ`ํ•œ๋‹ค๋Š” ๋ง์„ ๋ดค๋‹ค๋ฉด ์˜ˆ์ƒํ•˜๊ฒ ์ง€๋งŒ, ์ฟผ๋ฆฌ ๊ตฌ์กฐ๊ฐ€ ๋ณต์žกํ•ด์งˆ ์ˆ˜๋ก graphql ์—์„œ์˜ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ๋„ ์—ผ๋‘ํ•ด๋‘๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.

๊ทธ๋Ÿฌํ•œ ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ์ œ์™ธํ•˜๋ฉด ๋งŽ์€ ์ด์ ๋“ค์ด ์กด์žฌํ•œ๋‹ค.

1. ๋ณต์ˆ˜ ์š”์ฒญ์˜ ๊ฐ์†Œ
2. ์ •ํ™•ํ•œ ๋ฐ์ดํ„ฐ ์š”์ฒญ (ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋งŒ ๊ฐ€๋Šฅ)
3. ๋„คํŠธ์›Œํฌ ํŠธ๋ž˜ํ”ฝ ๊ฐ์†Œ(๋‹จ์ผ ์š”์ฒญ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—)

์ด๋Ÿฌํ•œ, ์ด ์ ์€ ์˜คํžˆ๋ ค ๋‹ค์–‘ํ•œ ์„œ๋น„์Šค๋ฅผ ๋งŒ๋“œ๋Š”๋ฐ ํฐ ๋„์›€์„ ์ค„ ๊ฒƒ์ด๋ผ ํ™•์‹ ํ•œ๋‹ค.

**Over-Fetching ์˜ˆ์ œ์˜ ๊ฒฝ์šฐ**๋Š” graphql์—์„œ `์˜ค๋ฒ„ํ—ค๋“œ`๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์ข‹์€ ์‚ฌ๋ก€๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค.

> ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค: ๋ฐฉ๊ธˆ๊นŒ์ง€๋งŒํ•ด๋„ GraphQl์ด ์ข‹๋‹ค๊ณ  ํ–ˆ์ž–์•„์š”!

> **๋ฌผ๋ก ์ด๋‹ค. ํ•˜์ง€๋งŒ ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ๊ณ ๋ คํ•ด์•ผํ•œ๋‹ค.**

์—ฌ๊ธฐ์„œ ์ž ๊น ์ฃผ๋ชฉํ•˜๋ฉด ์ข‹์€ ์ ์€ Response Size์ด๋‹ค. GraphQL์ด Rest API ๋ณด๋‹ค ํ›จ์”ฌ ์ ๋‹ค. ํ˜„์žฌ ์‹คํ—˜ ์ž์ฒด๋Š” Local์—์„œ ์ง„ํ–‰ํ–ˆ์ง€๋งŒ, ์—ฌ๋Ÿฌ remote ํ†ต์‹ ์ด ์žˆ์„ ๋•Œ Response Size๊ฐ€ ๋‚ฎ์€ ์ฆ‰, "๋Œ€์—ญํญ"์ด ๋‚ฎ์€ GraphQL์ด ์œ ๋ฆฌํ•ด์งˆ ์ˆ˜ ์žˆ๋‹ค.

#### GraphQL์˜ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์ด์œ 

GraphQL์—์„œ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์ด์œ ๋Š” ์ฟผ๋ฆฌ๋ฅผ ํ†ตํ•œ ์งˆ์˜๋‚˜ ์š”๊ตฌ์— ๋งž๊ฒŒ ๋ฐ์ดํ„ฐ ํ•ด์„๊ณผ์ •์„ ๊ฑฐ์น˜๊ธฐ ๋•Œ๋ฌธ์— ์‘๋‹ตํ•  ๋ฐ์ดํ„ฐ๋ฅผ ๋งŒ๋“ค์–ด๋‚ด๋Š”๋ฐ๊นŒ์ง€ ์‹œ๊ฐ„์ด ์˜ค๋ž˜๊ฑธ๋ฆฌ๋Š” ๊ฒƒ์ด๋‹ค.

์ด๋ฅผ ์ฟผ๋ฆฌ ์ตœ์ ํ™”, Resolver ์ตœ์ ํ™” ๋“ฑ๊ณผ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ํ•ด์†Œํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋Š” ์ถ”ํ›„ ์ฑ•ํ„ฐ์—์„œ ์†Œ๊ฐœํ•  ์˜ˆ์ •์ด๋‹ค.

์ง€๊ธˆ๊นŒ์ง€์˜ ๋‚ด์šฉ์œผ๋กœ ์•Œ์•˜์œผ๋ฉด ์ข‹๊ฒ ๋Š” ์ ์€ ์„œ๋กœ๊ฐ„์˜ **ํŠธ๋ ˆ์ด๋“œ ์˜คํ”„**๊ฐ€ ๋ถ„๋ช… ์กด์žฌํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.