BFF 패턴 (Backend for Frontend)
한 줄 정의
각 클라이언트(웹, 모바일, 앱 등) 전용 백엔드를 별도로 두는 아키텍처 패턴
왜 필요한가? — 문제에서 출발하기
API를 리소스 중심으로 잘게 분리하면 유연성은 올라가지만, 클라이언트 입장에서는 고통이 생긴다.
예를 들어 “사용자 프로필 화면”을 그리려면:
GET /users/{id}→ 유저 기본 정보GET /users/{id}/posts→ 작성 게시글GET /users/{id}/followers→ 팔로워 목록
이렇게 3번의 요청을 순차적으로 보내야 한다. 이게 바로 Waterfall 문제다. 앞 요청의 응답을 받아야 다음 요청을 보낼 수 있어서, 응답 시간이 누적된다.
게다가 클라이언트마다 필요한 데이터가 다르다:
- 웹 브라우저: 고해상도 이미지, 풍부한 데이터 → 네트워크 여유 있음
- 모바일 앱: 저해상도 썸네일, 최소한의 데이터 → 네트워크·배터리 절약이 중요
- IoT 디바이스: 극단적으로 가벼운 데이터만 필요
범용 API 하나로 이 모든 클라이언트를 만족시키려면, 결국 가장 많은 데이터를 필요로 하는 클라이언트 기준으로 설계하게 된다. 모바일은 필요 없는 데이터까지 받아서 파싱해야 하고, 이는 낭비다.
BFF 패턴의 구조
┌─────────────┐
│ Web App │
└──────┬──────┘
│
┌──────▼──────┐
│ Web BFF │ ← 웹 전용 백엔드
└──────┬──────┘
│
┌────────────────▼────────────────────┐
│ 내부 마이크로서비스들 │
│ Users API / Posts API / Feed API │
└────────────────┬────────────────────┘
│
┌──────▼──────┐
│ Mobile BFF │ ← 모바일 전용 백엔드
└──────┬──────┘
│
┌──────▼──────┐
│ Mobile App │
└─────────────┘
BFF는 클라이언트와 내부 서비스 사이의 중간 계층이다. 각 BFF는:
- 여러 내부 API를 조합·집계해서 클라이언트가 원하는 형태로 가공
- 클라이언트가 1번의 요청으로 필요한 데이터를 한 번에 받을 수 있게 함
- 클라이언트별로 최적화된 응답 제공 (웹은 풀 데이터, 모바일은 경량 데이터)
BFF가 해결하는 문제들
1. Waterfall 문제 해소
클라이언트가 여러 API를 순서대로 호출하는 대신, BFF가 내부적으로 병렬로 호출하고 결과를 합쳐서 1번의 응답으로 돌려준다.
2. Over-fetching / Under-fetching 해소
- Over-fetching: 필요 없는 데이터까지 받는 문제 → BFF에서 클라이언트에 맞게 필터링
- Under-fetching: 데이터가 부족해 추가 요청을 보내야 하는 문제 → BFF에서 미리 조합
3. 클라이언트별 최적화
모바일 BFF는 이미지 URL을 저해상도로 변환하거나, 불필요한 필드를 제거한 응답을 준다. 웹 BFF는 SEO에 맞는 데이터 구조로 제공한다.
4. 클라이언트 변경에 유연
모바일 앱 UI가 바뀌어 필요한 데이터 구조가 달라져도, Mobile BFF만 수정하면 된다. 내부 서비스나 Web BFF에는 영향이 없다.
BFF vs 범용 API vs GraphQL 비교
| 방식 | 장점 | 단점 |
|---|---|---|
| 범용 API | 단순, 관리 포인트 하나 | Over/Under-fetching, 클라이언트별 최적화 불가 |
| BFF | 클라이언트별 최적화, 관심사 분리 | BFF 수만큼 유지보수 포인트 증가 |
| GraphQL | 클라이언트가 필요한 필드만 요청 가능 | 학습 곡선, N+1 문제, 캐싱 어려움 |
GraphQL은 BFF의 대안으로 자주 언급된다. 클라이언트가 쿼리로 원하는 데이터 구조를 직접 명시하면, 서버가 그에 맞춰 응답하기 때문이다. 다만 캐싱이 어렵고 N+1 문제가 생기는 등 복잡성이 있어, BFF와 GraphQL을 함께 쓰는 구조도 존재한다.
실제 사례
- Netflix: 디바이스(TV, 모바일, 웹)마다 BFF를 두고 최적화된 응답 제공
- SoundCloud: 모바일 앱 전용 BFF를 도입해 응답 시간과 데이터 크기를 대폭 줄임 (BFF 패턴이 처음 공식 정의된 사례)
- Spotify: 마이크로서비스 + BFF 조합
API 설계와의 관계
리소스 중심으로 API를 잘게 분리하면 내부 서비스의 유연성은 올라가지만, 클라이언트의 부담이 커진다. BFF는 이 둘을 동시에 만족시키는 방법이다.
클라이언트 ←→ BFF (클라이언트별 최적화) ←→ 내부 API (리소스 중심 분리)
즉, 내부는 잘게 쪼개고, 외부 인터페이스는 BFF로 통합하는 전략이다.
언제 도입할까?
도입이 적합한 경우:
- 클라이언트 종류가 2개 이상이고 필요한 데이터가 명확히 다를 때
- 마이크로서비스 아키텍처를 사용할 때
- 클라이언트 팀이 BFF를 직접 관리할 수 있을 때 (프론트엔드가 BFF 코드를 소유)
굳이 안 해도 되는 경우:
- 클라이언트가 하나뿐이거나 데이터 요구사항이 유사할 때
- 팀이 작아서 BFF를 추가로 유지보수하기 부담스러울 때