🔵 REST 방식 엔드포인트 여러 개
"사용자 1명 + 그 사람 글 목록 + 각 글의 댓글"을 가져오려면
여러 번 왕복해야 합니다.
GET/users/1사용자 정보
GET/users/1/posts글 목록
GET/posts/101/comments댓글(글1)
GET/posts/102/comments댓글(글2)
🩷 GraphQL 방식 엔드포인트 1개
똑같은 요구사항을 쿼리 하나로 표현해서
단일 엔드포인트 POST /graphql 에 보냅니다.
query {
user(id: 1) {
name
posts {
title
comments { text }
}
}
}
📊 왕복(round-trip) 횟수
REST 요청 수
0
GraphQL 요청 수
0
🎯 필드 선택으로 보는 오버페칭 vs 언더페칭
체크박스로 화면에 실제로 필요한 필드만 골라보세요.
REST는 서버가 정해둔 고정 응답을 그대로 주지만(과다·부족 발생), GraphQL은 요청한 필드만 정확히 돌려줍니다.
REST 응답 고정 스키마
응답 크기(추정)
—
GraphQL 응답 선택한 필드만
응답 크기(추정)
—
⚠️ N+1 문제 리졸버 함정
글 목록을 가져온 뒤 각 글마다 작성자를 따로 조회하면,
글이 N개일 때 쿼리는 1(글 목록) + N(작성자)번 실행됩니다.
GraphQL 자체의 문제가 아니라 리졸버를 순진하게 짤 때 생기는 함정이며, DataLoader로 배치 처리해 해결합니다.
DataLoader 배치 적용 OFF
실행된 DB 쿼리 수
0
🐍 서버 쪽 코드 예시 (Strawberry + FastAPI)
@strawberry.type
class User:
id: int
name: str
email: str
@strawberry.field
def posts(self) -> list["Post"]:
# ❌ 이렇게 짜면 글마다 DB를 또 조회 → N+1
return db.query(Post).filter(Post.user_id == self.id).all()
@strawberry.type
class Query:
@strawberry.field
def user(self, id: int) -> User:
return db.query(User).get(id)
schema = strawberry.Schema(query=Query)
graphql_app = GraphQLRouter(schema)
app.include_router(graphql_app, prefix="/graphql") # 엔드포인트는 이거 하나뿐!
📐 한눈에 비교
| 기준 | REST | GraphQL |
| 엔드포인트 | 자원마다 여러 개 (/users, /posts, ...) | 단일 엔드포인트 (/graphql) |
| 응답 모양 | 서버가 정한 고정 스키마 | 클라이언트가 쿼리로 지정 |
| 흔한 문제 | 오버/언더페칭, 화면마다 새 엔드포인트 | N+1 쿼리, 캐싱이 더 복잡함 |
| HTTP 캐싱 | GET + URL 기반 캐싱 쉬움 | 대부분 POST라 표준 캐싱 어려움 |
| 대표 사용처 | 공개 API, 단순 CRUD 서비스 | GitHub API v4, Shopify, 복잡한 화면 다수 |