안녕하세요, Lune 입니다.

저는 이번에 실시간 웹 애플리케이션을 위한 API 전략이라는 주제로 기술 세미나를 진행했습니다.

이 주제를 통해 REST, GraphQL, WebSocket API에 대해 주로 설명하고 각각을 비교해보려고 합니다.

1. API란

먼저 API(Application Programming Interface)가 무엇인지 간단히 알아볼까요?

우선 Application은 고유한 기능을 가진 모든 소프트웨어, Interface는 애플리케이션 간의 서비스 계약이라고 할 수 있습니다. 그리고 계약은 요청과 응답을 사용하여 애플리케이션이 서로 통신하는 방법이라고 할 수 있죠.

좀 더 쉬운 설명을 위해 이미지를 가져와봤습니다. 식당을 예시로 들어볼게요.

  1. 손님은 점원이 가져다준 메뉴판으로 메뉴를 주문하고, 점원이 주문을 요리사에게 전달
  2. 요리사는 주문받은 요리를 만들어 점원에게 주고, 손님은 점원이 가져다준 요리로 맛있게 식사

여기서 점원이 바로 API와 같은 역할을 한다고 볼 수 있습니다.

api

식당 예시를 그대로 아래 이미지처럼 바꾼다고 하면 API는 좌측 프로그램이 요청할 수 있는 명령 목록을 제공하고, 명령을 받으면 우측 프로그램과 상호작용하여 명령에 대한 값을 받아 전달하게 되는 거죠. 쉽게 말해, API는 프로그램들이 서로 상호작용하는 것을 도와주는 매개체라고도 볼 수 있습니다.

api-2 (일부 설명 및 이미지 출처 → api란-쉽게-설명-그린클라이언트)

웹 API

웹 API는 웹 서버와 웹 브라우저 간의 애플리케이션 처리 인터페이스입니다. 웹 API의 종류는 REST API, GraghQL API, WebSocket API, SOAP API, RPC API 등 다양한데요. 그 중 앞의 3가지 API에 초점을 맞춰서 이야기해보겠습니다.

2. REST API

REST API는 REST 아키텍처 스타일을 따르는 API로 REST는 Representational State Transfer의 약어입니다. REST는 로이 필딩(Roy Fielding)이 HTTP의 장점을 최대한 활용할 수 있도록 고안한 아키텍처로 2000년에 처음올 소개되었고, 기본적으로 웹의 기존 기술과 HTTP 프로토콜을 그대로 활용하므로 웹의 장점을 최대한 활용할 수 있는 아키텍처 스타일 입니다.

주요 특징

REST API의 주요 특징은 다음과 같습니다.

  1. Stateless (무상태)
    • 서버는 요청이 오가는 동안 클라이언트의 상태를 저장하지 않음
  2. Cacheable (캐시 가능성)
    • 클라이언트가 응답을 캐시하여 네트워크 부하를 줄이고 성능을 향상시킬 수 있음
  3. Uniform Interface (통일된 인터페이스)
    • API 디자인이 통일되어 있어 사용하기 쉬움
    • 즉, 애플리케이션 요구사항별로 다른 형식이 아닌, 표준화된 형식으로 정보를 전송할 수 있도록 구성 요소 간 통합된 인터페이스를 가짐
  4. Server-Client (서버-클라이언트 구조)
    • 클라이언트와 서버가 각각 독립적으로 발전할 수 있음
    • 예를 들어, 웹 브라우저는 사용자에게 웹페이지를 보여주고, 서버는 데이터를 제공
  5. Layered System (계층화된 시스템)
    • 시스템이 계층으로 나뉘어 있음
    • 각 계층은 특정 역할을 수행하며, 상위 계층은 하위 계층의 구현을 알 필요가 없음
    • 예를 들어, 클라이언트는 데이터를 요청하면 중간에 여러 계층을 거쳐 서버에 도달할 수 있지만 클라이언트는 중간 계층의 존재를 몰라도 됨

3. GraphQL API

GraphQL API는 2012년 Facebook(현 Meta)에서 개발한 API용 쿼리 언어로 2015년 오픈소스화되었는데요. 클라이언트가 서버로부터 원하는 데이터를 효율적으로 요청할 수 있게 하는 기술로 REST의 대안으로 설계 되었다고 합니다.

