API Design Guide | REST vs GraphQL vs gRPC Complete Comparison

API Design Guide | REST vs GraphQL vs gRPC Complete Comparison

이 글의 핵심

API design guide comparing REST, GraphQL, and gRPC with optimal API style selection criteria for each project.

Introduction: Importance of API Design

”Which API Style Should I Choose?”

In backend development, API design is one of the most important decisions. Choosing between REST, GraphQL, and gRPC greatly affects developer experience, performance, and maintainability.

What This Guide Covers:

  • Core concepts of REST, GraphQL, and gRPC
  • Pros and cons of each API style
  • Performance comparison
  • Selection criteria by project

Table of Contents

  1. REST API
  2. GraphQL
  3. gRPC
  4. Comparative Analysis
  5. Selection Guide
  6. Summary

1. REST API

What is REST?

REST (Representational State Transfer) is an architectural style based on HTTP.

Core Principles of REST:

graph TB
    A[REST Principles] --> B[Resource]
    A --> C[HTTP Methods]
    A --> D[Stateless]
    A --> E[Cacheable]
    
    B --> B1[Identified by URI]
    C --> C1[GET POST PUT DELETE]
    D --> D1[Server does not store state]
    E --> E1[Utilize HTTP cache]

REST API Example

Endpoint Design:

GET    /api/users          # List users
GET    /api/users/123      # Get specific user
POST   /api/users          # Create user
PUT    /api/users/123      # Update user
DELETE /api/users/123      # Delete user

GET    /api/users/123/posts  # User's post list

Node.js Express Implementation:

const express = require('express');
const app = express();

app.use(express.json());

// List users
app.get('/api/users', (req, res) => {
  const users = [
    { id: 1, name: 'Alice', email: '[email protected]' },
    { id: 2, name: 'Bob', email: '[email protected]' }
  ];
  res.json(users);
});

// Get specific user
app.get('/api/users/:id', (req, res) => {
  const user = { id: req.params.id, name: 'Alice' };
  res.json(user);
});

// Create user
app.post('/api/users', (req, res) => {
  const newUser = req.body;
  res.status(201).json(newUser);
});

app.listen(3000);

REST Pros and Cons

Pros:

  • Simplicity: Uses HTTP standard
  • Caching: Can utilize HTTP cache
  • Tool support: Postman, curl, etc.
  • Low learning curve: Intuitive

Cons:

  • Over-fetching: Receives unnecessary data too
  • Under-fetching: Multiple requests needed (N+1 problem)
  • Version management: /api/v1/, /api/v2/
  • Lack of flexibility: Add endpoints when client requirements change

2. GraphQL

What is GraphQL?

GraphQL is a query language developed by Facebook, allowing clients to request exactly the data they need.

GraphQL Structure:

graph LR
    A[Client] -->|Query| B[GraphQL Server]
    B -->|Only exact data| A
    
    C[REST] -->|Fixed response| D[Client]
    D -->|Receives unnecessary data too| C

GraphQL Example

Schema Definition:

# schema.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!]!
  post(id: ID!): Post
}

type Mutation {
  createUser(name: String!, email: String!): User!
  updateUser(id: ID!, name: String): User!
  deleteUser(id: ID!): Boolean!
}

Query Example:

# Query user and posts at once
query {
  user(id: "123") {
    name
    email
    posts {
      title
      content
    }
  }
}

# Response (only needed fields)
{
  "data": {
    "user": {
      "name": "Alice",
      "email": "[email protected]",
      "posts": [
        {
          "title": "First Post",
          "content": "Content..."
        }
      ]
    }
  }
}

Node.js Apollo Server Implementation:

const { ApolloServer, gql } = require('apollo-server');

// Type definitions
const typeDefs = gql`
  type User {
    id: ID!
    name: String!
    email: String!
  }
  
  type Query {
    users: [User!]!
    user(id: ID!): User
  }
`;

// Resolvers
const resolvers = {
  Query: {
    users: () => [
      { id: '1', name: 'Alice', email: '[email protected]' },
      { id: '2', name: 'Bob', email: '[email protected]' }
    ],
    user: (_, { id }) => {
      return { id, name: 'Alice', email: '[email protected]' };
    }
  }
};

const server = new ApolloServer({ typeDefs, resolvers });
server.listen().then(({ url }) => {
  console.log(`🚀 Server ready at ${url}`);
});

GraphQL Pros and Cons

Pros:

  • Exact data: Request only needed fields
  • Single endpoint: All requests through one /graphql
  • Type system: Type guarantee with schema
  • Developer experience: GraphQL Playground, automatic documentation

Cons:

  • Complexity: High learning curve
  • Caching difficulty: Limited HTTP cache utilization
  • N+1 problem: Need additional tools like DataLoader
  • Overhead: Excessive for simple CRUD

3. gRPC

What is gRPC?

gRPC is a high-performance RPC (Remote Procedure Call) framework developed by Google. Uses Protocol Buffers to serialize data.

gRPC Structure:

graph LR
    A[Client] -->|Binary Protobuf| B[gRPC Server]
    B -->|Binary Protobuf| A
    
    C[REST] -->|JSON Text| D[Server]
    D -->|JSON Text| C

gRPC Example

Protobuf Definition:

// user.proto
syntax = "proto3";

package user;

service UserService {
  rpc GetUser (GetUserRequest) returns (User);
  rpc ListUsers (ListUsersRequest) returns (ListUsersResponse);
  rpc CreateUser (CreateUserRequest) returns (User);
}

message User {
  int32 id = 1;
  string name = 2;
  string email = 3;
}

message GetUserRequest {
  int32 id = 1;
}

message ListUsersRequest {
  int32 page = 1;
  int32 page_size = 2;
}

