AWS S3를 사용할 때 Presigned URL을 활용하면, 별도의 서버 프로세싱 없이도 안전하게 파일을 업로드하거나 다운로드할 수 있다. 이번 글에서는 Presigned URL이 무엇이고, 어떻게 구현하는지 파일 업로드로 예를 들어 간단히 정리해보려고 한다.
Presigned URL이란?
Presigned URL이란 특정 객체에 대해 일정 시간 동안만 유효한 접근 권한을 임시로 부여하는 URL을 말한다. 예를 들어, 파일 업로드를 위해 서버에서 생성한 Presigned URL을 클라이언트에게 넘겨주면, 클라이언트는 이 URL을 통해 S3 버킷에 직접 파일을 업로드할 수 있다. 이를 통해 서버는 파일 전송 업무를 맡지 않고 S3와 클라이언트를 바로 연결해주기만 하면 되므로, 트래픽과 서버 부하를 크게 줄일 수 있다.
Presigned URL의 특징을 정리해 보면 다음과 같다:
- 유효기간이 제한적이어서 보안성이 높다.
- 서버 부하 절감에 유리하다.
- S3 버킷 및 객체에 대한 접근 제어를 쉽게 할 수 있다.
상세 구현
Sequence Diagram
Presigned URL을 활용한 업로드 과정을 시퀀스로 그려보면 이렇다.
이 과정을 통해 서버는 파일 전송에 직접 관여하지 않으며, DB에 업로드된 파일 정보를 기록하거나 메타데이터를 갱신하는 역할만 담당한다.
Credentials
AWS SDK를 사용하기 위해서는 우선 인증 정보가 필요하다.
- 환경 변수(ENV): AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION 등을 설정한다.
- AWS CLI 인증서(credential) 파일: ~/.aws/credentials 파일에 프로파일별로 key와 secret을 저장한다.
- IAM Role: EC2, 같은 AWS 리소스에서 IAM Role을 연결하여 자동으로 권한을 부여한다.
aws-sdk
AWS SDK를 사용하면 Presigned URL을 쉽게 생성할 수 있다. (nest.js 기준)
// upload.service.ts
async getPresignedProfileUrl(puid: any): Promise<string> {
const presignedUrl = await this.awsService.createPresignedUrl(`${puid}/profile.png`);
console.log(presignedUrl);
return presignedUrl;
}
//aws.service.ts
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
async createPresignedUrl(key: string) : Promise<string> {
if (!key)
throw new CommonException(CommonError.INVALID_PARAMETER);
const bucket = this.configService.get('s3Info.bucket');
const command = new PutObjectCommand({ Bucket: bucket, Key: key });
console.log(`create presigned url for ${key} - ${bucket}`);
return await getSignedUrl(this.s3client, command, { expiresIn: 30 });
};
- region: 사용할 리전(region)
- Bucket: 업로드할 S3 버킷 이름
- Key: S3 객체의 경로(폴더/파일)와 이름
- Expires: URL의 만료 시간 (Seconds)
이렇게 생성된 URL은 일정 시간 동안만 유효하며, 해당 시간 내에 클라이언트가 이 URL로 파일스트림과 함께 PUT 요청을 보내면 S3에 바로 업로드가 이루어진다.
Entity Tag(Etag)
S3에 파일을 업로드하면, Etag(Entity Tag)가 포함되어 있다. Etag는 S3 객체의 특정 버전을 식별하는 데 쓰이는 고유 문자열이다. 이를 활용하면 파일이 변경되었는지 여부를 확인하거나, 캐싱을 최적화하는 등의 작업을 수행할 수 있다.
- 단순 문자열 비교: Etag 값이 달라졌다면 파일이 변경사항 있음
Etag를 사용하면, 클라이언트에서 캐싱 제어를 할 때 유용하게 활용할 수 있다. 예를 들어, 파일이 동일하다면 클라이언트에 불필요한 재다운로드를 방지할 수 있다.
후기
Presigned URL을 사용하면 서버가 파일 업로드 트래픽에서 오는 부하를 줄일 수 있다. 또한 만료 시간을 설정하여 보안성을 높이고, 서버 비용을 절약할 수 있다. AWS SDK만 잘 활용하면 구현이 비교적 간단한 편이다. 다만, 파일 크기가 매우 크거나 멀티파트 업로드(파일을 쪼개서 여러 개로 업로드)가 필요한 경우 Etag 처리를 비롯해 추가 설정이 필요하므로 유의해서 개발하는 것이 좋다.
이번 글에서 Presigned URL 개념과 구현 방법을 살펴보았다. AWS S3를 다루는 환경에서 안정적이고 확장성 있는 파일 업로드/다운로드 방식을 고민한다면, Presigned URL을 적극적으로 고려해 보길 권장한다. 앞으로 다양한 사례를 적용하면서 더 나은 방법을 모색해 볼 계획이다.
읽어주어서 감사합니다!
Reference
https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/userguide/PresignedUrlUploadObject.html
https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-presigned-url.html
'프로그래밍 > 개발 이야기' 카테고리의 다른 글
코드 리뷰를 놓치지 않는 방법: GitLab과 Slack을 연동한 자동화 봇 구축기 (2) | 2024.10.05 |
---|---|
[Notion API] 리소스 업로더 만들어보기 - 1 (API 연결, Database Query) (4) | 2024.01.30 |
[Google Analytics] 앱 분석해보기 (Unity) (2) | 2023.12.25 |
티스토리로 이전하며 (2) | 2023.12.06 |