그런데 REST API의 대안이라니.. 무슨 문제가 있다는 걸까요? GraphQL API을 더 잘 이해하기 위해 잠시 짚고 넘어가겠습니다.

REST API에 무슨 문제가 있나요?

아래 JSON 응답을 참고해 설명해보겠습니다.
(Fetch는 웹 페이지를 구성하기 위해서 다양한 서버에 요청을 보내고 데이터를 받아오는 작업 이라고 생각하시면 됩니다.)

  1. Over-Fetching
    • 원하는 응답 데이터 → 도서 ID, 도서명, 저자명만 필요, 그러나 해당 API Response 값에 가격, 출판사, ISBN 등이 포함되어 있다면 다 받아야 함
    • 즉, Over-Fetching은 필요한 데이터 이상으로 서버에서 데이터를 받아오게 되는 것을 의미하며, 필요없는 데이터까지 받아와 서버와 자원이 낭비됨
  2. Under-Fetching
    • 도서 상세 페이지에서 도서 정보와 리뷰 목록을 보여주려고 함, 그러나 API가 도서 정보와 도서 리뷰에 대해 각각 다른 End-Point를 사용한다면 필연적으로 2번의 API 호출 발생
    • 즉, 한 번의 요청으로 필요한 데이터를 모두 받아오지 못해 여러 번의 요청을 수행하는 것을 의미하며, 네트워크의 지연이 발생할 수 있고 사용자는 느린 로딩 속도로 인해 불편함을 겪을 수 있음
  3. 다양한 엔드포인트
    • REST API는 여러 엔드포인트가 존재하며, 각자의 역할을 하고 있으므로 클라이언트는 다양한 엔드포인트를 요청해야 함
{
  "books": [
    {
      // 필요한 정보
      "id": 1,
      "title": "Do it! 자바 프로그래밍 입문",
      "author": "박은종",
      // 필요하지 않은 정보
      "price": 25000,
      "publisher": " 이지스퍼블리싱",
      "isbn": "9791163030195"
    },
    {
      // 필요한 정보
      "id": 2,
      "title": "모두의 한국어 텍스트 분석 with 파이썬",
      "author": "박조은, 송영숙",
      // 필요하지 않은 정보
      "price": 27000,
      "publisher": "길벗",
      "isbn": "9791140704521"
    }
  ]
}

위 문제들이 와닿으셨을까요? GraphQL API를 사용하면 REST API의 단점 중 하나인 Over-Fetching이나 Under-Fetching 문제를 효과적으로 해결할 수 있다고 합니다.

주요 특징

GraphQL API의 주요 특징은 다음과 같습니다.

  1. 유연하고 강력한 데이터 쿼리 언어
    • 클라이언트가 필요한 데이터의 구조와 양을 정확하게 명시할 수 있는 강력한 쿼리 언어를 제공하므로 과도한 데이터 전송이나 다수의 요청을 최소화할 수 있음
    • 즉, REST API의 오버 페칭과 언더 페칭과 같은 이슈가 발생하지 않음
  2. 단일 엔드포인트
    • REST API에서는 각 엔드포인트마다 데이터를 요청해야 했지만, GraphQL은 단일 엔드포인트를 사용하여 클라이언트가 단일 요청으로 여러 데이터를 가져올 수 있음
    • ex) @PostMapping(“/graphql”)
  3. 실시간 데이터 업데이트
    • 실시간 데이터 업데이트를 지원
    • 일반적으로 Subscription이라 불리는 메커니즘을 통해 이루어짐
query {
    user(id: 123) { 
        id
        name
        email 
        posts { 
            title 
            content
        }
    }
}
{
  "data": {
    "user": {
      "id": 123,
      "name": "John Doe",
      "email": "john.doe@example.com",
      "posts": [
        {
          "title": "GraphQL Basics",
          "content": "Introduction to GraphQL"
        },
        {
          "title": "Advanced GraphQL",
          "content": "Deep dive into GraphQL concepts"
        }
      ]
    }
  }
}

4. WebSocket API

마지막으로 WebSocket API입니다. 일반적인 HTTP 통신은 클라이언트-서버간 요청-응답을 주고 받는 단방향 통신인데요. 채팅, 주식, 온라인 게임과 같은 실시간 애플리케이션에서는 빠른 속도로 정보를 전달하고 업데이트 하기 위해 양방향 통신이 필요합니다. WebSocket API는 이런 필요성이 요구될 때 사용되는 API랍니다.

