[Kotlin Spring] Relogging - AWS S3를 이용한 이미지 호스팅

2024. 11. 10. 23:00·백엔드/Kotlin + Spring
728x90
반응형

1. 서론

서비스를 개발하다 보면 이미지를 저장하고 제공해야 하는 상황이 자주 발생합니다. Relogging 프로젝트에서도 사용자 프로필 이미지, 플로깅 모임 배너 이미지, 뉴스 기사 썸네일 등 다양한 이미지 리소스를 다루어야 했습니다.

 

이미지 호스팅을 구현하는 방식은 크게 두 가지가 있습니다:

  1. 애플리케이션 서버에서 직접 이미지를 저장하고 제공하는 방식
    1. 구현이 비교적 간단하고 직관적
    2. 하지만 서버 리소스(디스크 공간, 네트워크 대역폭) 부담이 큼
    3. 확장성과 가용성 측면에서 한계가 있음
  2. 클라우드 스토리지 서비스(AWS S3 등)를 활용하는 방식
    1. 초기 설정과 구현이 다소 복잡할 수 있음
    2. 하지만 서버 부하를 줄일 수 있고 확장성이 뛰어남
    3. CDN과 연계하여 더 빠른 이미지 제공 가능
    4. 비용 효율적인 운영 가능

이 글에서는 Relogging 프로젝트에서 AWS S3를 활용하여 이미지 호스팅을 구현한 방법을 상세히 살펴보겠습니다. Spring Boot와 Kotlin을 기반으로 한 구현 방법과 실제 프로젝트에서 겪은 문제들, 그리고 해결 방법을 공유하고자 합니다.

 

이어서 AWS S3 설정부터 실제 구현까지 단계별로 알아보도록 하겠습니다.

 

2. 구현

2-1. AWS S3 버킷 생성

2024.11.08 - [백엔드] - [백엔드] AWS S3 버킷 생성

 

[백엔드] AWS S3 버킷 생성

서론Amazon S3는 업계 최고의 확장성, 데이터 가용성 및 보안과 성능을 제공하는 객체 스토리지 서비스이다. S3 버킷을 생성해보자.프로젝트를 하며 이미지를 호스팅하기 위해 S3를 사용하게 되었

campus-coder.tistory.com

 

2-2. AWS S3 권한 엑세스 키 발급

2024.11.09 - [백엔드] - [백엔드] AWS S3 엑세스 키 발급 방법

 

[백엔드] AWS S3 엑세스 키 발급 방법

AWS S3 엑세스 키, 비밀 엑세스 키를 발급 받는 방법을 알아보자.  AWS 계정 로그인 이후 오른쪽 위 계정 이름을 클릭한 후 보안 자격 증명 클릭  왼쪽의 엑세스 관리 - 사용자 클릭오른쪽 주황색

campus-coder.tistory.com

 

 

2-3. yml 환경설정

 

아래의 설명을 참고해서 구현하는 프로젝트의 설정을 해주면 된다.

  • bucket: S3 버킷 이름을 'relogging'으로 지정
  • path: 각 도메인별 S3 내부 이미지 저장 경로 설정
  • credentials: AWS 접근을 위한 인증 정보
    • ${AWS_XXX_KEY} 이 부분에 아까 발급 받은 AWS 엑세스 공개키와 비밀키를 설정하면 된다.

 

Key 부분은 중요한 정보니까 환경 변수 또는 env 파일로 분리하자.

2024.10.20 - [백엔드] - [Java, Kotlin Spring] 인텔리제이 application.yml 환경변수 설정하기

 

[Java, Kotlin Spring] 인텔리제이 application.yml 환경변수 설정하기

1. 실행 버튼 옆의 구성 편집 누르기 2. 환경 변수 옵션 추가 3. 환경 변수 설정환경 변수 칸에 다음과 같이 {환경변수}={값}; 형태로 입력 DATASOURCE_PASSWORD=0000;DATASOURCE_URL=jdbc:mysql://localhost:3306/test_d

campus-coder.tistory.com

 

2-4. 코드

Config

@Configuration
class AmazonConfig(
    @Value("\${cloud.aws.credentials.accessKey}")
    private val accessKey: String,
    @Value("\${cloud.aws.credentials.secretKey}")
    private val secretKey: String,
    @Value("\${cloud.aws.region.static}")
    private val region: String,
) {
    @Bean
    fun amazonS3Client(): AmazonS3Client {
        val basicAWSCredentials = BasicAWSCredentials(accessKey, secretKey)
        return AmazonS3ClientBuilder
            .standard()
            .withRegion(region)
            .withCredentials(AWSStaticCredentialsProvider(basicAWSCredentials))
            .build()
            as AmazonS3Client
    }
}

 

  • @Configuration: Spring의 설정 클래스임을 나타냄
  • AWS 접근에 필요한 인증 정보(accessKey, secretKey)와 리전을 프로퍼티에서 주입
  • amazonS3Client 빈을 생성하여 AWS S3 서비스와 통신

 

