AWS
[S3] AWS - SpringBoot 설정
공부 기록장
2025. 3. 2. 16:25
- application.properties 파일 설정
cloud.aws.s3.bucket=[생성한 버킷 이름]
cloud.aws.stack.auto=false
cloud.aws.region.static=ap-northeast-2
cloud.aws.credentials.access-key=[액세스 키]
cloud.aws.credentials.secret-key=[비밀 액세스 키]
- build.gradle 에 의존성 추가
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
- S3Config 파일 설정
@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.static}")
private String region;
@Bean
public AmazonS3Client amazonS3Client(){
BasicAWSCredentials credentials = new BasicAWSCredentials(this.accessKey, this.secretKey);
return (AmazonS3Client) AmazonS3ClientBuilder
.standard()
.withRegion(region)
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.build();
}
}
- S3Service 파일 설정
@Service
@RequiredArgsConstructor
public class S3Service {
private final S3Config s3Config;
@Value("${cloud.aws.s3.bucket}")
private String bucketName;
public String uploadPostImage(MultipartFile file) {
// 파일명 설정 (UUID + 원본 파일명)
String post_folderName = "post_image/";
String fileName = post_folderName + UUID.randomUUID();
// 메타데이터 설정 (파일 크기 및 타입)
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(file.getSize());
metadata.setContentType(file.getContentType());
try {
// S3에 파일 업로드
s3Config.amazonS3Client().putObject(new PutObjectRequest(bucketName, fileName, file.getInputStream(), metadata)
.withCannedAcl(CannedAccessControlList.PublicRead));
// 업로드된 이미지의 URL 반환
return s3Config.amazonS3Client().getUrl(bucketName, fileName).toString();
} catch (IOException e) {
throw new RuntimeException("게시글 이미지 업로드 실패", e);
}
}
- 프론트로부터 이미지를 받는 컨트롤러 작성
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/posts")
public class PostController {
private final PostService postService;
private final S3Service s3Service;
@PreAuthorize("isAuthenticated()")
@PostMapping("/create")
public ResponseEntity<?> createPost(@RequestPart("postData") PostCreateRequest request,
@RequestPart(value="image", required = false) MultipartFile file,
@AuthenticationPrincipal CustomUserDetails customUserDetails,
@AuthenticationPrincipal CustomOAuth2User customOAuth2User) throws IOException {
if (customUserDetails == null && customOAuth2User == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body("accessToken 재발급 요청");
}
if (request.getContent()== null || request.getContent().trim().isEmpty()) {
return ResponseEntity.badRequest().body("게시글 내용은 필수입니다.");
}
try {
String imagePath = null;
if(file != null){
imagePath = s3Service.uploadPostImage(file);
log.info("S3 에 이미지 업로드 완료 : " + imagePath);
}
if(customUserDetails != null){
postService.create(request, customUserDetails, imagePath);
}
if(customOAuth2User != null){
postService.create(request, customOAuth2User, imagePath);
}
return ResponseEntity.status(200).build();
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("게시글 작성 중 서버 오류가 발생했습니다.");
}
}
}