주요 특징

WebSocket API의 주요 특징은 다음과 같습니다.

  1. 양방향 통신
    • 클라이언트-서버간 양방향 통신 가능
    • 서버가 클라이언트에게 데이터를 푸시하고, 클라이언트가 서버에게 데이터를 전송할 수 있음
  2. 실시간성
    • 연결을 유지하면서 데이터를 실시간으로 전송
    • 단방향 통신과는 달리, 데이터의 지연 시간을 최소화하여 실시간 응용 프로그램을 구축하는 데 적합
  3. 단일 연결 유지
    • WebSocket은 한 번의 연결을 설정하고 유지함으로써 여러 요청에 대한 새로운 연결을 맺지 않아도 됨
  4. 효율적인 데이터 전송
    • 연결을 유지하면서 계속 데이터를 주고받기 때문에, 새로운 연결을 설정할 필요가 없어 헤더의 오버헤드가 감소함
  5. 이벤트 기반 모델
    • 이벤트 기반의 모델을 사용하여 메시지를 수신하고 처리할 수 있음

5. API 비교

앞서 설명했던 내용에 덧붙여 간략하게 API별 비교를 위해 표로 정리해보겠습니다.

특징 REST API GraphQL API WebSocket API
용도 주로 데이터 조회 및 간단한 상호 작용 (CRUD 작업) 복잡한 데이터 요청 및 실시간 업데이트 실시간 데이터 전송 및 양방향 통신
사용사례 소셜 미디어, 블로그 등 복잡한 데이터 요청이 필요한 애플리케이션 실시간 채팅, 주식 시세 업데이트, 실시간 협업 등
통신방식 단방향 요청-응답 구조 클라이언트가 필요한 데이터를 정의하고 서버가 응답 양방향 통신으로 실시간 데이터 전송
지연시간 새로운 연결마다 지연 시간이 발생 클라이언트가 필요한 데이터만을 요청하여 효율적인 전송 연결 유지로 낮은 지연 시간
실시간 업데이트 Polling 또는 Webhooks을 통한 업데이트 실시간 데이터 업데이트 실시간 데이터 업데이트
유연성 여러 리소스에 대한 각각의 고유한 엔드포인트를 사용 클라이언트가 필요한 데이터만 요청 가능 단일 연결로 다양한 메시지 처리
복잡한 쿼리 여러 엔드포인트에 각각의 요청을 보내 복잡한 쿼리 처리 복잡한 쿼리 및 중첩된 필드 지원 주로 간단한 메시지 전송에 사용되며, 덜 복잡한 데이터 구조
상태 상태 저장이 필요하지 않음 상태 저장이 필요하지 않음 상태 저장이 필요한 경우 (예: 게임 상태)
오버헤드 HTTP 헤더, 상태 코드 등의 오버헤드 발생 필요한 데이터만 요청하므로 상대적으로 적음 일반적으로 상대적으로 낮은 오버헤드

6. 정리

지금까지 기술 세미나에서 나눴던 얘기를 마무리했습니다.
아래에는 각각의 웹 API를 어떤 상황에서 사용하면 좋을지 간단히 작성해봤습니다. 하나의 프로젝트에서 여러 API를 함께 사용할 수도 있기 때문에 상황에 알맞은 API를 적용해 사용하면 되겠죠~?

  • 주로 상태를 저장하지 않고 단순한 데이터 전송에 사용되며, 서버의 부하가 크게 발생하지 않는 경우
    • REST API
  • 클라이언트와 서버 간의 상태를 유지하고 실시간 양방향 통신이 필요한 경우
    • WebSocket API
  • 복잡한 데이터 요청이 필요한 경우이거나 실시간 업데이트가 필요한 경우
    • GraphQL API

정말 정말 마지막으로 영상 하나를 추천하려고 해요!
이번 세미나를 준비하며 보게 된 영상으로 흥미롭게 들었던 내용이라 공유드립니다. REST API와 관련된 내용인데 자주 사용하는 API인 만큼 시간되실 때 참고해보면 좋을 것 같습니다.

그런 REST API로 괜찮은가

7. 참고자료