BFF(프런트엔드용 백엔드) 패턴 이해: 간단한 가이드

BFF(프런트엔드용 백엔드) 패턴 이해: 간단한 가이드

마이크로서비스 아키텍처에서 우리 시스템은 사용자 서비스, 주문 서비스, 제품 서비스 등 수십 개의 작고 집중적인 서비스로 분류됩니다.

그러나 이 정보를 사용자에게 표시하는 경우 장치마다 요구 사항이 매우 다릅니다. 고속 데스크톱 컴퓨터의 웹 브라우저에는 테이블, 사이드바, 그래프로 가득 찬 풍부한 대시보드가 ​​필요합니다. 느린 셀룰러 네트워크의 모바일 앱은 대역폭과 배터리를 절약하기 위해 간단하고 가벼운 레이아웃을 원합니다. 스마트워치 앱에는 한 줄의 텍스트만 필요할 수 있습니다.

이러한 프런트엔드가 모두 동일한 백엔드 API를 쿼리하는 경우 누군가 타협해야 합니다. 모바일 앱은 막대한 양의 쓸모 없는 데이터를 다운로드해야 하거나, 웹 앱은 필요한 모든 것을 가져오기 위해 수십 개의 별도 네트워크 요청을 해야 합니다.

이것이 바로 BFF(Backend for Frontend) 패턴으로 해결된 문제입니다. 이 가이드에서는 이 패턴을 간단한 단어로 설명하고 실제 비유를 살펴보고 이를 표준 API 게이트웨이와 비교하고 실용적인 코드 구현을 안내합니다.


실제 비유: 레스토랑 메뉴

세 가지 매우 다른 유형의 식사를 제공하는 레스토랑을 상상해 보십시오.

  1. 자세한 재료 목록이 포함된 전체 5코스 시식 메뉴를 원하는 음식 평론가.
  2. 기차에서 미리 포장된 빠른 간식을 먹고 싶은 바쁜 통근자.
  3. 매운 재료 없이 소량으로 간단한 어린이 식사를 원하는 아이.

레스토랑에 세 가지 옵션을 모두 자세히 나열한 단일 메뉴만 있다면 엄청난 일이 될 것입니다. 통근자는 5가지 코스 요리법을 읽는 데 시간을 낭비할 것이고, 아이의 부모는 간단한 음식 옵션을 찾는 데 어려움을 겪을 것입니다.

대신 레스토랑에서는 시식 메뉴, 간편 포장 메뉴, 어린이 메뉴 등 세 가지 맞춤 메뉴를 인쇄합니다.

각 메뉴는 동일한 주방(마이크로서비스)에서 가져오지만 해당 고객(클라이언트)을 위해 특별히 선택 항목의 형식과 크기를 지정합니다.

이 시나리오에서는:

  • 주방마이크로서비스(사용자, 카탈로그, 결제)를 나타냅니다.
  • 맞춤 메뉴는 귀하의 절친(웹 절친, 모바일 절친, 시계 절친)입니다.
  • 식사객프런트엔드(데스크톱 브라우저, 모바일 앱, 스마트워치)입니다.

문제: “모든 용도에 적용 가능한” API

마이크로서비스가 처음 대중화되었을 때 많은 팀에서는 모든 프런트엔드 클라이언트를 처리하기 위해 단일 공유 API 게이트웨이를 구축했습니다.

웹과 모바일 흐름을 비교하는 BFF(프런트엔드용 백엔드) 아키텍처 다이어그램

