웹 애플리케이션에서 파일 업로드는 흔하게 사용되는 기능이지만, 보안 취약점이 존재할 수 있습니다. 특히 이미지 파일 업로드 시, 단순히 확장자만 확인하는 방식은 보안상 매우 위험할 수 있습니다. 이번 글에서는 Spring에서 MultipartFile을 사용할 때 이미지 파일의 MIME 타입을 검증하는 방법과, 이를 실제 프로젝트에서 어떻게 적용했는지에 대해 다루겠습니다.
일반적으로 우리는 업로드된 파일이 .jpg, .png 등의 확장자를 가지고 있다면 이미지를 예상합니다. 그러나 클라이언트는 확장자를 쉽게 조작할 수 있기 때문에, 확장자만으로 파일을 판단하는 방식은 보안상 취약점이 될 수 있습니다.
예를 들어, .jpg 확장자를 가진 .exe 파일을 업로드한다고 가정해봅시다.
서버에서는 이를 이미지 파일로 착각하고 처리하게 되며, 이때 악성 코드가 실행될 위험이 존재합니다.
따라서 필요한 것이 바로 MIME 타입(Content-Type) 검사입니다. MIME 타입은 브라우저나 클라이언트가 해당 파일을 전송할 때 포함하는 "실제 파일의 형식"을 나타냅니다.
먼저, 우리가 허용할 이미지의 MIME 타입을 정의해야 합니다. 이미지 파일에 대한 허용된 MIME 타입 목록을 아래와 같이 설정할 수 있습니다.

이제, 업로드된 파일이 올바른 MIME 타입을 가지고 있는지 확인하는 메서드를 작성합니다.

위 코드에서 중요한 점은, 파일이 null이거나 비어 있는 경우에는 검사를 생략하는 부분입니다. 필수 이미지가 아닌 경우에는 유연하게 처리할 수 있도록 했습니다.
이제 이 검사 로직을 실제 서비스에 적용해보겠습니다. 이미지를 업로드할 때, 이미지의 MIME 타입을 확인한 후 유효하지 않으면 예외를 던지고, 유효한 경우에만 S3에 업로드하도록 합니다.

이미지가 유효하지 않으면 커스텀 예외를 던지고, 유효할 경우에만 S3에 업로드됩니다.
저는 처음에 파일의 확장자만 확인하는 방식으로 구현했었습니다. 예를 들어, .jpg나 .png 파일만 허용하는 방식이었죠. 그런데 실제로 .exe 파일을 파일명.jpg로 이름만 바꿔서 업로드해본 결과, 서버에서는 정상적인 이미지 파일로 처리하고 업로드까지 되는 걸 확인할 수 있었습니다.
예시: virus.exe → fake.jpg로 파일명만 변경 후 업로드
이때 느낀 점은 "확장자만으로는 충분히 안전하지 않다"는 것이었습니다. 따라서 MIME 타입 검사를 도입하게 되었습니다.
이미지 파일을 업로드하는 컨트롤러 부분도 아래와 같이 작성할 수 있습니다. 멀티파트 폼 데이터를 처리하면서, 이미지 파일의 MIME 타입을 검증한 후 업로드합니다.

위 코드에서 @RequestPart를 활용하여 JSON 데이터와 이미지 파일을 함께 처리하고, MIME 타입 검증을 거친 후에 업로드합니다.
파일 업로드 기능에서 보안을 강화하려면 단순한 확장자 검사만으로는 부족합니다.
MIME 타입(Content-Type)을 통해 보다 정확하고 안전하게 파일을 검증할 수 있습니다. 또한, MIME 타입 검사를 위한 유틸 클래스를 만들어두면 여러 곳에서 재사용이 가능하고 유지보수도 쉬워집니다.
파일 업로드 기능에서 보안을 강화하는 방법을 소개드렸습니다. 이처럼 작은 보안 점검을 추가하는 것만으로도 사용자에게 보다 신뢰할 수 있는 웹 애플리케이션을 제공할 수 있습니다.