올해 초 즈음부터 여러 기업의 테크 블로그에서 BFF(Backend-For-Frontend)에 관련된 글을 많이 읽었다. BFF 개념과 용도에 대해 알게 되었지만, MSA 환경에서 개발 경험이 없다 보니 필요성에 대한 공감은 크게 하지 못하고 있었다.
최근 회사에서 MSA 구조를 채택하여 신규 제품을 개발하고 있다. 개발을 진행하면서 BFF의 필요성을 느끼고 도입을 하게 되었는데 작업하며 느낀 점을 공유하고자 포스팅을 작성하게 되었다.
본격적으로 BFF 이야기를 하기 전에 MSA로 이야기를 시작해야 할 것 같다. MSA는 Microservice Architecture의 약자로 독립적인 배포가 가능한 서비스들로 구성된 아키텍처라는 의미를 갖는다.
기존에는 모든 서비스가 한 곳에 모인 Monolithic한 구조로 개발을 진행하는 경우가 많았지만, 서비스의 규모가 커지면서 Monolithic한 구조로는 해결이 어려운 문제들에 직면하게 되고 이를 해결하기 위해 MSA로 서비스를 전환하거나 전환을 시도하는 곳이 늘어나고 있다.
최근에는 설계 시점부터 MSA를 채택하는 곳도 많은 것 같다. (큰 X vs 작은 X..?)
MSA에서는 각 서비스를 도메인별로 분리시킨다. 서비스는 작은 서비스의 집합으로 구성되며 각 서비스는 독립적이고 단일 비즈니스 기능에 대한 책임만을 가진다.
이를 프론트엔드 관점에서 살펴보자. 프론트엔드의 궁극적인 업무는 화면을 그리는 일이다. MSA 구조에서는 각 서비스가 기능별로 흩어져 있으므로 화면을 완성하기 위해 호출해야 하는 서비스도 늘어나게 된다.
따라서 화면을 그리기 위해서는 다수의 서비스에 연동을 해야하며, 여러 서비스에 분산되어 있는 데이터를 가져와서 적절히 합쳐야 하는 경우도 발생하게 된다.
이를 돕기 위해 BFF가 등장하게 되었다. BFF란 BackEnd For FrontEnd의 약자인데, 말 그대로 프론트엔드를 위한 백엔드 서버를 의미한다. 프론트엔드를 요구사항에 맞게 구현하기 위한 도움을 주는 보조 서버 정도로 정의할 수 있을 것 같다.
BFF의 필요성을 살펴보기 위해 MSA 구조에서 이커머스 서비스를 만든다고 가정해보자.
MSA답게 고객, 주문, 물건, 장바구니 등 커머스 도메인 별로 나뉘어 서비스가 구현되어 있다. 각 서비스는 프론트엔드에서 사용하는 API를 제공한다.
얼핏 보면 기능별로 나뉘어져 서비스가 잘 분리되어 있어 문제가 될만한 점이 보이지 않을 수 있으나, 실제로 개발을 진행하다 보면 여러 고민들에 봉착하게 된다.
이를테면, 고객의 등급을 조회하는 페이지에서 등급 업그레이드까지 남은 주문 금액을 디스플레이 하기 위해 주문 데이터를 살펴보아야 할 수도 있다. 혹은 특정 주문 데이터의 결제 현황을 조회하기 위해 결제 서비스를 호출해야 하는 경우도 있을 수 있다. 즉 원하는 응답값을 얻기 위해 여러 서비스를 호출해야 하는 상황이다.
결제 서비스를 이용하기 위한 유저별 Secret Key와 같은 비공개성 정보들이 존재할 수 있다. 브라우저를 통한 네트워크 통신은 항상 위험에 노출되어 있기 때문에, 해당 정보를 보관하고 결제 서비스 요청 시 심어주기 위한 인터페이스 서버가 필요한 상황이다.
주문 정보 엑셀 다운로드와 같이 브라우저의 자원을 많이 소모하거나 고객 정보 일괄 수정 등 다수의 네트워크 통신을 유발하는 작업을 진행해야 하는 경우가 있을 수 있다. 브라우저에서 복잡한 연산을 수행하는 경우 렌더링 성능에 악영향을 끼칠 수 있기 때문에 역시 개선이 필요한 상황이다.
이런 경우 BFF가 좋은 해결책이 될 수 있다. BFF를 두는 목적은 프론트엔드의 로직을 중간 레이어를 두어 BFF에 위임하는 것이다. 이로써 프론트엔드는 구체적인 구현을 내용을 감추고 추상화된 API를 사용할 수 있게된다. 결과적으로 프론트엔드에는 더 적은 로직이 남게 된다.
그럼 지금까지 나온 내용을 토대로 BFF의 장점을 나열해보자.
- 프론트 엔드에서 복잡한 로직을 감추고 추상화된 인터페이스를 사용 가능하다.
- 연동하는 백엔드 API의 인터페이스가 변경되는 경우 BFF에서 수정사항을 반영하면 되므로 프론트엔드는 관심사를 분리하여 본연의 비즈니스 로직에 집중할 수 있다.
- 데이터를 전송하는 과정에서 민감하거나 불필요한 데이터는 숨길 수 있다.
위에서 언급한 이슈들은 실제로 개발하며 겪었던 사례들을 약간 각색하여 적어놓은 것이다. 처음에는 클라이언트 단에서 모든 로직이 구현되어 있었지만 BFF 도입 후 해당 고민들을 상당수 해결할 수 있었다.
그냥 마치기는 아쉬워서 어떤 경우에 BFF 도입을 고민하면 좋을지 나름대로 적어보았다.
💡 BFF 도입을 고려해봐도 좋은 경우
- 하나의 view(기능)를 완성하기 위해 여러 도메인의 API 응답값을 조작해야 하는 경우
- 데이터를 전송하는 과정에서 불필요한 데이터를 숨겨야 하는 경우
- 프론트엔드에서 많은 양의 연산을 요구하는 작업을 진행해야 하는 경우
- Open API 연동시 제공하는 API의 조합으로 특정 기능을 완성해야 하는경우