@@ -4,23 +4,37 @@ import com.amazonaws.HttpMethod
44import com.amazonaws.services.s3.AmazonS3
55import org.springframework.beans.factory.annotation.Value
66import org.springframework.stereotype.Service
7+ import java.net.URL
78import java.util.*
89
910@Service
1011class PresignedUrlProvider (
1112 private val amazonS3 : AmazonS3 ,
12- @Value(" \$ {cloud.aws.s3.bucket}" ) private val bucket : String
13+
14+ @Value(" \$ {cloud.aws.s3.bucket}" )
15+ private val bucket : String ,
16+
17+ @Value(" \$ {cloud.cdn.domain}" )
18+ private val cdnDomain : String
1319) {
1420
1521 /* *
16- * Presigned URL 생성 (임시 업로드 전용 )
22+ * Presigned URL 생성 (업로드는 S3에, 조회는 CDN으로! )
1723 */
18- fun generateUploadUrl (userId : Long , fileName : String , expirationMinutes : Int = 5): Map <String , String > {
24+ fun generateUploadUrl (
25+ userId : Long ,
26+ fileName : String ,
27+ expirationMinutes : Int = 5
28+ ): Map <String , String > {
29+
1930 val key = " temp/$userId /${UUID .randomUUID()} -$fileName "
2031 val expiration = Date (System .currentTimeMillis() + expirationMinutes * 60 * 1000 )
2132
33+ // 1) 업로드 URL (S3 PUT 용) 그대로 유지
2234 val uploadUrl = amazonS3.generatePresignedUrl(bucket, key, expiration, HttpMethod .PUT )
23- val fileUrl = amazonS3.getUrl(bucket, key).toString()
35+
36+ // 2) 조회 URL은 CloudFront CDN 도메인으로 생성
37+ val fileUrl = buildCdnUrl(key)
2438
2539 return mapOf (
2640 " uploadUrl" to uploadUrl.toString(),
@@ -34,19 +48,36 @@ class PresignedUrlProvider(
3448 */
3549 fun copyTempToRecipe (fileUrl : String , recipeId : String ): String {
3650 val sourceKey = extractKeyFromUrl(fileUrl)
51+
3752 if (! sourceKey.startsWith(" temp/" )) {
3853 throw IllegalArgumentException (" Source key must start with temp/: $sourceKey " )
3954 }
4055
4156 val targetKey = sourceKey.replaceFirst(" temp/" , " recipes/$recipeId /" )
42-
4357 amazonS3.copyObject(bucket, sourceKey, bucket, targetKey)
4458
45- return amazonS3.getUrl(bucket, targetKey).toString()
59+ // CloudFront URL 반환
60+ return buildCdnUrl(targetKey)
61+ }
62+
63+ /* *
64+ * CloudFront URL 또는 S3 URL에서 key 추출
65+ */
66+ private fun extractKeyFromUrl (url : String ): String {
67+ return when {
68+ url.contains(cdnDomain) -> {
69+ // ex: https://dxxxxxxx.cloudfront.net/temp/1/xxx.jpg
70+ URL (url).path.removePrefix(" /" )
71+ }
72+ else -> {
73+ // 기존 S3 URL fallback
74+ val bucketUrlPrefix = amazonS3.getUrl(bucket, " " ).toString()
75+ url.removePrefix(bucketUrlPrefix)
76+ }
77+ }
4678 }
4779
48- private fun extractKeyFromUrl (fileUrl : String ): String {
49- val urlPrefix = amazonS3.getUrl(bucket, " " ).toString()
50- return fileUrl.removePrefix(urlPrefix)
80+ private fun buildCdnUrl (key : String ): String {
81+ return " https://$cdnDomain /$key "
5182 }
5283}
0 commit comments