Spring Boot : 2.4.4 버전 입니다.

먼저 CKeditor와 AWS S3 버킷은 만들었다고 가정하겠습니다.

우선 기본적으로 CDN을 통해 CK editor를 붙이면 드래그&드롭기능은 있지만 이미지 업로드가 되지 않을텐데요. 먼저 이미지 업로드부터 활성화 시키겠습니다.

 

 

imageUploadUrl 이라는 키워드를 통해 드래그&드롭으로 이미지를 올릴 시 어떤 API로 보낼지 정할 수 있습니다. 저의 경우 /image/upload 입니다.

그 다음은 컨트롤러 부분을 보겠습니다.

 

 

CK Editor를 사용했다면서 왜 RestController있냐고 생각하실수도 있으신 분들을 위해 설명하겠습니다.

이미지 업로드를 하고 나면 정해진 형태의 json 양식으로 response를 보내주어야 CK Editor가 인식 할 수 있습니다.

 

 

response의 양식을 위와 같습니다.

그 다음은 Service 부분입니다.

코드가 길어 이미지 대신 코드블럭으로 대신하였습니다.

@Service
@RequiredArgsConstructor
@Slf4j
public class FileService {

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

    public FileUploadDTO fileUpload(MultipartFile upload, Principal principal) throws IOException {
        File uploadFile = convert(upload).orElseThrow(() -> new IllegalArgumentException("MultipartFile -> File 전환실패."));

        return upload(uploadFile, "static");
    }

    private FileUploadDTO upload(File uploadFile, String dir) {
        String sourceName = uploadFile.getName();
        String sourceExt = FilenameUtils.getExtension(sourceName).toLowerCase();

        String fileName = dir + "/" + LocalDateTime.now().toString().concat(".").concat(sourceExt);
        String uploadImageUrl = putS3(uploadFile, fileName);
        removeNewFile(uploadFile);

        return FileUploadDTO.builder()
                .uploaded(true)
                .fileName(fileName)
                .url(uploadImageUrl)
                .build();
    }

    private void removeNewFile(File targetFile) {
        if (targetFile.delete()) {
            log.info("파일이 삭제되었습니다.");
        } else {
            log.info("파일이 삭제되지 못했습니다.");
        }
    }

    private String putS3(File uploadFile, String fileName) {
        try {
            amazonS3Client.putObject(new PutObjectRequest(bucket, fileName, uploadFile)
                    .withCannedAcl(CannedAccessControlList.PublicRead));
        } catch (Exception e) {
            log.error("이미지 s3 업로드 실패");
            log.error(e.getMessage());
            removeNewFile(uploadFile);
            throw new RuntimeException();
        }

        return amazonS3Client.getUrl(bucket, fileName).toString();
    }

    private Optional<File> convert(MultipartFile file) throws IOException {
        File convertFile = new File(Objects.requireNonNull(file.getOriginalFilename()));
        if (convertFile.createNewFile()) {
            try (FileOutputStream fos = new FileOutputStream(convertFile)) {
                fos.write(file.getBytes());
            }

            return Optional.of(convertFile);
        }

        return Optional.empty();
    }
}

코드에 대해 자세한 설명이 필요하신 분들은 https://jojoldu.tistory.com/300 이 글을 보시면 자세히 알 수 있습니다.

저는 위의 글과는 조금 다르게 환경설정을 했습니다. 위의 글에서는 aws.yml 파일을 따로 만들어서 accessKey와 secretKey를 등록을 해줬는데요 저같은 경우에는 로컬, develop 서버, product 서버의 환경이 다르다보니 각 서버별로 RDS를 연결시켜주어야 했습니다. 그러기 때문에 yml파일을 환경별로 세팅하여서 위의 글과는 다른 점이 있습니다. 물론 하나의 yml 파일에 ---로 구분지어 환경을 나눌수 있다고 하는데 아직 해보지 않아서 모르겠습니다. 추후 해본다음에 포스트하도록 하겠습니다.

다른점은 yml파일과 main 함수 부분입니다.

 

 

spring:
  config:
    activate:
      on-profile: dev

  mvc:
    hiddenmethod:
      filter:
        enabled: false

  datasource:
    url: jdbc:mysql://${rds}:3306/board?autoReconnect=true&useUnicode=true&serverTimezone=UTC&characterEncoding=UTF8
    username: ${username}
    password: ${password}
    driver-class-name: com.mysql.cj.jdbc.Driver

  jpa:
    hibernate:
      ddl-auto: update
    properties:
      hibernate:
        show_sql: true
        format_sql: true
        use_sql_comments: true

  thymeleaf:
    prefix: classpath:/templates/
    suffix: .html
    cache: false

  loggin.level:
    org.hibernate.SQL: debug

server:
  port: 8888

cloud:
  aws:
    s3:
      bucket: hese-board
    region:
      static: ap-northeast-2
    credentials:
      accessKey: ${accessKey}
      secretKey: ${secretKey}
      use-default-aws-credentials-chain: false
      instance-profile: true
    stack:
      auto: false

accessKey와 secretKey 부분에 ${} 이렇게 되어있는걸 볼 수 있는데요 이렇게 해줌으로써 jar 파일을 실행할때 변수를 넘겨주어 acessKey와 secretKey를 설정해줄 수 있습니다.

제가 사용하는 명령어를 적어놓겠습니다.

java -Dspring.profiles.active=dev -jar /home/ubuntu/application/deploy/*.jar --rds=rds주소 --username=계정명 --password=비밀번호 --accessKey=액세스키 --secretKey=시크릿키

-Dspring.profiles.active로 사용할 application.yml 파일을 정해주고 뒤에 추가 변수로 전부 매핑시켜 줍니다.

+ Recent posts