message ListUsersResponse {
  repeated User users = 1;
}

message CreateUserRequest {
  string name = 1;
  string email = 2;
}

C++ Server Implementation:

#include <grpcpp/grpcpp.h>
#include "user.grpc.pb.h"

class UserServiceImpl final : public user::UserService::Service {
  grpc::Status GetUser(
      grpc::ServerContext* context,
      const user::GetUserRequest* request,
      user::User* response) override {
    
    response->set_id(request->id());
    response->set_name("Alice");
    response->set_email("[email protected]");
    
    return grpc::Status::OK;
  }
};

int main() {
  std::string server_address("0.0.0.0:50051");
  UserServiceImpl service;
  
  grpc::ServerBuilder builder;
  builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
  builder.RegisterService(&service);
  
  std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
  std::cout << "Server listening on " << server_address << std::endl;
  server->Wait();
  
  return 0;
}

gRPC Pros and Cons

Pros:

  • High performance: Binary protocol, HTTP/2
  • Type safety: Protobuf schema
  • Streaming: Bidirectional streaming support
  • Multi-language support: Generate clients in multiple languages

Cons:

  • Limited browser support: Needs gRPC-Web
  • Debugging difficulty: Binary protocol
  • Learning curve: Protobuf syntax
  • Tool shortage: Cannot use REST tools like Postman

4. Comparative Analysis

Comprehensive Comparison Table

FeatureRESTGraphQLgRPC
ProtocolHTTP/1.1HTTP/1.1HTTP/2
Data FormatJSONJSONProtobuf (Binary)
Type SystemNoneYes (Schema)Yes (Protobuf)
CachingExcellent (HTTP)LimitedLimited
PerformanceMediumMediumFast
Learning CurveLowMediumHigh
Browser SupportExcellentExcellentLimited
StreamingNoneSubscriptionBidirectional

Performance Benchmark

Test Environment: 100,000 requests, average response size 1KB

Throughput (requests/sec):
1. gRPC:     50,000  ⭐
2. REST:     20,000
3. GraphQL:  15,000

Response Time (ms):
1. gRPC:     2ms   ⭐
2. REST:     5ms
3. GraphQL:  7ms

Data Size (1000 objects):
1. Protobuf: 82KB  ⭐
2. JSON:     120KB

Use Case Comparison

REST Suitable For:

  • Simple CRUD API
  • Public API (external developer use)
  • When caching is important
  • Legacy system integration

GraphQL Suitable For:

  • Complex data requirements
  • Mobile apps (data savings)
  • Fast frontend development
  • Various clients (web, mobile, desktop)

gRPC Suitable For:

  • Microservice communication
  • Real-time streaming
  • High performance requirements
  • Internal API (browser not needed)

5. Selection Guide

Selection Flowchart

flowchart TD
    A[Start API Design] --> B{Browser Client?}
    B -->|No| C{Performance Top Priority?}
    C -->|Yes| D[gRPC]
    C -->|No| E[REST]
    
    B -->|Yes| F{Complex Data Requirements?}
    F -->|Yes| G[GraphQL]
    F -->|No| H{Public API?}
    H -->|Yes| I[REST]
    H -->|No| J[GraphQL or REST]

Recommendations by Project

1. Startup MVP

  • REST: Fast development, simplicity
  • Example: Express + MongoDB

2. Mobile App Backend

  • GraphQL: Data savings, flexibility
  • Example: Apollo Server + PostgreSQL

3. Microservices

  • gRPC: High performance, type safety
  • Example: gRPC + Kubernetes

4. Public API

  • REST: Standard, tool support
  • Example: Stripe API, GitHub API

5. Real-time App

  • GraphQL Subscription or gRPC Streaming
  • Example: Chat, notifications, dashboard

Hybrid Approach

Many projects mix multiple API styles.

Frontend (Browser)
    ↓ GraphQL
API Gateway
    ↓ gRPC
Microservices

Example:

  • External clients: REST or GraphQL
  • Internal services: gRPC
  • Real-time features: WebSocket or GraphQL Subscription

Implementation Patterns

REST + gRPC Hybrid:

// API Gateway (Express + REST)
app.get('/api/users/:id', async (req, res) => {
  // Call internal gRPC service
  const user = await grpcClient.getUser({ id: req.params.id });
  res.json(user);
});

GraphQL + gRPC Hybrid:

// GraphQL resolver calling gRPC
const resolvers = {
  Query: {
    user: async (_, { id }) => {
      // Call gRPC service
      return await grpcClient.getUser({ id });
    }
  }
};

6. Summary

Key Summary

REST:

  • HTTP-based, resource-centric
  • Simple and excellent caching
  • Suitable for public APIs

GraphQL:

  • Query language, client-centric
  • Exact data requests
  • Suitable for complex data requirements

gRPC:

  • Binary protocol, high performance
  • Type safety, streaming
  • Suitable for microservices

Selection Criteria

PriorityChoice
SimplicityREST
FlexibilityGraphQL
PerformancegRPC
Public APIREST
MobileGraphQL
MicroservicesgRPC

Next Steps

For detailed implementation methods of each API style, refer to these guides:

  • Node.js REST API Building
  • GraphQL Server Building
  • C++ gRPC Guide

Related Topics:

  • API Authentication Strategy
  • API Version Management
  • Microservices Architecture

Additional Learning Resources

Official Documentation:

Quick Decision Guide

Simple CRUD? → REST
Complex data fetching? → GraphQL
High performance internal? → gRPC
Public API? → REST
Mobile app? → GraphQL
Microservices? → gRPC
Real-time bidirectional? → gRPC or GraphQL Subscription

Keywords

API, REST, GraphQL, gRPC, API Design, Backend, Microservices, HTTP, Protocol Buffers, Performance, Comparison