Pre-signed URL이란 무엇인지에 대해 다룹니다.
Pre-signed URL은 S3에 저장된 객체에 대해 제한된 시간 동안 액세스 권한을 제공하는 특수한 URL입니다.
이 URL 을 통해 사용자 또는 클라이언트가 특정 파일을 읽거나 업로드할 수 있도록 허용하므로써 보안을 유지할 수 있습니다.
면시 프로젝트에는 전통적인 파일업로드(서버에서 업로드)와 Pre-signed URL 방식이 모두 구현되어있습니다.
개념자체는 생소할 수 있으나, @aws-sdk/s3-request-presigner 라이브러리를 이용하면 쉽게 구현가능합니다.
import { S3Client, GetObjectCommand, PutObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import { Injectable } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { randomUUID } from "crypto";
import { Files } from "openai/resources";
import { Member } from "src/interfaces/member.interface";
@Injectable()
export class S3Service {
private s3: S3Client;
constructor(private readonly configService: ConfigService) {
this.s3 = new S3Client({
region: this.getRegion(),
credentials: {
accessKeyId: this.configService.get<string>('AWS_ACCESS_KEY_ID') as string,
secretAccessKey: this.configService.get<string>('AWS_SECRET_ACCESS_KEY') as string,
},
});
}
/**
* 다운로드 가능한 Pre-signed URL 반환
*/
async createDownloadUrl(key: string): Promise<Files.PresignedResponse> {
const command = new GetObjectCommand({
Bucket: this.getBucket(),
Key: key,
});
const url = await getSignedUrl(this.s3, command, { expiresIn: 3600 });
return { url };
}
/**
* 업로드 가능한 Pre-signed URL 반환
*/
async createUploadUrl(memberId: Member['id']): Promise<Files.PresignedResponse> {
const key = `${memberId}/${randomUUID()}`;
const command = new PutObjectCommand({
Bucket: this.getBucket(),
Key: key,
});
const url = await getSignedUrl(this.s3, command, { expiresIn: 3600 });
return { url };
}