개발/Spring Boot

Spring Boot 시리즈 12편 – 파일 업로드 처리 전략: 이미지, 문서 업로드부터 S3 연동까지

B컷개발자 2025. 4. 26. 00:01
728x90
SMALL
Spring Boot에서 파일 업로드를 처리하는 전략을 소개합니다. 로컬 저장, 멀티파트 파일 처리, AWS S3 연동까지 실전 예제와 보안 고려사항을 함께 제공합니다.

 


 

Spring Boot 시리즈 12편 – 파일 업로드 처리 전략: 이미지, 문서 업로드부터 S3 연동까지

 

사용자 프로필 이미지, 게시글 첨부 파일, 문서 스캔 등

웹 서비스에서 파일 업로드는 거의 모든 도메인에서 요구되는 기능입니다.

 

이번 글에서는 Spring Boot에서 파일을 안전하게 업로드하고 저장하는 방법을,

 

  • 로컬 파일 시스템 기반
  • AWS S3 같은 외부 저장소 기반
  • 으로 나누어 설계 → 구현 → 보안 → 유지보수 전략까지 통합적으로 다루어보겠습니다.

 


 

📌 1. 파일 업로드 처리 방식

방식설명특징

로컬 저장 서버 디렉토리에 파일 저장 빠르고 설정 간단, 확장성 낮음
외부 저장소 (S3) 클라우드 스토리지에 저장 확장성 ↑, 보안 ↑, 유지보수 유리
DB 저장 DB에 BLOB로 저장 비추천, 속도↓, 트래픽↑

 

 


 

✅ 2. 멀티파트 파일 기본 처리

 

 

1️⃣ Controller 구성

@RestController
@RequestMapping("/api/files")
public class FileUploadController {

    @PostMapping("/upload")
    public ResponseEntity<ApiResponse<String>> upload(@RequestPart MultipartFile file) throws IOException {
        String fileName = file.getOriginalFilename();
        String path = "/upload-dir/" + UUID.randomUUID() + "_" + fileName;
        file.transferTo(new File(path));
        return ResponseEntity.ok(ApiResponse.success("파일 업로드 성공: " + path));
    }
}
기본 설정만으로도 Spring Boot는 MultipartFile을 자동 처리합니다.

 


 

2️⃣ application.yml 설정

spring:
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 20MB

 

  • 업로드 용량 제한 설정 필수
  • 대용량 파일 처리 시 파일 스트리밍 방식 고려 필요

 


 

🔐 3. 파일 저장 시 보안 고려사항

항목권장 설계

저장 경로 제한 외부 접근이 불가능한 서버 디렉토리 활용
확장자 제한 .exe, .sh 등 실행 파일 차단
파일명 변경 UUID 등으로 랜덤화 → 충돌 방지
파일 MIME 검사 file.getContentType()으로 서버단 확인
업로드 전 인증 반드시 로그인 사용자만 가능하도록 제한

 

 


 

☁️ 4. AWS S3 연동 파일 업로드

 

 

1️⃣ 의존성 추가 (Gradle)

implementation 'software.amazon.awssdk:s3:2.20.40'

 

 


 

2️⃣ S3Config 설정

@Configuration
public class S3Config {

    @Value("${cloud.aws.s3.bucket}")
    private String bucket;

    @Bean
    public S3Client s3Client() {
        return S3Client.builder()
            .region(Region.AP_NORTHEAST_2)  // 서울 리전
            .credentialsProvider(ProfileCredentialsProvider.create())
            .build();
    }

    @Bean
    public String bucketName() {
        return bucket;
    }
}

 

 


 

3️⃣ S3 업로드 서비스 구현

@Service
@RequiredArgsConstructor
public class S3FileService {

    private final S3Client s3Client;
    private final String bucketName;

    public String upload(MultipartFile file) throws IOException {
        String key = "uploads/" + UUID.randomUUID() + "_" + file.getOriginalFilename();

        PutObjectRequest putRequest = PutObjectRequest.builder()
            .bucket(bucketName)
            .key(key)
            .acl(ObjectCannedACL.PUBLIC_READ)  // 공개 여부 설정
            .build();

        s3Client.putObject(putRequest, RequestBody.fromInputStream(file.getInputStream(), file.getSize()));
        return s3Client.utilities().getUrl(builder -> builder.bucket(bucketName).key(key)).toExternalForm();
    }
}

 

 


 

4️⃣ Controller에서 호출

@PostMapping("/upload-s3")
public ResponseEntity<ApiResponse<String>> uploadToS3(@RequestPart MultipartFile file) throws IOException {
    String fileUrl = s3FileService.upload(file);
    return ResponseEntity.ok(ApiResponse.success(fileUrl));
}

 

 


 

🧠 실무 설계 팁

항목전략

고속 업로드 클라이언트에서 S3 Pre-signed URL 방식 활용 (권장)
삭제 처리 API → key → S3 delete 호출 필요
썸네일 생성 이미지 업로드 시 썸네일 서비스 별도 구성 가능
DB 저장 실제 파일은 URL만 저장 (S3 key 또는 full URL)
파일 그룹화 사용자별 prefix (user/123/avatar.png) 관리로 정리

 

 


 

✅ 마무리 요약

항목요약

기본 처리 MultipartFilefile.transferTo()
용량 제한 application.yml로 설정
로컬 저장 vs S3 빠른 개발 vs 확장성, 보안, 유지보수성
보안 고려 확장자 제한, 인증 체크, 경로 보호
실무 연동 AWS SDK 기반 파일 업로드, URL 생성 및 공개 처리

 

 


 

📌 다음 편 예고

 

Spring Boot 시리즈 13편: 스케줄러와 배치 처리 전략 – Spring Task와 Quartz로 구현하는 실무 배치 구조

 

728x90
LIST