본문 바로가기

업무

BFF 활용하여 프론트엔드만을 위한 API 만들기

 

 

이번 포스트는 최근 웹뷰 서비스를 개발하면서 백엔드 개발자와 커뮤니케이션 갈등을 BFF 기술을 활용해 해결했던 개인적인 경험을 소개하는 글입니다.

 

 

프론트엔드 개발자라면 누구나 겪는 상황이라 그런지 해외 개발자 커뮤니티에서도 위와 같은 재밌는 밈이 많았다.

프론트엔드 개발자가 바라는 가장 이상적인 백엔드 개발자는 화면에 Fit한 API를 제공받는 일이다.

아직 주니어 개발자인 나는 이번 웹뷰 서비스를 개발하면서 아주 아주 복잡한 API를 받자마자 당황했다.

 

이 하나의 API를 이해하기 위해 따로 회의를 잡아야 할 정도로 커뮤니케이션 비용이 컸는데

나는 이런 상황이 익숙하지 않아서 백엔드 개발자에게 화면에 맞춰서 새로운 API를 개발해줄 것을 요구했다.

 

하지만 백엔드 개발자도 이유가 있었다. 이미 만들어진 API를 분리하여 여러 API를 다시 만드는 일은 너무 많은 API가 만들어지게 되어 관리가 매우 어려워진다.

 

백엔드 개발자의 입장도 이해가 되어 이런 상황을 해결할 수 있는 기술은 없는 것인지 알아보다가

BFF 개념을 발견했다.

 

BFF(Backend for Frontend) 

프론트엔드를 위한 백엔드라는 뜻이다.

 

아직 사내에서 개발중인 서비스는 출시가 되지 않아서 공개가 어려워서 토스 증권 웹뷰 화면을 가져왔다.

토스 증권이 어떻게 개발하는지는 모르지만 예시를 위해 저 화면을 구성하기 위해 실시간 주식 가격을 가져오는 API를 프론트엔드에서 호출하고

어제 주식 가격 API도 호출하여 가격을 비교하여 오늘 얼만큼 오르고 있는지, 떨어지고 있는지 표시한다고 생각해보자.

 

이건 분명 비즈니스 로직인데 프론트엔드에서 다루게 되는 것은 프론트엔드 개발자에게 아주 곤란하다.

 

한 화면, 한 컴포넌트 데이터를 표현하기 위해 여러 API를 호출하는 일은 비동기 제어도 해야할 것이고 분산된 응답 상태를 어떻게 저장할지도 고민해야 한다. 그러다 보면 프론트엔드 코드는 매우 지저분해진다. 

 

만약 API 중 하나가 에러가 나거나 스펙이 바뀌거나 한다면 더욱 힘들어진다.

아주 가까이에 표현되는 데이터인데 API가 나뉘어 있다면 코드는 자연스럽게 지저분해진다.

 

왜냐면 그 화면을 수정하기 위해선 연결된 API들을 이해해야 하고, 어떻게 결합되고 어떻게 화면에 뿌려지는지 비즈니스 로직까지 파악해야 하기 때문이다.

 

만약 그 API가 정말 하나의 웹 화면에만 사용된다면 그 화면에 맞출 수도 있지만

IOS, AOS 등 다양한 기기의 다양한 화면에서 모두 사용이 된다면 API가 정말 많아지게 되는 이슈가 생긴다.

 

 

 

아마도 이런 식으로 구성되는 것이 프론트엔드 개발자에게 훨씬 기쁜 상황일 것이다.

 

내가 다니고 있는 회사의 코드베이스는 Next.js 12 버전으로 구성되어 있는데 Next.js의 최신 기능을 이용하면 위와 같은 상황을 훨씬 쉽게 해결할 수 있다.

 

Next.js에서는 api routes 기능을 제공하는데 pages/api 폴더 아래에 아래와 같은 handler 함수를 정의하면 화면에 프론트엔드를 위한 BFF API를 만들 수 있다.

 

pages/api 폴더 아래에 정의하는 파일은 브라우저가 아닌 서버사이드에서 실행된다.

 

// /pages/api/mypage

/**
 * 마이페이지 조회 API
 */
export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse<Data>,
) {
  if (req.method === 'GET') {
    /* 사용자 인증 (JWT) */
    try {
      const token = await getToken({ req });
    } catch (e) {
      return res.status(403).json({ error: '토큰 인증 실패' });
    }

    const [ profile, userInfo ] = await Promise.all([fetchProfile, fetchUserInfo]);

    /* 프로필 정보 + 사용자 정보 반환 */
    res.status(200).json({ profile, userInfo });
  }

  res.status(400);
  res.end();
}

 

위 코드는 토이프로젝트에서 사용하고 있는 코드인데 기존에는 데이터베이스가 사용자 정보 테이블, 프로필 정보 테이블이 나뉘어져 있고 조회는 하나씩 진행되어 각각 API가 있었는데 위 기능을 활용하여 손쉽게 하나의 API로 구성할 수 있었다.

 

나는 REST API로 구성했지만 더 효율적으로 사용하기 위해선 GraphQL를 활용할 수도 있다.

Next.js에서도 지원하고 있다.

 

결론

 

BFF를 쓰면 다음과 같은 장점이 있는 것을 발견했다.

- 프론트엔드 개발자에게 이상적인 화면에 Fit한 API를 만들 수 있다.

- 백엔드 개발자와 커뮤니케이션 비용을 줄일 수 있다.

- API와 관련된 비즈니스 로직은 코드베이스에서 분리할 수 있다.

- 잘 알아두면 토이프로젝트를 할 때 백엔드 개발자 없이도 할 수 있는 일이 많아진다.

- 여러 도메인의 API를 다룰 때도 브라우저 CORS 에러에서 자유로워진다.

 

 

 

참고

https://dev.to/adelhamad/bff-backend-for-frontend-design-pattern-with-nextjs-3od0

https://fe-developers.kakaoent.com/2022/220310-kakaopage-bff/

https://github.com/adelhamad/bff-demo/blob/master/pages/api/bff.ts