상세 컨텐츠

본문 제목

AWS S3에 파일을 업로드 하기 위한 Pre-signed URL과 Pre-signed POST

TECH

by walkinpcm 2021. 9. 8. 21:18

본문

요즘은 흔히 파일서버로 AWS S3를 이용합니다. 그래서 파일 업로드 기능을 만들때 S3에 어떻게 파일을 업로드 할지 고민하게 되는데요.

Front-end 입장에서는 S3에 파일을 업로드 하는 방법으로 크게 2가지를 생각할 수 있습니다.

- Front-end에서 AWS SDK를 이용해서 직접 업로드

- API 서버에 파일을 전달하고 API 서버에서 S3에 업로드

 

첫번째 방법은 AWS SDK를 써서 S3이용이 가능해야하기 때문에 Front-end 코드에서 AWS Access Key와 Secret Key를 알고 있어야합니다. 코드에 하드코딩 하지 않더라도 브라우저에서 AWS SDK를 이용하는 시점에는 결국 자바스크립트에서 Key 정보를 가지고 있어야합니다. 즉, Front-end에서 AWS SDK를 이용하는 방법은 Key 정보가 브라우저에서 노출 될 수 있고 악성 해커가 이를 이용하면 나의 S3 리소스를 자유롭게 이용할 수 있는 위험이 있습니다.

 

두번째 방법은 API 서버에서 파일을 업로드하기 때문에 AWS Access Key와 Secert Key 정보를 서버가 알고있으면 돼서 Key 정보가 노출되는 위험이 없습니다. 하지만 파일 자체가 서버를 통하기 때문에 서버의 리소스를 사용하게되고 과도한 업로드 작업이 생기면 서버에 과부하가 걸리게 될 수 있습니다. 또한, 서버를 한번 거쳐가는 지연시간이 생기게 됩니다.

 

결국 위 두 가지 방법 모두 단점이 존재하는데요. 그럼 어떻게 파일을 S3로 업로드 해야할까요?

AWS에서는 S3에 객체를 업로드하고 다운로드 하기 위한 방법으로 Pre-signed URL 기능을 지원하고 있습니다.

 

Pre-signed URL 이란?

Pre-signed URL이란 말그대로 '미리 서명된 URL'입니다. 여기서 URL은 S3 객체에 대한 접근 주소입니다. 그런데 단순히 객체의 저장 위치만을 가리키는게 아니라 Pre-signed URL을 이용해서 객체에 접근할 수 있는 권한 정보와 접근 가능 기간 등의 정보를 담고 있습니다. 그래서 특정 Pre-signed URL을 이용해서 수행할 수 있는 작업이 이미 제한되어 있고 객체에 접근 가능한 기간(Expire Time)이 지나면 더이상 해당 URL은 사용할 수 없습니다.

// Pre-signed URL 예시
"
https://BUCKETURL/test.txt?
  X-Amz-Algorithm=AWS4-HMAC-SHA256
  &X-Amz-Credential=<YOUR_ACCESS_KEY_ID>/20160115/ap-northeast-2/s3/aws4_request&
  &X-Amz-Date=20160115T000000Z
  &X-Amz-Expires=86400
  &X-Amz-SignedHeaders=host
  &X-Amz-Signature=<SIGNATURE_VALUE>
"

 

Front-end에서는 Pre-signed URL로 HTTP Get 요청을 하면 객체를 다운로드 할 수 있고, 파일을 body에 담아서 HTTP Put 요청을 하면 파일을 업로드 할 수 있습니다.

 

Pre-signed URL을 이용하여 파일을 업로드하는 절차는 아래와 같습니다.

1. Front-end에서 API 서버로 파일 업로드를 위한 Pre-signed URL 생성 요청

2. API 서버에서 AWS Key 정보를 이용해서 Pre-signed URL을 생성하고 Front-end로 응답

3. Front-end에서는 전달받은 Pre-signed URL을 이용해서 HTTP Put 요청으로 S3에 파일 업로드

 

Pre-signed URL을 이용한 파일 업로드는 Front-end에서 AWS S3로 바로 파일을 업로드 할 수 있으면서도 AWS Key 정보를 API 서버에 숨겨져 있어서 보안 위험을 줄일 수 있습니다.

 

그렇다면 Pre-signed POST 방식은 뭐지?

AWS에서는 S3에 파일을 업로드 하기 위해서 Pre-signed URL이외에 Pre-signed POST 방식도 지원합니다.

우선 Pre-signed URL은 HTTP Get, Put 요청으로 각각 파일 다운로드와 업로드를 할 수 있는 반면에, Pre-signed POST는 이름 그대로 HTTP Post 방식으로 파일을 업로드만 할 수 있습니다.

 

Pre-signed URL은 권한, 시간 등의 정보가 URL의 query string(url parameter)으로 붙습니다. 그러나 Pre-signed POST는 파일을 업로드 할 때 FormData에 파일과 함께 권한, 시간 등의 정보도 넣습니다.

 

Pre-signed POST를 이용하여 파일을 업로드하는 절차는 아래와 같습니다.

1. Front-end에서 API 서버로 파일 업로드를 위한 Pre-signed POST 정보 생성 요청

2. API 서버에서 AWS Key 정보를 이용해서 Pre-signed POST 정보를 생성하고 Front-end로 응답

3. Front-end에서는 전달받은 Pre-signed POST 정보를 FormData에 추가하고 (물론 파일도 FormData에 넣고) Request Body에 담아서 HTTP Post 요청으로 S3에 파일 업로드

 

// Pre-signed POST 정보 예시
{
  'url': 'https://mybucket.s3.amazonaws.com',
  'fields': {
    'acl': 'public-read',
    'key': 'mykey',
    'signature': 'mysignature',
    'policy': 'mybase64 encoded policy'
  }
}

위 예시를 기준으로, fields 객체에 있는 정보들을 모두 FormData에 추가하여 url에 명시된 주소로 HTTP Post 요청을 보내면 됩니다.

 


참고자료

- https://aws.amazon.com/ko/blogs/korea/aws-api-call-2-s3-pre-signed-url/

- https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.generate_presigned_post

 

관련글 더보기

댓글 영역