1편. GraphQL이 필요한 이유: REST와의 차이 완벽 이해
📚 목차
1. REST API의 구조적 한계와 N+1 문제
2. GraphQL 철학과 등장 배경
3. 데이터 요청 방식 비교: REST vs GraphQL
4. GraphQL 도입 판단 기준 (실무 시나리오)
✔ 마무리 - 실무 선택의 기준
현대의 웹 애플리케이션에서는 서버로부터 데이터를 요청하고 응답받는 구조가 사용자 경험에 큰 영향을 미칩니다.
특히 백엔드와 프론트엔드 간의 데이터 교환 방식은 API 설계 철학에 따라 크게 달라지며, 대표적인 방식으로 REST와 GraphQL이 있습니다.
이 글에서는 REST와 GraphQL의 구조적 차이, 요청 방식, 그리고 실무에서 GraphQL을 도입할지 판단하는 기준을 예시와 함께 살펴봅니다.
1. REST API의 구조적 한계와 N+1 문제
REST(Representational State Transfer)는 HTTP 기반의 리소스 중심 아키텍처로, 직관적인 설계와 높은 활용도로 널리 사용됩니다.
각 자원(리소스)은 고유한 URL로 식별되며, GET, POST, PUT, DELETE 등의 HTTP 메서드를 통해 데이터를 조회·생성·수정·삭제할 수 있습니다..
예를 들어, 사용자와 게시글 데이터를 다루는 REST API는 다음과 같이 구성될 수 있습니다.
GET /users → 사용자 목록 조회
GET /users/1 → ID가 1인 사용자 정보 조회
GET /users/1/posts → ID가 1인 사용자의 게시글 목록 조회
이 방식은 구조가 단순하고 명확하다는 장점이 있지만, 관계형 데이터를 처리하는 실제 서비스 환경에서는 N+1 API 호출 문제가 자주 발생합니다
🔷N+1 문제 예시
사용자 목록과 각 사용자의 게시글 제목을 함께 화면에 표시해야 하는 경우를 가정해 보겠습니다.
1. 사용자 목록 조회
GET /users
[
{ "id": 1, "name": "Alice" },
{ "id": 2, "name": "Bob" },
...
]
2. 각 사용자의 게시글 별도 조회
GET /users/1/posts
GET /users/2/posts
GET /users/3/posts
...
이 경우, 사용자 수가 10명이라면 1번의 목록 요청 + 사용자 수만큼의 개별 요청 = 총 11번의 API 호출이 필요합니다.
이러한 방식은 다음과 같은 실무 문제로 이어질 수 있습니다
🔸네트워크 지연 증가: 요청이 많아질수록 전체 응답 시간이 느려집니다.
🔸서버 부하 증가: 동일한 구조의 데이터를 반복적으로 요청하면서 서버 리소스를 낭비하게 됩니다.
🔸프론트엔드 로직 복잡도 상승: 비동기 요청의 병렬 처리, 결과 병합 등 추가 로직 구현이 필요합니다.
이러한 문제는 REST 설계 철학상 구조적으로 해결하기 어렵기 때문에, 실시간 데이터 응답성과 클라이언트 효율성이 중요한 환경에서는 큰 제약이 됩니다.
2. GraphQL 철학과 등장 배경
GraphQL은 Facebook에서 개발한 API 쿼리 언어로, 기존 REST 구조에서 나타나는 한계를 보완하고 클라이언트 주도 데이터 요청을 가능하게 합니다.
REST는 리소스별로 엔드포인트를 구분하고, 요청 시 사전에 정의된 응답 구조를 반환합니다.
반면 GraphQL은 단일 엔드포인트(/graphql)에서 모든 요청을 처리하며, 클라이언트가 필요한 데이터의 형태를 직접 선언하여 요청할 수 있습니다.
GraphQL의 주요 특징은 다음과 같습니다.
1. 단일 엔드포인트 사용
REST는 리소스마다 각각의 URL을 사용하지만, GraphQL은 /graphql 단일 엔드포인트에서 모든 요청을 처리합니다.
2. 필요한 필드만 선택적으로 요청 가능
클라이언트가 어떤 데이터가 필요한지를 명시하면, 서버는 그에 맞춰 정확한 필드만 응답합니다.
3. 관계형 데이터도 중첩 구조로 한 번에 조회 가능
사용자 → 게시글처럼 연관된 데이터를 하나의 쿼리로 연결하여 조회할 수 있습니다.

