배포 후 버그를 발견한 사용자에게 연락이 왔다.

위 두 파일에 대해서 업로드를 하면 24시간이 지나지 않았음에도 불구하고 오류가 난다는 연락이었다.
일단 뉴렐릭으로 로그를 확인했다.

해당 오류가 맞았다.
현재 업로드 된 파일을 담는 S3는 저작권 문제로 24시간이 지나면 자동으로 파일을 삭제한다. 만일 사용자가 로컬 스토리지에 저장된 파일 url로 다시 요청을 하면, 24시간이 지나 S3에 해당 파일이 없으니, 다시 사용자에게 입력을 받는 에러 메세지이다.

이런 식으로 화면에 뜬다.
S3에 이미 있어도, 로컬메모리에 저장된 url을 찾을 수 없으니 서버에서 없다고 판단하고 삭제되었다는 에러를 보내는 것이다.
내가 가지고 있는 파일을 넣으면 정상적으로 작동을 한다. 또한 개발 과정에서도 이런 경우가 한 번도 없어서 해당 파일에 문제가 있다고 생각했다. 근데 열어서 보니 text도 잘 인식이 되는 정상적인 pdf 파일이었다.
문제 해결 접근법
1. AWS 사용 시 문제
일단 S3 강제로 삭제를 한 후, 다시 요청을 해봤다. 기존에 설계된대로 에러가 잘 작동하는지를 확인하기 위해서.
근데.. S3에 파일이 없어도.. 잘 작동하더라..?

팀원에게 물어보니 cloudfront 캐시 무효화는 현재 되고 있지 않는다. S3에서 직접 파일을 삭제 후 20분 정도 지난 뒤 요청을 해도 정상적으로 찾을 수 있었다.
그러나 이건 때에 따라 다르게 적용됐고, 아마 cloudfront 캐시 무효화가 S3 24시간과 함께 진행되지만, 만일 S3에서 강제로 파일을 삭제하면 자동으로 되는 경우가 있고 안되는 경우가 있는 것 같다.
위 추측이 확실하지 않지만 일단 이건 원인이 아니다. cloudfront 캐시 무효화가 진행이 안된거면 오히려 24시간이 지난 뒤에도 파일을 찾을 수 있어야 한다. 못 찾는게 아니라.
2. 사용자 입력 파일의 문제
앞서 말했다싶이 파일 내부 내용은 문제가 없었다. 일반적인 강의 노트였고, text도 인식이 잘 됐다..
에러를 발견한 사용자가 준 파일 중 제목이 1인 파일은 정상적으로 작동했지만, "9주차" 파일은 작동하지 않았다.
혹시나 하는 마음으로.. 9주차 파일의 이름을 1로 변경하고 파일 업로드를 진행 후 문제를 제작했다.
정상적으로 제작되었다!! S3에서 해당 파일을 찾을 수 있었다. 이후, 다른 파일을 9주차로 적고 넣으니 해당 파일을 S3에서 찾을 수 없다는 오류가 떴다!
그럼 오류의 원인은 업로드 된 파일 제목이었다.
여러 가지 경우로 테스트를 해봤다.
1. 9주차 -> 안 됨
2. 주차 -> 안 됨
3. 주차주차 -> 안 됨
4. 100000주차 -> 안 됨
5. 9과제 -> 안 됨
처음엔 여러 사용자가 사용하다보니 9주차라는 제목의 파일이 많을 것이고, 그래서 동일한 이름의 파일이 여러 개 있어 못찾나? 했다. 그러나 10000주차에 대해서도 에러가 발생하고 (동일한 이름이 절대 없을 거 같은 경우) 애초에 S3에 저장 시 파일 이름에 타임스탬프를 함께 넣기 때문에 동일한 이름이 있긴 불가능하다.
한글 때문에 오류가 난다고는 생각 못했다. 왜냐면 배포 전 테스트 때도 한글 이름의 파일을 넣었는데 정상적으로 문제가 제작되었기 때문이다.

