stack-analysis
CHAPTER 38 / 90
읽기 약 2분
FUNCTION
GraphQL vs REST: 실전 선택 기준
핵심 개념
over/under-fetching·N+1·DataLoader·실전 도입 기준 — 무엇이 적합한가.
본문
REST vs GraphQL 비교
| 측면 | REST | GraphQL |
|---|---|---|
| 페치 | 여러 요청 | 단일 요청 |
| 응답 | 고정 | 클라이언트 선택 |
| 캐싱 | HTTP 자동 | 자체 구현 |
| 학습 곡선 | 낮음 | 중 |
| 도구 | 풍부 | 풍부 |
| 파일 업로드 | 표준 | 비표준 |
| 적합 | 공개 API·간단 | 복잡 UI·여러 리소스 |REST의 over-fetching 문제
// 클라이언트는 user.name만 필요한데 전체 받음
GET /users/123
{
"id": "123",
"name": "Alice",
"email": "...", // 불필요
"phone": "...", // 불필요
"address": {...}, // 불필요
"preferences": {...}, // 불필요
}
// 또는 under-fetching — 여러 요청 필요
GET /users/123 // 사용자
GET /users/123/posts // 포스트
GET /users/123/followers // 팔로워
→ 3번의 round tripGraphQL — 한 번에
query {
user(id: "123") {
name
posts(limit: 5) {
title
likes
}
followers(limit: 10) {
name
avatar
}
}
}
# 응답 — 정확히 요청한 데이터만
{
"user": {
"name": "Alice",
"posts": [{"title": "...", "likes": 42}, ...],
"followers": [{"name": "Bob", "avatar": "..."}, ...]
}
}GraphQL 서버 (Apollo)
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
const typeDefs = `#graphql
type User {
id: ID!
name: String!
email: String!
posts(limit: Int = 10): [Post!]!
}
type Post {
id: ID!
title: String!
content: String!
author: User!
}
type Query {
user(id: ID!): User
posts(limit: Int = 20, cursor: String): [Post!]!
}
type Mutation {
createPost(title: String!, content: String!): Post!
}
`;
const resolvers = {
Query: {
user: async (_: any, { id }: { id: string }, ctx: Context) => {
return ctx.userRepo.findById(id);
},
posts: async (_: any, { limit, cursor }: any, ctx: Context) => {
return ctx.postRepo.findMany({ limit, cursor });
},
},
User: {
posts: async (user: User, { limit }: { limit: number }, ctx: Context) => {
return ctx.postLoader.load(user.id); // DataLoader로 N+1 방지
},
},
Mutation: {
createPost: async (_: any, args: any, ctx: Context) => {
if (!ctx.userId) throw new GraphQLError('Unauthorized');
return ctx.postRepo.create({ ...args, authorId: ctx.userId });
},
},
};
const server = new ApolloServer({ typeDefs, resolvers });DataLoader — N+1 방지
import DataLoader from 'dataloader';
// 사용자별 포스트 배치 로더
function createPostLoader() {
return new DataLoader<string, Post[]>(async (userIds) => {
const posts = await db.post.findMany({
where: { authorId: { in: [...userIds] } },
});
return userIds.map(id => posts.filter(p => p.authorId === id));
});
}
// Context에 로더 주입
const server = new ApolloServer({
typeDefs, resolvers,
context: ({ req }) => ({
userId: getUserId(req),
postLoader: createPostLoader(), // 요청별 새 인스턴스
}),
});
// 효과:
// 100명 사용자 → 100번 쿼리 (N+1)
// DataLoader → 1번 쿼리 (배치 + 캐싱)언제 무엇을 선택?
GraphQL 적합:
- 모바일 앱 (대역폭 제한)
- 복잡한 UI (대시보드·관리자)
- 여러 리소스 동시 페치
- BFF (Backend For Frontend) 패턴
REST 적합:
- 공개 API (생태계 풍부)
- 캐싱이 중요 (CDN)
- 단순 CRUD
- 마이크로서비스 간 통신
- 파일 업로드
하이브리드 (가장 흔함):
- GraphQL: 프론트엔드 → BFF
- REST/gRPC: 서비스 간한국 시장 채택률
2026년 한국 백엔드:
- REST: 80% (압도적)
- GraphQL: 15% (당근·토스·쿠팡 일부)
- gRPC: 5% (서비스 간 내부)
스타트업: REST 우선
대규모 (네카라쿠배): 혼합다음 챕터
CH.39 "PostgreSQL 성능 튜닝: EXPLAIN ANALYZE".
AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude
무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6
내 코드의 GraphQL vs REST 부분을 분석해서 실전 분석 + 개선 우선순위를 알려줘.
ChatGPT
무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro
GraphQL vs REST 관련 인기 라이브러리/패턴 5개를 비교 분석해서 패턴 추출를 알려줘.
Gemini
무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro
내 프로젝트 전체에서 GraphQL vs REST 최적화 가능 위치를 보고해줘.
Grok
무료: Grok 4.1 / SuperGrok $30/mo
2026년 한국 백엔드 시장의 GraphQL vs REST 트렌드를 솔직히 알려줘.
⭐ 이것만 기억하세요
GraphQL vs REST: 실전 선택 기준은 이 3가지만 확실히 잡으세요
1.GraphQL은 over/under-fetching 해결 — 복잡 UI에 적합
2.DataLoader로 N+1 방지 — 배치 + 요청별 캐싱
3.REST는 여전히 표준 — 공개 API·캐싱·생태계
공유하기
진행도 38 / 90