이야기를 디버깅하는 개발자.

개발과 창작 사이에서, 사람들이 자기만의 이야기를 만들 수 있는 도구와 기록을 만듭니다.

roslyn.dev 자세히보기

개발 노트/프론트엔드

BFF 구조에서 리액트는 화면에 집중하고 인증은 서버가 맡는 방식

Roslyn 2026. 7. 9. 19:21
반응형

프론트엔드를 리액트로 만들다 보면 어느 순간 인증 처리를 어디까지 맡겨야 하는지 고민하게 됩니다. 화면을 그리는 일은 리액트가 잘합니다. 상태를 다루고, 컴포넌트를 나누고, 사용자와 빠르게 상호작용하는 것도 리액트의 장점입니다.

하지만 인증은 조금 다릅니다. 토큰을 어디에 저장할지, 쿠키는 어떻게 다룰지, API 호출 권한은 어디서 확인할지, 새로고침 후 세션은 어떻게 유지할지 같은 문제들이 따라옵니다. 처음에는 단순해 보이지만, 실제 서비스를 운영하려고 하면 생각보다 신경 쓸 부분이 많아집니다.

그래서 요즘 다시 관심을 두고 있는 구조가 BFF입니다. Backend for Frontend의 줄임말인데, 이름 그대로 프론트엔드를 위한 백엔드 계층을 하나 두는 방식입니다. 저는 이 구조를 “서버사이드가 프론트엔드를 한 번 감싸주는 방식”으로 이해하고 있습니다.

리액트가 모든 것을 직접 알 필요는 없습니다
SPA 구조에서는 리액트 앱이 브라우저에서 실행되고, 필요한 데이터를 API로 직접 가져오는 흐름이 자연스럽습니다. 이 방식 자체가 나쁜 것은 아닙니다. 작은 서비스나 내부 도구에서는 충분히 단순하고 빠르게 만들 수 있습니다.

문제는 인증과 권한 처리까지 브라우저 쪽으로 많이 내려왔을 때입니다. 액세스 토큰을 브라우저에 저장해야 하고, 갱신 토큰을 어떻게 보호할지도 고민해야 합니다. API 서버 주소나 인증 흐름도 프론트엔드 코드에서 점점 많이 알게 됩니다.

BFF 구조에서는 이 부담을 조금 다르게 나눕니다. 사용자는 먼저 서버사이드에 접근합니다. 서버는 사용자가 로그인되어 있는지 확인합니다. 조회 가능한 페이지라면 리액트 앱을 내려주고, 리액트는 그 안에서 화면을 그립니다. 반대로 권한이 없거나 인증이 필요한 상태라면 서버가 먼저 막거나 로그인 흐름으로 보냅니다.

서버사이드가 문지기 역할을 합니다
이 구조에서 중요한 점은 서버사이드가 문지기 역할을 한다는 것입니다. 브라우저에 있는 리액트 앱이 “이 사용자가 누구인지”를 모든 책임으로 들고 있지 않습니다. 서버가 먼저 세션이나 쿠키를 확인하고, 이 사용자가 이 화면에 접근할 수 있는지 판단합니다.

예를 들어 관리자 페이지가 있다고 가정해보겠습니다. 사용자가 /admin 경로에 접근하면 서버가 먼저 인증 상태를 확인합니다. 권한이 있으면 리액트 앱과 필요한 초기 정보를 내려줍니다. 권한이 없으면 리액트가 렌더링되기도 전에 접근을 막습니다.

이렇게 하면 프론트엔드는 화면에 집중할 수 있습니다. 물론 리액트 안에서도 사용자의 상태에 따라 버튼을 숨기거나 메뉴를 다르게 보여줄 수는 있습니다. 하지만 그것은 사용자 경험을 위한 처리이지, 최종 보안 판단의 기준이 되어서는 안 됩니다.

