Troubleshooting - BFF에 대한 생각

dev_will_d·2024년 5월 27일
0
post-thumbnail

현업에서 아키텍처 구성은 보통 Three-tier Architecture로 구성된다. Three-tier Architecture의 구성과 각 레이어의 역할과 책임은 아래의 설명과 같다.

Three-tier Architecture
1. Presentation Tier
   - 사용자에게 보여지는 부분을 담당
   - React, Native App ...
2. Logic Tier
   - 서비스와 관련된 기능과 정책 등등 비지니스 로직을 담당
   - Spring, Django
3. Data Tier
   - 데이터를 저장, 관리, 제공 역할
   - MySQL, Oracle, MongoDB

MSA를 통한 분리/분해로 인해 생긴 문제

Presentation Tier는 사용자에게 보여지는 부분을 담당한다. 즉 사용자와의 상호작용 및 표현을 담당하는 중요한 부분이다. Presentation Tier는 무엇에 집중해야 되냐 묻는다면 사용자와의 상호작용과 표현에 집중해야 한다고 말하는것이 올바를것이다.

개발의 자원과 시간은 유한하다 무한하지 않다. 이말은 Presentation Tier를 담당하는 개발자의 수와 개발을 하는 시간은 유한하다는 뜻이다. Presentation Tier를 담당하는 개발자가 Business Logic 처리에 과중한 집중을 하다 보면 서비스의 성패를 좌우하는 UI/UX 개발에 집중하지 못할 수 있다. Three-tier Architecture 관점에서 비지니스 로직은 Logic Tier(백엔드)에 집중시키고 Presentation Tier(프론트엔드, Native App)에서는 UI/UX 개발에 집중하여 역할과 책임을 분명히 하여 각 레이어에서 최대 장점을 발휘하는 개발과 그 목적성에 부합하는 개발을 하여 서비스 전체의 퀄리티를 올리는것이 적합하다.

그러나 서버 구성을 MSA로 구성하여 각 서버를 비지니스와 도메인에 따라 분리/분해 하면 발생하는 문제가 있다.
각 서버의 도메인은 특정 클라이언트가 아닌 모두를 만족하는 응답을 내린다. 즉, 도메인 속성을 내린다. 각각의 클라이언트 (모바일, 앱, 서버)는 이 응답값을 자체적으로 필요에 의한 로직으로 처리해야 한다. 즉, 서버에서 처리해야 할 비지니스 로직을 UI/UX에 집중해야 할 Presentation Tier의 클라이언트가 처리하는 문제가 발생 할 수 있음을 야기한다.

이 외에도 발생하는 문제가 있다. 비지니스 능력과 도메인을 기준으로 서버를 분리하다 보면 특정 페이지를 완성하기 위한 API를 Aggregate하여 완성하기 힘든 경우가 있다. 이럴때는 클라이언트가 서버에 요청을 물리적으로 여러번 해야 하는 경우가 생긴다. 클라이언트에서 여러번 물리적 통신을 여러번 하는것은 성능 문제를 야기할수 있다. (로컬망에서의 통신보다 네트워크를 통한 통신이 더욱 느리기 때문이다.)

문제 해결 BFF

MSA에서 이 문제를 해결하는 방법 중 하나가 BFF (Backend For Frontend)이다.

BFF는 Presentation Tier를 위한 백엔드라고 할 수 있다. 즉, 각각의 Presentation Tier에 최적화 되어 있어 각각의 페이지와 기능에 맞게 응답값을 내려줄수 있다. 또한 서버의 분리 / 분해로 인해 클라이언트가 물리적으로 여러번 서버를 호출해야 하는 문제도 해결 할 수 있다.

그렇다면 BFF는 만능인가?

BFF Troubleshooting

  1. BFF에 너무 많은 책임을 위임하지 말자.
GET teachers/{teacherId}
RESPONSE: Teacher

GET courses?teacherIds=
RESPONSE: List<Course>

GET text-books?teacherIds=
RESPONSE: List<TextBook>

GET teachers/{teachdrId}
RESPONSE: Teacher

GET teachers/{teacherId}/courses
RESPONSE: List<TeacherCourse>

GET teacher/{teacherId}/text-books
RESPONSE: List<TeacherTextBook>

특정 선생님의 페이지를 완성한다고 가정하자. 선생님 페이지에는 선생님의 정보와, 선생님의 강의 정보, 선생님의 교재 정보가 필요하다.

필자는 처음에 BFF 서버에서 모두 Aggregate 하기 때문에 얽힘 없이 순수하게 필요한 데이터를 요청하여 Aggregate 하는것이 적합하다고 생각했다. 그러나 이렇게 얽힘 없이 순수하게 데이터를 가져와 비지니스 로직을 처리하면 비지니스 로직이 복잡해지고 BFF가 커진다는 사실을 알게되었다. 이는 너무 많은 책임을 부여하여 유지보수를 어렵게한다.

그래서 두번째와 같은 방식을 통해 도메인과 도메인이 특정 관계를 가지면 관계를 맺어주고 이렇게 맺어진 데이터를 기반으로 비지니스 로직을 처리하도록 구성을 바꿨다. 이렇게 하면 BFF에 로직 처리 부담을 줄이고 BFF의 크기를 줄일수 있다.

각 도메인 서버에서는 각 상황과 맥락을 충분히 고려하여 도메인과 도메인의 관계를 명확히 하여 이와 관련한 응답을 주는 Endpoint을 제공 할 수 있도록 하자.

* 참고) REST API 설계

참고) BFF는 각 페이지의 복잡한 요구사항을 충족하기 위해 여러 서버를 호출하여 Aggregate 하는 특징을 지닌다. 이러한 특징으로 인해 BFF 서버를 Spring Framework로 구성한다면 Non Blocking I/O를 모델로한 WebFlux를 사용한다.


  1. 작은 서비스에서 BFF는 오히려 유지보수의 비용을 증가 시킨다.

    특정 페이지와 기능을 완성하기 위해 연관성이 낮은 도메인과 도메인이 많이 역여있는 큰 서비스에서 BFF는 적합 할 수 있다. 그러나 작은 서비스, 연관성이 낮은 도메인과 도메인이 적게 역여있는 서비스에서는 BFF는 오히려 관리 포인트를 증가 시킬 수 있다. 이러한 경우에는 BFF의 도입은 적합하지 않을 수 있다.

    이럴 때는 각각의 도메인에서 클라이언트의 요구사항을 처리하는것이 적합할 수 있다. 서비스의 요구사항과 각 도메인의 관계를 종합적으로 판단하여 BFF 도입을 할 수 있도록 하자.

Next.js

최근 Chrome 개발자 모드를 통해 API를 확인해보면 .../_next/data/...와 같은 API를 볼 수 있다. 이는 Next.js에서 백엔드를 구성하여 API를 만든것이다. Next.js에서 백엔드 서버는 BFF 서버로 활용될 수 있다. 그리고 각 회사의 상황에 따라 Next.js 서버는 프론트엔드 개발자가 개발할 수 있다.

이러한 상황까지 복합적으로 고려를 하여 프론트엔드 개발자가 UI/UX에 더욱 집중할 수 있도록 위에서 언급한 BFF에 너무 많은 책임을 위임하지 말자.

profile
질문의 질이 답의 질을 결정한다.

0개의 댓글