내가 Capa-BFF를 만든 이유: 해커톤 금상을 차지한 비용 제로(Zero-Cost) BFF 솔루션
요약
해커톤 우승을 위해 개발된 Capa-BFF는 추가 인프라 비용 없이 기존 백엔드 서비스에 사이드카 형태로 실행되는 BFF 솔루션입니다. API 어그리게이션, CORS 처리, JSON DSL 기반 변환 기능을 제공하여 개발 생산성을 높입니다.
핵심 포인트
- 추가 인프라 및 배포 비용이 없는 Zero-cost BFF 솔루션
- API 어그리게이션 및 JSON DSL을 통한 요청/응답 변환 지원
- Spring Boot 의존성 추가만으로 간편하게 적용 가능
- CORS 문제 해결 및 자동 캐싱 기능 제공
내가 Capa-BFF를 만든 이유: 해커톤 금상을 차지한 비용 제로(Zero-Cost) BFF 솔루션
솔직히 말해서, 이 프로젝트로 해커톤에서 우승할 줄은 몰랐습니다. 전체 이야기를 들려드릴게요.
해커톤 제출 마감 전날 새벽 3시였고, 우리 팀은 막다른 길에 다다랐습니다. 클라우드 네이티브 (Cloud-native) 애플리케이션에 대한 멋진 아이디어가 있었지만, 계속해서 같은 문제에 부딪혔습니다. 바로 BFF (Backend For Frontend) 레이어가 필요하다는 것이었습니다. 하지만 우리는 앞으로 8시간 동안 상용구 코드(Boilerplate)인 CRUD 엔드포인트를 작성하고, CORS를 설정하고, 또 다른 서비스를 배포하며, 그에 따르는 모든 DevOps 관련 골칫거리들을 처리하고 싶지 않았습니다.
저는 해커톤에서 배포하는 모든 추가 서비스가 또 다른 장애 지점 (Point of failure)이 된다는 것을 뼈아픈 경험을 통해 배웠습니다. 배포를 성공시키는 시점에는 이미 밤의 절반을 날려버리고 생산성도 바닥난 상태가 됩니다.
그래서 이런 생각이 들었습니다. 별도의 BFF 서비스를 전혀 배포할 필요가 없다면 어떨까? 인프라 비용 제로, 추가 배포 제로, 그리고 단 몇 줄의 설정만으로 완전한 BFF 레이어를 얻을 수 있다면 어떨까?
그것이 바로 Capa-BFF가 하는 일입니다. 그리고 오늘 저는 왜 제가 이것을 만들었는지, 어떻게 작동하는지, 그리고 여러분의 다음 프로젝트에 적합할지 공유하고자 합니다.
Capa-BFF란 무엇인가?
Capa-BFF는 기존 백엔드 옆에서 완전히 사이드카 (Sidecar)로 실행되는 비용 제로(Zero-cost) BFF 솔루션입니다. 다음과 같은 기능을 제공합니다:
- 여러 백엔드 서비스로부터의 동적 API 어그리게이션 (Aggregation)
- 내장된 CORS 처리 (더 이상 그것과 싸울 필요가 없습니다)
- JSON DSL을 이용한 요청/응답 변환 (Transformation)
- 자동 캐싱 (Automatic caching)
- 말 그대로 추가 인프라 비용 제로
- 기존 앱이 실행되는 어디에서나 배포 가능
GitHub: https://github.com/capa-cloud/capa-bff
현재 별(Stars) 개수: 36
핵심 아이디어는 매우 간단합니다. 백엔드와 통신하는 별도의 BFF 서비스를 배포하는 대신, Capa-BFF는 기존 백엔드 서비스와 나란히 실행됩니다. 이는 BFF 요청을 가로채서 어그리게이션/변환을 수행하고, 결합된 응답을 프론트엔드(Frontend)로 반환합니다.
추가적인 VM, 추가적인 컨테이너, 추가적인 비용이 들지 않습니다. 기존 애플리케이션에 의존성(Dependency)만 추가하면 끝입니다.
실제로 어떻게 작동하나요?
실제 사례를 보여드리겠습니다. 여러분이 소셜 미디어 앱을 만들고 있고, 프론트엔드(Frontend)에서 다음과 같은 정보가 필요하다고 가정해 봅시다:
- 사용자 서비스(User service)로부터의 사용자 정보
- 포스트 서비스(Post service)로부터의 최근 게시물
- 알림 서비스(Notification service)로부터의 읽지 않은 알림 개수
BFF가 없다면, 프론트엔드는 세 번의 별도 요청을 보내야 합니다. 이는 느리고, 통신량이 많으며(Chatty), 번거롭습니다. Capa-BFF를 사용하면 간단한 JSON 설정(Config)에 하나의 어그리게이션 엔드포인트(Aggregation endpoint)를 정의하기만 하면 됩니다:
{
"name": "userDashboard",
"aggregations": [
...
그게 전부입니다. 이 파일을 설정 디렉토리에 저장하고, Spring Boot 애플리케이션에 Capa-BFF 의존성을 추가하면(현재 Java/Spring Boot를 지원하며, 더 많은 프레임워크가 추가될 예정입니다), 바로 완료됩니다:
@SpringBootApplication
@EnableCapaBFF
public class MyApplication {
...
이제 /bff/userDashboard라는 완전히 새로운 엔드포인트가 생겼으며, 이 엔드포인트는 세 서비스 모두를 자동으로 호출하고, 결과를 어그리게이션(Aggregation)하여 프론트엔드에 필요한 모든 것을 단 한 번의 요청으로 반환합니다.
{
"user": {
"id": 123,
...
정말 멋지지 않나요? 저희 해커톤 프로젝트에서 이 설정은 원래 계획했던 4시간 이상의 시간 대신, 작동하기까지 약 15분밖에 걸리지 않았습니다. 덕분에 저희는 대회 우승을 이끈 실제 기능들을 구현하는 데 집중할 수 있었습니다.
저조차 놀라게 만든 성능 수치
이것을 만들 때 성능 면에서는 큰 기대를 하지 않았습니다. 결국 기존 서버에서 추가적인 작업을 수행하는 것이니까요. 하지만 벤치마킹(Benchmarking)을 통해 얻은 수치는 솔직히 저를 놀라게 했습니다.
저희는 세 개의 백엔드 서비스를 어그리게이션하는 1,000개의 동시 요청(Concurrent requests)으로 간단한 벤치마크를 실행했습니다:
| 설정 | 평균 지연 시간 (Average Latency) | QPS |
|---|---|---|
| 세 번의 별도 프론트엔드 요청 | ~180ms | ~660 |
| Capa-BFF 어그리게이션 | ~82ms | ~1200 |
이는 프론트엔드에서 세 번의 별도 요청을 보내는 것과 비교했을 때 2.2배 더 빠르고 처리량(Throughput)은 거의 두 배에 달하는 수치입니다. 그리고 기억하세요, 이 모든 것은 여러분의 기존 인프라 위에서 실행됩니다.
1200 QPS는 0.5 vCPU와 256MB 메모리를 가진 단일 컨테이너에서 나왔습니다. 우리는 백엔드 호출 외에 평균 0.8ms의 프로세싱 오버헤드(Processing Overhead)로 1200 QPS를 달성했습니다. 이는 거의 무시할 만한 수준입니다. 대부분의 시간은 어차피 백엔드 서비스들이 병렬로 응답하기를 기다리는 데 사용되기 때문입니다.
솔직히 말해서, 저는 오버헤드가 훨씬 더 높을 것이라고 생각했습니다. 하지만 한동안 프로파일링(Profiling)을 해본 결과, 대부분의 시간은 이미 상당히 잘 최적화되어 있는 JSON 파싱(Parsing)과 네트워크 I/O에 소비되고 있었습니다.
장단점: 솔직하게 이야기해 봅시다
저는 모든 문제를 해결하는 완벽한 솔루션을 여러분에게 팔러 온 것이 아닙니다. Capa-BFF는 특정 유스케이스(Use Case)에는 훌륭하지만, 분명 모든 사람을 위한 것은 아닙니다. 솔직하게 분석해 보겠습니다.
✅ 장점
-
추가 비용 제로 (Zero extra cost). 진심입니다. 추가로 지불하는 비용이 전혀 없습니다. 기존 인프라에서 실행됩니다. 저와 같은 사이드 프로젝트 개발자나 자원이 한정된 스타트업에서 일하고 있다면, 이는 게임 체인저(Game-changer)가 될 것입니다.
-
매우 빠른 시작. "BFF가 뭐지?"라는 질문에서 "작동하네!"까지 단 15분이면 충분합니다. 그 정도의 타임라인입니다. DevOps도, 업데이트해야 할 배포 파이프라인(Deployment Pipeline)도, 아무것도 필요 없습니다.
-
즉시 사용 가능한 병렬 요청 (Parallel requests out of the box). 모든 어그리게이션(Aggregation)이 자동으로 병렬로 실행됩니다. 이를 구현하기 위해 별도의 코드를 작성할 필요가 없습니다. 그냥 작동합니다.
-
더 이상 CORS 문제로 골머리 앓을 필요 없음. Capa-BFF가 CORS를 자동으로 처리해 줍니다. 프론트엔드는 하나의 도메인과 통신하고, 나머지는 모두 사이드카(Sidecar)를 통해 프록시(Proxy)됩니다. 지난 몇 년간 서로 다른 서비스에서 CORS 설정을 붙잡고 씨름하며 얼마나 많은 시간을 아꼈는지 말로 다 할 수 없을 정도입니다.
-
동적 업데이트 (Dynamic updates). 어그리게이션 설정을 변경하시나요? JSON 파일을 업데이트하고 재시작하기만 하면 됩니다. 백엔드 서비스를 별도로 실행 중이라면 전체 서비스를 재배포할 필요도 없습니다 (물론 저희의 경우에는 어차피 모두 함께 실행되지만요).
❌ 단점
-
매우 높은 트래픽의 프로덕션 시스템에는 적합하지 않음 (Not suitable for very high-traffic production systems). 만약 Netflix 규모의 트래픽을 처리하고 있다면, 아마 여전히 전용 BFF 배포(deployment)를 원할 것입니다. 이 방식은 메인 백엔드(backend)와 리소스를 공유하므로, 이 점을 반드시 인지해야 합니다.
-
현재 Java/Spring Boot만 지원함. 알고 있습니다, 알고 있어요. Go와 Node.js 버전도 작업 중이지만 아직 준비되지 않았습니다. Java 생태계에 있지 않다면 기다리거나 직접 기여(contribute)해야 합니다. (이게 바로 오픈 소스의 묘미죠?)
-
JSON DSL만 지원함. 어떤 사람들은 어그리게이션 (aggregation)에 대해 코드 수준의 제어를 원합니다. JSON 방식은 대부분의 경우에 훌륭하지만, 정말 복잡한 변환 로직 (transformation logic)이 필요하다면 한계에 부딪힐 수 있습니다. 추후 커스텀 스크립트 지원을 추가할 계획이지만, 아직 구현되지는 않았습니다.
-
BFF가 메인 배포 환경과 결합됨 (Couples your BFF to your main deployment). 백엔드와 별개로 BFF를 독립적으로 확장(scale)해야 한다면, 이 방식은 적합하지 않습니다. 이 방식의 핵심은 둘이 함께 움직인다는 점입니다. 독립적인 확장이 필요하다면 전용 BFF 서비스를 사용하세요.
이것을 만들며 겪은 개인적인 여정
저는 약 8년 동안 사이드 프로젝트와 스타트업을 만들어 왔는데, 정확히 이 문제에 직면했던 적이 얼마나 많은지 모릅니다.
BFF는 필요하지만, 또 다른 서비스를 관리하고 싶지는 않다.
매번 저는 똑같은 보일러플레이트 (boilerplate) 어그리게이션 코드를 작성하고, CORS와 싸우고, 캐싱을 설정하는 등 똑같은 과정을 반복해야 했습니다. 다섯 번째 이런 일을 겪으면서 저는 생각했습니다. "왜 사이드카 (sidecar)로 바로 실행할 수 있는 기성 솔루션은 없는 걸까?"
주변을 둘러보았습니다. 제가 찾은 모든 것은 별도의 배포가 필요하거나, 너무 무겁거나, 혹은 비용이 들었습니다. 제 사용 사례에 딱 맞는 것을 찾을 수 없었습니다. "그저 기존 앱에 이것을 넣기만 하면 바로 끝나는 것" 말이죠.
그래서 컨퍼런스를 마치고 집으로 돌아가는 기차 안에서 Capa-BFF를 만들기 시작했습니다. 네, 제 사이드 프로젝트 대부분이 그렇게 시작됩니다. 기차 안에서 지루해지면 코딩을 시작하곤 하죠. 3시간 뒤, 저는 작동하는 프로토타입 (prototype)을 갖게 되었습니다.
한 달 뒤 해커톤 (hackathon)이 열렸고, 우리는 이것을 사용하기로 결정했습니다. 우리는 금상을 차지했고, 다른 팀들은 계속해서 우리에게 "어떻게 그렇게 빨리 모든 것을 끝낼 수 있었나요?"라고 물었습니다. 그때 저는 이것이 실제로 다른 사람들에게도 유용하다는 것을 깨달았습니다. 그래서 오픈 소스 (open-source)로 공개했습니다.
솔직히 말씀드리면, 저는 전업 유지보수자 (maintainer)가 아닙니다. 이것은 시간이 날 때 작업하는 사이드 프로젝트 (side project)입니다. 하지만 PR (Pull Request)을 검토하고 버그 (bug)가 들어오면 수정합니다. 지금까지 꽤 안정적이었으며, 제 본업에서 사용하는 일부 내부 도구들의 프로덕션 (production) 환경에서도 문제없이 사용해 오고 있습니다.
빛을 발하는 주요 유스케이스 (Use Cases)
지금까지 제가 지켜본 바로는, Capa-BFF는 다음과 같은 시나리오에서 매우 잘 작동합니다:
-
해커톤 (Hackathons). 당연하죠. 우리는 이것으로 해커톤에서 우승했습니다. 속도가 전부이며, 이것은 15분 만에 완전한 BFF를 제공합니다.
-
사이드 프로젝트 (Side projects). 돈이 무한정 있는 것은 아닙니다. 실행하는 모든 추가 서비스는 또 다른 비용입니다. 필요하지 않은데 왜 또 다른 서비스를 실행하겠습니까?
-
내부 도구 및 관리자 대시보드 (Internal tools and admin dashboards). 여기서는 독립적인 스케일링 (scaling)이 필요하지 않습니다. 그저 최소한의 노력으로 작동하는 무언가가 필요할 뿐입니다.
-
초기 단계 스타트업 (Early-stage startups). 빠르게 움직이고 반복 (iteration)해야 하며, 인프라 (infrastructure)에 시간을 쓰고 싶지 않을 것입니다. 일단 제품을 시장에 내놓으세요. 서비스 분할은 실제로 필요할 때 고민해도 됩니다.
-
BFF 로직이 단순한 애플리케이션. 대부분의 BFF는 어차피 몇 개의 서비스에서 데이터를 집계 (aggregating)하는 역할만 합니다. 이것이 바로 이 도구가 만들어진 목적입니다.
이것을 만들며 배운 점
Capa-BFF를 만들면서 공유할 가치가 있다고 생각하는 몇 가지 교훈을 얻었습니다:
첫째, 단순함은 언제나 기능을 이깁니다. 전체 시스템은 약 2,000줄의 코드 (lines of code)로 이루어져 있습니다. 그게 전부입니다. 수만 가지 일을 하지는 않습니다. 단 한 가지, 추가 배포 (deployment) 없이 API를 집계하는 일을 정말 잘 해냅니다. 그것만으로도 충분합니다.
둘째, 사이드카 아키텍처 (sidecar architecture)는 사이드 프로젝트와 소규모 팀에게 과소평가되어 있습니다. 모두가 거대한 Kubernetes 클러스터 내의 서비스 메시 (service mesh)를 위한 사이드카에 대해 이야기하지만, 동일한 패턴은 작은 애플리케이션에도 매우 잘 작동합니다. 필요하기 전부터 왜 미리 분리하려 하나요?
셋째, 항상 "베스트 프랙티스 (best practice)" 아키텍처가 필요한 것은 아닙. 베스트 프랙티스는 별도의 BFF 서비스를 가져야 한다고 말합니다. 리소스가 풍부한 대규모 팀이라면 그것은 훌륭한 방법입니다. 하지만 1인 개발자나 소규모 팀이라면, 때로는 "정답"인 접근 방식보다 실용적인 접근 방식이 더 나을 수 있습니다. 저는 아키텍처를 과하게 설계하느라 결국 아무것도 출시하지 못하는 것보다, 지금 당장 무언가를 출시하는 쪽을 택하겠습니다.
이것이 모든 아키텍처 전문가 (architecture astronauts)들이 말하는 것에 반하는 내용이라는 것을 알고 있습니다. 하지만 솔직히 말해서, 대부분의 프로젝트는 첫날부터 Netflix 규모의 아키텍처를 필요로 하지 않습니다. 여러분, YAGNI를 기억하세요. You Ain't Gonna Need It (정말 필요할 때까지는 만들지 마세요).
시작하기
Capa-BFF를 사용해보고 싶다면 정말 쉽습니다. Spring Boot 프로젝트에 의존성 (dependency)을 추가하기만 하면 됩니다:
<dependency>
<groupId>cloud.capa</groupId>
<artifactId>capa-bff-spring-boot-starter</artifactId>
...
애플리케이션 클래스에 @EnableCapaBFF 어노테이션 (annotation)을 추가하고, src/main/resources/bff/에 집계 (aggregation) 설정을 생성하면 준비가 끝납니다.
더 자세한 예제와 문서는 GitHub 저장소를 확인하세요: https://github.com/capa-cloud/capa-bff
마치며
Capa-BFF가 여러분의 모든 문제를 해결해 주지는 않을 것입니다. 대규모 환경에서 독립적인 확장성 (scaling)이나 고가용성 (high availability)이 필요하다면 전용 BFF 서비스를 대체할 수는 없습니다. 하지만 해커톤, 사이드 프로젝트, 초기 단계 스타트업, 그리고 내부 도구(internal tools)를 위해서라면? 추가 비용 없이 단 15분의 설정만으로 해낼 수 있는 일들이 정말 놀라울 정도입니다.
제가 이것을 만든 이유는 저에게 필요했기 때문이며, 오픈 소스로 공개한 이유는 다른 사람들도 아마 같은 문제를 겪고 있을 것이라고 생각했기 때문입니다. 어쩌면 여러분은 해커톤 제출 마감 직전인 새벽 3시에, 어떻게 이 모든 일을 다 끝낼 수 있을지 고민하며 이 글을 읽고 계실지도 모르겠습니다. 한번 시도해 보세요. 저희의 사례처럼 여러분의 경연에서도 구원투수가 되어줄지도 모릅니다.
여러분의 생각은 어떠신가요?
궁금합니다. 여러분은 여전히 모든 프로젝트마다 별도의 BFF 서비스를 배포하시나요, 아니면 여러분에게 잘 맞는 지름길을 찾으셨나요? 이전에 BFF를 위해 사이드카 (sidecar) 접근 방식을 시도해 보신 적이 있나요? 효과가 있었나요, 아니면 제가 여기서 언급하지 않은 문제들에 부딪히셨나요?
아래에 댓글을 남겨 여러분의 경험을 알려주세요. 다른 분들은 이 문제를 어떻게 해결하고 계신지 정말 듣고 싶습니다.
그리고 만약 Capa-BFF를 사용해 보신다면, 결과가 어땠는지 알려주세요! 만약 유용하다고 느끼신다면 리포지토리 (repo)에 스타 (Star)를 눌러주세요. 다른 사람들이 이 프로젝트를 찾는 데 큰 도움이 됩니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기