본문 바로가기
기타

AWS S3 에서 POST 메소드 사용하기 (405 Method Not Allowed)

by 유세지 2022. 1. 22.

이번에 AWS S3에 프로젝트를 배포할 일이 생겼는데, POST 요청으로 데이터를 전송하려 했지만 정책상의 문제로 405 method not allowed 에러에 막히게 되었습니다. 기존에 리액트 프로젝트를 S3에 올려서 사용하시는 분들이 계시기에 분명 방법은 있을것이라 생각했고, 결국 해결되었는데 어떻게 해결하였는지 제 사례를 공유해보려 합니다.

 

들어가기 전 저는 AWS 프로젝트를 사용해 본 경험이 극히 적고, 배경지식이 거의 없었다는 점을 감안해주시면 감사하겠습니다.

 

 

 

문제 상황

 

기본적인 구조

 

우선 프로젝트의 구조는 위와 같은 모습입니다. 리액트로 이루어진 프론트 단과, 스프링으로 이루어진 백 단이 서로 요청과 응답을 주고받는 평범한 상황입니다. 기본적으로 유저에 관한 데이터를 주고 받는 회원가입이나 로그인 같은 동작을 하게 될 때, POST 방식을 일반적으로 사용했기에 저도 POST 메소드로 구현하였습니다.

 

백과 프론트가 모두 로컬에서 실행중인 환경에서는 아무 문제없이 동작했었기에, 아무 의심없이 AWS 서버에 올린 뒤 테스트 해보았습니다. 백엔드는 EC2, 프론트엔드는 S3에 각각 배포된 상태였습니다.

 

 

현재 상태

 

 

문제는 여기서 발생했습니다. S3에 올려진 프론트에서 API 서버로 POST 요청을 보냈을때

 

> POST https://apiserver.com/login 405 (Method Not Allowed)

 

오류를 받게 되었습니다. 당연히 api 서버로는 아무런 요청이 오지 않았고, 응답도 받을 수 없었습니다. 여기서부터 문제를 찾기 위한 고민이 시작되었습니다.

 

 

원인 분석

로컬 환경에선 정상적으로 동작했던 코드들이니, 코드 자체의 문제는 아닐 것이라 생각했습니다. (맞다고 하더라도 나중에 살펴보겠습니다.) POST 요청이 제대로 나가지 않는다면 누군가 요청을 중간에서 막고있는 것일텐데, 따로 거쳐가는 곳이 없으니 S3 자체에서 요청을 막고있다는게 가장 유력한 가설처럼 보입니다.

 

access-control-allow-methods

 

네트워크 탭을 확인해보니, access-control-allow-methods에 POST 요청이 명시되어있지 않았습니다. S3가 POST 요청을 받고있지 않는게 맞다는 확신이 들기 시작했습니다. 곧바로 S3의 버킷 정책을 확인해보았습니다.

 

{
  "Statement": [
    ...
    "Action": "s3:GetObject",
    ...
  ]
}

Action이 s3:GetObject로 설정되어 안되는건지 싶어 다른 값을 대입할 수 있는지 찾아보았는데, PUT에 관련된 요청은 찾을 수 있었지만 아무리 보아도 POST에 관련된 요청은 찾을 수 없었습니다. 결국 이곳에서는 해결할 수 없다고 잠정적으로 결론을 지은 뒤, 비슷한 문제에 대한 해결 방법이 있는지 구글링을 해보았습니다.

 

 

https://stackoverflow.com/questions/32033597/amazon-s3-405-method-not-allowed-using-post-although-i-allowed-post-on-the-bu 에서 발췌한 답변

 

위 글에서 질문자는 php를 사용하긴 했지만, 저와 동일한 오류를 겪고 있었습니다. 답변 내용을 요약하면 S3는 그저 저장소일뿐 어플리케이션 서버가 아니며, S3가 할 수 없는 일(서버-사이드 동작) 을 시키고 있기 때문에 문제가 발생했다. 이었습니다. 하지만 우리는 이미 많은 사람들이 리액트 프로젝트를 S3에 올려서 사용하고 있다는 결과를 알고 있고, 어떻게든 방법은 있다는 것을 유추할 수 있습니다.

 

문제가 되고 있는 POST 요청만 S3에서 바로 나가지 않는다면 해결될 것 같습니다. 그렇다면...?

 

 

 

해결 방법

정적 웹 사이트 호스팅이 이루어진 S3에서 직접 POST 요청이 나가지 않도록, S3 프로젝트를 한 번 감싸주도록 하겠습니다. CloudFront를 생성해서 프론트와 백에 연결해줍니다.

 

CloudFront를 연결한 모습

 

 

이제 프로젝트의 구조는 다음과 같이 바뀌었습니다.

 

 

CloudFront를 거쳐가는 모습

 

 

이제 여기서 POST 메소드를 사용하는 요청을 하나로 묶고, 뷰어의 허용된 HTTP 방법 탭에서 GET, HEAD, OPTION, PUT, POST, PATCH, DELETE 모두 허용해주도록 하겠습니다. 저는 /api*로 묶어주었습니다.

 

POST 메소드를 허용하도록 설정

 

 

이제 모든 설정이 끝났습니다. CloudFront가 원본을 캐싱할 수 있도록 잠시 기다려주고, 테스트 해보도록 하겠습니다.

 

 

 

결과

모든 변경사항이 적용된 후, 회원가입을 시도한 결과입니다.

 

access-control-allow-methods 가 모두 허용된 모습

 

현재 테스트 서버가 잠시 꺼져있기 때문에 502 에러를 받았지만, 문제가 되었던 POST 요청은 정상적으로 수행된 모습입니다. (사전에 정상적으로 작동되는 것을 확인했습니다!)

 

이렇게 S3의 정책상 직접적인 POST 통신이 불가능했던 문제를 CloudFront를 통해 우회함으로서 해결하는 과정을 살펴보았습니다. 예상치 못한 오류 덕분에 잘 몰랐던 AWS의 서비스들을 사용해보고 배우는 좋은 기회가 된 것 같아 다행이었습니다. 혹시 틀린 내용이나 부족한 내용이 있다면 댓글로 알려주시면 감사하겠습니다. 😁

반응형

댓글