AWS CloudFront와 S3를 활용한 React SPA 배포 중 발생한 403 Access Denied 에러 해결 정리

김민서·2025년 3월 12일

whyyouarebroke

목록 보기
15/15

개요

작년에 진행했던 whyyouarebroke 프로젝트를 배포해놨던 AWS 프리티어 계정이 만료되면서, 정확히 일년 만에 새로운 프리티어 계정을 생성해 새로 배포를 진행하게 되었다. 과거의 나에게 감사하는 마음을 가지고 작년에 남겨놨던 내 벨로그 글을 참고하면서 순조롭게 배포를 진행했지만, 실수로 빠뜨렸던 부분으로 인해 에러를 마주했다.

금방 해결하긴 했지만 작년보다 에러의 원인을 더 잘 이해하게 되었기 때문에, 이를 정리해두면 좋을 것 같아서 글을 작성하게 되었다.

에러 상황

상황 설명

사이트의 루트 경로(/)로 들어갔을 때에는 페이지가 정상적으로 보여지지만, 버튼을 클릭해서 이동하는 것이 아닌, URL을 직접 입력해서 특정 페이지(/mypage, /signup)에 접근하려고 하면 403 Access Denied 에러가 발생했다.

해결 방법

해결 방법부터 말하면, CloudFront의 오류페이지에서 사용자 정의 오류 응답을 생성해서 403 오류가 발생했을 때 응답 코드를 200으로 설정하고, 응답 코드 경로를 index.html로 설정하여 리다이렉트 하도록 하면 된다.

그렇다면 왜? 이렇게 하면 해결되는 것일까?

원인 분석

일단 해당 프로젝트는 React로 만들어졌으며, React는 SPA(Single Page Application)로 동작하는 라이브러리이다. SPA는 Single Page, 즉 하나의 HTML 파일(index.html)을 기반으로 모든 콘텐츠가 이 페이지에서 동적으로 로드된다.

S3과 CloudFront의 동작 방식

S3에 업로드된 프로젝트 구조를 보면 HTML 파일이 index.html 하나만 존재한다.

CloudFront는 기본적으로 클라이언트가 요청한 경로 (/mypage, /signup)에 해당하는 파일을 S3에서 찾으려 하지만, 실제로 S3에는 index.html 파일 밖에 존재하지 않는다.
따라서 CloudFront는 요청한 파일을 찾지 못했음을 나타내는 403 Access Denied 오류를 반환한다.

해결 방식 작동 원리

하지만 이때 index.html로 리다이렉션 되도록 설정해 놓으면, index.html 파일은 존재하기 때문에 클라이언트가 이 파일이 정상 로드되었다고 인식한다.

브라우저가 로드된 index.html 파일을 실행하고, React 앱이 클라이언트 측 라우팅(예: React Router)을 통해 요청된 경로(/mypage, /signup)를 처리할 수 있게 된다.

결국, SPA에서는 모든 경로가 서버가 아닌 클라이언트에서 처리된다. 따라서 서버는 요청 경로를 확인하거나 처리할 필요 없이, 모든 요청을 index.html로 리다이렉트하는 설정만으로 문제가 해결되는 것이다.

마무리

사실 작년에 배포를 진행하면서 같은 문제가 발생했었고, 그때도 왜 이렇게 해결되는지 이유가 궁금해 찾아봤던 기억이 난다. 하지만 당시에는 제대로 이해하지 못하고 넘어갔던 것 같은데, 이번에 다시 겪고 정리하면서 확실히 이유를 알게 되어 뿌듯하다.

과거의 내가 작성한 블로그 글이 큰 도움이 되었던 만큼, 이번 정리도 미래의 나나 비슷한 문제를 겪는 분들에게 도움이 되길 바라면서 마무리한다.

0개의 댓글