조회 가능한 페이지라면 리액트가 그립니다
BFF를 쓴다고 해서 모든 화면을 서버 렌더링으로 만들어야 하는 것은 아닙니다. 제가 관심 있는 방식은 조금 더 현실적인 절충입니다. 인증과 접근 가능 여부는 서버가 확인하고, 실제 화면 구성은 리액트가 맡는 방식입니다.

이 방식에서는 서버가 먼저 “이 사용자가 이 페이지를 볼 수 있는가”를 확인합니다. 볼 수 있다면 리액트 앱을 실행할 수 있는 HTML을 내려줍니다. 이후 화면 안에서 필요한 데이터는 BFF를 통해 가져오게 합니다. 리액트는 외부 API를 직접 호출하기보다, 같은 서버의 엔드포인트를 호출하는 형태가 됩니다.

이 구조가 좋은 이유는 역할이 비교적 분명해지기 때문입니다. 서버는 인증, 권한, 민감한 API 호출, 외부 서비스 연동을 맡습니다. 리액트는 화면 상태, 사용자 입력, 목록과 상세 화면, 컴포넌트 구성을 맡습니다. 서로의 책임이 겹치지 않도록 선을 그을 수 있습니다.

토큰을 브라우저에 오래 들고 있지 않아도 됩니다
BFF 구조를 선택하는 이유 중 하나는 토큰 관리입니다. 브라우저 안에 액세스 토큰이나 갱신 토큰을 직접 보관하는 방식은 늘 조심스럽습니다. 저장 위치에 따라 XSS 같은 공격에 취약해질 수 있고, 만료와 갱신 흐름도 프론트엔드 코드에 많이 들어가게 됩니다.

BFF를 두면 민감한 토큰은 서버 쪽에서 다루고, 브라우저에는 세션 쿠키만 전달하는 방식으로 정리할 수 있습니다. 물론 쿠키도 안전하게 설정해야 합니다. HttpOnly, Secure, SameSite 같은 설정을 제대로 해야 하고, CSRF에 대한 고려도 필요합니다.

다만 중요한 차이는 있습니다. 프론트엔드 코드가 직접 토큰을 읽고 들고 다니는 구조보다, 서버가 인증 흐름을 감싸는 구조가 운영 관점에서는 더 다루기 쉬울 때가 많습니다. 특히 혼자 서비스를 만들고 운영하는 입장에서는 인증 관련 코드를 여러 군데 흩뿌리지 않는 것이 중요합니다.

API도 프론트엔드 전용으로 정리할 수 있습니다
BFF의 또 다른 장점은 프론트엔드에 맞춘 API를 만들 수 있다는 점입니다. 실제 내부 API나 외부 API는 서비스 구조에 맞게 복잡할 수 있습니다. 하지만 화면에서 필요한 데이터는 조금 다릅니다. 한 화면을 그리기 위해 여러 API를 호출해야 할 수도 있고, 반대로 너무 많은 데이터가 내려올 수도 있습니다.

BFF는 이 중간에서 화면에 맞는 형태로 데이터를 정리해줄 수 있습니다. 리액트는 여러 내부 시스템의 구조를 몰라도 됩니다. 화면에 필요한 모델만 받아서 렌더링하면 됩니다.

예를 들어 대시보드 화면이 있다고 하면, BFF가 사용자 정보, 알림 개수, 최근 활동, 권한 정보를 한 번에 조합해서 내려줄 수 있습니다. 리액트는 그 결과를 받아 화면을 그립니다. 내부 API가 나중에 바뀌어도, BFF 계층에서 맞춰줄 수 있다면 프론트엔드의 변경 범위를 줄일 수 있습니다.

단점도 있습니다
물론 BFF가 항상 정답은 아닙니다. 백엔드 계층이 하나 더 생긴다는 것은 관리할 코드가 늘어난다는 뜻이기도 합니다. 단순한 정적 사이트나 인증이 거의 없는 서비스라면 오히려 구조가 무거워질 수 있습니다.

