CSS 입문 6편 - 반응형 웹 만들기

반응형 디자인이 필수인 이유
2025년 현재, 웹사이트 방문자의 70% 이상이 모바일로 접속해요. 데스크톱에서만 잘 보이는 웹사이트는 절반 이상의 사용자를 잃는 거죠.
반응형 디자인(Responsive Web Design)은 하나의 HTML로 모든 기기에 대응하는 기술이에요. 모바일 앱 따로, 웹사이트 따로 만들 필요 없이 CSS만으로 해결합니다!
제가 처음 만든 웹사이트는 데스크톱에서만 확인해서 모바일에서 완전 망가진 걸 나중에 알았어요. 지금은 항상 모바일부터 확인합니다.
뷰포트 메타 태그 (필수!)
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
설명:
viewport 메타 태그가 없으면: 모바일에서 데스크톱 화면이 축소되어 표시됨
viewport 메타 태그가 있으면: 기기 너비에 맞춰 적절하게 표시됨
이게 없으면 모바일에서 데스크톱 화면이 축소되어 보여요. 모든 웹사이트에 필수!
width=device-width: 기기 너비에 맞춤initial-scale=1.0: 초기 확대 배율 1배
미디어 쿼리 기본
특정 화면 크기에서 다른 CSS를 적용해요.
/* 기본 스타일 (모든 화면) */
.container {
padding: 20px;
}
/* 768px 이하 (태블릿, 모바일) */
@media (max-width: 768px) {
.container {
padding: 10px;
}
}
주요 브레이크포인트
/* 모바일 (0~480px) */
@media (max-width: 480px) {
/* 스타일 */
}
/* 태블릿 (481~768px) */
@media (min-width: 481px) and (max-width: 768px) {
/* 스타일 */
}
/* 데스크톱 (769px~) */
@media (min-width: 769px) {
/* 스타일 */
}
/* 대형 데스크톱 (1200px~) */
@media (min-width: 1200px) {
/* 스타일 */
}
실무에서 자주 쓰는 브레이크포인트:
- 480px: 모바일
- 768px: 태블릿
- 1024px: 작은 데스크톱
- 1280px: 일반 데스크톱
Mobile First vs Desktop First
Desktop First (예전 방식)
/* 기본: 데스크톱 */
.container {
width: 1200px;
}
/* 작은 화면에서 수정 */
@media (max-width: 768px) {
.container {
width: 100%;
}
}
Mobile First (현대적 방식) ⭐ 추천
/* 기본: 모바일 */
.container {
width: 100%;
padding: 10px;
}
/* 큰 화면에서 확장 */
@media (min-width: 768px) {
.container {
width: 750px;
padding: 20px;
}
}
@media (min-width: 1024px) {
.container {
width: 1000px;
}
}
Mobile First가 좋은 이유:
- 모바일이 기본이 되는 시대
- 성능 최적화 (작은 화면부터 시작)
- 점진적 향상 (Progressive Enhancement)
유동 레이아웃
고정 크기 → 상대 크기
/* ❌ 나쁜 예 (고정 크기) */
.container {
width: 1200px;
}
/* ✅ 좋은 예 (상대 크기) */
.container {
width: 90%;
max-width: 1200px;
}
% vs vw/vh
/* 부모 기준 */
.box {
width: 50%; /* 부모의 50% */
}
/* 뷰포트 기준 */
.hero {
width: 100vw; /* 뷰포트 너비의 100% */
height: 100vh; /* 뷰포트 높이의 100% */
}
언제 뭘 쓸까?
%: 일반적인 레이아웃vw/vh: 전체 화면 섹션 (히어로 이미지 등)
반응형 이미지
1. 기본 방법
img {
max-width: 100%;
height: auto;
}
이것만 해도 이미지가 컨테이너를 벗어나지 않아요!
2. srcset 속성
<img
src="image-small.jpg"
srcset="image-small.jpg 480w,
image-medium.jpg 768w,
image-large.jpg 1200w"
sizes="(max-width: 480px) 100vw,
(max-width: 768px) 50vw,
33vw"
alt="반응형 이미지"
>
브라우저가 자동으로 적절한 크기 선택!
3. picture 태그
<picture>
<source media="(max-width: 480px)" srcset="mobile.jpg">
<source media="(max-width: 768px)" srcset="tablet.jpg">
<img src="desktop.jpg" alt="반응형 이미지">
</picture>
화면 크기별로 완전히 다른 이미지 사용 가능!

실전 예제 1: 반응형 네비게이션
<nav class="navbar">
<div class="logo">MyLogo</div>
<button class="menu-toggle">☰</button>
<ul class="menu">
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 2rem;
background: #333;
color: white;
}
.menu {
display: flex;
gap: 2rem;
list-style: none;
}
.menu-toggle {
display: none; /* 데스크톱에서 숨김 */
background: none;
border: none;
color: white;
font-size: 1.5rem;
cursor: pointer;
}
/* 모바일 */
@media (max-width: 768px) {
.menu {
display: none; /* 기본 숨김 */
position: absolute;
top: 60px;
left: 0;
right: 0;
flex-direction: column;
background: #333;
padding: 1rem;
}
.menu.active {
display: flex; /* 토글 시 표시 */
}
.menu-toggle {
display: block; /* 햄버거 버튼 표시 */
}
}
JavaScript로 .active 클래스만 토글하면 됩니다!
실전 예제 2: 반응형 그리드
<div class="grid">
<div class="card">Card 1</div>
<div class="card">Card 2</div>
<div class="card">Card 3</div>
<div class="card">Card 4</div>
</div>
.grid {
display: grid;
gap: 20px;
padding: 20px;
}
/* 모바일: 1열 */
@media (max-width: 480px) {
.grid {
grid-template-columns: 1fr;
}
}
/* 태블릿: 2열 */
@media (min-width: 481px) and (max-width: 768px) {
.grid {
grid-template-columns: repeat(2, 1fr);
}
}
/* 데스크톱: 3열 */
@media (min-width: 769px) and (max-width: 1024px) {
.grid {
grid-template-columns: repeat(3, 1fr);
}
}
/* 대형 데스크톱: 4열 */
@media (min-width: 1025px) {
.grid {
grid-template-columns: repeat(4, 1fr);
}
}
미디어 쿼리 없는 자동 반응형:
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
}
이게 훨씬 간단하죠!
실전 예제 3: 반응형 타이포그래피
/* 기본 (모바일) */
body {
font-size: 14px;
}
h1 { font-size: 1.8rem; }
h2 { font-size: 1.5rem; }
p { line-height: 1.5; }
/* 태블릿 */
@media (min-width: 768px) {
body {
font-size: 16px;
}
h1 { font-size: 2.2rem; }
h2 { font-size: 1.8rem; }
p { line-height: 1.6; }
}
/* 데스크톱 */
@media (min-width: 1024px) {
body {
font-size: 18px;
}
h1 { font-size: 2.5rem; }
h2 { font-size: 2rem; }
p { line-height: 1.7; }
}
clamp() 함수로 유동 타이포그래피:
h1 {
font-size: clamp(1.8rem, 5vw, 2.5rem);
/* 최소 1.8rem, 이상적 5vw, 최대 2.5rem */
}
화면 크기에 따라 자동으로 조정!
컨테이너 쿼리 (최신 기능)
요소의 크기에 따라 스타일 변경 (뷰포트가 아닌!)
.sidebar {
container-type: inline-size;
}
.card {
padding: 1rem;
}
@container (min-width: 400px) {
.card {
padding: 2rem;
display: grid;
grid-template-columns: 1fr 1fr;
}
}
사이드바가 넓어지면 카드 레이아웃이 바뀝니다! (2024년부터 주요 브라우저 지원)
숨기기/보이기 패턴
/* 모바일에서만 보임 */
.mobile-only {
display: block;
}
@media (min-width: 768px) {
.mobile-only {
display: none;
}
}
/* 데스크톱에서만 보임 */
.desktop-only {
display: none;
}
@media (min-width: 768px) {
.desktop-only {
display: block;
}
}
터치 기기 감지
/* 터치 기기 (모바일, 태블릿) */
@media (hover: none) and (pointer: coarse) {
.button {
min-height: 44px; /* 터치하기 쉽게 크게 */
min-width: 44px;
}
}
/* 마우스 기기 (데스크톱) */
@media (hover: hover) and (pointer: fine) {
.button:hover {
background: #0056b3;
}
}
다크 모드 대응
/* 라이트 모드 (기본) */
body {
background: #fff;
color: #333;
}
/* 다크 모드 */
@media (prefers-color-scheme: dark) {
body {
background: #1a1a1a;
color: #e0e0e0;
}
}
사용자의 시스템 설정을 자동으로 따라갑니다!
성능 최적화 팁
1. 불필요한 미디어 쿼리 줄이기
/* ❌ 나쁜 예 */
@media (max-width: 768px) {
.box { padding: 10px; }
}
@media (max-width: 768px) {
.card { margin: 5px; }
}
/* ✅ 좋은 예 */
@media (max-width: 768px) {
.box { padding: 10px; }
.card { margin: 5px; }
}
2. min-width 우선 사용 (Mobile First)
/* 기본: 모바일 */
.container { padding: 10px; }
/* 확장: 큰 화면 */
@media (min-width: 768px) {
.container { padding: 20px; }
}
3. CSS 변수 활용
:root {
--spacing: 10px;
--container-width: 100%;
}
@media (min-width: 768px) {
:root {
--spacing: 20px;
--container-width: 750px;
}
}
.container {
padding: var(--spacing);
max-width: var(--container-width);
}
반응형 체크리스트
- viewport 메타 태그 추가
- 이미지에 max-width: 100%
- 고정 크기 대신 상대 크기 사용
- Mobile First 접근
- 터치 타겟 최소 44x44px
- 가로 스크롤 방지
- 실제 기기에서 테스트
- 개발자 도구로 여러 화면 크기 확인
디버깅 팁
Chrome DevTools
- F12 → 기기 툴바 토글 (Ctrl+Shift+M)
- 상단에서 기기 선택 (iPhone, iPad 등)
- 커스텀 크기도 입력 가능
반응형 테스트 사이트
- Responsive Design Checker
- BrowserStack (실제 기기 테스트)
- Mobile-Friendly Test (Google)
운영자 실전 노트
실제 프로젝트 진행하며 겪은 문제
- 미디어쿼리 순서 실수 → max-width를 큰 순서대로 안 씀. 768px 이후에 1024px 쓰면 override됨
- 모바일 퍼스트 미적용 → 데스크톱 먼저 작성 후 모바일 대응. 처음부터 Mobile First가 효율적이다
- 고정 단위 사용 → px로 고정하니 유연하지 못함. rem, %, vw 등 상대 단위 사용해야 한다
이 경험을 통해 알게 된 점
- 브레이크포인트 768px, 1024px가 표준. 디바이스 실사용 통계 기반이다
- 개발 시 브라우저 창을 반만 열어두면 자연스럽게 반응형으로 만들게 된다
다음 단계
다음 글에서는 애니메이션과 전환 효과를 배운다. 움직임을 추가하면 사용자 경험이 훨씬 좋아진다.
실습 과제:
- 네비게이션 바를 모바일에서 햄버거 메뉴로 바꿔보기
- 3열 그리드를 모바일에서 1열로 변경하기
- 타이포그래피를 화면 크기별로 다르게 설정하기
- 실제 휴대폰에서 웹사이트 확인해보기
Chrome DevTools의 기기 에뮬레이션을 활용하되, 최종적으로는 실제 기기에서 테스트하자.
시리즈 네비게이션
- 이전글: CSS 독학 가이드 - 색상과 타이포그래피
- 현재글: CSS 독학 가이드 - 반응형 디자인
- 다음글: CSS 독학 가이드 - 애니메이션과 전환 효과