Skip to content
isdnetworks
Go back

이름만으로 판정하지 않은 파일

업로드된 파일을 저장할 때 이름이 겹치는지만 보고 겹치면 이름을 바꿔서 넣었다. 이름이 안 겹치는데도 같은 파일이 여러 벌씩 쌓이는 문제가 생겼다.

Table of contents

Open Table of contents

이름이 안 겹쳐도 겹치는 내용

버전이 붙은 이름과 최종이라는 이름으로 같은 문서가 여러 번 올라오고 있었다. 이름이 다르니 충돌 검사에 안 걸리고 전부 별개 파일로 들어갔다.

이름은 사용자가 정하는 값이고 같은 내용에 다른 이름을 붙이는 것을 막을 방법이 없다. 이름의 충돌과 내용의 중복은 서로 다른 문제였다.

내용 해시와 참조 분리

파일 내용의 해시를 계산해서 같은 것이 이미 있으면 새로 넣지 않고 기존 것을 가리키게 했다. 처음 돌렸을 때 4만 개 중 8천 개가 같은 내용이었다.

다만 전부 하나로 합치면 안 되는 경우가 있었는데 서로 다른 사용자가 같은 문서를 올린 자리였다. 실체는 하나만 두고 소유자별 참조를 여럿 두어서 마지막 참조가 사라질 때 실체를 지우게 했다.

확장자와 실제 내용의 불일치

내용 말고도 크기와 형식과 안전성을 봐야 했다. 특히 확장자가 문서인데 앞부분을 읽어 보면 실행 파일인 것이 섞여 있었다.

파일 앞부분의 서명을 읽어 확장자와 맞는지 비교하니 그런 것이 걸렸다. 이름이 무엇을 주장하는지와 내용이 무엇인지는 별개이므로 이름만 믿을 수 없었다.

싼 검사부터 두는 순서

검사를 크기와 확장자와 형식과 중복 순서로 배치했다. 앞의 둘은 목록 정보만 보면 되고 형식은 앞부분만 읽으면 되지만 중복 판정은 파일 전체를 읽어야 한다.

싼 것에서 걸리면 비싼 것을 하지 않아도 되므로 큰 파일에서 시간이 크게 갈렸다. 검사 순서를 비용순으로 두는 것만으로 전체 처리 시간이 눈에 띄게 줄었다.

옮겼다는 것과 저장됐다는 것은 다르다

옮기고 나서 실제로 존재하는지와 크기가 기대값과 맞는지를 다시 확인하게 했다. 디스크가 찼을 때 예외가 나지 않고 파일이 잘린 채로 옮겨진 적이 있었기 때문이다.

실패했을 때 임시 파일이 남아 며칠 만에 임시 폴더가 차는 문제도 있었다. 예외 처리에서 지우게 하되 프로세스가 죽으면 그것도 안 돌므로 오래된 임시 파일을 지우는 정리를 따로 뒀다.

저장 이름은 해시로 정하고 사용자가 올린 이름은 별도 값으로 담았다. 저장 이름을 우리가 정하니 경로 문자나 운영체제가 못 다루는 글자나 지나치게 긴 이름이 들어와도 문제가 되지 않았다.

정리


Share this post on:

Previous Post
착수 전에 미해결을 세어 본다
Next Post
다시 하려면 무엇이 0이어야 하나