GraphQL이란? RESTful API와의 차이점부터 기본 개념까지 정리!
GraphQL이란?
먼저, GraphQL이 어떻게 등장하게 되었는지 살펴보자.
GraphQL(Query Language) 은 페이스북(Facebook)이 2012년 내부 프로젝트로 개발한 후, 2015년에 오픈소스로 공개한 API 쿼리 언어다.
페이스북은 처음에 RESTful API를 활용해 데이터를 제공했지만, 안드로이드, iOS 등 다양한 클라이언트마다 필요한 데이터의 형태가 달랐다.
이로 인해 각 클라이언트에 맞춰 개별적인 API를 개발해야 했고, 시간이 지날수록 API 엔드포인트가 증가하면서 유지보수 비용도 급격히 증가했다.
이 문제를 해결하기 위해, 클라이언트가 원하는 형태로 데이터를 요청하고 수정할 수 있는 쿼리 언어인 GraphQL이 탄생했다.
그렇다면, GraphQL은 RESTful API와 어떤 차이점이 있을까?
GraphQL vs RESTful API
차이점을 표로 한번 정리해봤다.
비교 항목 | GraphQL | REST API |
---|---|---|
데이터 요청 방식 | 원하는 데이터만 요청 가능 | 정해진 구조의 데이터 반환 |
엔드포인트 개수 | 1개 (단일 엔드포인트) | 여러 개 (리소스별 엔드포인트) |
Over-fetching 문제 | ❌ 해결됨 (필요한 데이터만 요청) | ✅ 발생 가능 (불필요한 데이터 포함) |
Under-fetching 문제 | ❌ 해결됨 (한 번 요청으로 필요한 데이터 가져옴) | ✅ 발생 가능 (추가 요청 필요) |
버전 관리 | 필요 없음 (단, 이전 버전 API와 호환성 필요) | 필요함 (API 버전 v1, v2 등) |
오류 검사 | 잘못된 요청은 스키마 구조로 거부(이로 인해 오류 메시지 자동 생성) | 클라이언트 측에서 반환된 데이터 유효성 검사 필요 |
Query, Mutation, Subscription 개념 및 예제
간단하게 3가지 개념을 간단한 예제를 통해 알아보자.
Query
GraphQL에서 Query는 데이터를 조회(읽기)할 때 사용한다. REST API의 ‘GET’ 요청과 유사하지만, Query Language이기 때문에 SQL의 ‘SELECT’문처럼 필요한 데이터만 선택적으로 가져올 수 있다.
REST API 방식
- 요청
GET /users/1
- 응답
{ "id": 1, "name": "kyeonkim", "email": "kyeonkim@example.com", "location": "Seoul" }
-> Over-fetching 발생: 클라이언트가 ‘name’과 ‘email’만 필요해도, 불필요한 ‘location’ 값까지 포함된다. ‘email’만 가져오려면 기존 메서드를 수정하거나 새로운 API 엔드포인트를 추가해야 한다.
-> Under-fetching 발생: 반대로, ‘name’만 가져오는 메서드를 만들었는데 사용자 전체 정보가 필요해지면, 별도의 API 엔드포인트를 또 추가해야 한다.
GraphQL 방식(사용자 데이터 요청)
- 요청
query { user(id: 1) { name email } }
- 응답
{ "data": { "user": { "name": "kyeonkim", "email": "kyeonkim@example.com" } } }
-> 필요한 데이터만 가져올 수 있다.(Over-fetching, Under-fetching 해결!)
-> 서버는 만들어두기만해도 클라이언트가 입맛대로 데이터 구조를 정의해서 가져올 수 있다.
Mutation
Mutation은 데이터를 변경(쓰기)할 때 사용된다. REST API에서 ‘POST’, ‘PUT’, ‘DELETE’ 요청과 유사하다.
REST API 방식(새 사용자 추가)
- 요청
POST /users
Content-Type: application/json
{
"name": "kyeonkim",
"email": "kyeonkim@example.com"
}
- 응답
{ "id": 1, "name": "kyeonkim", "email": "kyeonkim@example.com" }
GraphQL 방식
- 요청
mutation { createUser(name: "kyeonkim", email: "kyeonkim@example.com") { id email } }
- 응답
{ "data": { "createUser": { "id": 1, "email": "kyeonkim@example.com" } } }
-> GraphQL은 요청에서 어떤 데이터를 반환받을지 선택할 수 있다!
Subscription
Subscription은 실시간 데이터를 업데이트할 때 사용된다.
WebSocket 기반으로 동작하며, 채팅, 알림 시스템, 실시간 데이터 스트리밍
에 활용할 수 있다.
간단한 채팅 예시를 보며 익숙해져보자.
- A, B, C가 아래 subscription을 통해 ‘chatRoom’을 구독을 했다.
subscription { chatRoom { id content sender } }
- C가 채팅방에 메시지를 보낸다.
mutation { sendMessage(content: "아~반갑고", sender: "반갑이") { id content sender } }
- C는 현재 ‘chatRoom’을 구독한 상태이므로 A, B는 자동으로 메시지를 받는다.
{ "data": { "chatRoom": { "id": 1, "content": "아~반갑고", "sender": "반갑이" } } }
즉, A, B, C는 같은 채팅방을 구독하고 있기 때문에, A와 B가 따로 요청하지 않아도 C가 메시지를 보낼 때마다 자동으로 데이터를 받을 수 있다.
GraphQL vs REST API, 어떤 걸 선택할까?
GraphQL이 유리한 경우
- 클라이언트마다 필요한 데이터가 다를 때 → Over-fetching & Under-fetching 문제 해결
- API 엔드포인트가 너무 많을 때 → 단일 엔드포인트로 효율적 관리
- 대역폭이 제한되어 있으며 요청 및 응답 수를 최소화하려는 경우
REST API가 유리한 경우
- 애플리케이션 규모가 작고 데이터가 덜 복잡한 경우 → 학습 비용이 적고 캐싱이 쉬움
- 모든 클라이언트에서 유사하게 사용되는 데이터와 작업이 있는 경우
- 복잡한 데이터 쿼리가 필요 없는 경우
마무리
GraphQL은 REST API의 한계를 보완하며, 필요한 데이터만 요청하고 단일 엔드포인트로 효율적으로 관리할 수 있는 강력한 쿼리 언어다. 하지만, 복잡한 쿼리는 서버 부하를 증가시킬 수 있으며, 캐싱 및 보안 관리가 필요하다는 점도 고려해야 한다.
항상 생각하지만 개발자는 상황에 따라 적절한 방식을 선택하는 것이 중요하다!
참조
https://www.youtube.com/watch?v=xiE9-S7s9rs
https://chanhuiseok.github.io/posts/gql-1/
https://aws.amazon.com/ko/compare/the-difference-between-graphql-and-rest/
https://graphql.org/learn/
Leave a comment