: (Multipurpose Internet Mail Extensions Type)
인터넷에서 파일 형식을 식별하는 표준 방식
text/html (HTML 문서)
image/png (PNG 이미지)
application/json (JSON 데이터)
- extension & mimetype
https://developer.mozilla.org/ko/docs/Web/HTTP/Guides/MIME_types/Common_types
:HTTP에서 사용되는 헤더 필드로, 응답 본문의 MIME 타입을 지정
클라이언트(브라우저 등)가 데이터를 해석하는 방법을 결정하는 데 사용
Content-Type: text/html; charset=UTF-8
Content-Type: text/html; charset=UTF-8
avif 파일을 확장자 변조 후 업로드했다. avif 파일을 jpeg으로 인식하게 되었고, 파일 유형을 잘못 파악했기 때문에문제가 발생했다.mimetype값을 파일의 버퍼값을 기반으로 계산하면 위와 같은 확장자 변조 문제를 해결할 수 있다.<input type="file">
위 코드를 사용할 때 브라우저가 mimetype을 자동으로 설정하는데, AVIF가 정확히 지원되지 않으면 JPEG으로 처리할 가능성이 있다.
우리는 NestJs 공식문서에서 제안한 방식대로 파일을 업로드받고 있었고
@Post('upload')
@UseInterceptors(FileInterceptor('file'))
uploadFile(@UploadedFile() file: Express.Multer.File) {
console.log(file);
}
Express.Multer.File.mimetype에는 잘못된 mimetype이 들어있었다. 이게 문제가 되어서 magic number로 구분하는 방식을 서치하게 된것이다.
- file magic number
https://en.wikipedia.org/wiki/List_of_file_signatures
위의 링크에 들어가면 파일 확장자 별로 바이트(=magic number)가 정리되어있다.

파일의 버퍼에
0xFF, 0xD8, 0xFF
가 포함되어있으면 그 파일을 jpeg으로 판단할 수 있다.
몇가지 파일 유형 검사만 필요한 경우에는 직접 구현하는것이
외부 라이브러리의 의존성을 낮춰 장점이 될 수 있으나
파일 유형도 다양하고 예외의 경우가 많기때문에 사실은 라이브러리를 사용하는 것을 추천한다.
import {fileTypeFromBuffer} from 'file-type';
await fileTypeFromBuffer(buffer);
사용법이 굉장히 간단하고 입력값으로 버퍼와 파일을 모두 지원한다.
mime-types 라이브러리도 테스트해봤는데 위에서 언급한 확장자 변조 파일을(.heic) jpeg으로 판단했다.
- file-type는 이번에 처음사용해봤는데 npm 다운로드 수를 보면 믿을만 한것 같다.
- (레포 구경하다가 이 패키지 만든 사람이 awesome 만든사람이랑 동일인물인걸 알게됐다.)
사용법은 너무나도 간단했으나 패키지 설치과정에서 문제가 생겼다.
npm file-type Error: No "exports" main defined
우리 프로젝트는 기존에 NestJs commonJs 방식을 사용하고 있었기때문에
해당 패키지를 설치하니 다음과 같은 에러가 발생했다.
⭕️ESM 방식에서는 CJS방식의 모듈을 사용할수있지만
❌CJS 방식에서는 ESM방식의 모듈을 사용할 수 없었다.
file-type 레포의 이슈에서 해결방법을 찾기는 했으나 우리의 상황에서는 ESM으로 전환해도 큰 문제가 없다고 생각해 업그레이드 했다.
- CommonJs 모듈 시스템 프로젝트에서 file-type 패키지 사용법
https://github.com/sindresorhus/file-type/issues/661#issuecomment-2314845720
(참고로 저 에러메시지만 쳐도 file-type이 자동완성으로 뜰 정도였다ㅋㅋㅠㅠ)