본문 바로가기

AWS

Presigned URL을 통해 S3에 업로드하기

728x90

Presigned URL을 사용하기에 앞서 왜 사용을 하는가 ? 를 알아보겠습니다.

 

퍼포먼스 목적

보통 파일 업로드는 권한설정 때문에 서버를 경유해야하는 경우가 있는데 영상파일 같이 컨텐츠의 용량이 높은 경우

서버에 넘겨준 후 서버에서 스토리지에 저장하는 이중 작업은 비효율적일 때가 있다.

이때 서버에서는 Presgined URL만 발행해서 클라이언트에 던져주고 해당 url을 이용해 클라이언트단에서 직접 파일 업로드를 함으로 서버단의 리소스를 사용하지 않고 업로드가 가능하다.

 

 

다음 이름과 같이 버킷을 생성해줍시다!

버킷 -> 권한에 들어가서  CORS를 다음과 같이 설정을 합니다.

"AllowedHeaders": 허용된 요청 헤더의 목록을 지정합니다. 여기서는 "*"를 사용하여 모든 헤더를 허용하도록 설정되어 있습니다.

"AllowedMethods": 허용된 HTTP 요청 메서드의 목록을 지정합니다. 여기서는 "GET", "DELETE", "POST" 메서드를 허용하도록 설정되어 있습니다.

"AllowedOrigins": 허용된 오리진(도메인)의 목록을 지정합니다. 여기서는 "*"를 사용하여 모든 오리진을 허용하도록 설정되어 있습니다. 따라서 어떤 도메인에서든지 이 서버의 리소스에 접근할 수 있습니다.

"ExposeHeaders": 브라우저에서 접근할 수 있는 응답 헤더의 목록을 지정합니다. 여기서는 빈 배열([])로 설정되어 있으므로 어떠한 응답 헤더도 노출되지 않습니다.

"MaxAgeSeconds": 사전 검증 없이 리소스에 접근할 수 있는 최대 시간(초)을 지정합니다. 여기서는 3000초(약 50분)로 설정되어 있으므로, 브라우저는 이 설정된 시간 동안에는 다시 사전 검증 없이 같은 오리진에 대한 요청을 보낼 수 있습니다.

 

IAM:AWS 리소스에 대한 액세스를 안전하게 제어할 수 있는 웹 서비스

 

IAM에 들어가서 사용자에 권한을 추가해주겠습니다.

사용자 추가를 눌러

s3FullAccess 권한을 주도록 하겠습니다.

 

 

다음으로 만들어진 사용자->보안자격증명 탭에 들어가서 Access key 와 Secret Key를 생성하도록 합니다.

 

만들어 진 Access key 와 Secret key는 csv 파일로 저장하여 잘 보관하고 있어야합니다.

 

 

Intellij를 키도록 하겠습니다.

 

application.yml

amazon:
  aws:
    accessKey: accesskey
    secretKey: 시크릿키
    region: ap-northeast-2
    bucket: 버킷명

AwsS3Config.class

해당하는 클래스는 사용자의 자격증명을 검증하는 코드입니다.

import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AWSS3Config {
    @Value("${amazon.aws.accessKey}")
    private String accessKeyId;

    @Value("${amazon.aws.secretKey}")
    private String accessKeySecret;

    @Value("${amazon.aws.region}")
    private String s3RegionName;

    @Bean
    public AmazonS3 getAmazonS3Client(){
        final BasicAWSCredentials basicAWSCredentials =new BasicAWSCredentials(accessKeyId, accessKeySecret);
        // Get Amazon S3 client and return the s3 client object

        return AmazonS3ClientBuilder
                .standard()
                .withCredentials(new AWSStaticCredentialsProvider(basicAWSCredentials))
                .withRegion(s3RegionName)
                .build();
    }

}

FileUploadService.class

해당 클래스는 PresignedUrl을 생성해주는 코드입니다. 유효시간은 10분으로 잡았습니다.

import com.amazonaws.HttpMethod;
import com.amazonaws.services.s3.AmazonS3;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.stereotype.Service;

import java.util.Calendar;
import java.util.Date;

@Service
public class FileUploadService {

    @Autowired
    private AmazonS3 amazonS3;


    public String generatePreSignUrl(String filePath,
                                     String bucketName,
                                     HttpMethod httpMethod){

        Calendar calendar= Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.MINUTE,10); //validfy of 10 minutes
        return amazonS3.generatePresignedUrl(bucketName, filePath, calendar.getTime(),httpMethod).toString();

    }

}

FileUploadController.class

해당 클래스에서는 확장자명이 무엇인지에 따라 PresignedUrl 을 반환해주는 코드입니다.

@RestController
@RequiredArgsConstructor
public class FileUploadController {


    private final FileUploadService awsS3Service;

    @Value("${amazon.aws.bucket}")
    private String bucketName;

    @GetMapping("/api/generate-presigned-url")
    public ResponseEntity<String> generatePresignedUrl(@RequestParam String extension){
        return ResponseEntity.ok(
                awsS3Service.generatePreSignUrl(UUID.randomUUID()+"."+extension,bucketName, HttpMethod.PUT));

    }


}

 

pom.xml

Amazon sdk 의존성을 추가해야합니다.

        <!-- AWS SDK -->
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk</artifactId>
            <version>1.11.64</version>
        </dependency>

 

테스트 시작

해당 URL에 GET 요청을 해보았습니다. 확장자명이 jpg 인 url에 요청을 했더니 ? PreSignedUrl을 잘 반환 해주는군요!

 

해당하는 URL을 복사하여 Put요청을 하고 이미지파일을 전송해겠습니다.

성공적으로 200코드가 떳네요 ! 

 

이제 S3버킷을 확인해보겠습니다

.성공적으로 해당 img 파일이 들어왔습니다!

 

 

728x90