[백엔드 기본 개념 정리] GraphQL
GraphQL
GraphQL은 2015년에 페이스북에 의해 공개된 쿼리 언어(Query Language)로 클라이언트 중심적으로 원하는 데이터를 정확하게 요청할 수 있도록 한다.
탄생 배경 — REST API의 한계
REST API는 오랫동안 웹의 표준처럼 사용되었지만 프론트엔드가 별도의 개발 분야로 분리되고 중요성과 복잡도가 올라가면서 REST가 가진 구조적 제약은 한계를 드러내기 시작했다.
REST는 자원 중심(Resource Oriented)으로, URI로 명확한 리소스를 표현하고 HTTP 메소드로 행동을 나타낸다. 이 구조는 단순하고 직관적이지만 서비스가 커지면서 발생하는 단점들이 있다.
예를 들어 클라이언트가 다음 데이터를 필요로 한다고 하자.
- 사용자 이름
- 사용자가 작성한 게시글 목록
- 각 게시글에 달린 댓글 수 REST 방식이라면 각 리소스에 대해 아래처럼 여러 번의 요청을 해야 한다.
- /users/1 → 이름을 포함한 사용자 전체 정보
- /users/1/posts → 게시글 목록
- 각 게시글마다 /posts/:id/comments → 댓글 수
결국, over-fetching(필요 이상의 데이터)과 under-fetching(필요한 데이터를 다 못 받는 현상)이 반복된다. 이런 비효율을 해결하기 위해 등장하게 된 것이 GraphQL이다.
GraphQL의 핵심 개념
GraphQL은 API의 동작 방식을 데이터 질의(Query) 중심으로 바꾼다.
REST처럼 자원 단위로 요청하는 것이 아니라, 클라이언트가 필요한 데이터의 구조를 직접 선언하는 방식이다.
앞서 REST API에서 여러번의 요청을 보내야했던 데이터를 얻는 과정이 GraphQL에서는 아래와 같은 쿼리 한번으로 처리가 가능하며 정확히 필요로 하는 데이터들만 요청할 수 있다.
요청
{
user(id: 1) {
name
posts {
title
commentCount
}
}
}
응답
{
"data": {
"user": {
"name": "Lucas",
"posts": [
{ "title": "GraphQL", "commentCount": 12 },
{ "title": "REST API vs GraphQL", "commentCount": 5 }
]
}
}
}
스키마 (Schema)
GraphQL 서버 구현을 위해서는 API의 규칙을 정의한 계약서이자, 데이터 구조의 청사진인 스키마 정의가 반드시 필요하다. 스키마에는 클라이언트가 사용할 수 있는 쿼리와 데이터 타입이 명세되며 이를 통해 자동 문서화, 타입 검증, 개발자 경험 상승 등의 이점을 취할 수 있다.
예시
type User {
id: ID!
name: String!
posts: [Post!]!
}
type Post {
id: ID!
title: String!
commentCount: Int!
}
type Query {
user(id: ID!): User
}
REST와의 차이
| 특징 | REST | GraphQL |
|---|---|---|
| 데이터 구조 | 고정된 엔드포인트 기반 | 클라이언트 정의형 쿼리 기반 |
| 통신 방식 | HTTP Method 중심 | Query/Mutation 중심 |
| 데이터 요청 | 클라이언트가 여러 엔드포인트에 요청을 보내야 함 | 단일 엔드포인트에 클라이언트가 쿼리 언어로 원하는 데이터 구조를 명시 |
| 응답 데이터 | 필요한 데이터 외에 추가 정보가 포함될 수 있음 | 요청한 데이터만 받음 (Over-fetching 문제 해결) |
| 버전 관리 | /v1, /v2 등으로 분리 | 스키마 변경으로 대응 |
| 문서화 | Swagger/OpenAPI | Schema 자체가 문서 |
Mutation
Mutation은 GraphQL에서 데이터 변경에 사용되는 양식으로 REST의 POST, PUT, DELETE 메소드에 해당하는 개념이다.
요청
mutation {
createPost(input: { title: "새 글", userId: 1 }) {
id
title
}
}
응답
{
"data": {
"createPost": {
"id": 42,
"title": "새 글"
}
}
}
mutation에서도 데이터를 수정 후 다시 필요한 데이터만 받는 흐름을 따른다.
단점
물론 GraphQL이 완벽한 대안은 아니며 아래와 같은 단점들을 가진다.
- 엔드포인트가 하나뿐이기 때문에 캐싱 구현이 어렵다.
- 데이터 쿼리 작업을 처리하기 위한 서버 복잡도가 높아진다.
- 단순한 API엔 오히려 과한 선택일 수 있다.
⇒ React 기반 대시보드, 모바일 앱 같이 프론트엔드 규모가 크고 비중이 높은 많은 환경에 적합하며 단순한 CRUD 위주의 서비스에서는 여전히 REST가 효율적이다.