Responsive web design

김동현·2026년 3월 18일

mdn 학습 번역 - CSS

목록 보기
28/190

안녕하세요! 프론트엔드 개발의 세계로 오신 것을 환영합니다. 오늘 다룰 주제는 현대 웹 개발에서 숨 쉬는 것만큼이나 당연하고 중요한 개념인 반응형 웹 디자인(Responsive Web Design, RWD)입니다.

모바일, 태블릿, 거대한 데스크톱 모니터까지 사용자들이 웹사이트를 보는 화면 크기가 정말 천차만별인 요즘, 하나의 코드로 모든 기기에서 아름답게 보이게 만드는 이 마법 같은 기술을 공식 문서를 통해 차근차근 번역해 드리겠습니다. 제가 실무에서 겪은 생생한 팁들도 팍팍 넣어드릴 테니 기대해 주세요!


반응형 웹 디자인 (Responsive web design)

반응형 웹 디자인(RWD)은 훌륭한 사용성(usability)을 보장하면서, 모든 화면 크기와 해상도에서 웹 페이지가 잘 렌더링 되도록 만드는 웹 디자인 접근 방식입니다. 다중 기기(multi-device) 시대의 웹을 디자인하기 위한 필수적인 방법이죠. 이 문서에서는 반응형 웹 디자인을 마스터하기 위해 사용할 수 있는 여러 테크닉들을 이해할 수 있도록 도와드리겠습니다.

선행 조건 (Prerequisites):HTML로 콘텐츠 구조화하기, CSS 스타일링 기초, 기본적인 텍스트와 폰트 스타일링, 그리고 CSS 레이아웃 기초 개념에 대한 친숙함.
학습 목표 (Learning outcomes):
  • 반응형 디자인이란 무엇인가 — 다양한 기기의 화면 크기, 해상도 등에서 유연하게 잘 작동하도록 웹 레이아웃을 디자인하는 것.
  • 그리드(Grid)나 플렉스박스(Flexbox) 같은 모던 레이아웃 도구들과 반응형 디자인 사이의 관계.
  • 모바일 퍼스트(mobile-first)와 중단점(breakpoints)을 포함하여, 반응형 디자인에 미디어 쿼리를 사용하는 배경 개념.
  • 모바일 기기에서 웹 문서가 적절하게 표시되기 위해 왜 <meta viewport=""> 태그가 꼭 필요한지 알아보기.

반응형 디자인의 전신: 모바일 웹 디자인 (Precursor to responsive design: mobile web design)

반응형 웹 디자인이 다양한 기기 유형에서 웹사이트를 작동하게 만드는 표준적인 접근법이 되기 전에는, 웹 개발자들이 모바일 웹 디자인(mobile web design), 모바일 웹 개발(mobile web development), 또는 때때로 모바일 친화적 디자인(mobile-friendly design)이라는 용어를 쓰곤 했습니다. 사실 목표는 반응형 웹 디자인과 본질적으로 같습니다. 즉, 다양한 물리적 속성(화면 크기, 해상도)을 가진 기기들 전반에 걸쳐 레이아웃, 콘텐츠(텍스트 및 미디어), 그리고 성능 면에서 웹사이트가 원활하게 작동하도록 만드는 것이죠.

하지만 반응형 웹 디자인과 과거의 모바일 웹 디자인의 차이점은 주로 관련된 기기들해결책을 만드는 데 사용 가능한 기술들에 있습니다:

  • 예전에는 '데스크톱이냐 모바일이냐' 이분법적으로 이야기했지만, 지금은 데스크톱, 노트북, 모바일, 태블릿, 스마트워치 등 정말 다양한 유형의 기기들이 존재합니다. 과거처럼 서너 가지 화면 크기만 신경 쓰는 대신, 이제는 흔히 쓰이는 화면 크기와 해상도뿐만 아니라 '아직 알 수 없는 미지의 기기'들까지 커버할 수 있도록 방어적으로(defensively) 사이트를 디자인해야 합니다.
  • 과거의 모바일 기기들은 CPU/GPU 성능이나 사용 가능한 네트워크 대역폭(인터넷 속도) 면에서 몹시 열악했습니다. 일부 기기는 CSS나 심지어 HTML조차 제대로 지원하지 않았죠. 그래서 과거에는 사용자가 접속했을 때 서버 측에서 브라우저 스니핑(browser sniffing, 접속한 기기가 뭔지 몰래 알아내는 기술)을 수행하여 기기나 브라우저 유형을 판단한 다음, 그 기기가 감당할 수 있는 전용 사이트(예: m.naver.com 같은 모바일 전용 사이트)를 따로 서비스하는 것이 일반적이었습니다. 모바일 기기들이 감당할 수 있는 게 그것뿐이었기 때문에 아주 단순하고 기본적인 형태의 경험만 제공받았죠. 요즘 모바일 기기들은 데스크톱 컴퓨터와 똑같은 웹 기술들을 거뜬히 처리할 수 있기 때문에, 그런 옛날 방식은 이제 거의 쓰이지 않습니다.
    • 그렇다고 방심하면 안 됩니다! 여전히 배터리 수명이나 데이터 요금(대역폭) 같은 제약 사항들을 고려해야 하므로, 이 문서에서 다루는 테크닉들을 사용해 모바일 사용자에게 적합한 경험을 제공해야 합니다.
    • 사용자 경험(UX) 또한 여전히 중요한 고민거리입니다. 예를 들어 여행 사이트에 접속한 모바일 사용자는 당장 비행기 시간이나 지연 정보 정도만 확인하고 싶어 할 텐데, 화면 가득 비행경로를 보여주는 화려한 3D 애니메이션 지구본이나 회사 연혁 따위를 보여주는 것은 적절하지 않겠죠.
  • 현대의 웹 기술들은 반응형 경험을 만드는 데 훨씬 더 강력합니다. 예를 들어, 이제는 서버 측 스니핑 같은 꼼수에 의존하지 않고도, 반응형 이미지/미디어 기술들을 사용해 다양한 기기에 알아서 가장 적절한 미디어를 제공할 수 있게 되었습니다.

반응형 웹 디자인 소개 (Introducing responsive web design)

HTML은 그 자체로 근본적으로 반응형이며, 유동적(fluid)입니다. 만약 여러분이 CSS를 단 한 줄도 쓰지 않고 오직 HTML만으로 웹 페이지를 만든 뒤 브라우저 창 크기를 조절해 본다면, 브라우저는 뷰포트(화면) 너비에 맞춰 텍스트를 자동으로 줄 바꿈(reflow)하여 화면에 꽉 차게 보여줄 것입니다.

이 기본 반응형 동작만 들으면 굳이 무슨 해결책이 더 필요할까 싶겠지만, 넓은 모니터에서 텍스트가 한 줄로 끝없이 길게 이어지면 눈으로 읽기가 매우 힘들어집니다. 이 문제는 CSS를 써서, 예를 들어 좁은 단(column)을 만들어 텍스트의 줄 길이를 제한하는 식으로 해결할 수 있죠. 하지만 고정된 단을 만들어 버리면, 사용자가 브라우저 창을 좁게 줄이거나 모바일 기기에서 사이트를 볼 때 새로운 문제가 발생합니다. 단들이 찌그러지고 뭉개져서 글씨를 읽기가 훨씬 더 힘들어지는 것이죠.

두 개의 단으로 나뉜 레이아웃이 모바일 크기의 좁은 뷰포트에 억지로 우겨넣어져서 글씨가 심하게 찌그러지고 읽기 힘든 모습의 일러스트입니다.

그렇다고 요소에 고정된 너비(fixed width, 예: width: 800px)를 지정해서 크기가 변하지 않는 뻣뻣한 웹 페이지를 만드는 것 역시 해결책이 될 수 없습니다. 그렇게 하면 좁은 모바일 화면에서는 짜증 나는 가로 스크롤바가 생기고, 넓은 모니터에서는 양옆으로 텅 빈 여백이 너무 많이 남게 되니까요.

반응형 웹 디자인(RWD)은 시중에 존재하는 모든 범위의 기기와 화면 크기를 대응하는 디자인 접근법입니다. 태블릿, 폰, 텔레비전, 심지어 스마트워치에서 콘텐츠를 보든 간에 화면에 맞춰 자동으로 적응(adaption)할 수 있게 해 주죠.

반응형 웹 디자인은 어떤 특정한 '신기술' 하나를 지칭하는 것이 아니라 접근 방식(approach)입니다. 콘텐츠를 보는 데 사용되는 그 어떤 기기에든 반응(respond)할 수 있는 레이아웃을 만들기 위해 사용되는 일련의 모범 사례(best practices)들을 설명하는 용어죠.

반응형 디자인(responsive design)이라는 용어는 2010년 Ethan Marcotte가 처음 만들었으며, 반응형 콘텐츠를 만들기 위해 유동적 그리드(fluid grids), 유동적 이미지(fluid images), 그리고 미디어 쿼리(media queries)를 사용하는 방식을 설명했습니다.

당시에는 레이아웃을 잡기 위해 CSS float을 사용하고, 브라우저의 너비를 확인하여 다양한 중단점(breakpoints)마다 각기 다른 레이아웃을 만들어내기 위해 미디어 쿼리를 사용하는 것이 권장사항이었습니다. 유동적 이미지는 자신을 감싸는 컨테이너의 너비를 절대 넘지 않도록, max-width 속성을 100%로 설정하여 구현했습니다. 이렇게 하면 유동적 이미지는 컨테이너 열(column)이 좁아질 때 알아서 크기가 줄어들지만, 컨테이너가 커지더라도 자신의 원래(고유) 크기보다 더 크게 늘어나지는 않습니다. 덕분에 이미지가 화면 밖으로 넘치지 않게 줄어들면서도, 컨테이너가 넓어졌다고 해서 이미지가 강제로 늘어나 픽셀이 깨지는(pixelated) 현상을 막을 수 있었죠.

현대의 CSS 레이아웃 방식들은 기본적으로 반응형을 내포하고 있으며, Marcotte의 글이 발표된 이후로 웹 플랫폼 자체에도 반응형 사이트를 더 쉽게 디자인할 수 있도록 수많은 기능이 내장되었습니다.

이 문서의 나머지 부분에서는 반응형 사이트를 만들 때 여러분이 사용하게 될 다양한 웹 플랫폼의 기능들을 설명해 드리겠습니다.


미디어 쿼리 (Media Queries)

미디어 쿼리(Media queries)를 사용하면 일련의 테스트(예를 들어, 사용자의 화면이 특정 너비보다 넓은지, 해상도가 어떤지 등)를 실행한 뒤, 사용자의 환경에 알맞게 페이지 스타일을 지정하도록 특정 CSS만 선택적으로 적용할 수 있습니다.

예를 들어, 다음 미디어 쿼리 코드는 현재 웹 페이지가 화면 매체(screen media, 즉 인쇄된 문서가 아님)에 표시되고 있고, 동시에 뷰포트(브라우저 창)의 너비가 최소 80rem 이상인지 테스트합니다. 이 두 가지 조건이 모두 참(true)일 때만 그 안에 있는 .container 규칙이 짠! 하고 적용됩니다.

@media screen and (width >= 80rem) {
  .container {
    margin: 1em 2em;
  }
}

스타일시트 안에 미디어 쿼리를 여러 개 추가해서, 다양한 화면 크기에 가장 잘 맞도록 전체 레이아웃이나 일부 요소를 미세하게 조정할 수 있습니다. 미디어 쿼리가 도입되어 레이아웃이 확 변하는 이 기준점들을 우리는 중단점(breakpoints)이라고 부릅니다.

미디어 쿼리를 사용할 때 가장 흔하고 권장되는 접근법은, 먼저 좁은 화면의 기기(예: 휴대폰)를 위한 심플한 1단(single-column) 레이아웃을 기본으로 작성하는 것입니다. 그런 다음 화면이 넓어질 때 미디어 쿼리로 이를 감지하여, 화면 너비가 충분히 넓어졌다는 판단이 들면 그때 다단(multiple-column) 레이아웃으로 변경하는 것이죠. 이렇게 모바일 환경을 먼저 디자인하는 방식을 모바일 퍼스트(mobile first) 디자인이라고 합니다.

💡 강사님의 실무 팁!
모바일 퍼스트가 왜 중요할까요? 모바일 기기는 데스크톱보다 성능이 낮고 인터넷이 느릴 확률이 높습니다. 그래서 복잡한 CSS를 나중에 미디어 쿼리로 얹어주는 방식이 렌더링 성능에 유리하죠. 또한, 좁은 화면에서 꼭 보여줘야 할 핵심 콘텐츠를 먼저 고민하게 되므로 기획/디자인적으로도 훌륭한 방법론입니다!

중단점(breakpoints)을 사용할 때는 개별 기기의 절대적인 크기(픽셀 등)보다는 상대적인 단위(relative units) (예: em이나 rem)를 사용하여 미디어 쿼리 중단점을 정의하는 것이 모범 사례로 권장됩니다.

미디어 쿼리 블록 안에서 스타일을 정의하는 방식도 여러 가지가 있습니다. 단순히 각 중단점에 따라 다른 CSS 파일들을 <link>로 불러오는 방식부터, 각 중단점과 연관된 값들을 저장하기 위해 커스텀 속성(CSS 변수)만을 변경하는 방식까지 다양하죠.

미디어 쿼리는 반응형 웹 디자인에 큰 도움을 주지만, 무조건 써야 하는 필수 조건은 아닙니다. 유연한 그리드, 상대 단위, 그리고 최소/최대 길이 값(min-width, max-width 등)을 적절히 사용하면 미디어 쿼리 없이도 충분히 반응형을 구현할 수 있습니다.

참고:
Scrimba에 미디어 쿼리 활용하기(Aside: Media queries)라는 튜토리얼이 있습니다. 미디어 쿼리에 대한 대화형 소개와 기본 개념을 이해했는지 테스트할 수 있는 챌린지를 제공하니 참고해 보세요.


반응형 레이아웃 기술 (Responsive layout technologies)

반응형 사이트는 '유연한 그리드(flexible grids)' 위에 구축됩니다. 즉, 세상에 존재하는 수만 가지 기기의 화면 크기에 맞춰 픽셀 단위로 완벽한(pixel-perfect) 레이아웃을 일일이 만들 필요가 없다는 뜻이죠.

유연한 그리드를 사용하면, 화면이 줄어들면서 콘텐츠가 보기 싫게 망가지는 딱 그 시점에 중단점(breakpoint)을 추가해서 디자인을 변경할 수 있습니다. 예를 들어, 화면이 커지면서 텍스트 줄이 너무 길어져서 읽기 힘들어지는 것을 막기 위해 columns 속성을 사용할 수 있고; 화면이 좁아지면서 박스가 찌그러져 한 줄에 단어 두 개만 겨우 들어가는 흉한 꼴이 된다면 그 위치에 중단점을 설정해서 배치를 바꿀 수 있습니다.

FlexboxCSS Grid를 포함한 현대의 여러 레이아웃 방식들은 기본적으로 반응형을 띠도록 설계되어 있습니다. 이들은 여러분이 유연한 그리드를 만들려 한다는 것을 전제로 작동하며, 이를 훨씬 쉽게 구현할 수 있는 방법들을 제공합니다.

Flexbox (플렉스박스)

플렉스박스에서는 플렉스 아이템들이 컨테이너 안의 남은 공간에 따라 알아서 수축하거나(shrink) 팽창합니다(grow). flex-growflex-shrink 값을 변경하여, 아이템 주변에 공간이 남거나 모자랄 때 아이템들이 각각 어떻게 행동해야 할지 지시할 수 있죠.

아래 예제에서 플렉스 아이템들은 이전에 다루었던 flex: 1 이라는 축약형 코드를 사용하여 플렉스 컨테이너 안에서 각각 동일한 양의 공간을 차지하게 됩니다. (플렉스박스: 플렉스 아이템의 유연한 크기 조절 참고).

.container {
  display: flex;
}

.item {
  flex: 1;
}

이제 미디어 쿼리와 플렉스박스를 결합하여 반응형 디자인을 어떻게 구현하는지 살펴볼까요?

<div class="wrapper">
  <div class="col1">
    <p>
      This layout is responsive. See what happens if you make the browser window
      wider or narrow.
    </p>
  </div>
  <div class="col2">
    <p>
      One November night in the year 1782, so the story runs, two brothers sat
      over their winter fire in the little French town of Annonay, watching the
      grey smoke-wreaths from the hearth curl up the wide chimney. Their names
      were Stephen and Joseph Montgolfier, they were papermakers by trade, and
      were noted as possessing thoughtful minds and a deep interest in all
      scientific knowledge and new discovery.
    </p>
    <p>
      Before that night—a memorable night, as it was to prove—hundreds of
      millions of people had watched the rising smoke-wreaths of their fires
      without drawing any special inspiration from the fact.
    </p>
  </div>
</div>
body {
  font: 1.2em / 1.5 sans-serif;
  margin: 20px;
  padding: 0;
  background-color: #eeeeee;
}
.wrapper {
  max-width: 960px;
  margin: 2em auto;
}

.col1,
.col2 {
  background-color: white;
}

여기에 다음 CSS를 추가합니다:

@media screen and (width >= 600px) {
  .wrapper {
    display: flex;
  }

  .col1 {
    flex: 1;
    margin-right: 5%;
  }

  .col2 {
    flex: 2;
  }
}

MDN Playground에서 직접 예제 코드 만져보기

브라우저 창 크기를 조절해 보세요. 위 예제의 레이아웃은 우리가 설정한 600px이라는 너비 기준점(임계값)을 통과할 때, 1단(single-column) 레이아웃(모바일용)과 2단(two-column) 레이아웃(데스크톱용) 사이를 매끄럽게 전환하게 됩니다. 이게 바로 반응형의 기본입니다!

CSS grid (CSS 그리드)

CSS 그리드 레이아웃에서는 fr이라는 마법의 단위를 사용하여 그리드 트랙(행/열) 전체에 걸쳐 사용 가능한 공간을 비율로 분배할 수 있습니다. 다음 예제는 각각 1fr 크기를 가지는 세 개의 트랙을 가진 그리드 컨테이너를 만듭니다. 이렇게 하면 세 개의 열(column) 트랙이 생성되며, 각각은 컨테이너에서 사용할 수 있는 공간의 1/3씩을 차지하게 되죠. 여러분은 이 접근법에 대해 이미 살펴보셨을 겁니다. (기억이 안 나신다면 fr 단위로 유연한 그리드 만들기를 복습해 보세요).

.container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
}

이번에는 반응형 디자인을 위해 그리드 레이아웃과 미디어 쿼리를 어떻게 함께 쓰는지 볼까요? 아까와 똑같은 HTML/CSS 기본 세팅에 아래 그리드 코드를 추가해 봅니다.

<div class="wrapper">
  <div class="col1">
    <p>
      This layout is responsive. See what happens if you make the browser window
      wider or narrow.
    </p>
  </div>
  <div class="col2">
    <p>
      One November night in the year 1782, so the story runs, two brothers sat
      over their winter fire in the little French town of Annonay, watching the
      grey smoke-wreaths from the hearth curl up the wide chimney. Their names
      were Stephen and Joseph Montgolfier, they were papermakers by trade, and
      were noted as possessing thoughtful minds and a deep interest in all
      scientific knowledge and new discovery.
    </p>
    <p>
      Before that night—a memorable night, as it was to prove—hundreds of
      millions of people had watched the rising smoke-wreaths of their fires
      without drawing any special inspiration from the fact.
    </p>
  </div>
</div>
body {
  font: 1.2em / 1.5 sans-serif;
  margin: 20px;
  padding: 0;
  background-color: #eeeeee;
}
.wrapper {
  max-width: 960px;
  margin: 2em auto;
}

.col1,
.col2 {
  background-color: white;
}
@media screen and (width >= 600px) {
  .wrapper {
    display: grid;
    grid-template-columns: 1fr 2fr;
    column-gap: 5%;
  }
}

MDN Playground에서 직접 예제 코드 만져보기

이전 예제와 마찬가지로 브라우저 창 크기를 조절해 보세요. 600px 너비 임계값에서 레이아웃이 1단에서 2단(왼쪽은 1비율, 오른쪽은 2비율)으로 바뀌는 것을 볼 수 있습니다. Flexbox와 느낌은 비슷하지만, Grid를 쓰면 행과 열을 동시에 제어하기가 훨씬 수월합니다.


반응형 이미지/미디어 (Responsive images/media)

가장 간단한 형태의 반응형 이미지는 우리가 초반에 언급했던 기술을 사용합니다. 이미지나 비디오 등 미디어 요소가 절대 자신을 감싸는 반응형 컨테이너보다 커져서 삐져나오지 않도록 보장하려면, 다음과 같은 접근법을 사용할 수 있습니다:

img,
picture,
video {
  max-width: 100%;
}

이렇게 하면 미디어 요소들은 컨테이너 크기에 맞춰 자동으로 스케일링(축소)되어 넘침(overflow) 현상을 방지합니다.

참고:
사실, 아주 커다란 고해상도 이미지 하나만 덜렁 올려두고 작은 모바일 기기에서 max-width: 100%로 줄여서 보여주기만 하는 것은 치명적인 문제가 있습니다. 조그만 모바일 화면에서 볼 건데 쓸데없이 수 메가바이트짜리 큰 이미지를 다운로드하게 만들어서 사용자의 귀중한 데이터(대역폭)를 낭비하게 되거든요. 또한 시각적으로도 나쁠 수 있습니다. 와이드스크린에 멋지게 어울리는 가로로 긴 풍경 이미지는, 세로로 긴 모바일 기기 화면에서는 너무 작게 보여서 세로형(인물 모드) 이미지로 교체해 주는 것이 훨씬 낫습니다.
이러한 문제들은 HTML의 <picture> 요소와 <img> 태그의 srcsetsizes 속성을 사용하여 기가 막히게 해결할 수 있습니다. 이 고급 기능들은 이 코스의 범위를 벗어나지만, 반응형 이미지(Responsive images) 가이드에서 아주 상세하게 배울 수 있으니 나중에 꼭 읽어보세요!

기타 유용한 팁들:

  • 웹사이트에 쓰일 이미지 포맷(PNG, JPG, WebP 등)을 항상 적절히 선택하고, 웹사이트에 올리기 전에 그래픽 편집기(또는 이미지 최적화 도구)를 사용해 파일 용량을 최소한으로 최적화(optimize)하세요.
  • 진짜 이미지를 쓰지 않고도, CSS의 그라데이션(gradients)이나 그림자(shadows) 같은 기능을 활용해 멋진 시각적 효과를 구현할 수 있습니다. 이미지가 없으니 로딩 속도는 훨씬 빨라지겠죠!
  • 비디오/오디오의 경우, <video><audio> 태그 안에 중첩된 <source> 요소의 media 속성 안에서 미디어 쿼리를 사용하여, 기기 화면에 따라 서로 다른 비디오/오디오 파일을 서빙할 수도 있습니다(반응형 비디오/오디오).

반응형 타이포그래피 (Responsive typography)

반응형 타이포그래피란 미디어 쿼리 안에서 글자 크기(font sizes)를 변경하거나, 뷰포트 단위(vw, vh 등)를 사용하여 화면 공간이 좁아지거나 넓어짐에 따라 글씨 크기도 동적으로 바뀌게 만드는 기법을 말합니다.

미디어 쿼리를 사용한 반응형 타이포그래피 (Using media queries for responsive typography)

이번 예제에서는 가장 중요한 제목(Level 1 heading, h1)을 기본 폰트 크기의 무려 4배인 4rem으로 설정하고 싶습니다. 정말 어마어마하게 큰 제목이죠! 하지만 이렇게 거대한 제목은 모니터 화면이 충분히 넓을 때만 보여주고 싶습니다. 그래서 우리는 먼저 기본 크기를 모바일 친화적인 2rem으로 작게 설정해 둔 다음, 사용자의 화면 너비가 최소 1200px 이상이 될 때 미디어 쿼리를 발동시켜서 폰트 크기를 더 큰 4rem으로 덮어쓰도록 만들 겁니다.

html {
  font-size: 1em;
}

h1 {
  font-size: 2rem;
}

@media (width >= 1200px) {
  h1 {
    font-size: 4rem;
  }
}

다음 예제는 아까 우리가 만들었던 반응형 그리드 예제를 살짝 수정한 버전입니다. 앞서 설명한 방식을 사용해 반응형 제목을 추가했어요. 좁은 모바일 화면에서는 제목이 작게 보이지만, 화면을 넓혀 데스크톱 크기가 되면 갑자기 제목이 확 커지는 걸 볼 수 있습니다:

<div class="wrapper">
  <div class="col1">
    <h1>Watch my size!</h1>
    <p>
      This layout is responsive. See what happens if you make the browser window
      wider or narrow.
    </p>
  </div>
  <div class="col2">
    <p>
      One November night in the year 1782, so the story runs...
    </p>
  </div>
</div>
html {
  font-size: 1em;
}

body {
  font:
    1.2em "Helvetica",
    "Arial",
    sans-serif;
  margin: 20px;
  padding: 0;
  background-color: #eeeeee;
}
.wrapper {
  max-width: 960px;
  margin: 2em auto;
}

h1 {
  font-size: 2rem;
  margin: 0;
}

.col1,
.col2 {
  background-color: white;
}

@media screen and (width >= 600px) {
  .wrapper {
    display: grid;
    grid-template-columns: 1fr 2fr;
    column-gap: 5%;
  }

  h1 {
    font-size: 4rem;
  }
}

MDN Playground에서 직접 예제 코드 만져보기

이전 예제들처럼 브라우저 창 크기를 조절해 보세요. 600px 너비 임계값을 지날 때 레이아웃(1단 -> 2단)이 바뀔 뿐만 아니라, 제목의 크기까지 다이내믹하게 바뀌는 것을 눈으로 확인할 수 있습니다.

이 타이포그래피 접근법이 보여주듯이, 미디어 쿼리를 꼭 페이지의 '레이아웃'을 바꾸는 데만 써야 하는 것은 아닙니다. 미디어 쿼리를 사용하면 화면 크기에 따라 어떤 요소든 미세하게 조정하여 사이트를 훨씬 더 사용하기 편하고 매력적으로 만들 수 있습니다.

뷰포트 단위를 사용한 반응형 타이포그래피 (Using viewport units for responsive typography)

미디어 쿼리로 중단점을 일일이 설정하지 않고도 반응형 타이포그래피를 구현할 수 있는 신박한 방법이 있습니다. 바로 뷰포트 단위(Viewport units)vw를 사용하는 것이죠. 1vw는 브라우저 창(뷰포트) 너비의 1%와 완벽히 같습니다. 즉, 폰트 크기를 vw로 설정하면, 창 크기를 늘리거나 줄일 때마다 글자 크기가 부드럽게 고무줄처럼 연동되어 변하게 됩니다.

h1 {
  font-size: 6vw;
}

하지만 이 방식에는 치명적인 문제가 하나 있습니다. 텍스트 크기가 오직 뷰포트 크기에만 절대적으로 의존하기 때문에, 시력이 안 좋은 사용자가 브라우저 설정에서 글자 크기를 강제로 '확대(zoom)'하려고 해도 글자 크기가 꿈쩍도 하지 않게 되어버린다는 점입니다. 따라서, 접근성을 위해 절대로 vw 단위 하나만 단독으로 사용해서 텍스트 크기를 설정해서는 안 됩니다.

💡 강사님의 실무 팁!
"어? 그럼 글자가 부드럽게 커지는 효과는 포기해야 하나요?"
아닙니다! 프론트엔드 개발자들의 마법 지팡이인 calc() 함수를 쓰면 됩니다.

해결책은 em이나 rem처럼 사용자의 환경 설정에 반응하는 고정 단위에 vw 단위를 살짝 더해주는(add) 것입니다. 이렇게 하면 사용자가 브라우저 줌을 할 때 기본 텍스트는 정상적으로 커지면서도, 창 크기가 넓어지면 vw가 추가로 힘을 발휘해 글자가 점진적으로 커지는 두 마리 토끼를 모두 잡을 수 있습니다.

h1 {
  font-size: calc(1.5rem + 4vw);
}

이 방식을 쓰면 모바일용 크기를 지정하고 미디어 쿼리에서 데스크톱용 크기를 다시 재정의(redefine)하는 귀찮은 짓을 할 필요 없이, 딱 한 번만 폰트 크기를 선언해주면 됩니다. 폰트는 뷰포트 크기가 커짐에 따라 계단식이 아니라 아주 스무스하게(gradually) 커집니다.

<div class="wrapper">
  <div class="col1">
    <h1>Watch my size!</h1>
    <p>
      This layout is responsive. See what happens if you make the browser window
      wider or narrow.
    </p>
  </div>
  <div class="col2">
    <p>
      One November night in the year 1782...
    </p>
  </div>
</div>
body {
  font: 1.2em / 1.5 sans-serif;
  margin: 20px;
  padding: 0;
  background-color: #eeeeee;
}

.wrapper {
  max-width: 960px;
  margin: 2em auto;
}

h1 {
  font-size: calc(1.5rem + 4vw);
  margin: 0;
}

.col1,
.col2 {
  background-color: white;
}

@media screen and (width >= 600px) {
  .wrapper {
    display: grid;
    grid-template-columns: 1fr 2fr;
    column-gap: 5%;
  }
}

MDN Playground에서 직접 예제 코드 만져보기

이전처럼 브라우저 창 크기를 조절해 보세요. 이번에는 특정 중단점(600px)을 넘을 때 갑자기 제목 크기가 확 튀는 것이 아니라, 창 너비가 변하는 족족 제목의 크기가 그에 맞춰 부드럽게 커지고 작아지는 걸 보실 수 있습니다.


뷰포트 메타 태그 (The viewport meta tag)

반응형 웹 페이지의 HTML 소스를 열어보면, 문서의 <head> 태그 영역 안에 항상 다음과 같은 <meta> 태그가 박혀 있는 것을 보게 될 것입니다.

<meta name="viewport" content="width=device-width,initial-scale=1" />

viewport 메타 태그는 모바일 브라우저에게 매우 강력한 명령을 내립니다. "이 웹페이지를 렌더링할 뷰포트(가상 화면)의 너비를, 네가 가진 기기의 실제 물리적인 화면 너비(device-width)와 동일하게 맞추고, 처음 화면을 띄울 때 화면 배율(zoom)을 정확히 1 (100%)로 해라!" 라는 뜻이죠. 이렇게 해야 여러분이 힘들게 코딩한 모바일 최적화 화면이 딱 알맞은 비율로 유저에게 보여집니다.

이게 도대체 왜 필요한 걸까요? 왜냐하면 모바일 브라우저들은 뷰포트 너비에 대해 거짓말을 하는 나쁜 버릇이 있기 때문입니다.

이 메타 태그가 등장한 역사적 배경은 이렇습니다. 스마트폰(아이폰 등)이 처음 세상에 등장했을 당시, 인터넷에 있는 거의 모든 웹사이트는 데스크톱용으로만 만들어져 있었고 모바일 최적화 따위는 안 되어 있었습니다. 그래서 애플의 사파리 같은 모바일 브라우저는 아주 영악한 꼼수를 썼죠. 뷰포트(가상의 렌더링 공간) 너비를 강제로 980픽셀(당시 일반적인 데스크톱 해상도)로 넓게 잡아버린 다음, 그 넓은 공간에 데스크톱용 페이지를 다 그린 후, 마치 돋보기를 뒤로 뺀 것처럼 화면 전체를 콱 축소(zoomed-out)해서 코딱지만 한 폰 화면에 보여준 것입니다.
사용자는 페이지의 미니미 버전을 보다가, 자기가 읽고 싶은 부분을 두 손가락으로 줌인(zoom-in)하고 화면을 이리저리 문지르며(pan) 웹서핑을 해야 했습니다. 작동은 했지만 몹시 불편하고 못생겼었죠.

width=device-width를 설정한다는 것은, "나 아이폰인데 내 너비 980px이야"라고 우기는 모바일 기기의 거짓말 기본값을 엎어버리고, "아니, 넌 너비 375px짜리 폰이니까 375px 기준으로 화면을 그려!"라고 기기의 실제 물리적 너비를 강제하는 것입니다.
만약 이 메타 태그를 빼먹는다면, 여러분이 아무리 480px 이하에서 작동하도록 모바일용 미디어 쿼리와 중단점을 예쁘게 짜 놓았더라도, 폰은 자기가 980px이라고 굳게 믿고 있기 때문에 모바일 레이아웃은 영원히 발동하지 않습니다. 유저는 여전히 축소된 끔찍한 데스크톱 화면을 보게 되겠죠.

따라서 여러분은 작성하는 모든 HTML 문서의 <head> 태그 안에 이 뷰포트 메타 태그를 무조건, 항상, 절대적으로 포함시켜야 합니다. (Create React App이나 Next.js 같은 툴을 쓰면 기본적으로 다 들어가 있으니 안심하세요!)

뷰포트 메타 태그의 content 속성 안에는 이 밖에도 여러 가지 옵션을 넣을 수 있습니다. 더 자세한 내용은 <meta name="viewport"> 레퍼런스 문서를 참고하세요.


요약 (Summary)

반응형 디자인이란 사이트나 앱이 구동되는 환경(화면 크기 등)에 '반응'하여 적응하는 디자인을 말합니다. 이는 특정 기술 하나가 아니라 수많은 CSS와 HTML 기능, 그리고 테크닉들을 아우르는 개념이며, 본질적으로 현대에 웹사이트를 구축하는 숨 쉬듯 당연한 기본 방식(default)입니다.
당장 여러분이 폰으로 접속하는 웹사이트들을 떠올려 보세요. 폰으로 들어갔는데 글씨가 콩알만 한 데스크톱 화면이 뜨거나, 내용을 읽기 위해 가로로 낑낑대며 스크롤해야 하는 사이트를 본 적이 거의 없으실 겁니다. 전 세계의 웹 생태계가 이미 이런 반응형 디자인 접근법으로 완전히 넘어왔기 때문이죠.

이 문서에서 다룬 여러 가지 레이아웃 기법들의 도움을 받으면, 이제는 과거보다 훨씬 쉽게 반응형 디자인을 완성할 수 있습니다. 만약 여러분이 오늘날 웹 개발에 막 입문하신 거라면, 반응형 디자인 초창기의 개발자들(float으로 고통받던...)보다 훨씬 강력하고 편리한 도구(Flexbox, Grid)들을 처음부터 손에 쥐고 계신 셈입니다.

그래서 구글링하실 때 블로그 글이나 튜토리얼 자료의 작성 연도(age)를 꼭 확인하는 것이 좋습니다. 오래된 자료의 논리도 여전히 유용하긴 하지만, 최신 CSS와 HTML을 활용하면 기기에 상관없이 우아하고 사용하기 편한 디자인을 구축하는 것이 예전보다 비교할 수 없을 만큼 쉬워졌으니까요.

다음 시간에는 미디어 쿼리를 조금 더 깊이 파고들어, 실무에서 마주치는 흔한 문제들을 해결하는 방법에 대해 알아보겠습니다.


같이 보기 (See also)


MDN 개선에 도움을 주세요 (Help improve MDN)

기여하는 방법 알아보기 (Learn how to contribute)

이 페이지의 마지막 수정일은 Dec 19, 2025 이며, MDN 기여자들(MDN contributors)에 의해 작성되었습니다.

수고하셨습니다! 반응형 웹 디자인은 처음엔 뷰포트랑 미디어 쿼리가 헷갈릴 수 있지만, 손에 익으면 마법처럼 늘었다 줄었다 하는 화면을 보는 재미가 아주 쏠쏠하답니다. 궁금한 점이 있다면 편하게 질문해 주세요!

profile
프론트에_가까운_풀스택_개발자

0개의 댓글