T_era
Spring Boot + AWS S3 프로필 이미지 API 구현 본문
🎯 개요
Spring Boot에서 AWS S3를 활용해 사용자 프로필 이미지를 관리하는 API를 구현해보기
1️⃣ 환경 설정
AWS S3 버킷 생성
- 버킷명:
your-project-bucket - 리전:
ap-northeast-2
환경변수 설정
DB_USERNAME=your_db_username // RDS DB master
DB_PASSWORD=your_db_password // RDS DB master password
AWS_ACCESS_KEY=your_aws_access_key
AWS_SECRET_KEY=your_aws_secret_key
AWS_REGION=ap-northeast-2
AWS_S3_BUCKET=your-project-bucket
build.gradle 의존성
implementation 'software.amazon.awssdk:s3:2.24.12'
2️⃣ 핵심 코드 구현
S3 설정 클래스
@Configuration
public class S3Config {
@Value("${AWS_ACCESS_KEY}")
private String accessKey;
@Bean
public S3Client s3Client() {
return S3Client.builder()
.region(Region.of(region))
.credentialsProvider(StaticCredentialsProvider.create(awsCredentials))
.build();
}
}
AWS S3 클라이언트를 Bean으로 등록하여 애플리케이션에서 사용할 수 있도록 설정한다.
S3 서비스 핵심 메서드
@Service
public class S3Service {
public String uploadProfileImage(MultipartFile file, Long userId) {
validateFile(file); // 파일 검증
String key = "profile-image/" + userId + "/" + generateFileName(file);
s3Client.putObject(PutObjectRequest.builder()
.bucket(bucketName)
.key(key)
.build(), RequestBody.fromInputStream(file.getInputStream(), file.getSize()));
return getFileUrl(key);
}
}
설명: 파일을 S3에 업로드하고 URL을 반환하는 메서드. 파일 검증과 중복 방지를 위한 파일명 생성도 포함.
User 엔티티 수정
@Entity
public class User {
private String profileImageUrl; // 추가
public void updateProfileImage(String profileImageUrl) {
this.profileImageUrl = profileImageUrl;
}
}
설명: 사용자 엔티티에 프로필 이미지 URL 필드와 업데이트 메서드를 추가
컨트롤러 엔드포인트
@RestController
public class UserController {
@PostMapping("/users/profile-image")
public ResponseEntity<ProfileImageResponse> uploadProfileImage(
@AuthenticationPrincipal AuthUser authUser,
@RequestParam("image") MultipartFile image) {
// 이미지 업로드 로직
}
@DeleteMapping("/users/profile-image")
public ResponseEntity<Void> deleteProfileImage(@AuthenticationPrincipal AuthUser authUser) {
// 이미지 삭제 로직
}
}
설명: 이미지 업로드와 삭제를 위한 REST API 엔드포인트를 구현.
3️⃣ 배포 및 실행
JAR 빌드 및 업로드
./gradlew clean build -x test
scp -i "your-key.pem" build/libs/your-app.jar ec2-user@your-ec2-ip:~/
EC2 환경변수 설정
# 환경변수 추가
echo "export AWS_ACCESS_KEY=your_key" >> ~/.bashrc
echo "export AWS_S3_BUCKET=your_bucket" >> ~/.bashrc
source ~/.bashrc
포트 확인 및 프로세스 정리
sudo lsof -i :8080 # 포트 사용 확인
kill -9 <PID> # 기존 프로세스 종료
서버 실행
nohup java \
-DAWS_ACCESS_KEY=${AWS_ACCESS_KEY} \
-DAWS_S3_BUCKET=${AWS_S3_BUCKET} \
-jar your-app.jar > ~/app.log 2>&1 &
4️⃣ API 테스트
회원가입 및 로그인
# 회원가입 (JWT 토큰 획득)
curl -X POST http://localhost:8080/auth/signup \
-H "Content-Type: application/json" \
-d '{"email": "test@example.com", "password": "Test1234"}'
이미지 업로드 테스트
# 테스트 이미지 준비
curl -o test-image.jpg https://dummyimage.com/300x300/000/fff
# 이미지 업로드
curl -X POST \
http://localhost:8080/users/profile-image \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-F "image=@test-image.jpg"
예상 결과:
{
"imageUrl": "https://your-bucket.s3.amazonaws.com/profile-image/1/1_uuid.jpg",
"message": "프로필 이미지가 성공적으로 업로드되었습니다."
}
사용자 정보 조회
curl -X GET \
http://localhost:8080/users/1 \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
예상 결과:
{
"id": 1,
"email": "test@example.com",
"profileImageUrl": "https://your-bucket.s3.amazonaws.com/profile-image/1/1_uuid.jpg"
}
5️⃣ 주요 트러블슈팅
포트 충돌
문제: Port 8080 was already in use
해결: sudo lsof -i :8080 → kill -9 <PID>
환경변수 인식 실패
문제: @Value에서 환경변수를 찾지 못함
해결: source ~/.bashrc 실행
S3 권한 에러
문제: S3 업로드 시 권한 에러
해결: IAM 사용자에게 S3 접근 권한 부여
✅ 완성된 기능
- 이미지 업로드: S3에 안전하게 저장
- 파일 검증: 크기(5MB), 확장자(jpg, png, gif) 검증
- 중복 처리: 기존 이미지 자동 삭제
- JWT 인증: 보안된 API 접근
- 환경변수 관리: 민감 정보 보안
'Programing > Spring' 카테고리의 다른 글
| RestTemplate 직접 생성 vs 빌더 생성 차이와 동작 원리 (0) | 2025.07.08 |
|---|---|
| 실시간 데이터 전송 방식 정리 (1) | 2025.07.01 |
| Spring Boot EC2 배포 & 테스트 과정에서 문제 해결 (0) | 2025.06.30 |
| 헬퍼(Helper)와 유틸(Utility)의 차이, 그리고 실전 코드 예시 (0) | 2025.06.25 |
| Spring API와 Postman으로 네트워크 오버헤드 실험하기 (0) | 2025.06.24 |