Backend 개발자/아키텍처

마이크로 소프트 아키텍처(MSA) 4편 BFF(Backend For Frontend) 계층 점진적 설계 및 GraphQL 대체 하는 방법

by 앵과장 2022. 3. 3. 10:56
반응형

안녕하세요
앵과장입니다

마이크로 서비스 아키텍처 멀티모듈 구성에 대해서 개발해보고 레이어단위로 필요한 정책 소스코드에 대한 내용을 공유 하였습니다.

아직 못보신분은 아래링크를 클릭하세요

 

마이크로 소프트 아키텍처(MSA) 3편 멀티 모듈(Multi Module)

안녕하세요 앵과장입니다. 이글을 읽기전에 소스코드부터 필요하신분들을 위해서 github 링크 걸어둡니다. https://github.com/lswteen/product MSA로 가기위해서 많은 부분들을 점진적으로 만들어보고 삽

angryfullstack.tistory.com


오늘 시간은 BFF계층에 대해서 왜필요한지 그리고 어떻게 사용하면 되는지에 대한 내용을 공유 해보도록 하겠습니다.

 

BFF 를 사용하기전 Frontend 처리 방법

Rest API 는 다음을 정의합니다.

  • API end-point
  • HTTP verb
  • Path
  • Query parameters
  • Header
  • Body
  • Response

예를 들어 NASA에서 행성 날씨 데이터를 제공하는 API가 있다고 설명해보도록 하겠습니다.

 

클라이언트는 Response된 부분에 대해서 몇가지 문제점을 고려해볼 수 있습니다.

 

Over-fetching

Response받은 Payload 정보가 클라이언트에서 원하는것보다 불필요하게 많은 데이터를 제공할경우가 존재합니다.

Mobile Application에서는 Payload데이터가 많아질수록 네트워크 비용이 발생하고 트래픽이 증가하고 페이지 로드되는 시간이 증가합니다.

 

Under-fetching

날씨 데이터와 함께 다른 정보도 함께 표시 하고싶다면 

날씨 API와 다른 API 를 호출해야합니다.

2개의 클라이언트에 연결되며 그만큼 네트워크 비용이 발생합니다.

 

BFF란?
(Backend For Frontend)

BFF 목적은 Orchestration, Business Logic 을 공유 하고 Backend 서비스가 제공하는것보다는 UI에 친화적인 모델 제공입니다.

 

그래서 각 클라이언트별로 BFF를 구성하게 됩니다.

 

Frontend 프리젠테이션 계층에서 노출되어야하는 도메인이 하나 이상일 경우

예를 들어 이커머스 도메인에서
마이페이지 > 주문내역 이라면 상품, 주문, 배송, 회원 이렇게 4개

도메인Api를 조합해야만 표현 가능한형태가 됩니다.


이때 Frontend에서 처리하기 위해서 각 도메인에서 제공하는 Api를 호출하고 해당 내용을 표현할수 있는 Object Mapping해주는 과정 그리고 순서가 필요하다면 핸들링까지 처리가 들어가야합니다.

Gateway 처럼 중앙집중형( centralize )이라면 이러한 형태의 호출 방식으로 표현이 됩니다.


좀더 UI친화적 레이어를 위해서 BFF라는 계층을 구성하여 집합(Aggregation) 으로 처리 되어야 하는 비지니스를 Frontend 에서는 각도메인별 Api 호출방식이 아닌 BFF라는 프리젠테이션 계층에 비지니스를 도와주는 역활을 하게 됩니다.


이렇게 되면 도메인별로 집합(Aggregation) 되어 표현되어야하는곳에 좀더 직관적이고 의미가 명확한 API를 도출할수 있게되는것입니다.

 

많은 서비스 회사에서도 각 도메인 API로 표현하기에는 용도가 어디에도 두기참 어려운 상황에서 사용되기도 하기때문에 옵션으로 넣기도 하지만 가능한 상황이라면 사용하는것을 권장하기도 합니다.

 

BFF 를 사용한다면 문제점은 어떤것들이 존재하나요 ?