Service

@Service
class AmazonS3Service(
    private val amazonS3Client: AmazonS3Client,
    @Value("\${cloud.aws.s3.bucket}")
    private val bucket: String,
) {
    fun uploadFile(
        file: MultipartFile,
        uploadDir: String,
    ): String {
        val originalFileName: String? = file.originalFilename

        if (!isImageFile(originalFileName as String)) {
            throw IllegalArgumentException("png, jpeg, jpg에 해당하는 파일만 업로드할 수 있습니다.")
        }

        val objectMetadata = ObjectMetadata()
        objectMetadata.contentLength = file.size
        objectMetadata.contentType = file.contentType

        val inputStream: InputStream = file.inputStream
        val fileName = uploadDir + "/" + UUID.randomUUID().toString() + "_" + file.originalFilename

        try {
            amazonS3Client.putObject(bucket, fileName, inputStream, objectMetadata)
            amazonS3Client.getUrl(bucket, originalFileName).toString()
        } catch (e: IOException) {
            throw GlobalException(GlobalErrorCode.BAD_REQUEST)
        }
        return amazonS3Client.getUrl(bucket, fileName).toString()
    }

    private fun isImageFile(fileName: String): Boolean {
        val allowedExtensions = listOf("png", "jpg", "jpeg")
        val extension = fileName.substringAfterLast(".", "")
        return extension.lowercase() in allowedExtensions
    }
}

 

 

  • 파일 유효성 검사 (이미지 파일만 허용)
  • 메타데이터 설정 (파일 크기, 컨텐츠 타입)
  • UUID를 사용한 고유한 파일명 생성
  • S3에 파일 업로드 후 URL 반환

 

728x90
반응형

'백엔드 > Kotlin + Spring' 카테고리의 다른 글

[Kotlin Spring] 스프링 스케줄러를 이용한 매일 오전 3시 작업 예약하기  (0) 2024.11.16
[Kotlin Spring] Relogging - 뉴스 기사 스크래핑하기 (크롤링과 스크래핑 차이)  (1) 2024.11.14
[Kotlin Spring] Relogging - Spring AI 활용 구현하기 정리 (OpenAI, ChatGPT API 사용하기)  (4) 2024.11.07
[Kotlin Spring] Relogging - 파일 다중 업로드와 Http 415 오류 및 해결 (스웨거 오류, MultipartFile)  (1) 2024.10.16
'백엔드/Kotlin + Spring' 카테고리의 다른 글
  • [Kotlin Spring] 스프링 스케줄러를 이용한 매일 오전 3시 작업 예약하기
  • [Kotlin Spring] Relogging - 뉴스 기사 스크래핑하기 (크롤링과 스크래핑 차이)
  • [Kotlin Spring] Relogging - Spring AI 활용 구현하기 정리 (OpenAI, ChatGPT API 사용하기)
  • [Kotlin Spring] Relogging - 파일 다중 업로드와 Http 415 오류 및 해결 (스웨거 오류, MultipartFile)
dev_ares
dev_ares
대학에서 컴퓨터공학을 전공하고 있는 학생입니다.
    반응형
    250x250
  • dev_ares
    노트
    dev_ares
  • 전체
    오늘
    어제
    • 분류 전체보기 (188)
      • IT 트랜드 (2)
      • 백엔드 (18)
        • Java + Spring (8)
        • Kotlin + Spring (5)
        • 백엔드 (5)
      • 프론트엔드 (1)
        • React (1)
      • 대외활동 (17)
        • 42서울 (17)
      • 백준 (6)
        • Java (2)
        • C++ (3)
      • 전공 (121)
        • 객체지향프로그래밍 (17)
        • 자료구조 (23)
        • 리눅스시스템관리 (16)
        • 컴퓨터구조 (25)
        • 네트워크 (25)
        • 데이터베이스 (15)
        • 기타 전공 (0)
      • 프로그래밍 언어 (18)
        • Java (5)
        • Swift (4)
        • C++ (1)
        • Kotlin (8)
      • 기타 (4)
      • 공군 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    자료구조
    컴퓨터구조
    데이터패스
    반복자
    사설 문제
    오블완
    명령어
    자바
    메모리 계층 구조
    티스토리챌린지
    C++
    추가 문제
    리눅스
    상속
    백준
    단일 사이클
    컴퓨터 구조 및 설계
    컴공 포트폴리오
    코틀린
    42서울
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
dev_ares
[Kotlin Spring] Relogging - AWS S3를 이용한 이미지 호스팅
상단으로

티스토리툴바