2024년 1월 10일
조회 : 194|1분 읽기
Cloudflare R2 - 사용
Cloudflare R2의 최신 기능들 중 사용할 수 없는것이 있을 수 있지만 ASW S3 SDK로 빠르고 간단하게 사용할 수 있습니다.
업로드
이때 메타 데이터를 사용합니다.
키값은 소문자로 변경됩니다.
java1 // 이미지 path를 만들 유니크한 객체 2개, 이미지를 받음 2 public void uploadPlantImage(User user, Plant plant, ByteBuffer imageBuffer) { 3 // 이미지를 분별할 해시 값 생성 4 String imageHash = cloudFlareR2Utils.calculateImageHash(imageBuffer); 5 6 // 이미지의 위치 지정 7 String imageType = "thumbnail"; 8 String filePath = user.getEmail() + "/" + plant.getId() 9 + "/" + imageType + "/image.jpg"; 10 11 String fileName = storagePointUri + filePath; 12 plant.setImgUrl(fileName); 13 logger.info("img URL :: {}", plant.getImgUrl()); 14 15 // R2에 Object 전송 16 putObjectToR2(imageBuffer, imageHash, filePath); 17 } 18 19 20 21 private void putObjectToR2(ByteBuffer imageBuffer, String imageHash, String filePath) { 22 PutObjectRequest putObjectRequest = PutObjectRequest.builder() 23 .bucket(bucketName) 24 .contentType("image/jpeg") // MIME 타입 설정 25 .metadata(Map.of("Content-Disposition", "inline", "image-hash", imageHash)) 26 .key(filePath).acl(ObjectCannedACL.PUBLIC_READ) 27 .build(); 28 29 s3Client.putObject(putObjectRequest, RequestBody.fromByteBuffer(imageBuffer)); 30 }
수정
- 이미지에 메타태그를 설정하고 같은 이미지라면 업로드하지 않도록 만듭니다.
- 만약 이미지를 수정해야한다면 CDN에 있는 캐싱을 삭제하도록합니다.
java1 2 public void editPlantImage(User user, Plant plant, ByteBuffer imageBuffer) { 3 String imageType = "thumbnail"; 4 String filePath = user.getEmail() + "/" + plant.getId() + "/" + imageType + "/image.jpg"; 5 String fileName = storagePointUri + filePath; 6 7 // 해시값 생성 8 String imageHash = cloudFlareR2Utils.calculateImageHash(imageBuffer); 9 10 String existingImageHash = retrieveImageHashFromR2(filePath); 11 12 // 이미지 해시 비교 13 if (!imageHash.equals(existingImageHash)) { 14 logger.info("Image hash Changed now : {}, exist : {}", imageHash, existingImageHash); 15 16 // 이미지 업로드 17 uploadPlantImage(user, plant, imageBuffer); 18 // 이미지 다르면 캐시 삭제 19 cloudFlarePurgeCache.purgeCache(fileName); 20 21 } 22 } 23 24 // 존재했던 이미지의 해시값 찾기 25 public String retrieveImageHashFromR2(String filePath) { 26 try { 27 HeadObjectResponse response = s3Client.headObject(HeadObjectRequest.builder() 28 .bucket(bucketName) 29 .key(filePath) 30 .build()); 31 32 return response.metadata().get("image-hash"); 33 } catch (S3Exception e) { 34 throw new RuntimeException("Failed to retrieve image hash from R2", e); 35 } 36 }
삭제
키값을 받고 안에 있는 객체들을 모두 삭제합니다.
java1 2 public void deletePlant(Long plantId, String userEmail) { 3 4 try { 5 String filePath = userEmail + "/" + plantId; 6 7 // plantId의 하위 키값들을 모두 가져올 준비 8 ListObjectsRequest listObjects = ListObjectsRequest.builder() 9 .bucket(bucketName) 10 .prefix(filePath) // userEmail/PlantId/ 11 .build(); 12 13 ListObjectsResponse listObjectsResponse = s3Client.listObjects(listObjects); 14 15 // 하위 키를 사용해 모두 삭제 16 for (S3Object object : listObjectsResponse.contents()) { 17 DeleteObjectRequest deleteRequest = DeleteObjectRequest.builder() 18 .bucket(bucketName) 19 .key(object.key()) 20 .build(); 21 s3Client.deleteObject(deleteRequest); 22 } 23 24 25 } catch (S3Exception e) { 26 // 로그 기록, 예외 처리 로직 27 throw new RuntimeException("파일 삭제 중 오류가 발생했습니다.", e); 28 } 29 }
결론
Cloudflare R2의 최대 장점은 아웃바운드 Get의 비용과 저장비용이 저렴한 것입니다.
따라서 최대한 장점을 살리기 위해선 Put을 줄여야 하기 때문에 메타태그를 사용해 수정을 줄인다면 더 저렴하게 이용할 수 있습니다.