S3란 무엇일까?
Amazon S3는 업계 최고의 확장성, 데이터 가용성 및 보안과 성능을 제공하는 객체 스토리지 서비스이다.
즉, 사진과 동영상을 저장하기 위해 사용하는 서비스이다.
S3는 버킷과 키로 구성되어 있다.
버킷 (Bucket) : 객체를 담는 바구니(컨테이너)
객체 (Objects) : S3에 저장되는 데이터
키 (Keys) : 버킷 내 객체의 고유한 식별자
버킷주소는 버킷 이름, 키 등등의 조합을 통해 고유하게 주소가 지정된다.
ex) https://yuseonjunbucket.s3.ap-northeast-2.amazonaws.com/jeon.png
라는 주소가 저장되었을 때
yuseonjunbucket ⇒ 버킷 이름
ap-northeast-2 ⇒ 리전
jeon.png ⇒ 파일 이름
S3에 버킷을 만들어보고 파일 업로드를 해보겠다.
먼저 S3에 들어가 버킷 만들기를 눌러 버킷을 만든다.
버킷 이름을 입력한 후, 모든 퍼블릭 액세스 차단을 체크 해제한다.
* 버킷을 생성할 때 외부에선 이미지를 확인할 수 없기 때문에 ssr 이 아니라면 퍼블릭으로 수정해줘야 한다.
* 퍼블릭 액세스가 차단된 상태면 나중에 Access Denied 에러가 발생할 수 있습니다.
그다음 IAM 설정을 위해 IAM 검색 후 사용자를 생성한다.
그 다음 사용자 이름을 입력한 후
직접 정책 연결을 누른 후 AmazonS3FullAccess를 입력 후 추가한다.
만들어진 사용자를 누른 후 보안 자격 증명 탭에 들어간 후, 액세스 키를 생성한다.
이중에선 아무거나 해도 무관하다.
만든 후 액세스 키와 비밀 액세스 키가 만들어졌을 텐데 완료를 누르면 앞으로 다시 볼 수 없다.
.csv 파일 다운로드를 통해 따로 저장하는 걸 추천한다.
프로젝트에 적용하기
gradle 설정하기
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
application.yml
cloud:
aws:
credentials:
accessKey: {본인의 액세스 키}
secretKey: {본인의 비밀 액세스 키}
s3:
bucket: {버킷 이름}
region:
static: ap-northeast-2
aws 설정을 완료한 후 application.yml 또는 properties에 버킷이름과 바로 전에 만든 액세스키를 가지고 연결을 해야 한다.
중요정보 이므로 따로 분리해 관리해야 한다.
S3Config
import com.amazonaws.auth.AWSStaticCredentialsProvider
import com.amazonaws.auth.BasicAWSCredentials
import com.amazonaws.services.s3.AmazonS3Client
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
class S3Config {
@Value("\${cloud.aws.credentials.access-key}")
private val accessKey: String? = null
@Value("\${cloud.aws.credentials.secret-key}")
private val secretKey: String? = null
@Value("\${cloud.aws.region.static}")
private val region: String? = null
@Bean
fun amazonS3Client(): AmazonS3Client {
val credentials = BasicAWSCredentials(accessKey, secretKey)
return AmazonS3ClientBuilder
.standard()
.withRegion(region)
.withCredentials(AWSStaticCredentialsProvider(credentials))
.build() as AmazonS3Client
}
}
S3에 연결하기 위한 코드이다.
FileUploadController
package org.mungchi.writings.ui.controller
import com.amazonaws.services.s3.AmazonS3
import com.amazonaws.services.s3.model.ObjectMetadata
import org.springframework.beans.factory.annotation.Value
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.multipart.MultipartFile
import java.io.IOException
@RestController
@RequestMapping("/upload")
class FileUploadController(
private val amazonS3Client: AmazonS3,
@Value("\${cloud.aws.s3.bucket}") private val bucket: String
) {
@PostMapping
fun uploadFile(@RequestParam("file") file: MultipartFile): ResponseEntity<String> {
return try {
val fileName = file.originalFilename
val fileUrl = "https://${bucket}/test/${fileName}"
val metadata = ObjectMetadata()
metadata.contentType = file.contentType
metadata.contentLength = file.size
amazonS3Client.putObject(bucket, fileName, file.inputStream, metadata)
ResponseEntity.ok(fileUrl)
} catch (e: IOException) {
e.printStackTrace()
ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build()
}
}
}
putObject ⇒ 객체 업로드를 담당하는 메서드로 버킷 이름, 키 이름, 업로드할 파일을 지정합니다. 버킷이름이 존재하지 않으면 에러가 발생합니다.
이제 Postman으로 확인해 보겠다.
잘 실행되는 걸 볼 수 있다.
파일 업로드하는 방법은 Body에 들어가 File형식을 누른 후 원하는 파일을 누르면 된다.
S3에도 잘 들어가는 걸 볼 수 있다.