단일 진입점이 훌륭하지만 공유 API에는 여러 가지 확장 병목 현상이 발생합니다.

  • 모바일용 페이로드 블로트: 데스크톱 웹 앱에는 사용자의 주문 내역, 청구서 수신 주소, 프로필 사진, 적립 포인트가 필요합니다. 모바일 앱에는 ‘마지막 주문: 배송됨’만 표시하면 됩니다. 공유 API를 사용하면 모바일 앱이 전체 프로필 페이로드를 다운로드하므로 귀중한 데이터가 낭비되고 로드 시간이 느려집니다.
  • API 병목 현상: 단일 팀이 공유 게이트웨이의 병목 현상이 됩니다. iOS 팀이 작은 레이아웃 필드를 변경하려는 경우 공유 게이트웨이 팀이 새 버전을 배포할 때까지 기다려야 하므로 개발 주기가 느려집니다.
  • 다양한 보안 요구 사항: 웹 브라우저에는 XSS(Cross-Site Scripting)를 방지하기 위해 쿠키 기반 세션이 필요할 수 있는 반면, 모바일 앱은 토큰 기반 OAuth 헤더를 선호합니다. 단일 서버에서 두 가지를 모두 처리하면 복잡하고 지저분한 코드가 생성됩니다.

해결책: BFF 패턴

BFF 패턴은 모든 장치에 대해 하나의 거대한 게이트웨이를 만드는 대신 각 프런트엔드 애플리케이션에 대해 하나의 전용 백엔드 서버를 구축하는 것을 옹호합니다.

당신은 다음을 갖게 될 것입니다 :

  • 웹 BFF: 데스크톱 브라우저의 요청을 처리합니다. 전체 프로필, 제품 카탈로그 및 자세한 결제 정보를 집계합니다.
  • 모바일 BFF: iOS 및 Android 앱의 요청을 처리합니다. 데이터를 집계하고, 불필요한 필드를 필터링하고, 최종 응답을 압축하여 빠른 성능을 보장합니다.

API 게이트웨이와 BFF: 차이점은 무엇인가요?

이 두 패턴은 모두 클라이언트와 마이크로서비스 사이에 있기 때문에 혼동하는 것이 일반적입니다. 차이점은 다음과 같습니다.

기능 일반 API 게이트웨이 프론트엔드용 백엔드(BFF)
게이트웨이 수 일반적으로 전체 시스템에 하나입니다. 여러(클라이언트 장치 유형별로 하나씩).
책임 높은 수준의 라우팅, 속도 제한 및 글로벌 보안. 특정 프런트엔드에 대한 데이터 집계 및 페이로드 조정
소유권 전담 백엔드/플랫폼 인프라 팀이 관리합니다. 해당 앱을 빌드하는 프런트엔드 팀이 관리합니다.
맞춤화 낮은. 변경 사항은 모든 클라이언트에 영향을 미칩니다. 높은. 변경 사항은 하나의 클라이언트 애플리케이션에만 영향을 미칩니다.

실용적인 구현(Node.js/Express)

이것이 실제로 어떻게 작동하는지 이해하기 위해 간단한 Node.js 예제를 작성해 보겠습니다.

내부적으로 실행되는 두 개의 마이크로서비스가 있다고 가정해 보세요.

  • 사용자 서비스(기본 사용자 프로필 정보 반환)
  • 주문 서비스(자세한 내용이 포함된 주문 목록 반환)

우리는 데스크톱 사이트와 모바일 앱을 다르게 제공하기 위해 웹 BFF모바일 BFF를 구축하고 싶습니다.

1. 공유 마이크로서비스 모의

먼저, 두 가지 기본 마이크로서비스에 대한 모의 데이터는 다음과 같습니다.

// Internal User Service Response
const userProfile = {
    id: 42,
    username: "dev_coder",
    email: "coder@ghaznix.com",
    avatarUrl: "https://ghaznix.com/avatars/42.png",
    preferences: { theme: "light", newsletter: true }
};

// Internal Order Service Response
const orderHistory = [
    { id: "ORD-99", date: "2026-06-25", items: ["Laptop", "Mouse"], status: "Shipped", tax: 15.00, total: 1215.00 },
    { id: "ORD-88", date: "2026-05-12", items: ["Keyboard"], status: "Delivered", tax: 5.00, total: 105.00 }
];

2. 웹 BFF(완전한 세부 페이로드 반환)

Web BFF는 데스크탑 화면에 표시할 공간이 충분하기 때문에 모든 필드를 집계합니다.

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

