Skip to content

Graphql과 REST API, 그리고 BFF #43

@yuiseo

Description

@yuiseo

📝 Graphql과 REST API, 그리고 BFF

📚 주제:
GraphQL, REST API, 그리고 Backend for Frontend(BFF)의 개념과 차이점을 비교하고, 각각의 장단점과 활용 사례를 조사한다.


🎯 스터디 목표
GraphQL과 REST API의 기본 개념을 이해하고, BFF의 필요성과 역할을 분석하여 실무에서 적절한 아키텍처를 선택할 수 있도록 한다.


📖 핵심 내용:

Grpahql


GraphQL은 쿼리(Query) 기반 API로, 클라이언트가 필요한 데이터만 선택적으로 요청 할 수 있는 방식

  • 단일 엔드포인트(/grpahql)를 사용하여 필요한 필드만 선택 하고, 한 번의 요청으로 여러 데이터를 가져올 수 있다.

장점

  • 오버페칭 방지 → 필요한 데이터만 가져올 수 있음
  • 언더페칭 방지 → 한 번의 요청으로 연관 데이터까지 가져올 수 있음
  • 유연한 API 확장 가능 → 필드 추가 시 기존 API 변경 없이 사용 가능

단점

  • 초기 설정이 복잡 → 스키마 정의 및 백엔드 설정 필요
  • 캐싱이 어렵다 → 모든 요청이 POST로 처리될 경우 CDN 캐싱 활용이 어려움
  • N+1 문제 발생 가능 → 리졸버 최적화 필요 (DataLoader 사용)

grpahql의 리졸버(resolver)?


👉 graphql에서 쿼리를 해석하고 데이터를 반환하는 함수

즉, 클라이언트가 요청한 데이터를 백엔드에서 찾아서 반환하는 역할

근데 왜 리졸버가 더 많아져?

  • graphql은 각 필드마다 리졸버를 따로 만들어야 하기 때문!

  • 예시

    사용자 정보와 게시글을 함께 요청하는 GraphQL 쿼리

    query {
      user(id: 1) {
        name
        posts {
          title
          content
        }
      }
    }
    

    백엔드 리졸버 (각 필드별로 따로 존재)

    const resolvers = {
      Query: {
        user: (_, { id }) => getUserById(id) // 사용자 정보 가져오는 리졸버
      },
      User: {
        posts: (parent) => getPostsByUserId(parent.id) // 사용자의 게시글 가져오는 리졸버
      }
    };
    

    📌 user 리졸버와 posts 리졸버가 따로 있음!

    📌 ➡ 데이터가 많아질수록 리졸버가 계속 증가하게 됨.

    📌 ➡ 유지 보수가 어려워짐!!

    📌 ➡ 데이터 타입마다 리졸버가 계속 추가됨

    📌➡ 코드가 많아지고, 유지보수가 어려워짐

    📌➡ 각 리졸버가 따로 동작하다 보면 N+1 문제 발생 가능

Graphql의 N+1 문제


데이터를 요청할 때 비효율적인 쿼리 실행으로 인해 발생하는 성능 문제인데, 리졸버를 사용하여 데이터를 가져올 때 발생

예시 사용자 목록과 각 사용자의 게시글 리스트를 가져오는 graphql 쿼리를 작성

query {
  users {
    id
    name
    posts {
      id
      title
    }
  }
}

💡 실행 흐름 (문제 발생 과정)

  • users 데이터를 가져오기 위해 1개의 쿼리 실행

    SELECT * FROM users;  -- (1개의 쿼리 실행)
    
  • posts 데이터를 가져오기 위해 N개의 쿼리 실행

    SELECT * FROM posts WHERE user_id = 1;  -- (N번 실행)
    SELECT * FROM posts WHERE user_id = 2;
    SELECT * FROM posts WHERE user_id = 3;
    ...
    SELECT * FROM posts WHERE user_id = N;
    

👩🏻‍💻

users 데이터를 먼저 가져온 후, 각 사용자별 posts를 개별적으로 가져오면 총 N+1개의 쿼리가 발생(1개의 users 조회 + N개의 posts 조회)

사용자가 많아질수록 (N이 커질수록) 데이터베이스 쿼리 요청이 기하급수적으로 증가하게 되고, 이는 성능 저하를 초래하게 된다.

해결 방법

  • DataLoader(Facebook이 만든 라이브러리)를 활용 - 가장 많이 사용
    • 원리는 쿼리 갯수를 1개로 줄여 성능을 향상 시키는 것
      • data loader 사용시 batching(일괄 처리)와 caching(캐싱)을 적용하여 쿼리 갯수를 줄이는 것