예를 들어, 사용자 목록과 각 사용자의 게시글 제목을 한 번에 가져오려면 다음과 같은 쿼리를 작성할 수 있습니다.
query {
users {
id
name
posts {
title
}
}
}
서버는 아래와 같이 요청된 데이터만 포함한 응답을 반환합니다.
{
"data": {
"users": [
{ "id": 1, "name": "Alice", "posts": [{ "title": "첫 번째 글" }] },
{ "id": 2, "name": "Bob", "posts": [{ "title": "Bob의 글" }] }
]
}
}
이처럼 GraphQL은 클라이언트가 필요한 데이터만, 요청한 구조 그대로 전달하므로, 네트워크 효율성과 데이터 활용 유연성을 동시에 확보할 수 있습니다.
3. 데이터 요청 방식 비교: REST vs GraphQL
REST 기반 API를 사용할 때 가장 자주 마주치는 문제 중 하나는 Over-fetching과 Under-fetching입니다.
이는 클라이언트가 실제로 필요로 하는 데이터 양과 API가 반환하는 데이터 양이 일치하지 않아서 발생합니다.

🔷 Over-fetching (과다 응답)
Over-fetching은 클라이언트가 요청한 정보보다 훨씬 더 많은 데이터를 받는 상황을 말합니다.
예를 들어, 사용자 이름만 필요한 경우에도 REST API는 전체 사용자 정보를 모두 반환합니다.
GET /users/1
→ 응답:
{
"id": 1,
"name": "Alice",
"email": "alice@example.com",
"address": "서울시 강남구 ...",
"createdAt": "2024-01-01",
"updatedAt": "2025-01-01"
}
위 예시에서 프론트엔드가 name 값만 사용하더라도, 응답에는 email, address, createdAt과 같이 사용하지 않는 필드가 포함됩니다.
이로 인해 네트워크 전송량이 불필요하게 증가하고, 클라이언트 측 렌더링 성능에도 영향을 줄 수 있습니다.
🔷 Under-fetching (과소 응답)
Under-fetching은 한 번의 요청으로 필요한 데이터를 모두 얻을 수 없어, 여러 번 API를 호출해야 하는 상황입니다.
관계형 데이터가 대표적인 예입니다.
GET /users/1
→ 사용자 정보만 응답
GET /users/1/posts
→ 게시글 목록 별도 요청 필요
위 시나리오에서 클라이언트가 사용자 이름과 게시글 제목 목록을 함께 보여주고 싶어도, REST 구조에서는 두 개 이상의 API 요청이 필요합니다.
이는 네트워크 지연과 서버 부하를 유발하며, 프론트엔드 로직도 복잡해집니다.
🔷 GraphQL의 선언형 쿼리로 해결
GraphQL은 이러한 문제를 구조적으로 해결합니다.
클라이언트는 필요한 필드를 명확히 지정하여 요청하고, 서버는 지정된 데이터만 반환합니다.
query {
user(id: 1) {
name
posts {
title
}
}
}
이 요청에 대한 응답은 다음과 같이 정확히 요청한 데이터 구조만 포함됩니다.
{
"data": {
"user": {
"name": "Alice",
"posts": [
{ "title": "첫 번째 글" },
{ "title": "두 번째 글" }
]
}
}
}
이 방식에서는 email, address와 같은 불필요한 필드가 포함되지 않으며, 사용자 정보와 게시글 목록을 한 번의 요청으로 가져올 수 있습니다.
그 결과 네트워크 효율성이 높아지고, 데이터 병합이나 추가 호출이 필요 없어 개발 속도와 유지보수성이 향상됩니다.
4. GraphQL 도입 시점과 실무 판단 기준
GraphQL은 모든 환경에서 무조건 REST를 대체하는 기술이 아니라, 특정한 조건에서 특히 강력한 효과를 발휘하는 도구입니다.
따라서 도입 여부를 판단할 때는 프로젝트 특성과 운영 환경을 함께 고려해야 합니다.
🔷 GraphQL 도입이 적합한 상황
🔸다양한 디바이스에서 동일한 API 활용이 필요한 경우
웹, 모바일, IoT 등 서로 다른 환경에서 하나의 API를 사용해야 할 때, GraphQL은 각 클라이언트가 자신에게 필요한 데이터만 선택적으로 요청할 수 있어 효율적입니다.
🔸프론트엔드 주도 개발(FE-Driven Development)이 중요한 경우
프론트엔드 개발자가 백엔드 변경 없이 필요한 데이터 구조를 직접 정의할 수 있어, UI 개발 속도와 유연성이 높아집니다.
🔸API 엔드포인트가 많아 관리가 복잡해진 경우
REST에서는 리소스별로 개별 엔드포인트를 만들어야 하지만, GraphQL은 단일 엔드포인트 구조로 API 관리가 단순화됩니다.
🔸Over-fetching / Under-fetching 문제가 반복되는 경우
GraphQL은 선언형 쿼리를 통해 필요한 데이터만 정확히 요청할 수 있어 네트워크 낭비를 줄입니다.
🔷 GraphQL 도입 시 고려해야 할 사항
🔸인증·인가 방식 재설계 필요
GraphQL은 HTTP 메서드 기반이 아니므로, 권한 제어를 스키마 단위나 리졸버 단위에서 설계해야 합니다.
예를 들어 특정 필드나 타입에 접근 권한을 부여하는 방식이 필요합니다.
🔸HTTP 캐싱이 어려움
REST는 URL 단위 캐싱이 가능하지만, GraphQL은 요청 내용이 동적이기 때문에 일반적인 HTTP 캐싱을 적용하기 어렵습니다.
대신 Apollo Client 캐시, Persisted Query, CDN 기반 캐싱 전략 등을 별도로 마련해야 합니다.
🔸쿼리 복잡도 관리 필요
GraphQL은 중첩 쿼리와 반복 쿼리를 허용하기 때문에, 무분별한 요청은 서버 자원을 과도하게 소모할 수 있습니다.
이를 방지하려면 쿼리 복잡도 제한(Query Cost Analysis)이나 최대 중첩 깊이 제한 등을 설정해야 합니다.
🔸REST와 병행 운영 전략 필요
기존 서비스에서 GraphQL을 전면 도입하기는 쉽지 않으므로, 일정 기간은 REST와 병행 운영이 필요합니다.
이 경우 마이그레이션 계획, 문서화, API Gateway 설정 등을 미리 준비해야 합니다.
✔ 마무리 - 실무 선택의 기준
REST와 GraphQL은 모두 검증된 API 설계 방식이며, 각각의 장단점이 분명합니다.
특히 GraphQL은 단순한 최신 기술 도입이 아니라, 데이터 요청의 주도권을 서버에서 클라이언트로 이동시키는 구조적 변화를 가져옵니다.
도입 여부를 판단할 때는 기술적 장점뿐만 아니라 팀의 개발 문화와 조직 구조, 데이터 모델의 복잡도, 보안 정책, 운영 전략까지 종합적으로 고려해야 합니다.
적절한 시점과 범위를 설정해 점진적으로 도입한다면, GraphQL은 네트워크 효율성을 높이고 개발 생산성을 향상시키는 강력한 도구가 될 것입니다.
※ 게시된 글 및 이미지 중 일부는 AI 도구의 도움을 받아 생성되거나 다듬어졌습니다.
'3.SW개발 > GraphQL 배우기' 카테고리의 다른 글
| 6편. GraphQL Scalar 타입 완전 정복 (0) | 2025.11.30 |
|---|---|
| 5편. GraphQL 스키마와 리졸버 구조 이해 (0) | 2025.11.30 |
| 4편. GraphQL 실무 아키텍처 설계: 도메인 구조와 책임 분리 (0) | 2025.11.27 |
| 3편. GraphQL Hello Query 실습: 첫 서버 구축하기 (0) | 2025.11.27 |
| 2편. GraphQL 서버 개발 환경 구축 (Node.js + TS) (0) | 2025.11.25 |