webBff.get('/dashboard', (req, res) => {
    // Web needs everything: profile + full order details + settings
    const responsePayload = {
        user: {
            username: userProfile.username,
            email: userProfile.email,
            avatar: userProfile.avatarUrl,
            theme: userProfile.preferences.theme
        },
        orders: orderHistory // Send all order details, taxes, and items
    };
    
    res.json(responsePayload);
});

webBff.listen(3001, () => console.log('Web BFF running on port 3001'));

3. 모바일 BFF(최소화되고 집계된 페이로드 반환)

모바일 BFF는 불필요한 필드(예: 이메일, 설정, 세금)를 필터링하고 주문 항목을 집계하여 대역폭을 절약합니다.

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

mobileBff.get('/dashboard', (req, res) => {
    // Mobile only wants: username, avatar, and summary of the latest order
    const latestOrder = orderHistory[0];
    
    const responsePayload = {
        user: {
            username: userProfile.username,
            avatar: userProfile.avatarUrl
        },
        latestOrderStatus: {
            orderId: latestOrder.id,
            status: latestOrder.status,
            date: latestOrder.date,
            itemCount: latestOrder.items.length // Send count instead of array list
        }
    };
    
    res.json(responsePayload);
});

mobileBff.listen(3002, () => console.log('Mobile BFF running on port 3002'));

페이로드 크기 비교

  • 웹 BFF 응답 크기: 중첩된 구성, 기본 설정, 전체 주문 목록, 세금, 항목 등을 포함합니다(약 400바이트).
  • 모바일 BFF 응답 크기: 핵심을 나타내는 6개의 키-값 쌍만 포함합니다. (약 120바이트—네트워크 크기 70% 감소!)

BFF 패턴의 장점과 단점

BFF 패턴은 매우 효과적이지만 다음과 같은 장단점이 있습니다.

어드밴티지(프로) 단점(단점)
최적화된 클라이언트 성능: 클라이언트는 필요한 정확한 데이터만 로드하므로 배터리 소모와 메모리 사용량이 줄어듭니다. 코드 중복: 여러 BFF 코드베이스에서 유사한 데이터 가져오기 논리를 작성하게 될 수도 있습니다.
빠른 릴리스 주기: 모바일 프런트엔드 팀은 웹 개발자와 협력할 필요 없이 BFF 서버를 업데이트할 수 있습니다. 서버 수 증가: 이제 하나의 API 게이트웨이를 관리하는 대신 여러 BFF 서비스를 배포하고 관리해야 합니다.
단순화된 프런트엔드 코드: 클라이언트는 복잡한 정렬, 필터링 또는 병합 논리를 처리할 필요가 없습니다. 단지 수신한 JSON을 표시할 뿐입니다. 보안 관리: SSL/TLS 인증, 속도 제한 규칙 및 방화벽은 여러 게이트웨이에서 관리되어야 합니다.

결론

BFF(프런트엔드용 백엔드) 패턴은 웹, 모바일 및 IoT 장치와 같은 여러 클라이언트 유형을 제공하는 시스템을 위한 강력한 아키텍처입니다. 각 특정 프런트엔드에 대한 맞춤형 게이트웨이를 생성하면 클라이언트 개발을 분리하고 페이로드 크기를 최소화하며 더 빠르고 응답성이 뛰어난 사용자 경험을 제공할 수 있습니다.

시스템에 단일 웹 애플리케이션만 있는 경우 공유 API 게이트웨이로 충분합니다. 그러나 웹 애플리케이션과 함께 모바일 앱이나 특수 장치 경험을 구축하기 시작하는 순간 BFF를 구현하는 것이 프런트엔드 및 백엔드 아키텍처를 깔끔하고 최적화되며 독립적으로 유지하는 가장 좋은 방법입니다.


Ghaznix 블로그에서 더 많은 소프트웨어 개발 및 백엔드 엔지니어링 통찰력을 살펴보세요 →