React API Key 노출을 서버 경계로 옮기며 배운 BFF의 필요성
PHP와 React를 함께 사용하는 신규 리조트 서비스를 구축하면서 한 가지 경계를 잘못 이해했습니다. React 환경변수에 넣은 값은 브라우저에서 확인할 수 없다고 생각해 외부 API를 직접 호출했고, 개발계 테스트 중 빌드 산출물에 API Key가 포함될 수 있다는 사실을 발견했습니다.
이 글에서 다루는 질문은 브라우저가 외부 API를 호출할 때 어디까지 직접 알아도 되고, 언제 서버 Proxy나 BFF가 경계를 맡아야 하는가입니다.
개발계 테스트에서 발견한 서버 경계 오해
문제는 운영 사고나 침해로 발견된 것이 아닙니다. 프로젝트 중간 개발계 테스트에서 브라우저에 전달되는 빌드 결과를 확인하다가 API Key가 포함될 수 있음을 알았습니다. 제3자가 키를 악용한 일은 없었습니다.
실수의 원인은 환경변수라는 이름을 서버의 비공개 설정과 동일하게 생각한 데 있었습니다. 클라이언트 사이드에서 사용하는 값은 빌드 과정에서 코드에 포함될 수 있고, 브라우저에 전달된 값은 더 이상 Secret이 아닙니다. 중요한 것은 변수 이름이나 파일 위치가 아니라 최종적으로 그 값이 어느 실행 경계에 도달하는가였습니다.
당시에는 모든 요청을 PHP Proxy 뒤로 옮겼다
발견 직후 API Key가 브라우저에 머물지 않도록 모든 요청을 PHP Proxy로 보내도록 변경했습니다. JWT 쿠키 검증은 PHP 미들웨어에서 처리했고, Proxy는 요청을 확인해 외부 API로 보낼지 내부 API로 보낼지 판단했습니다. 외부 요청에 필요한 API Key와 인증 헤더는 PHP 서버에서 붙였습니다.
당시 Proxy의 역할은 여기까지였습니다. 외부 API의 원본 응답을 그대로 React에 전달했고, 화면에 필요한 형태로 가공하는 일은 프론트엔드에서 처리했습니다. 따라서 당시 구현을 BFF였다고 소급해 부르지는 않습니다. API Key를 붙여 요청을 대신 전달하는 단순 Proxy에 가까웠습니다.
이 수정으로 API Key가 React 빌드 결과에 포함되는 경로를 서버 쪽으로 옮겼습니다. 다만 개발계에서 발견한 구조 수정이므로 실제 침해를 차단했다거나 운영 보안 사고를 해결했다는 성과로 확대하지 않습니다.
외부 API라면 모두 BFF가 필요한가
이 경험 뒤에는 모든 외부 API 요청을 서버로 보내야 한다고 생각하기도 했습니다. 지금의 기준은 API가 외부에 있는지가 아니라 브라우저가 알아도 되는 정보와 서버가 책임져야 하는 처리가 있는지입니다.
- 클라이언트 사이드 렌더링 기반의 React·Next.js에서 API Key·Secret·인증 헤더가 필요한 요청은 반드시 서버를 거칩니다.
- 공개 정보이고 별도 인증 정보가 없다면 브라우저의 직접 호출도 허용할 수 있습니다.
- 사용자 권한 통제, 응답 조합·가공, 여러 API 취합이 필요하면 단순 Proxy보다 BFF를 선택합니다.
- 백엔드 API를 설계할 때는 브라우저가 직접 사용할 수 있는 public API와 인증·권한이 필요한 private API의 경계를 구분합니다.
외부 서버 URL을 보이지 않게 만드는 것만으로 보안이 생기지는 않습니다. 핵심은 자격 증명과 권한 검증을 서버에 두는 것입니다. 다만 브라우저가 알 필요 없는 외부 엔드포인트와 헤더 형식을 서버 구현 세부사항으로 감추면 클라이언트와 외부 API의 결합도 함께 낮출 수 있습니다.
Proxy에서 BFF로 확장되는 지점
블랙스톤에서는 JWT 쿠키 인증이 필요했고 모든 요청이 PHP Proxy를 통과했지만, 응답은 그대로 전달하고 React에서 가공했습니다. 지금 돌아보면 처음부터 BFF로 설계했다면 다음 책임을 한 경계에서 다룰 수 있었습니다.
- PHP 미들웨어의 JWT 검증 결과에 따른 요청 권한 통제
- 외부 API의 URL·인증 헤더와 화면에 불필요한 필드의 서버 측 격리
- 화면이 필요한 형태로 응답을 조합하고 가공하는 계약
- 여러 내부·외부 API 호출이 필요할 때의 취합과 오류 형식 통일
이 내용은 당시 구현한 기능 목록이 아니라 현재의 회고입니다. 당시에는 노출 경로를 즉시 닫는 것이 먼저였고, BFF를 대안으로 비교해 선택한 것은 아닙니다.
현재의 적용 기준
로그인과 JWT 검증이 있고 외부 응답을 화면 계약에 맞게 바꿔야 하는 프로젝트라면 BFF를 기본 후보로 검토합니다. 이런 조건에서는 단순 전달 Proxy로 시작해도 인증, 권한, 응답 가공이 흩어지면서 결국 서버 책임이 커질 가능성이 높기 때문입니다.
반대로 인증 정보가 없는 공개 API를 그대로 표시하고 서버가 가공하거나 통제할 이유가 없다면 브라우저의 직접 호출도 가능합니다. BFF는 모든 외부 API 앞에 세우는 의무 계층이 아니라, 브라우저에 넘기지 말아야 할 책임이 생겼을 때 선택하는 경계입니다.
회고
이 경험의 핵심은 API Key를 잘못 넣었다는 사실보다, 잘못된 이해를 개발계에서 발견한 뒤 즉시 서버 경계로 수정하고 그 경계가 맡아야 할 책임을 다시 정의한 데 있습니다.
그때는 PHP Proxy로 노출 경로를 닫는 데 집중했습니다. 지금은 같은 요구를 만나면 시크릿 은닉만 보지 않고 쿠키 인증, 권한 통제, 응답 계약, 외부 API 결합도를 함께 살펴 Proxy로 충분한지 BFF가 필요한지 처음부터 결정합니다.