100일차 - aws (RDS 운영, S3, 클라이언트에서 받은 사진 S3 버킷에 저장하기)

Yohan·2024년 7월 22일
0

코딩기록

목록 보기
142/156
post-custom-banner

aws에서 DB 연결하여 운영 (RDS)

  • putty에서 위 4개 과정 실행 후

  • mysql -u (db 마스터 아이디) -p -h 엔드포인트 로 입력후에 비밀번호까지 입력하면 DB와 연결 성공

  • 사용하고싶은 DB와 연결 (ex- use teamprj)

  • 테이블이 잘 생성되고 있음


S3

  • 구글 클라우드라고 생각
  • 무제한 저장용량을 제공하는 객체(Object) 스토리지 서비스
  • 각 유닛에는 고유의 식별자 혹은 키가 있어서 분산된 시스템 내 어디에 저장되어 있든지 상관없이 데이터를 찾을 수 있음
  • 사진, 서버 로그 등 저장 가능

S3 버킷 버전 관리

  • 버전 표시 클릭하면 같은 파일의 버전들을 볼 수 있음

S3 객체 암호화

S3 버킷 정책 생성

  • 버킷에 파일을 업로드하면 객체 URL이 나오는데 URL을 입력해보면 정책이 허용되지않아 ERROR 메세지가 뜨게됨
  • 권한에 들어가서 버킷 정책을 설정해주어야함
  • 버킷 생성
  • 버킷 / 권한 / 퍼블릭 액세스 차단 활성화 -> 비활성으로 바꿈

  • 정책 생성기로 생성
  • principal에 입력, Actions에서 Get Object 선택, ARN에는 ARN/ 입력
  • 다 누르면 Add statement
  • Generate Policy 누르면 json 생성
  • 정책에 입력
  • 버킷 정책 설정이 완료되었고 이미지 URL에 다시 들어가보면 들어가지는 것을 볼 수 있음

클라이언트에서 받은 것 aws bucket에 저장하기

  • aws에서 file-admin 이라는 IAM 사용자를 만들고, 액세스키, 시크릿키를 발급 받기
  • build.gradle에 s3 추가
	// s3 라이브러리
	implementation 'software.amazon.awssdk:s3:2.17.52'
  • application.yml에 등록
# s3 setting (웹에서 발급받은 key, secret key)
aws:
  credentials:
    accessKey: {my_key}
    secretKey: {my_secret_key}
  region: {my_region} ex) ap-northeast-2
  bucketName: {my_bucket_name}
  • FileUploadController
package com.study.event.api.event.controller;

@RestController
@Slf4j
@RequiredArgsConstructor
public class FileUploadController {

    private final FileUploadService uploadService;

    // 파일 업로드 처리
    @PostMapping("/file/upload")
    public ResponseEntity<?> upload(
            @RequestPart(value = "userData", required = false) EventUserSaveDto dto,
            @RequestPart(value = "profileImage") MultipartFile uploadFile
    ) {

        log.info("userData: {}", dto);
        log.info("profileImage: {}", uploadFile.getOriginalFilename());

        // 파일을 업로드
        String fileUrl = "";
        try {
            fileUrl = uploadService.uploadProfileImage(uploadFile);
        } catch (IOException e) {
            log.warn("파일 업로드에 실패했습니다.");
            return ResponseEntity.badRequest().body(e.getMessage());
        }

        return ResponseEntity.ok().body(fileUrl);
    }
}
  • FileUploadService
package com.study.event.api.event.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.UUID;

@Service
@Slf4j
@RequiredArgsConstructor
public class FileUploadService {

    private final AwsS3Service s3Service;

    /**
     * 파일 업로드 처리
     * @param profileImage - 클라이언트가 전송한 파일 바이너리 객체
     * @return - 업로드된 파일의 URL
     */
    public String uploadProfileImage(MultipartFile profileImage) throws IOException {

        // 파일명을 유니크하게 변경
        String uniqueFileName = UUID.randomUUID() + "_" + profileImage.getOriginalFilename();

        // 파일을 S3 버킷에 저장 (핵심)
        // (AMAZON에 연결할 수 있는 api를 gradle에 추가하고, yml에서 코드 추가)
        String url = s3Service.uploadToS3Bucket(profileImage.getBytes(), uniqueFileName);

        return url;
    }
}
  • AwsS3Service
package com.study.event.api.event.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;

import javax.annotation.PostConstruct;
import java.time.LocalDate;

@Service
@Slf4j
public class AwsS3Service {

    // s3 버킷을 제어하는 객체
    private S3Client s3;

    // 인증 정보
    @Value("${aws.credentials.accessKey}")
    private String accessKey;
    @Value("${aws.credentials.secretKey}")
    private String secretKey;
    @Value("${aws.region}")
    private String region;
    @Value("${aws.bucketName}")
    private String bucketName;

    // AWS S3에 접근하여 인증
    @PostConstruct // 본 서비스 객체가 생성될 때 단 1번 실행
    private void initAmazonS3() {
        // 액세스키와 비밀키로 사용자 인증
        AwsBasicCredentials credentials = AwsBasicCredentials.create(accessKey, secretKey);

        this.s3 = S3Client.builder()
                .region(Region.of(region))
                .credentialsProvider(StaticCredentialsProvider.create(credentials))
                .build();
    }

    /**
     * 버킷에 파일을 업로드하고, 업로드한 버킷의 URL을 리턴
     * @param uploadFile - 파일의 바이너리
     * @param fileName - 저장할 파일명
     * @return - 저장된 URL
     */
    public String uploadToS3Bucket(byte[] uploadFile, String fileName) {

        // 현재 날짜를 기반으로 폴더 생성
        // 2024-07-22  =>  2024/07/22
        String datePath = LocalDate.now().toString().replace("-", "/");

        String fullPath = datePath + "/" + fileName;

        // 업로드 수행
        PutObjectRequest request = PutObjectRequest.builder()
                .bucket(bucketName) // 버킷명
                .key(fullPath)      // 저장 경로
                .build();

        s3.putObject(request, RequestBody.fromBytes(uploadFile)); // 실질적인 명령

        // 업로드된 경로 URL을 반환
        return s3.utilities()
                .getUrl(b -> b.bucket(bucketName).key(fullPath))
                .toString();
    }

}
profile
백엔드 개발자
post-custom-banner

0개의 댓글