문제 및 고려 사항

 

  • Gateway를 사용하고 있었다면 BFF라는 계층을 두기위한 리소스가 추가됩니다.
  • 물리적인 비용이 발생할수 있습니다.
  • 네트워크에서 I/O 가 추가적으로 발생합니다.
  • Frontend와 진행할 방향에 대해서 점진적으로 확장할수있는 형태의 API 가 고려되어야합니다.
  • 추후 운영에서 Bounded Context에 대한 고민을 할수도 있습니다. ( 이게 내꺼냐 니꺼냐 ..로가는순간 헬이열리게됩니다.)

 

  • 업무 조직간 교차 관리 어려움
  • Traffic에 대한 용량 사이징 예측 어려움
  • 단일 실패 지점이 될가능성 존재함
  • 추가적인 아키텍처 복잡성 발생

 

BFF 레이어 구성 2가지 방안

BFF 표현하는 방법은 상황에 맞게 변경이 가능할것 같아 아래 2가지 방안에 대한 예시를 만들어봤습니다.

보통 Legacy가 존재할경우 한번에 여러 데이터베이스를 나누기란 쉽지 않습니다.

 

기존에 서비스를 마이크로서비스로 변경하는 단계라고 볼수 있습니다.

모놀리식에서 미니 서비스가 중간에 위치하고 각 도메인별로 분리된 마이크로서비스가 구성되게 됩니다.

 

BFF Case A

MSA 구성으로 도메인 별구성이된 각 서비스를 API Gateway 대신 BFF 사용하기위한 구성 아키텍처 입니다.

 

API Application Layer 는 바운디트컨텍스트 도메인 별로 실행가능한 Application Was 서비스가 존재합니다.

BFF로 표현하는 계층에서는 Http 프로토콜 을 사용하여 Rest 로 데이터들을 호출하여 Frontend 프리젠테이션 계층에 전달하게됩니다. 

 

여기서 발생하는 문제점은 I/O가 발생하는부분이며 트랜잭션에 대한 관리가 필요한 상황입니다.

 

BFF Case B

MSA로 가기전에 데이터베이스는 아직 분리되지 않은 상태에서 어플리케이션에서 최대한 필요한용도에 맞게 모듈단위에 계층으로 구성된 도메인서비스가 있다고 가정해보도록 하겠습니다. 

멀티모듈형태 레이어이며 "도메인 모듈 계층"은 Independently available 에 해당하는 RDBMS를 바운디드컨텍스트로 구성한 형태입니다.

 

Persistent 비지니스를 처리하는 역활을 하기때문에 역활과 책임이 각 도메인에 명확하게 나눠져있는 상태라서 

BFF에 필요한 도메인 모듈만 직접 Gradle에 implementation 으로 사용하는 방법입니다.

 

위에서 언급한 BFF Case A 에서 발생하는 물리적 리소스와 I/O 및 트랜잭션에 단위에 부분을 모놀리식 하지만 데이터베이스를 하나로 쓴다는 가정에서는 리소스를 줄일수있는 방안입니다.

 

Infrastruture config를 한개 이상 사용해야하기때문에 멀티 컨넥션에 대한 설정을 고려하셔서 작업하셔야 합니다.

 

How to use GraphQL to build Backend-For-Frontends 

 

Rest API와 달리 GraphQL을 사용하면 서버에서 DSL로 제공할수 있는 데이터를 정의할수 있습니다.

클라이언트는 서버에서 제공하는 DSL로 작성된 요청을 보내면 필요한 데이터와 원하는 정보에 Payload만 처리할수 있게되는겁니다.

이렇게 하면 클라이언트에 응답을 제어하기때문에 오버패칭(Over-fetching)과 언더패칭(Under-fetching)이 방지됩니다.

 

 

클라이언트는 BFF 대신 GraphQL에서 제공하는 QueryDSL을 통해서 요청한 데이터 처리가 가능합니다.

Schema

서버가 제공하는 데이터 스키마 및 Query DSL정의

 

Query DSL

클라이언트가 서버에서 필요로 하는데이터를 조회하기위한 DSL

 

Avoid over-fetching and under-fetching

응답 수신에 대한 데이터 제어

 

Documentation / Introspection

GraphQL endpoint 에있는 클라이언트가 쿼리를 적절하게 구성할수 있도록 하는 스키마 및 Query제공

 

 

단점으로 러닝커브와 클라이언트 입장에서 제공하는 데이터에 대한 스키마분석이 필요합니다.

하지만 리소스를 줄일수 있고 클라이언트가 최대한 백앤드에 결합도 없이 독립적인계층에 대한 GraphQL을 처리할수있게된다는 장점이 존재합니다.