Cloudflare R2 - 사용

최정환·2023년 12월 1일
0

cloudflare

목록 보기
2/2

ASW S3 SDK로 빠르고 간단하게 사용할 수 있습니다.

업로드

이때 메타 데이터의 키값은 소문자로 변경됩니다.

	// 이미지 path를 만들 유니크한 객체 2개, 이미지를 받음
    public void uploadPlantImage(User user, Plant plant, ByteBuffer imageBuffer) {
	    // 이미지를 분별할 해시 값 생성
        String imageHash = cloudFlareR2Utils.calculateImageHash(imageBuffer);

		// 이미지의 위치 지정
        String imageType = "thumbnail";
        String filePath = user.getEmail() + "/" + plant.getId()
                + "/" + imageType + "/image.jpg";

        String fileName = storagePointUri + filePath;
        plant.setImgUrl(fileName);
        logger.info("img URL :: {}", plant.getImgUrl());

		// R2에 Object 전송
        putObjectToR2(imageBuffer, imageHash, filePath);
    }
    
    
    
        private void putObjectToR2(ByteBuffer imageBuffer, String imageHash, String filePath) {
        PutObjectRequest putObjectRequest = PutObjectRequest.builder()
                .bucket(bucketName)
                .contentType("image/jpeg") // MIME 타입 설정
                .metadata(Map.of("Content-Disposition", "inline", "image-hash", imageHash))
                .key(filePath).acl(ObjectCannedACL.PUBLIC_READ)
                .build();

        s3Client.putObject(putObjectRequest, RequestBody.fromByteBuffer(imageBuffer));
    }

수정

  1. 이미지에 메타태그를 설정하고 같은 이미지라면 업로드하지 않도록 만듭니다.
  2. 만약 이미지를 수정해야한다면 CDN에 있는 캐싱을 삭제하도록합니다.

    public void editPlantImage(User user, Plant plant, ByteBuffer imageBuffer) {
        String imageType = "thumbnail";
        String filePath = user.getEmail() + "/" + plant.getId() + "/" + imageType + "/image.jpg";
        String fileName = storagePointUri + filePath;

		// 해시값 생성
        String imageHash = cloudFlareR2Utils.calculateImageHash(imageBuffer);

        String existingImageHash = retrieveImageHashFromR2(filePath);

        // 이미지 해시 비교
        if (!imageHash.equals(existingImageHash)) {
            logger.info("Image hash Changed now : {}, exist : {}", imageHash, existingImageHash);

			// 이미지 업로드
            uploadPlantImage(user, plant, imageBuffer);
            // 이미지 다르면 캐시 삭제
            cloudFlarePurgeCache.purgeCache(fileName);

        }
    }
    
    // 존재했던 이미지의 해시값 찾기
      public String retrieveImageHashFromR2(String filePath) {
        try {
            HeadObjectResponse response = s3Client.headObject(HeadObjectRequest.builder()
                    .bucket(bucketName)
                    .key(filePath)
                    .build());

            return response.metadata().get("image-hash");
        } catch (S3Exception e) {
            throw new RuntimeException("Failed to retrieve image hash from R2", e);
        }
    }

삭제

키값을 받고 안에 있는 객체들을 모두 삭제합니다.


 public void deletePlant(Long plantId, String userEmail) {

        try {
            String filePath = userEmail + "/" + plantId;

			// plantId의 하위 키값들을 모두 가져올 준비
            ListObjectsRequest listObjects = ListObjectsRequest.builder()
                    .bucket(bucketName)
                    .prefix(filePath) // userEmail/PlantId/
                    .build();

            ListObjectsResponse listObjectsResponse = s3Client.listObjects(listObjects);
            
            // 하위 키를 사용해 모두 삭제
            for (S3Object object : listObjectsResponse.contents()) {
                DeleteObjectRequest deleteRequest = DeleteObjectRequest.builder()
                        .bucket(bucketName)
                        .key(object.key())
                        .build();
                s3Client.deleteObject(deleteRequest);
            }


        } catch (S3Exception e) {
            // 로그 기록, 예외 처리 로직
            throw new RuntimeException("파일 삭제 중 오류가 발생했습니다.", e);
        }
    }

결론

Cloudflare R2의 최대 장점은 아웃바운드 Get의 비용과 저장비용이 저렴한 것입니다.
따라서 최대한 장점을 살리기 위해선 Put을 줄여야 하기 때문에 메타태그를 사용해 수정해야할 일을 줄인다면 더 저렴하게 이용할 수 있습니다.

0개의 댓글