1. Pre-Signed URL이란?
AWS S3에서 파일을 안전하게 공유할 수 있는 임시 URL
✔️ 특징
- 보안 강화: S3 버킷을 퍼블릭으로 설정하지 않아도 파일 접근 가능
- 유연한 접근 제어: IAM을 이용해 특정 사용자에게만 권한 부여 가능
- 서버 부담 감소: 파일 전송을 서버를 거치지 않아 서버의 자원 절약
- 만료 시간 설정 가능: URL 만료 시간을 조정하여 보안 및 사용 편의성 조절 가능
2. Pre-Signed URL 사용 예시
✔️ 직원 프로필 업로드 & 다운로드 시스템 구축
직원들이 자신의 프로필 사진을 업로드하고 다운로드할 수 있는 시스템이 필요한 경우
✔️ 보고서 다운로드 시스템 구축
회사 내부 시스템에서 직원들이 기밀 문서를 다운로드해야 하는 경우
3. Pre-Signed URL 생성하는 법
S3 파일을 다운로드받을 수 있는 Pre-Signed URL을 생성하는 방법은 아주 간단하므로 업로드하는 방법부터 작성하겠습니다.
(1) 파일 업로드하기
리소스: S3, API-Gateway, lambda(python, JavaScript 등 URL을 생성하는 함수를 만들 용도기 때문에 VSCode에서 실행해도 상관없음)
a. S3 생성
제목은 상관없습니다. 저는 "pre-signed-02"로 설정하였습니다. 설정에서는 퍼블릭 액세스를 차단해줍니다.
마지막으로 한 가지만 설정해주면 됩니다.
CORS(cross-origin 리소스 공유) 편집에 아래와 같이 넣어줍니다.
📌 CORS(Cross-Origin Resource Sharing) 정책: 웹 브라우저에서 보안상의 이유로 서로 다른 출처(도메인, 프로토콜, 포트) 간의 요청을 제한하는 보안 메커니즘
기본적으로 브라우저는 보안상의 이유로 다른 출처에서 온 요청을 차단하지만, 서버에서 적절한 CORS 헤더를 설정하면 특정 출처의 요청을 허용할 수 있음
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"GET",
"PUT"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": [],
"MaxAgeSeconds": 3000
}
]
# 파라미터 설명
- AllowedHeaders:
- ["*"]: 모든 요청 헤더 허용
- 예를 들어, Authorization, Content-Type 등의 헤더가 포함된 요청도 허용됨
- AllowedMethods:
- ["GET", "PUT"]:
- GET: 클라이언트가 S3에서 파일을 다운로드할 수 있도록 허용
- PUT: 클라이언트가 S3에 파일을 업로드할 수 있도록 허용
- ["GET", "PUT"]:
- AllowedOrigins:
- ["*"]: 모든 출처(도메인)에서 요청 가능
- 즉, 웹사이트의 도메인이 무엇이든지 관계없이 요청을 허용함
- 보안상 필요하다면 특정 도메인만 허용하는 것이 좋음 (예: ["https://example.com"])
- ExposeHeaders:
- [] (빈 배열): 클라이언트가 응답에서 접근할 수 있는 헤더가 없음
- 예를 들어, ETag 같은 특정 응답 헤더를 노출하고 싶다면 ["ETag"]처럼 설정할 수 있음
- MaxAgeSeconds:
- 3000: 브라우저가 Preflight 요청(OPTIONS 요청)의 응답을 3000초(약 50분) 동안 캐싱할 수 있도록 설정
- 즉, 3000초 동안 동일한 요청에 대해 OPTIONS 요청을 다시 보내지 않음
b. Lambda
저는 파이썬으로 만들었습니다. 역할 설정에서 AmazonS3FullAccess 를 추가해주세요.
다음 코드는 upload url을 생성하는 코드입니다. bucket name만 위에 설정한대로 수정해줍니다.
import boto3
import json
def lambda_handler(event, context):
s3_client = boto3.client("s3")
# 설정한 s3 버킷명 입력
bucket_name = "pre-signed-02"
filename = event["queryStringParameters"]["filename"]
# Pre-Signed URL 생성
url = s3_client.generate_presigned_url(
"put_object",
Params={"Bucket": bucket_name, "Key": f"uploads/{filename}"},
ExpiresIn=600, #유효 시간 10분
)
return {
"statusCode": 200,
"body": json.dumps({"uploadUrl": url})
}
아래는 테스트 코드에서 파라미터를 설정하는 곳에 넣어주시면 됩니다. 저는 'Cat03.jpg'를 업로드할 것이기 때문에 아래와 같이 입력하여 실행하였습니다.
{
"queryStringParameters": {
"filename": "Cat03.jpg"
}
}
c. API Gateway
API Gateway에서는 REST API를 생성해줍니다. 아래와같이 GET 메소드와 OPTIONS 메소드를 추가해주시면 됩니다.
아래는 GET 메소드와 Lambda함수를 연결해주는 과정입니다.
아래 사진에서 수정하지 못한 부분이 있는데요, Lambda proxy integration 을 꼭! 활성화해주셔야 합니다.
API Gateway에서도 CORS 정책을 활성화시켜 OPTIONS 메소드를 추가해야 합니다.
📌 OPTIONS 메소드: 브라우저가 서버와의 CORS 정책을 확인하기 위해 사용하는 사전 요청(Preflight Request)
클라이언트가 서버에 요청을 보내기 전에 서버가 특정 HTTP 메서드 및 헤더를 허용하는지 확인하는 용도로 사용됨
이제 아래와 같이 API를 배포합니다.
이제 Pre-Signed URL 생성에 필요한 세 리소스를 모두 생성하였습니다.
이제 lambda 함수를 실행하여 Pre-Signed URL을 얻습니다.위 파라미터를 넣고 테스트를 실행해서 나온 URL을 복사하면 됩니다.
lambda 함수에서 다음과 같이 API Gateway와 연결된 것을 확인할 수 있습니다.
저는 이 API를 PUT으로 실행하기 위해 PostMan을 사용하였습니다.
Pre-Signed URL을 넣고, Body에서 binary를 선택한 후 업로드를 원하는 파일을 첨부합니다.
이후 Send를 누르면, 아래 결과창(Body) 부분에 아무것도 뜨지 않는 것을 확인할 수 있습니다.
혹시 에러 메시지가 뜬다면, lambda 함수의 역할 등 정책 설정을 확인해보시길 바랍니다.
아래와 같이 업로드된 것을 확인할 수 있습니다.
(2) 파일 다운로드하기
정말 간단합니다. 위와같이 CORS 정책을 설정한 버킷에 파일을 업로드합니다.
이후 작업에서 미리 서명된 URL과 공유를 선택하고, 주어진 URL을 인터넷 창에 입력하면 됩니다. 아래 사진과 같이 확인할 수 있습니다.
4. 주의할 점
- URL이 유출되면 누구나 해당 파일을 업로드/다운로드할 수 있음
- 최대한 짧은 만료 시간을 설정하는 것이 좋음
- S3 IAM 정책을 통해 특정 IP 또는 역할(Role)에서만 URL을 사용할 수 있도록 제한 가능
마치며
개인적으로 공부하다가 알게된 Pre-Signed URL에 대해 알아보았습니다. Pre-Signed URL은 서버 자원의 낭비 없이
s3에 직접적으로 다운로드, 업로드할 수 있어 보안성을 챙기면서 편리하게 이용할 수 있습니다. 물론 대용량의 파일도 가능합니다. 다양한 곳에 이용할 수 있을 것으로 보여, 저도 실전에서 이용하게 되어 공유할 기회가 생기면 좋겠습니다.
🍋 궁금한 점이 있으시다면 언제든 댓글 남겨주세요! 🍋
'Study & Article > 인프라 (클라우드)' 카테고리의 다른 글
AWS에서 VPN 사용하는 법 / OpenVPN 배포 (4) | 2024.11.30 |
---|---|
[AWS] Amazon Bedrock을 통한 생성형 AI 활용 실습 참여 후기 (2) | 2024.11.07 |