REST API


REST API는 리소스 기반의 HTTP 요청 방식으로, 각 리소스(데이터)에 대해 고정된 엔드포인트(URL)을 사용해 요청하는 방식

장점

  • 구조가 단순하고 익숙함 (RESTful 원칙 따름)
  • 캐싱 활용 가능 (브라우저 및 CDN 지원)
  • HTTP 상태 코드 활용 가능 (200, 404, 500 등)

단점

  • 오버페칭(Over-fetching) → 불필요한 데이터까지 포함될 수 있음
  • 언더페칭(Under-fetching) → 원하는 데이터를 위해 여러 번 요청해야 할 수도 있음
  • API 버전 관리 필요 → 새로운 필드 추가 시 /v1/, /v2/ 같은 엔드포인트 추가 필요

오버 페칭

👉 필요한 데이터보다 더 많은 데이터를 받아오는 문제

즉, 클라이언트가 원하지 않는 정보까지 같이 전달되는 상황

예시 사용자의 이름(name)만 필요한 상황

REST 방식 (오버페칭 문제 발생)


GET /users/1
{
  "id": 1,
  "name": "Alice",
  "email": "[email protected]",
  "age": 30,
  "address": {
    "street": "123 Main St",
    "city": "Seoul"
  },
  "phone": "010-1234-5678"
}
  • 클라이언트는 이름(name)만 필요한데,
  • 이메일, 나이, 주소, 전화번호 등 불필요한 정보까지 받아옴
  • 👉 불필요한 데이터 전송으로 네트워크 비용 증가 & 성능 저하

GraphQL 방식 (오버페칭 해결)


query {
  user(id: 1) {
    name
  }
}
{
  "data": {
    "user": {
      "name": "Alice"
    }
  }
}

오직 필요한 name 필드만 가져오기 때문에 오버페칭 방지 가능! 🔥

언더페칭

👉 필요한 데이터를 한 번의 요청으로 가져오지 못하고, 여러 번 요청해야 하는 문제

예시 클라이언트에서 특정 사용자(user)와 해당 사용자의 게시글(posts)을 한 번에 가져오고 싶다면?

REST 방식


  1. GET /users/1 → 사용자 정보 요청
  2. GET /users/1/posts → 해당 사용자의 게시글 요청

이렇게 2번의 API 호출이 필요

만약 사용자와 댓글 정보까지 같이 가져오려면 3개의 요청이 필요!

언더페칭은 API가 분리 되어 있어 원하는 데이터를 한 번에 가져오지 못하는 경우 발생

GraphQL 방식


query {
  user(id: 1) {
    name
    posts {
      title
      comments {
        text
      }
    }
  }
}

한 번의 요청으로 모든 데이터를 가져올 수 있음.

BFF(backend for frontend)


  • 프론트엔드 애플리케이션의 특성에 맞게 백엔드 API를 제공하는 아키텍처 패턴
  • BFF는 특정 프론트엔드 클라이언트(웹, 모바일, 데스크톱 등)에 최적화된 API를 제공
  • BFF는 프론트엔드와 백엔드 사이의 '맞춤형 API 레이어' 역할

📌 BFF와 GraphQL 비교

  BFF GraphQL
개발 방식 프론트엔드별 맞춤형 API 서버 개발 클라이언트가 원하는 데이터만 요청 가능
데이터 가공 BFF가 데이터 조합 및 가공 GraphQL 서버가 데이터 조합
오버페칭 해결 맞춤 API 제공 원하는 필드만 요청 가능
언더페칭 해결 여러 API를 조합해서 제공 한 번의 요청으로 필요한 데이터 제공

📌 BFF vs GraphQL 차이점

  • GraphQL은 단일 API로 해결, 하지만 BFF는 맞춤형 API 서버를 추가로 운영
  • GraphQL을 사용하면 BFF 없이도 프론트엔드가 필요한 데이터만 요청 가능

💡 참고 자료:
https://graphql.org/learn/
https://tech.kakao.com/posts/364
https://blog.toktokhan.dev/rest-api-vs-graphql-7348f54a220b
https://blog.postman.com/graphql-vs-rest/
https://fe-developers.kakaoent.com/2022/220310-kakaopage-bff/
https://docs.github.com/ko/rest/about-the-rest-api/comparing-githubs-rest-api-and-graphql-api?apiVersion=2022-11-28
https://kosaf04pyh.tistory.com/341

Metadata

Metadata

Assignees

Labels

백엔드질문 리스트의 직무 구분을 위한 라벨프론트엔드질문 리스트의 직무 구분을 위한 라벨

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions