JavaScript / matchMedia()로 미디어 쿼리 검사와 변경 감지하기
window.matchMedia()는 CSS 미디어 쿼리를 JavaScript에서 검사해 현재 문서가 조건에 맞는지 알려줍니다. 반환되는 MediaQueryList의 matches로 현재 상태를 읽고, change 이벤트로 조건이 바뀔 때 대응합니다. 단순히 모양만 바꿀 목적이라면 CSS @media 규칙을 사용하세요.
미디어 쿼리와 matches 읽기
함수에는 CSS에서 쓰는 미디어 쿼리 문자열을 전달합니다. 예를 들어 (min-width: 600px)는 문서 뷰포트 너비가 600 CSS 픽셀 이상인지 검사합니다. media는 쿼리 문자열을 나타내고, matches는 현재 판정의 불리언 값입니다. 모니터의 전체 너비가 아니라 해당 브라우저 문서가 놓인 뷰포트 조건을 검사합니다.
const query = window.matchMedia('(min-width: 600px)');
console.log(query.media); // '(min-width: 600px)'
console.log(query.matches); // 현재 뷰포트가 600px 이상이면 true
위 코드는 그 줄이 실행된 시점의 결과를 읽습니다. 처음 한 번만 읽어서 변수에 저장하면 창 크기를 바꾼 뒤 표시가 자동으로 갱신되지는 않습니다. MDN의 Window.matchMedia() 문서에서 반환 객체와 검사 방식을 확인할 수 있습니다.
조건이 바뀔 때 change 이벤트 받기
화면이 경계를 넘는 순간을 따라가려면 반환 객체에 addEventListener("change", handler)를 등록하세요. 이벤트의 matches에는 바뀐 조건의 결과가 들어 있습니다. 이벤트는 너비가 한 픽셀씩 달라질 때마다 항상 발생하는 것이 아니라 미디어 쿼리의 참·거짓이 바뀔 때 발생합니다.
const query = window.matchMedia('(min-width: 600px)');
function update(matches) {
console.log(matches ? '넓은 화면' : '좁은 화면');
}
update(query.matches); // 최초 상태
query.addEventListener('change', event => update(event.matches));
페이지에 들어왔을 때 이미 조건에 맞아도 change 이벤트가 먼저 발생하지는 않습니다. 최초 상태를 한 번 읽고, 이후 변화를 구독하는 두 단계를 모두 넣으세요. MDN의 MediaQueryList change 이벤트 문서를 참고하세요.
CSS와 JavaScript의 역할 구분하기
글자 크기, 여백, 표시 여부 등 화면 표현은 CSS @media만으로 처리하는 편이 간단합니다. JavaScript는 상태 문구를 갱신하거나 다른 동작을 실행해야 할 때 사용합니다. 같은 경계를 두 곳에 적으면 서로 다른 값으로 바뀌기 쉬우므로 600px 같은 기준을 함께 관리하세요.
#panel { background: #e8f4ff; }
@media (min-width: 600px) {
#panel { background: #e6f4e9; }
}
과거 예제의 MediaQueryList.addListener()는 호환 목적의 오래된 메서드입니다. 현재 브라우저를 대상으로 새 코드를 작성할 때는 addEventListener("change", ...)를 사용하고, 아주 오래된 브라우저 지원이 계약상 필요한 경우에만 해당 환경의 호환성을 따로 점검하세요.
전체 예제: 600px 경계를 넘겨 보기
아래 코드를 UTF-8로 match-media.html에 저장해 브라우저에서 엽니다. 창의 가로 너비를 600px보다 좁게, 그 다음 넓게 바꾸세요. CSS는 상자 배경을, JavaScript는 상태 문구와 경계 통과 횟수를 갱신합니다.
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>matchMedia 화면 너비 확인</title>
<style>
body { margin: 24px; font: 16px/1.6 sans-serif; }
#panel { padding: 20px; background: #e8f4ff; }
@media (min-width: 600px) {
#panel { background: #e6f4e9; }
}
</style>
</head>
<body>
<h1>화면 너비 비교</h1>
<p>브라우저 창 너비를 600px 경계 양쪽으로 바꾸세요.</p>
<div id="panel">CSS도 같은 600px 기준으로 이 상자의 배경을 바꿉니다.</div>
<p>JavaScript 판정: <strong id="state" aria-live="polite"></strong></p>
<p>경계를 넘은 횟수: <span id="changes">0</span></p>
<script>
const query = window.matchMedia('(min-width: 600px)');
const state = document.querySelector('#state');
const changes = document.querySelector('#changes');
let changeCount = 0;
function render() {
state.textContent = query.matches ? '넓은 화면 (600px 이상)' : '좁은 화면 (600px 미만)';
changes.textContent = String(changeCount);
}
query.addEventListener('change', () => {
changeCount += 1;
render();
});
render();
</script>
</body>
</html>
600px 미만이면 상자는 옅은 파란색이고 상태는 ‘좁은 화면’입니다. 600px 이상에서는 옅은 녹색과 ‘넓은 화면’이 보입니다. 같은 쪽에서 너비를 조금 바꿔도 통과 횟수는 늘지 않고, 경계를 넘을 때만 1씩 늘어야 합니다. 개발자 도구의 반응형 화면 모드에서 뷰포트 너비를 지정하면 경계값도 정확히 시험할 수 있습니다.




