Spring Server 와 S3 연결하기
Spring Server 와 S3 연결하기
S3 버킷 생성이 완료되지 않았다면 S3 버킷 포스팅를 먼저 따라해주시면 됩니다.
S3 to EC2 포스팅에서는 SSH 를 통해 EC2 인스턴스에 접근해서 S3 와 연결해서 접근할 수 있었다면, 지금 작업은 백엔드 서버에서 접근하는 방법입니다.
IAM 사용자 세팅하기
검색창에 IAM 을 입력해서 IAM 메뉴를 클릭합니다.
액세스 관리 > 사용자 > 사용자 생성을 클릭합니다.
사용자 이름을 작성한 후 다음 버튼을 눌러줍니다.
직접 정책 연결 > AmazonS3FullAccess 체크 -> 다음
AmazoneS3FullAccess 는 모든 접근에 대해 열어두는 것입니다.
그러나 S3 bucket 정책을 설정했음으로 정해진 IP 주소에서만 업로드가 가능합니다.
이전에 작성한 것들을 보여주는 검토 및 생성 페이지에서는 사용자 생성 버튼을 눌러 사용자를 만들어줍니다.
사용자에서 해당 이름을 클릭하면 다음과 같이 뜨는데 여기서 액세스 키 만들기를 눌러줍니다.
액세스 키 모범 사례 및 대안이 나오는데 아무거나 체크하고 다음 눌러줍니다.
여기서는 선택했을때 사용 사례와 대안만 나타내는 기능이기 때문에 무엇을 선택하던지 상관없습니다.
태그를 작성하고 액세스 키 만들기 버튼을 클릭합니다.
엑세스 키가 나오게 되는데 이부분은 딱 한번만 나오는 부분이기 때문에 액세스키와 비밀 엑세스키를 저장을 잘해둬야 합니다.
( .csv 파일 다운로드도 같이 받아두는 것이 좋습니다. )
Spring 서버 세팅하기
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
먼저 Gradle 에 다음줄을 추가해줍니다.
## aws
cloud.aws.s3.bucket=test
cloud.aws.stack.auto=false
cloud.aws.region.static=ap-northeast-2
cloud.aws.credentials.access-key=아까 받은 access-key
cloud.aws.credentials.secret-key=아까 받은 secret-key
그다음 application-prod.properties 에 추가해줍니다.
- cloud.aws.s3.bucket: 아까 설정한 bucket 이름
- cloud.aws.stack.auto: false 를 하지 않으면 애플리케이션 시작시 자동으로 CloudFormation 스택을 생성하게 되는데 우리는 이미 위에서 수동으로 설정했기때문에 false 로 세팅합니다.
- cloud.aws.region.static: ap-northeast-2 ( 한국 )
시크릿 정보가 들어가있음으로 application.properties 에 추가하면 안됩니다. ( git 저장 X )
@Configuration
@Profile("prod")
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.static}")
private String region;
@Bean
public AmazonS3Client amazonS3Client() {
BasicAWSCredentials awsCredentials= new BasicAWSCredentials(accessKey, secretKey);
return (AmazonS3Client) AmazonS3ClientBuilder.standard()
.withRegion(region)
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.build();
}
}
이후 코드에서 S3Config 를 세팅해줘야 합니다. 위 코드를 통해서 빈으로 S3 Client 를 등록해서 Service 단에서 사용할 수 있게 됩니다.
참고) profile 에 prod 를 설정해줘야 해당 설정이 들어가게 됩니다.
ex) nohup java -jar app-20240802.jar –spring.profiles.active=prod &
@RequiredArgsConstructor
@RequestMapping("/admin/file")
@RestController
public class S3Controller {
private final FileService fileService;
// @GetMapping("/download")
// public ResponseEntity<byte[]> get(@RequestParam("fileName") String fileName) throws IOException {
// S3Object s3Object = amazonS3.getObject(bucket, fileName);
// S3ObjectInputStream objectInputStream = s3Object.getObjectContent();
// byte[] bytes = IOUtils.toByteArray(objectInputStream);
// HttpHeaders httpHeaders = new HttpHeaders();
// httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
// httpHeaders.setContentDispositionFormData("attachment", fileName);
//
// return new ResponseEntity<>(bytes, httpHeaders, HttpStatus.OK);
// }
@PostMapping("/upload")
public ApiResponse<String> upload(@RequestParam("file") MultipartFile file) {
String url = fileService.upload(file);
return ApiResponse.success(url);
}
}
본인의 경우 upload 만 사용하고 있어서 download 는 주석처리해두었습니다.
또한 url 을 상황에 따라 바로 데이터 베이스에 저장하거나 저장 페이지로 url 을 돌려주어 파라미터 받아 저장하는 방법이 있는데 저는 후자를 선택하였습니다.
@Service
@RequiredArgsConstructor
public class FileService {
private final AmazonS3 amazonS3;
@Value("${cloud.aws.s3.bucket}")
private String bucket;
public String upload(MultipartFile file) {
File uploadFile = convert(file);
String url = uploadToS3(uploadFile);
return url;
}
public File convert(MultipartFile multipartFile) {
File file = new File(multipartFile.getOriginalFilename());
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(multipartFile.getBytes());
} catch (IOException e) {
throw new RuntimeException();
}
return file;
}
private String uploadToS3(File uploadFile) {
try {
amazonS3.putObject(bucket, uploadFile.getName(), uploadFile);
return amazonS3.getUrl(bucket, uploadFile.getName()).toString();
} catch (SdkClientException e) {
throw e;
} finally {
removeNewFile(uploadFile);
}
}
private void removeNewFile(File uploadFile) {
uploadFile.delete();
}
}
서비스 코드이며, 해당 코드로 이미지를 업로드하고 URL 을 받아올 수 있습니다.
Leave a comment