모니터 크기에 맞춰 디자인한 반응형 웹사이트가 실제 모바일에서는 엉망으로 보인다. 미디어 쿼리 코드는 분명히 제대로 썼는데 왜 작동 안 할까. 대부분의 개발자들은 CSS 파일만 들었다 놨다 하면서 시간을 낭비한다. 실제로는 HTML 구조, 뷰포트 설정, CSS 캐싱, 선택자 우선순위 같은 여러 요인이 복합적으로 작용한다. 이번에는 미디어 쿼리가 작동하지 않는 진짜 원인을 찾아내고, 테스트 방법부터 완벽한 해결책까지 정리해서 소개하겠다.
미디어 쿼리 작동의 첫 번째 전제 조건은 뷰포트 메타 태그다. 이 태그가 없으면 모바일 브라우저는 데스크톱 크기(보통 980px)로 페이지를 렌더링한 다음 축소해서 보여준다. 그러면 당신의 @media (max-width: 768px)는 절대 작동하지 않는다.
✗ 잘못된 것. HTML의 <head> 섹션에 뷰포트 메타 태그가 없다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>내 사이트</title>
<!-- 뷰포트 태그 없음 -->
<link rel="stylesheet" href="style.css">
</head>
<body>...
✓ 올바른 것. 반드시 <head> 안에 뷰포트 메타 태그를 추가한다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>내 사이트</title>
<link rel="stylesheet" href="style.css">
</head>
<body>...
width=device-width는 페이지 폭을 기기의 실제 폭에 맞춘다. initial-scale=1.0은 처음 로드 시 확대/축소 없이 100% 크기로 표시한다는 뜻이다. 이것만으로도 대부분의 반응형 문제가 해결된다.
뷰포트 태그가 있는데도 미디어 쿼리가 안 되면, 문법 오류를 의심해야 한다. 개발자들이 가장 자주 하는 실수 5가지를 정리했다.
오류 1: min-width와 max-width 역순
모바일 우선 설계(Mobile First)에서는 기본 스타일을 먼저 쓰고 큰 화면용으로 min-width를 사용한다. 반대로 데스크톱 우선이면 max-width를 써야 한다. 순서를 뒤집으면 겹쳐서 작동 안 한다.
/* ✗ 잘못됨. max-width: 768px인데 또 min-width: 1200px을 쓰면 겹치지 않음 */
@media (max-width: 768px) {
body { font-size: 14px; }
}
@media (min-width: 768px) {
body { font-size: 16px; }
}
/* ✓ 올바름. 논리적 순서로 명확하게 분리 */
/* 모바일 기본 */
body { font-size: 14px; }
/* 768px 이상 */
@media (min-width: 768px) {
body { font-size: 16px; }
}
/* 1200px 이상 */
@media (min-width: 1200px) {
body { font-size: 18px; }
}
오류 2: 쉼표 누락 또는 중복
여러 조건을 OR로 연결할 때는 쉼표를 쓴다. 괄호 안에 쉼표를 쓰면 문법 오류가 된다.
/* ✗ 잘못됨. 괄호 안에 쉼표가 있으면 문법 오류 */
@media (max-width: 768px, max-height: 600px) {
body { color: red; }
}
/* ✓ 올바름. 괄호 밖에 쉼표를 쓴다 */
@media (max-width: 768px), (max-height: 600px) {
body { color: red; }
}
/* ✓ 올바름. AND 조건은 and 키워드를 쓴다 */
@media (max-width: 768px) and (min-height: 600px) {
body { color: red; }
}
오류 3: 단위 빠뜨림
768만 쓰면 안 되고, 반드시 768px 같이 단위를 붙여야 한다.
/* ✗ 잘못됨. 단위 없음 */
@media (max-width: 768) {
body { color: red; }
}
/* ✓ 올바름. 단위를 붙인다 */
@media (max-width: 768px) {
body { color: red; }
}
HTML에서 CSS 파일을 링크할 때도 주의할 점이 있다. 뷰포트 설정과 마찬가지로, 많은 개발자들이 놓친다.
✗ 잘못된 것. CSS 파일에 미디어 쿼리가 있는데 link 태그에 media 속성을 잘못 썼다.
<link rel="stylesheet" href="style.css" media="print">
<!-- 이렇게 쓰면 프린트할 때만 적용되고 화면에는 안 됨 -->
✓ 올바른 것. 일반적인 경우 media 속성을 쓰지 않거나 screen을 명시한다.
<link rel="stylesheet" href="style.css">
<!-- 또는 명시적으로 -->
<link rel="stylesheet" href="style.css" media="screen">
개발자 도구를 열어서 Network 탭을 보면 CSS 파일이 제대로 로드되었는지 확인할 수 있다. 404 에러가 뜨면 경로를 확인하자.
미디어 쿼리 코드가 맞아도 인라인 스타일이나 더 높은 우선순위의 선택자가 있으면 덮어씌워진다.
✗ 잘못된 것. HTML에 인라인 스타일이 있으면 미디어 쿼리가 무시된다.
<div style="width: 100%; color: blue;">...</div>
<!-- CSS 파일 -->
<style>
@media (max-width: 768px) {
div { color: red; } /* 인라인 스타일에 밀려서 작동 안 함 */
}
</style>
✓ 올바른 것. !important를 써서 우선순위를 강제한다(단, 과용은 금지).
@media (max-width: 768px) {
div { color: red !important; } /* 인라인 스타일도 무시 */
}
일반적으로는 HTML에서 인라인 스타일을 제거하는 게 가장 깔끔하다. CSS 캐시도 브라우저 개발자 도구(F12)에서 캐시 비우기로 확인해보자.
개발 단계에서는 브라우저 창 크기를 줄여도 잘 작동한다. 하지만 실제 모바일 기기에서는 다를 수 있다. 정확한 테스트 방법을 정리했다.
방법 1: 브라우저 개발자 도구 Device Emulation
Chrome, Firefox, Safari 모두 F12를 눌러 개발자 도구를 열고, 기기 토글 버튼(또는 Ctrl+Shift+M)을 눌러 모바일 뷰를 켠다. iPhone 12, Galaxy S10 등 실제 기기 해상도로 테스트할 수 있다.
방법 2: 실제 모바일 기기에서 테스트
개발 PC의 IP 주소를 알아낸 다음 모바일에서 그 IP로 접속한다. 예를 들어 개발 서버가 localhost:8000에서 돌고 있다면, 실제 모바일에서는 http://192.168.1.100:8000처럼 접속한다. 이 방식이 가장 정확하다.
방법 3: 온라인 반응형 테스트 도구
Responsively App, BrowserStack 같은 도구를 쓰면 다양한 기기를 한 화면에서 동시에 테스트할 수 있다.
지금까지 배운 모든 내용을 포함한 완벽한 예제를 만들어봤다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>반응형 웹사이트</title>
<style>
/* 모바일 기본 스타일 */
body {
margin: 0;
padding: 16px;
font-size: 14px;
background-color: #f5f5f5;
}
.container {
max-width: 100%;
background-color: white;
padding: 20px;
border-radius: 8px;
}
h1 {
font-size: 20px;
color: #333;
}
/* 테블릿 (768px 이상) */
@media (min-width: 768px) {
body {
padding: 24px;
font-size: 15px;
}
.container {
max-width: 750px;
margin: 0 auto;
}
h1 {
font-size: 28px;
}
}
/* 데스크톱 (1200px 이상) */
@media (min-width: 1200px) {
body {
padding: 32px;
font-size: 16px;
}
.container {
max-width: 1140px;
}
h1 {
font-size: 36px;
}
}
</style>
</head>
<body>
<div class="container">
<h1>반응형 웹사이트</h1>
<p>이 페이지는 모든 크기의 기기에서 제대로 표시됩니다.</p>
</div>
</body>
</html>
이 코드에서는 모바일 우선 설계를 따르고, 뷰포트 메타 태그도 있고, 미디어 쿼리 문법도 정확하다. 개발자 도구에서 기기별로 테스트해보면 폰트 크기와 여백이 각각 변하는 것을 확인할 수 있다.
| 문제 | 해결 방법 |
|---|---|
| 모바일에서도 데스크톱 크기로 보임 | 뷰포트 메타 태그 추가 |
| 미디어 쿼리를 써도 반응 없음 | 문법 확인(단위, 쉼표, and/or) |
| 특정 스타일만 작동 안 함 | 인라인 스타일이나 우선순위 확인 |
| 개발자 도구에서는 되는데 폰에서 안 됨 | 캐시 삭제 또는 실제 기기 IP 접속 |
| 미디어 쿼리가 겹쳐서 엉망 | min-width 범위를 명확히 분리 |
CSS 미디어 쿼리는 반응형 웹의 핵심이다. 단 한 줄의 뷰포트 메타 태그 누락이 모든 노력을 물거품으로 만들 수 있다는 점을 절대 잊으면 안 된다. 이 글에서 배운 뷰포트 설정부터 미디어 쿼리 문법, 우선순위까지 5단계를 차례대로 점검하면, 대부분의 반응형 문제를 스스로 해결할 수 있을 것이다. 지금 바로 진행 중인 프로젝트의 HTML head 섹션을 열어서 뷰포트 메타 태그부터 확인해보자.