또한 BFF가 모든 것을 대신해주다 보면, 어느 순간 화면 전용 로직이 서버에 너무 많이 쌓일 수도 있습니다. 그러면 서버도 복잡해지고, 프론트엔드도 서버 응답에 과하게 묶일 수 있습니다. 그래서 BFF를 둘 때는 “보안과 조합은 서버가 맡고, 표현과 상호작용은 프론트가 맡는다”는 기준을 계속 유지해야 합니다.

작은 서비스에서는 특히 더 그렇습니다. 구조가 좋아 보여도 혼자 감당하기 어려우면 오래 유지하기 어렵습니다. 그래서 BFF도 처음부터 크게 만들기보다, 인증과 민감한 API 호출을 감싸는 작은 계층으로 시작하는 편이 현실적이라고 생각합니다.

닷넷으로 만들 때의 느낌
닷넷 환경에서는 ASP.NET Core가 이 BFF 역할을 맡기에 꽤 자연스럽습니다. 쿠키 기반 인증, 정책 기반 권한 처리, API 라우팅, 정적 파일 제공, 프록시 구성 등을 한 서버 안에서 비교적 안정적으로 다룰 수 있습니다.

리액트 앱은 빌드된 정적 파일로 배포하고, ASP.NET Core가 해당 파일을 내려주면서 인증이 필요한 경로를 감싸는 방식으로 구성할 수 있습니다. 필요한 경우 서버 API는 /api 같은 경로로 노출하고, 리액트는 같은 출처의 API를 호출하게 만들 수 있습니다.

이렇게 하면 CORS 설정이나 토큰 전달 문제도 줄어듭니다. 브라우저 입장에서는 같은 서버와 통신하는 구조가 되고, 서버는 내부적으로 필요한 서비스나 데이터베이스에 접근합니다. 구조가 단순해지는 만큼, 장애가 났을 때 원인을 추적하기도 쉬워질 수 있습니다.

제가 이 구조를 보는 이유
저는 요즘 서비스를 만들 때 “기능을 얼마나 많이 넣을 수 있는가”보다 “혼자 오래 운영할 수 있는가”를 자주 생각합니다. 

인증은 그중에서도 초반에 잘 정리해두지 않으면 나중에 계속 발목을 잡는 영역입니다.

BFF 구조는 리액트의 장점을 버리지 않으면서도, 인증과 보안의 중심을 서버 쪽에 둘 수 있는 방법입니다. 리액트는 사용자가 볼 수 있는 화면을 빠르게 구성하고, 서버는 사용자가 봐도 되는지 먼저 판단합니다. 이 분리가 생각보다 중요합니다.

특히 관리자 화면, 유료 사용자 전용 화면, 개인 데이터가 포함된 화면처럼 접근 제어가 중요한 서비스에서는 이 방식이 더 안정적으로 느껴집니다. 프론트엔드에서 숨기는 것과 서버에서 막는 것은 완전히 다른 문제이기 때문입니다.

마무리
BFF는 새로운 유행어라기보다, 프론트엔드와 백엔드의 책임을 다시 나누는 방식에 가깝습니다. 서버사이드가 프론트엔드를 한 번 감싸고, 인증과 접근 가능 여부를 먼저 판단합니다. 조회 가능한 페이지라면 리액트가 화면을 그립니다.

이 구조가 모든 서비스에 필요한 것은 아닙니다. 하지만 인증이 중요하고, 브라우저에 민감한 정보를 오래 들고 있게 만들고 싶지 않다면 충분히 검토해볼 만합니다. 특히 혼자 서비스를 만들고 운영하는 입장에서는 보안 판단의 위치를 분명히 해두는 것만으로도 나중의 부담을 줄일 수 있습니다.

아직 이 방식이 제가 만드는 모든 서비스의 정답이라고 말하기는 어렵습니다. 다만 지금 기준에서는 리액트는 화면에 집중하고, 서버는 인증과 권한을 책임지는 구조가 오래 운영하기에 더 편한 방향처럼 느껴집니다. 그래서 이번 글은 BFF를 기술 패턴으로 소개하기보다, 제가 서비스를 만들며 역할을 어떻게 나누고 싶은지 정리해둔 기록에 가깝습니다.

반응형