REST API vs GraphQL

Kingmo·2022년 3월 14일
post-thumbnail

웹 프론트엔드와 백엔드가 데이터를 주고받기 위한 소통 수단이 바로 API(Application Programming Interface)다.

1. API의 기본 개념

API는 클라이언트의 HTTP 요청을 백엔드 서버에 전달하고, 백엔드가 비즈니스 로직을 수행한 후 처리 결과를 다시 클라이언트에 돌려주는 연결 통로다.

함수에 비유하자면 다음과 같다.

  • API 요청 데이터 (Request Payload / Query String): 함수의 매개변수(인자)
  • API 응답 데이터 (Response Body): 함수의 반환값(Return)

2. REST API vs GraphQL API 핵심 차이

비교 항목REST APIGraphQL API
엔드포인트(URI)자원(Resource)마다 고유한 URI 엔드포인트 존재 (/users/1, /boards/10)단 하나의 엔드포인트(POST /graphql)로 모든 요청 처리
요청 구조HTTP Method(GET, POST, PUT, DELETE 등)로 행위 표현일반 함수 호출 형태의 쿼리(query, mutation) 사용
응답 데이터 형태백엔드에서 사전에 정의한 고정된 데이터 스키마 전부 수신클라이언트가 쿼리에 명시한 필드만 선택적으로 수신
대표 통신 라이브러리axios, fetch@apollo/client, urql, relay
네트워크 캐싱HTTP 표준 캐싱 헤더(Cache-Control, ETag 등) 완벽 지원대부분 단일 POST 요청이므로 별도의 클라이언트 정규화 캐시 필요

요청 및 응답 예시 비교

REST API

  • 요청: GET [https://api.example.com/users/1](https://api.example.com/users/1)
  • 응답: 필요한 필드 외에도 서버 모델의 모든 필드가 한 번에 반환된다.
{
  "name": "nate",
  "height": "187",
  "hair_color": "blond",
  "skin_color": "fair",
  "eye_color": "blue",
  "gender": "male",
  "study": [3, 4, 21, 23, 31],
  "created": "2014-12-09T13:50:51.644000Z",
  "edited": "2014-12-20T21:17:56.891000Z"
}

GraphQL API

  • 요청: POST [https://api.example.com/graphql](https://api.example.com/graphql)
query {
  user(userId: 1) {
    name
    height
    gender
  }
}
  • 응답: 쿼리에 적어 넣은 name, height, gender 필드만 정확히 반환된다.
{
  "data": {
    "user": {
      "name": "nate",
      "height": 187,
      "gender": "male"
    }
  }
}

3. REST API의 고질적 한계: 오버패칭과 언더패칭

GraphQL이 탄생하게 된 배경은 REST API의 오버패칭(Over-fetching)과 언더패칭(Under-fetching) 문제를 해결하기 위함이다.

오버패칭 (Over-fetching)

  • 문제: 클라이언트는 화면에 오직 유저의 name과 profileImage 두 개만 띄우면 되는데, /users/1 엔드포인트가 계좌번호, 주소, 생성일자 등 수십 개의 필드를 불필요하게 묶어서 반환하는 현상이다.
  • 영향: 불필요한 네트워크 대역폭(Payload size) 낭비와 클라이언트 메모리 부담을 초래한다.

언더패칭 (Under-fetching)

  • 문제: 한 화면을 그리기 위해 유저 정보뿐만 아니라 유저가 작성한 최근 게시글 목록까지 필요한 상황을 가정하자.
  • REST 방식:
    1. /users/1 호출로 유저 기본 정보 조회
    2. 받아온 정보를 기반으로 /users/1/posts를 다시 호출하여 게시글 목록 조회
    • 필요한 데이터를 한 번에 다 채우지 못해 여러 번의 HTTP 요청(Round-trip)이 발생한다.
  • GraphQL 방식: 중첩 쿼리(Nested Query)를 통해 한 번의 단일 요청으로 원하는 깊이의 연관 데이터까지 동시에 받아온다.
query {
  user(userId: 1) {
    name
    email
    boards {
      id
      title
      contents
    }
  }
}

4. GraphQL API 실전 사용법 (Docs 읽기와 쿼리 작성)

스키마 Docs 타입 기호 규칙

  • Type! : 해당 인자는 반드시 넘겨주어야 하는 필수값(Non-nullable)이다.
  • [Type!] : 배열 내부의 요소가 존재한다면 반드시 null이 아닌 유효한 값이어야 함을 의미한다.

데이터 조회: query

데이터를 순수하게 읽어올 때는 query 문을 사용한다. 실행할 쿼리 함수명 뒤에 인자값을 전달하고, 중괄호 안에 응답받고 싶은 필드 목록을 지정한다.

query fetchBoardsWithPage {
  fetchBoards(page: 1) {
    _id
    writer
    title
    createdAt
  }
}

데이터 생성/수정/삭제: mutation

서버의 상태를 변경하는 작업(CUD: Create, Update, Delete)을 수행할 때는 mutation 문을 사용한다.

mutation createBoardInput {
  createBoard(
    createBoardInput: {
      writer: "철수"
      password: "password123"
      title: "제목입니다"
      contents: "내용입니다"
    }
  ) {
    _id
    title
    message
  }
}

5. 실무 선택 기준

  • GraphQL이 유리한 경우:
    • 모바일 앱, 웹 등 디바이스별로 요구하는 데이터 필드의 형태와 크기가 크게 다를 때.
    • 연관 관계가 복잡하게 얽힌 리소스를 화면 하나에서 한 번에 모아서 렌더링해야 할 때.
    • 프론트엔드 개발자가 백엔드 엔드포인트 추가 개발 의존도 없이 필요한 필드 조합을 유연하게 조합하고 싶을 때.
  • REST API가 유리한 경우:
    • 정적 리소스나 파일 업로드/다운로드 등 멀티파트 바이너리 스트리밍을 다룰 때.
    • 브라우저 및 CDN 레벨의 정밀한 HTTP 캐싱(Cache-Control, 304 Not Modified)을 적극적으로 활용해야 할 때.
    • 서비스 규모가 작고 CRUD 구조가 직관적이며 정형화되어 있을 때.
profile
Developer

0개의 댓글