S3 스토리지에서 업로드/다운로드 링크를 생성하는 방법입니다.
아래에서는 링크를 생성하는 예제만 작성할 것이고,
링크 생성 전, 사용자 인증, 권한 체크 등 필요한 보안 절차는 반드시 있어야 합니다.
1. Maven 의존성 추가
<dependencies>
<!-- AWS S3 SDK -->
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
</dependency>
</dependencies>
2. application.yml 설정
이 설정 내용 중 키 값 같은 것은 원하는 대로 하시면 됩니다.
cloud:
aws:
s3:
bucket: ${BUCKET_NAME}
credentials:
access-key: ${AWS_ACCESS_KEY}
secret-key: ${AWS_SECRET_KEY}
region: ${REGION_NAME}
3. S3Client Bean
@Configuration
public class S3Config {
@Value("${cloud.aws.credentials.access-key}")
private String accessKey;
@Value("${cloud.aws.credentials.secret-key}")
private String secretKey;
@Value("${cloud.aws.region}")
private String region;
@Bean
public S3Client s3Client() {
AwsBasicCredentials credentials = AwsBasicCredentials.create(accessKey, secretKey);
return S3Client.builder()
.credentialsProvider(StaticCredentialsProvider.create(credentials))
.region(Region.of(region))
.build();
}
// Presigned URL 전용 S3Presigner
@Bean
public S3Presigner s3Presigner() {
AwsBasicCredentials credentials = AwsBasicCredentials.create(accessKey, secretKey);
return S3Presigner.builder()
.credentialsProvider(StaticCredentialsProvider.create(credentials))
.region(Region.of(region))
.build();
}
}
4. Presigned URL 생성 서비스
@Service
@RequiredArgsConstructor
public class S3PresignedUrlService {
private final S3Presigner s3Presigner;
@Value("${cloud.aws.s3.bucket}")
private String bucket;
// 업로드용 Presigned URL (PUT)
public String generateUploadUrl(String fileName) {
PutObjectRequest putObjectRequest = PutObjectRequest.builder()
.bucket(bucket)
.key(fileName)
.build();
PutObjectPresignRequest presignRequest = PutObjectPresignRequest.builder()
.signatureDuration(Duration.ofMinutes(10)) // 유효시간
.putObjectRequest(putObjectRequest)
.build();
PresignedPutObjectRequest presignedRequest =
s3Presigner.presignPutObject(presignRequest);
return presignedRequest.url().toString();
}
// 다운로드용 Presigned URL (GET)
// 아래의 fileName 변수는 builder().key()에 들어가는데, 꼭 fileName만 들어가는 것은 아니고
// 스토리지 디렉터리에 따라서 파일명을 포함한 경로가 들어갈 수도 있습니다.
// 경로일 경우 -> dir/fileName 이런식으로
public String generateDownloadUrl(String fileName, String downloadFileName) {
GetObjectRequest getObjectRequest = GetObjectRequest.builder()
.bucket(bucket)
.key(fileName)
.responseContentDisposition(
"attachment; filename=\"" + downloadFileName + "\""
)
.build();
GetObjectPresignRequest presignRequest = GetObjectPresignRequest.builder()
.signatureDuration(Duration.ofMinutes(5))
.getObjectRequest(getObjectRequest)
.build();
PresignedGetObjectRequest presignedRequest =
s3Presigner.presignGetObject(presignRequest);
return presignedRequest.url().toString();
}
}
5. Controller
@RestController
@RequiredArgsConstructor
@RequestMapping("/files")
public class FileDownloadController {
private final S3PresignedUrlService presignedUrlService;
/**
* 파일 다운로드 요청 → 302로 S3 Presigned URL로 리다이렉트
*/
@GetMapping("/{fileId}/download")
public ResponseEntity<Void> redirectToS3(@PathVariable Long fileId) {
// 1. 위에서 fileName은 경로를 포함할 수 있다고 설명드렸습니다.
// 그래서 bucket내에서 디렉토리가 있는 경우에는 아래처럼 쓰시면 됩니다.
String fileName = "uploads/2025/11/sample-" + fileId + ".pdf";
String downloadFileName = "downloadFile.pdf";
// 2. Content-Disposition 포함된 Presigned URL 생성
String presignedUrl =
presignedUrlService.generateDownloadUrl(s3Key, downloadFileName);
// 3. 302 Redirect 응답 (Location 헤더에 presigned URL)
return ResponseEntity.status(HttpStatus.FOUND) // 302
.location(URI.create(presignedUrl))
.build();
}
}
여기서 링크를 클라이언트로 보낸 후, 클라이언트에서 해당 링크로 요청하는 방법도 있습니다.
편하신대로 쓰시면 됩니다.
'AWS' 카테고리의 다른 글
| S3 Presigned URL 간략 정리 (0) | 2025.11.27 |
|---|---|
| [AWS] RDS 외부 툴 연결 (0) | 2023.01.09 |
| [AWS] RDS 생성 (0) | 2023.01.09 |