개발일지/2023_한이음

[aws] com.amazonaws.services.s3.model.AmazonS3Exception:

기억지기 개발자 2023. 9. 3. 20:40

🏕️상황

실제 post men 화면

  • 프런트 팀원이 해당 사진을 보내주면서 imageurl이 반환이 안 된다고 했다.
    (맥북에서 캡처를 하니 저렇게 이름이 길어졌다고 했다.)
  • 평상시랑 다른 점(내가 테스트했을 때와 다른 점)이라고 한다면 파일의 이름이 지나치게 길다는 것이다.
  • 그래서 aws 인스턴스에 실행중인 프로젝트의 로그를 확인해 보니 오류가 발생하고 있었다. 
com.amazonaws.services.s3.model.AmazonS3Exception: The specified key does not exist. (Service: Amazon S3; Status Code: 404; Error Code: NoSuchKey; Request ID: --이 부분은 혹시 몰라 삭제--; S3 Extended Request ID:  --이 부분은 혹시 몰라 삭제--=; Proxy: null), S3 Extended Request ID:  --이 부분은 혹시 몰라 삭제--

 


💦과정 - 1

업로드 한 파일(이미지)의 풀 네임은 [01a3384f-b7e8-4238-b1f1-d3d9dca8e236.%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA+2023-04-10+%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE+1.45.20] 이다. 

 

그런데 키(제목?)을 보면 풀 네임 중에 앞부분만 지정이 되어있었다. 
🔜 그래서 프로젝트 코드에서는 풀 네임으로 찾으니 [해당 객체를 찾을 수 없음] 이라는 오류가 발생하여 저렇게 아무런 값도 imageurl로 넘어오지 않는 것이었다.

 

그래서 의문이 들었다.

왜 풀네임이 아니라 저렇게 앞부분만 짤라서 키 값으로 저장하는 것인지!!

그래서 알아보니 내가 모르던 사실을 알게 되었다.  

https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/userguide/object-keys.html

나의 경우에는 +와 %들이 잔뜩 들어가 있으니 

'해당 파일명에 들어가면 안 되는 문자들이 잔뜩 들어가서 저렇게 된 것이 아닌가~ ' 라는 생각이 들었다.

 


💦과정 - 2

그래서 알아보니 저런 특수 문자는 인코딩을 해서 해당 문자를 적절하게 변환 값으로 대체해주면 된다고 해서 그 방법을 실시해 보았다.   아래의 코드(저런 특수문자에 해당되는 파일명이라면 인코딩을 실시)를 실행해도 문제는 해결되지 않았다. 

private String upload(File uploadFile, String dirName) {
        String firstfileName = uploadFile.getName();

        // 파일 이름에 특수 문자나 공백이 있는지 확인
        boolean hasSpecialCharacters = firstfileName.matches(".*[!@#$%^&*()_+={}\\[\\]:;<>,.?/~`\\s]+.*");

        if (hasSpecialCharacters) {
            // 파일 이름에 특수 문자가 있는 경우 URL 인코딩 적용
            try {
                firstfileName = URLEncoder.encode(firstfileName, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        String fileName = dirName + "/" + UUID.randomUUID() + "." + firstfileName; //이름 중복 방지를 위한 렌덤 코드를 추가(UUID.randomUUID())
        String uploadImageUrl = putS3(uploadFile, fileName);
        removeNewFile(uploadFile);
        return uploadImageUrl; //이미지 url 반환
    }

실제 s3 화면

이제 객체의 url과 키의 파일(이미지)의 이름이 동일해졌다.

하지만 문제는 그렇게 해도 아래와 같은 오류가 발생하였다.

[s3에서 해당 이미지를 찾을 수 없다는 오류]

실제 콘솔의 오류화면

 

파일명이 너무 길어서 싶었으나 S3는 기본적으로 매우 긴 파일명을 지원한다고 하니,

아마도 위에서 말했던 %이 있어서 그런 거 같았다. 

 

 


🗝️해결

생각해 보면 굳이 사용자가 올린 파일명을 굳이 그~대로 올릴 필요가 없다는 느낌이었다. 

왜냐? 

  1. 사용자는 사진을 올리는 순간 사용자의 품을 떠나서 개발자가 이제 처리하는 것이니, 겹치지 않게 올릴 수 있는 것이 핵심이라는 생각!
  2. 사용자가 어떤 희한한 파일명을 올릴 수 있으니 거기에 대한 오류처리를 일일이 하느니 개발자가 일관되게 랜덤함수로 이미지 이름을 짓는 것이 낫다는 생각!

그래서 아래와 같이 코드를 변경하였다.

private String upload(File uploadFile, String dirName) {
        String fileName = dirName + "/" + UUID.randomUUID() + "." + UUID.randomUUID(); //이름 중복 방지를 위한 렌덤 코드를 추가(UUID.randomUUID())
        String uploadImageUrl = putS3(uploadFile, fileName);
        removeNewFile(uploadFile);
        return uploadImageUrl; //이미지 url 반환
    }

이렇게 의도한 대로 이미지 값이 반환되었다ㅎㅎ

 

+) 새로운 사실을 알게 해준 팀원에게 고맙다ㅎ