한글 이름에 대해서 에러가 생기진 않았다.
그럼.. 정말 뭐가 문제일까... 그러다가 띄어쓰기를 했더니 잘 잘동 되었다.
?
"9주차"는 안되지만, "9 주차"는 된다. (이게 뭐람)
영어를 해봤지만 영어의 경우 띄어쓰기가 있던, 없던 모두 정상적으로 작동했다. 그러면 문제는 한글때문에 생기는게 맞다!
기존 S3에 업로드 된 url를 확인하는 코드는 다음과 같다.
public void validateUploadedUrl() {
try {
HttpURLConnection connection = (HttpURLConnection) new URL(
uploadedUrl).openConnection();
int responseCode = connection.getResponseCode();
if (responseCode != HttpURLConnection.HTTP_OK) {
throw new CustomException(ExceptionMessage.FILE_NOT_FOUND_ON_S3);
}
} catch (Exception e) {
throw new CustomException(ExceptionMessage.FILE_NOT_FOUND_ON_S3);
}
}
위 코드에 한글 인코딩을 추가했다.
public void validateUploadedUrl() {
try {
URL url = new URL(uploadedUrl);
String encodedPath = encodePath(url.getPath());
URL encodedUrl = new URL(url.getProtocol(), url.getHost(), url.getPort(), encodedPath);
HttpURLConnection connection = (HttpURLConnection) encodedUrl.openConnection();
int responseCode = connection.getResponseCode();
if (responseCode != HttpURLConnection.HTTP_OK) {
throw new CustomException(ExceptionMessage.FILE_NOT_FOUND_ON_S3);
}
} catch (Exception e) {
throw new CustomException(ExceptionMessage.FILE_NOT_FOUND_ON_S3);
}
}
private String encodePath(String path) {
String[] segments = path.split("/");
StringBuilder encoded = new StringBuilder();
for (String segment : segments) {
if (!segment.isEmpty()) {
encoded.append("/")
.append(UriUtils.encodePathSegment(segment, StandardCharsets.UTF_8));
}
}
return encoded.toString();
}
위 코드로 하면 정상적으로 S3에 있는 url을 찾고 문제 생성까지 올바르게 됐다.
띄어쓰기 유무에 따라 인코딩 에러가 생긴다는게 이해가 가진 않았다. 일단 PR을 하고 천천히 찾아봐야겠다 생각했다.
다음날.. 멋진 스승님께서 친절히 정리해주셨다.

기존에 작성한 코드 중 HttpURLConnection은 인코딩 없이 보내고, AWS에서는 한글만 있는 파일명을 percent 인코딩을 하지 않는다. 공백의 경우는 AWS 서버 내부에서 인코딩을 처리해 에러가 나지 않는 것이다. (이 원인도 찾고 싶은데 그건 못찾겠다..)
또한 나는 URLEncoder가 %20이 아닌 +로 인코딩하길래 이를 UrlUtils로 변경했다. 그러나 위 S3 파일 명을 보면 AWS 내부 서버에서도 +로 변경함을 확인할 수 있다. 그래서
if (!segment.isEmpty()) {
encoded.append("/")
.append(UriUtils.encodePathSegment(segment, StandardCharsets.UTF_8));
}
해당 코드를
if (!segment.isEmpty()) {
encoded.append("/").append(URLEncoder.encode(segment, StandardCharsets.UTF_8));
}
다음과 같이 기존 URLEncoder로 변경했다.

띄어쓰기가 없는 한글 제목에 대해서 잘 작동함을 알 수 있다.
후기
이런 오류가 생길 것이라 생각도 하지 못했다. 띄어쓰기에 따라서 url을 찾을 수도 있고, 아닐 수도 있고.. 되게 재미있는 버그였다.
배포를 하니 이런 재미난 버그도 찾네. 발견하고 친절히 해당 파일까지 준 사용자한테 너무 감사하다.
이번에도 느낀 건데 나는 개발을 좋아하는거 같다. 빨리 개발자가 되어서 이런 버그 맨날맨날 찾고 싶다.
'개발 끄적끄적' 카테고리의 다른 글
| [Spring] Security - OAuth 2.0 (3) | 2025.08.01 |
|---|---|
| [GitHub Actions + AWS] IAM role 접근 권한에 따른 오류 해결 + GitHub Actions 성공 기준 (1) | 2025.07.15 |
| [GitHub Actions] 엑세스 키 없을 때 S3, Cloudfront 배포 자동화 (0) | 2025.07.12 |
| [AWS] AWS Certified Cloud Practitioner 자격증 취득 (0) | 2025.04.26 |
| [Python] embedded python 설치 및 c#에서 python process 돌리기 (0) | 2024.08.30 |