GraphQL vs REST API
Categories:tech
GraphQL vs REST API
발생
최근에 새로운 프로젝트를 시작하면서 API 설계에 대해 고민하고 있다. 기존에는 REST API를 주로 사용했는데, GraphQL에 대한 이야기를 자주 듣게 되었다.
GraphQL이 REST API의 문제점을 해결한다고 하는데, 정말 그런지 실제로 어떤 차이가 있는지 알아봐야겠다.
REST API란?
REST(Representational State Transfer)는 웹 서비스의 아키텍처 스타일이다.
REST의 특징
- 리소스 기반: URL로 리소스를 식별
- HTTP 메서드: GET, POST, PUT, DELETE 사용
- 무상태성: 각 요청이 독립적
- 캐시 가능: HTTP 캐싱 메커니즘 활용
REST API 예시
# 사용자 정보 조회
GET /api/users/123
# 사용자 목록 조회
GET /api/users
# 새 사용자 생성
POST /api/users
Content-Type: application/json
{
"name": "John Doe",
"email": "john@example.com"
}
# 사용자 정보 수정
PUT /api/users/123
Content-Type: application/json
{
"name": "John Smith"
}
GraphQL이란?
GraphQL은 Facebook에서 개발한 쿼리 언어이자 런타임이다.
GraphQL의 특징
- 단일 엔드포인트: 하나의 URL로 모든 요청 처리
- 클라이언트 중심: 클라이언트가 필요한 데이터만 요청
- 강타입 시스템: 스키마로 API 구조 정의
- 실시간 쿼리: Subscription으로 실시간 데이터 처리
GraphQL 예시
# 스키마 정의
type User {
id: ID!
name: String!
email: String!
posts: [Post!]!
}
type Post {
id: ID!
title: String!
content: String!
author: User!
}
type Query {
user(id: ID!): User
users: [User!]!
}
type Mutation {
createUser(name: String!, email: String!): User!
}
# 쿼리 예시
query GetUserWithPosts($userId: ID!) {
user(id: $userId) {
name
email
posts {
title
content
}
}
}
주요 차이점 비교
1. 데이터 페칭
REST API
# 사용자 정보
GET /api/users/123
# 사용자의 포스트
GET /api/users/123/posts
# 포스트의 댓글
GET /api/posts/456/comments
GraphQL
query {
user(id: "123") {
name
posts {
title
comments {
content
}
}
}
}
2. 오버페칭과 언더페칭
REST API의 문제점
# 오버페칭: 필요 없는 데이터까지 가져옴
GET /api/users/123
# 응답: { id, name, email, phone, address, birthDate, ... }
# 언더페칭: 여러 번 요청해야 함
GET /api/users/123
GET /api/users/123/posts
GET /api/users/123/followers
GraphQL의 해결책
# 필요한 데이터만 정확히 요청
query {
user(id: "123") {
name
posts {
title
}
followers {
name
}
}
}
3. 버전 관리
REST API
# API 버전 관리 필요
GET /api/v1/users/123
GET /api/v2/users/123
GraphQL
# 스키마 진화로 버전 관리
type User {
id: ID!
name: String!
email: String!
# 새로운 필드 추가 시 기존 쿼리는 영향 없음
phone: String
}
장단점 비교
REST API
장점
- 단순함: 이해하기 쉬운 구조
- 캐싱: HTTP 캐싱 메커니즘 활용 가능
- 표준화: 널리 알려진 표준
- 도구 지원: 다양한 도구와 라이브러리
단점
- 오버페칭/언더페칭: 데이터 효율성 문제
- 버전 관리: API 버전 관리의 복잡성
- 네트워크 요청: 여러 번의 요청 필요
GraphQL
장점
- 효율적 데이터 페칭: 필요한 데이터만 요청
- 단일 엔드포인트: 하나의 URL로 모든 요청
- 강타입 시스템: 스키마로 API 문서화
- 실시간 기능: Subscription 지원
단점
- 복잡성: 학습 곡선이 가파름
- 캐싱: HTTP 캐싱 활용 어려움
- 성능: 복잡한 쿼리 시 성능 이슈 가능
- 도구 지원: 상대적으로 적은 도구
실제 사용 사례
REST API가 적합한 경우
- 단순한 CRUD 작업
- 캐싱이 중요한 경우
- 기존 시스템과의 호환성
- 팀의 GraphQL 경험 부족
GraphQL이 적합한 경우
- 복잡한 데이터 관계
- 모바일 앱: 네트워크 효율성 중요
- 실시간 기능 필요
- 다양한 클라이언트 지원
구현 예시
REST API (Express.js)
const express = require('express');
const app = express();
// 사용자 목록
app.get('/api/users', (req, res) => {
res.json(users);
});
// 특정 사용자
app.get('/api/users/:id', (req, res) => {
const user = users.find(u => u.id === req.params.id);
res.json(user);
});
// 사용자의 포스트
app.get('/api/users/:id/posts', (req, res) => {
const posts = posts.filter(p => p.userId === req.params.id);
res.json(posts);
});
GraphQL (Apollo Server)
const { ApolloServer, gql } = require('apollo-server');
const typeDefs = gql`
type User {
id: ID!
name: String!
email: String!
posts: [Post!]!
}
type Post {
id: ID!
title: String!
content: String!
author: User!
}
type Query {
users: [User!]!
user(id: ID!): User
}
`;
const resolvers = {
Query: {
users: () => users,
user: (_, { id }) => users.find(u => u.id === id),
},
User: {
posts: (parent) => posts.filter(p => p.userId === parent.id),
},
};
const server = new ApolloServer({ typeDefs, resolvers });
결론
REST API와 GraphQL은 각각의 장단점이 있다. 프로젝트의 요구사항과 팀의 상황에 따라 선택해야 한다.
REST API 선택 시기:
- 단순한 CRUD 작업
- 캐싱이 중요한 경우
- 기존 시스템과의 호환성
GraphQL 선택 시기:
- 복잡한 데이터 관계
- 네트워크 효율성이 중요한 경우
- 실시간 기능 필요
최근에는 두 방식을 함께 사용하는 하이브리드 접근법도 인기를 얻고 있다. 중요한 것은 프로젝트에 맞는 최적의 선택을 하는 것이다.
Day-20