MIME 타입이란 무엇인가 - 브라우저가 파일 형식을 구분하는 원리와 오류 해결법
자바스크립트가 실행되지 않고 이미지가 다운로드되는 이유, 대부분 MIME 타입 문제입니다. Content-Type의 구조부터 자주 쓰는 타입 정리표, 실무에서 만나는 오류 해결법까지 한번에 정리했습니다.
![]()
웹사이트에 분명히 자바스크립트 파일을 올렸는데 브라우저가 실행을 거부하거나, 이미지를 클릭했더니 화면에 뜨지 않고 다운로드 창이 열리는 경험을 해보셨을 겁니다. 이런 문제의 원인은 대부분 MIME 타입 설정에 있습니다. MIME 타입이란 웹에서 주고받는 파일의 형식을 알려주는 표준 식별자로, 브라우저가 파일을 어떻게 처리할지 결정하는 기준입니다. 개념만 정확히 잡아두면 콘솔에 뜨는 낯선 오류의 절반은 원인을 바로 짚을 수 있습니다.
MIME 타입이란 무엇인가
MIME은 Multipurpose Internet Mail Extensions의 약자입니다. 이름 그대로 원래는 이메일을 위해 만들어진 표준입니다. 1990년대 초까지 이메일은 7비트 영문 텍스트만 전송할 수 있었는데, 이미지나 첨부파일 같은 바이너리 데이터를 보내기 위해 1992년 처음 표준화된 것이 MIME입니다. 현재는 RFC 2045와 RFC 2046이 기본 규격입니다.
이때 바이너리 데이터를 텍스트로 바꾸는 데 사용된 것이 base64 인코딩입니다. base64는 데이터를 64진법 기반의 문자 64개로 표현하는 방식인데, 2진수와 16진수 같은 진법 개념이 낯설다면 진법 변환기에서 직접 숫자를 변환해 보면 원리를 이해하는 데 도움이 됩니다.
이후 MIME 타입은 웹으로 확장되었습니다. 웹 서버는 파일을 전송할 때 HTTP 응답 헤더의 Content-Type 필드에 MIME 타입을 담아 보내고, 브라우저는 이 값을 보고 화면에 렌더링할지, 실행할지, 다운로드할지를 결정합니다.
브라우저는 파일 확장자가 아니라 서버가 보내는 MIME 타입을 기준으로 파일을 처리합니다. 확장자가 .js여도 서버가 text/html로 응답하면 브라우저는 그 파일을 자바스크립트로 실행하지 않습니다.
타입과 서브타입 - MIME 타입의 구조
MIME 타입은 슬래시(/)를 사이에 둔 타입/서브타입 두 부분으로 구성됩니다. 예를 들어 image/png에서 image는 큰 분류, png는 세부 형식입니다. 주요 타입은 다음과 같습니다.
- text: 사람이 읽을 수 있는 텍스트. text/html, text/css, text/plain 등
- image: 정지 이미지. image/png, image/jpeg, image/webp 등
- audio, video: 소리와 영상. audio/mpeg, video/mp4 등
- application: 특정 프로그램이 처리하는 데이터. application/json, application/pdf, application/zip 등
- multipart: 여러 데이터를 하나로 묶은 형식. 파일 업로드에 쓰이는 multipart/form-data가 대표적입니다
text/html; charset=UTF-8처럼 세미콜론 뒤에 문자 인코딩 같은 매개변수를 덧붙일 수도 있습니다.
자주 쓰이는 MIME 타입 정리표
실무에서 자주 만나는 확장자와 MIME 타입을 정리했습니다. 이 표만 알아도 웹 개발에서 마주치는 상황의 대부분을 처리할 수 있습니다.
| 확장자 | MIME 타입 | 설명 |
|---|---|---|
| .html | text/html | 웹 문서 |
| .css | text/css | 스타일시트 |
| .js | text/javascript | 자바스크립트 |
| .json | application/json | 데이터 교환 형식 |
| .png | image/png | 무손실 압축 이미지 |
| .jpg | image/jpeg | 손실 압축 사진 |
| .webp | image/webp | 웹 최적화 이미지 |
| .svg | image/svg+xml | 벡터 이미지 |
| .mp4 | video/mp4 | 동영상 |
| application/pdf | 문서 | |
| .zip | application/zip | 압축 파일 |
| 알 수 없음 | application/octet-stream | 정체불명의 바이너리. 브라우저는 다운로드 처리 |
자바스크립트는 오랫동안 application/javascript와 text/javascript가 혼용되었는데, 2022년 발표된 RFC 9239에서 text/javascript가 공식 타입으로 확정되었습니다. 요즘 만들어지는 서버와 프레임워크는 대부분 이 기준을 따릅니다.
내 사이트의 MIME 타입 확인하는 방법
브라우저 개발자 도구
크롬에서 F12를 눌러 개발자 도구를 열고 Network 탭으로 이동한 뒤 페이지를 새로고침합니다. 확인하고 싶은 리소스를 클릭하면 Response Headers 영역에서 Content-Type 값을 바로 볼 수 있습니다.
curl 명령어
터미널에서 curl -I https://내도메인/파일경로를 입력하면 응답 헤더만 빠르게 확인할 수 있습니다. 서버 설정을 바꾼 직후 브라우저 캐시의 영향 없이 결과를 검증할 때 특히 유용합니다.
X-Content-Type-Options: nosniff를 추가하면 브라우저가 MIME 타입을 임의로 추측(스니핑)하는 동작을 막을 수 있습니다. 업로드된 파일이 의도치 않게 스크립트로 실행되는 보안 사고를 예방하는 기본 설정이므로 꼭 적용하는 것이 좋습니다.자주 만나는 MIME 타입 오류와 해결법
브라우저 콘솔에서 만나는 대표적인 오류와 원인은 다음과 같습니다.
- Expected a JavaScript module script but the server responded with a MIME type of text/html: SPA에서 존재하지 않는 js 경로 요청이 index.html로 대체 응답되는 경우가 대부분입니다. 빌드 산출물 경로와 배포 경로가 일치하는지 먼저 확인합니다
- Refused to apply style because its MIME type is not text/css: CSS 파일 경로가 잘못되었거나 서버가 text/css로 응답하지 않는 경우입니다
- 이미지나 폰트가 화면에 뜨지 않고 다운로드됨: 서버가 해당 확장자의 MIME 타입을 몰라 application/octet-stream으로 응답하는 경우입니다
해결 방법은 서버 설정에 올바른 매핑을 추가하는 것입니다. nginx는 mime.types 파일에서, Apache는 AddType 지시어로 확장자와 MIME 타입을 연결합니다. 예를 들어 nginx에서 webp 이미지가 자꾸 다운로드된다면 mime.types에 image/webp webp; 한 줄을 추가하고 재시작하면 됩니다.
파일 업로드 기능을 직접 만든다면 확장자만 믿지 말고 서버에서 MIME 타입과 실제 파일 시그니처를 함께 검증해야 안전합니다. 이때 업로드 용량 제한은 바이트 단위로 지정하는 경우가 많아 10MB가 10,485,760바이트라는 식의 계산이 필요한데, 숫자가 헷갈린다면 단위 변환기 같은 도구로 확인하면 실수를 줄일 수 있습니다.
핵심 정리와 지금 할 일
MIME 타입은 웹에서 파일의 신분증 역할을 합니다. 브라우저는 확장자가 아니라 Content-Type 헤더를 믿는다는 것, 그리고 오류가 나면 실제 응답 헤더부터 확인한다는 것. 이 두 가지만 기억해도 문제 해결 속도가 크게 빨라집니다.
지금 바로 할 수 있는 액션 두 가지를 제안합니다. 첫째, 운영 중인 사이트가 있다면 개발자 도구 Network 탭에서 주요 리소스의 Content-Type이 위 표와 일치하는지 점검해 보세요. 둘째, 응답 헤더에 X-Content-Type-Options: nosniff가 없다면 오늘 추가해 두세요. 5분이면 끝나는 작업이지만 보안과 안정성에서 확실한 차이를 만듭니다.