[AWS] S3 pre-signed Url 이용하여 이미지 업로드

minji Jung·2023년 5월 2일
0

AWS

목록 보기
1/2

외주 작업하면서 이미지 업로드할 때 서버분이 pre-signed Url 이용한다고 api를 만들어 주셨다. 해서 이건 또 어떻게 쓰는거지...?를 해결하기 위한 구글링과 삽질의 결과를 정리해보자한다.

pre-signed Url ?

S3 bucket에 이미지를 업로드하기 위해서는

  1. 해당 S3에 대한 접근 권한을 인증
  2. 인증을 마치면 S3에 업로드 할 수 있는 URL을 발급
  3. 발급받은 URL을 이용하여 웹에서 S3 bucket에 파일 업로드

과정이 필요하다 이 때 쓰이는 URL이 pre-signed Url이다.

전체 프로세스

  1. 서버 api 호출
  2. 서버에서 AWS S3에 pre-signed Url 요청
  3. 인증 후 pre-signed Url 발급
  4. 서버에서 웹으로 pre-signed Url 전달
  5. 웹에서 pre-signed Url로 보내어 파일 업로드
  6. 서버에게 해당 요청이 종료 되었음을 알림

내가 진행한 방식✨

우선 서버분이 만들어 주신 api를 이용하여 post 요청을 한다.

이후 response.result 값을 확인해보면

이런식으로 콘솔에 찍히는 것을 확인할 수 있는데 여기서 받은 presignedUrl로 이미지 파일을 s3에 업로드를 하면 된다.

이 두 과정이 200 OK 가 뜨면 이미지 인증과 업로드가 완료되었다!

response.result 의 presignedUrl ~~? 이후를 잘라내면 이미지의 url이 된다.

전체코드

interface PreSignedURLType {
  presignedUrl: string
  key: string
}

export const webtoonUploadImg = async (webtoonId: number, file: File) => {
  try {
    const response: ReponseType<PreSignedURLType> = await request({
      params: {
        imageFileExtension: file.type.split('/')[1].toUpperCase(),
      },
      method: 'POST',
      url: `/api/v1/webtoons/${webtoonId}/images`,
    })

    if (response.isSuccess) {
      await axios({
        headers: {
          'Content-Type': 'image/jpeg',
        },
        data: file,
        method: 'PUT',
        url: response.result.presignedUrl,
      })
    }
    return response.result.presignedUrl.split('?')[0]
  } catch (error) {
    console.log(error)
    return
  }
}

참조 : https://medium.com/developing-koan/uploading-images-to-s3-from-a-react-single-page-application-45a4d24af09f

(´。_。`)

사실 이거보단 CORS 403 hidden 오류 때문에 삽질을 많이 했는데
담당 서버분에게 CORS 체크해달라 몇번 요청했지만 문제 없다고 하여
뭐가 문젤까😭 하고 공을 들인 결과.......코드가 좀 더 괜찮아(?)지긴 했지만
요리보고 조리봐도 S3 문제라 직접 계정 받아서 확인해보니 역시나!!!
해당 설정이 빠져있었다😖

잊을 수 없는 S3 > 권한 > CORS 에
아래 코드 추가하기

[
      {
          "AllowedHeaders": [
              "*"
          ],
          "AllowedMethods": [
              "PUT"
          ],
          "AllowedOrigins": [
              "*"
          ],
          "ExposeHeaders": []
      }
  ]

포스팅 다음날 생긴 이슈

1MB가 넘으면 인증과정에서 오류가 발생하는 것...!
난 용량 제한을 설정한 적이 없으므로 당연히 서버 문제겠거니~ 하고 넘겼는데 알고 보니 post 요청 할때 data에 file을 담아보내 생긴 오류였다....
nginx 제한이 1MB 란다. (<- 잘모름. 확인필요)

swagger를 다시 확인해보니 진짜 file을 담는 영역이 없었고 😩
아래 코드를 위의 포스팅 내용으로 변경하니 잘(^^) 되었다구 한다....

  const formData = new FormData()
  formData.append('file', file)

  const response: ReponseType<PreSignedURLType> = await request({
    headers: {
      'Content-Type': 'multipart/form-data',
    },
    params: {
      imageFileExtension: file.type.split('/')[1].toUpperCase(),
    },
    data: formData,
    method: 'POST',
    url: `/api/v1/webtoons/${webtoonId}/images`,
  })

ㅂ...분명 구글사람들은 ㅇ..이렇게 해야된다고 했는데...!
😭😭😭

뭐 쨌든 결론은 swagger를 잘 확인하자!!!

profile
현실적인 낙천주의자

0개의 댓글