웹 디자인을 시작할 때 우리가 가장 먼저 집어 드는 무기는 픽셀(px)입니다. width: 300px;, font-size: 16px; 등 직관적이고 절대적인 수치를 제공하는 px은 포토샵이나 일러스트레이터 같은 고전적인 그래픽 툴에 익숙한 디자이너와 개발자들에게 엄청난 안도감을 줍니다. 하지만 모던 웹 개발의 세계로 깊숙이 들어가는 순간, 이 '절대적인 고정 단위'는 반응형 웹(Responsive Web)과 웹 접근성(Accessibility)을 파괴하는 거대한 족쇄로 돌변합니다. 사용자가 손바닥만 한 아이폰으로 접속하든, 거대한 32인치 4K 모니터로 접속하든 똑같이 300px의 크기를 고집하는 요소는 필연적으로 화면 밖으로 잘리거나 현미경으로 봐야 할 만큼 작아지는 촌극을 빚어냅니다. 현대 프론트엔드의 진정한 고수가 되기 위해서는 고정된 px의 감옥에서 벗어나, 주변 환경에 맞춰 카멜레온처럼 크기를 바꾸는 **상대 단위(Relative Units)**와 **뷰포트 단위(Viewport Units)**를 자유자재로 다뤄야만 합니다. 이번 03단계 포스팅에서는 실무에서 필수적으로 쓰이는 %, em, rem의 치명적인 차이점과 모바일 레이아웃의 구세주 vw, vh, 그리고 골치 아픈 '100vh 모바일 스크롤 버그'의 원인 및 해결책까지 상세히 알아보겠습니다.

1. 불변의 단위와 그 착각: 픽셀(px)은 진짜 픽셀이 아니다?
우리는 흔히 1px이 모니터 화면의 진짜 빛나는 점(Dot) 하나라고 생각합니다. 과거 1990년대 배불뚝이 CRT 모니터 시절에는 그것이 사실이었습니다. 하지만 애플의 레티나(Retina) 디스플레이를 필두로 초고해상도 스마트폰 시대가 열리면서 이 공식은 산산조각 났습니다. 최신 스마트폰은 물리적인 모니터 픽셀은 엄청나게 많지만, CSS가 그 물리적 픽셀 1개에 1px을 매칭 시켜버리면 웹사이트의 글씨가 개미만큼 작아져서 읽을 수 없게 됩니다. 그래서 W3C와 브라우저 제조사들은 'CSS 픽셀(논리적 픽셀)'이라는 개념을 만들었습니다. 고해상도 기기에서는 CSS의 1px을 그리기 위해 기기의 실제 물리적 픽셀 4개(2x2) 또는 9개(3x3)를 병합하여 사용합니다. 즉, 우리가 코드에 적는 px은 더 이상 절대적인 물리 단위가 아니라, 기기의 디스플레이 픽셀 비율(Device Pixel Ratio)에 따라 고무줄처럼 늘어나는 가상의 기준점일 뿐입니다. 그럼에도 불구하고 px은 여전히 부모나 화면 크기가 변해도 '자기 자신의 크기를 꿋꿋이 유지하려는' 속성이 강하기 때문에, 레이아웃 골조보다는 1px 테두리 두께(Border)나 미세한 그림자(Box-shadow) 오프셋을 조정할 때만 제한적으로 사용하는 것이 현대 웹의 트렌드입니다.
2. 상대 단위의 핵심: 백분율(%), em, 그리고 구원자 rem
반응형 웹을 구축하려면 부모나 화면 환경에 따라 크기가 알아서 수학적으로 계산되는 상대 단위를 써야 합니다. 상대 단위를 지배하는 자가 곧 반응형 웹을 지배합니다.
① 직관적인 비율: 백분율 (%)
width: 50%;는 아주 직관적입니다. "나를 감싸고 있는 직속 부모 박스 너비의 딱 절반만 차지할게!"라는 뜻입니다. 하지만 백분율에는 주니어 개발자들을 미치게 만드는 함정이 하나 숨어있습니다. 만약 자식 요소에 padding-top: 50%를 주면, 이 50%는 부모의 '높이'를 기준으로 계산될까요? 아닙니다! 마진과 패딩에 적용된 % 단위는 무조건 부모 요소의 '너비(Width)'를 기준으로 수학적 계산이 들어갑니다. 이 기이한 스펙 덕분에 우리는 aspect-ratio 속성이 없던 과거 시절에, 유튜브 영상이나 반응형 이미지를 16:9 비율로 찌그러지지 않게 끼워 넣는 'Padding Hack'이라는 마법 같은 꼼수를 부릴 수 있었습니다.

② 폰트 기반 상대 단위: em의 복리 이자 재앙
em 단위는 인쇄 타이포그래피에서 유래했으며, '자기 자신의 요소에 적용된 폰트 사이즈'를 1em으로 취급합니다. 폰트가 16px이면 1em도 16px입니다. padding: 2em;을 주면 글씨가 커지면 패딩도 같이 두꺼워지므로 버튼의 비율을 유지하는 데 환상적입니다. 하지만 폰트 사이즈 지정에 em을 쓰기 시작하면 지옥문이 열립니다. 부모가 font-size: 1.2em을 주고, 그 자식이 font-size: 1.2em을 주면 크기가 누적곱(1.2 * 1.2)되어 손자 뻘로 가면 글씨가 집채만 해집니다. 문서가 깊어질수록 크기를 예측할 수 없게 되는 '중첩 재앙(Compounding Issue)'이 발생합니다.
③ 현대 웹 타이포그래피의 표준: rem (Root em)
em의 끔찍한 연쇄 팽창을 막기 위해 rem(Root em)이라는 구원자가 등장했습니다. rem은 부모가 누구든 족보를 완전히 무시하고 오직 최상단 뿌리 태그인 <html>에 지정된 폰트 사이즈(기본 16px) 단 하나만을 바라봅니다. 1rem = 16px, 2rem = 32px로 계산이 극도로 직관적입니다. 게다가 사용자가 시력이 나빠 브라우저 설정에서 기본 글꼴 크기를 아주 크게 키우면, px로 짠 사이트는 글씨가 커지지 않지만 rem으로 짠 사이트는 모든 레이아웃과 글씨가 사용자 설정에 맞춰 유연하게 뻥튀기됩니다. 즉, rem을 사용하는 것은 선택이 아니라 시각 장애인과 저시력자를 위한 웹 접근성(A11y) 확보의 필수 의무입니다.
3. 브라우저 창을 기준점으로: 뷰포트(Viewport) 단위와 100vh 버그
백분율(%)은 훌륭하지만 항상 '부모'의 크기에 종속된다는 맹점이 있습니다. "부모가 아무리 좁아터졌어도, 나는 브라우저 전체 화면을 꽉 채우는 팝업창이 될 거야!"라고 선언하고 싶을 때 등장하는 것이 뷰포트 단위입니다.
- vw (Viewport Width): 브라우저 창(화면) 전체 너비의 1/100 크기입니다.
50vw는 현재 화면 너비의 절반(50%)을 의미합니다. - vh (Viewport Height): 브라우저 창(화면) 전체 높이의 1/100 크기입니다. 랜딩 페이지 맨 처음에 화면을 꽉 채우는 대형 배경 이미지를 넣을 때
height: 100vh;는 거의 공식처럼 쓰입니다.
🚨 모바일 브라우저의 100vh 스크롤 버그와 차세대 단위
모바일 사파리(iOS)나 크롬(Android)에서 height: 100vh;를 주면, 화면 하단에 있는 버튼이 잘려서 안 보이는 기괴한 버그가 수년간 전 세계 프론트엔드 생태계를 괴롭혀왔습니다. 원인은 모바일 브라우저 상단의 주소창(URL bar)과 하단 네비게이션 바가 뷰포트 높이 계산에 꼈다 빠졌다 하면서 혼란을 주기 때문이었습니다. 브라우저 제조사들은 '주소창이 보이는 상태의 높이'와 '스크롤해서 주소창이 숨겨진 상태의 높이' 사이에서 100vh를 어찌할 바를 몰라 헤맸습니다. 이를 해결하기 위해 수많은 자바스크립트 꼼수들이 난무했지만, 최근 W3C는 이 문제를 원천 해결하는 강력한 차세대 단위들을 발표했습니다.
- dvh (Dynamic Viewport Height): 주소창이 생기고 사라질 때마다 화면의 실제 보여지는 높이를 실시간(Dynamic)으로 재계산하여 빈틈없이 맞춰줍니다. 모바일 웹 풀스크린 개발의 궁극적인 정답입니다.
- svh (Small) / lvh (Large): 주소창이 가장 크게 펼쳐져서 화면이 제일 좁을 때(Small)와, 주소창이 사라져서 화면이 제일 클 때(Large)를 고정적으로 참조하는 하드코어 단위입니다.
정리하며
이번 03단계 포스팅에서는 절대 굽히지 않는 고집쟁이 px부터, 똑똑하지만 위험한 복리 이자 em, 접근성의 수호자 rem, 그리고 모바일의 한계를 돌파한 dvh까지 웹 레이아웃을 주무르는 마법의 단위 체계를 완벽하게 파헤쳐 보았습니다. 단위에 대한 확고한 철학이 세워졌다면, 뼈대에 생명을 불어넣을 차례입니다. 인간의 눈길을 가장 먼저 사로잡는 것은 결국 화려한 '색상'과 감각적인 '배경'입니다. 단순히 color: red를 넘어서, 심리학이 섞인 컬러 모델과 이미지를 화면에 까는 정밀한 기법들. 다음 04단계 포스팅에서는 화면을 화려한 캔버스로 바꿔버리는 "CSS Color & Background: 헥스, RGB, HSL 컬러의 세계와 배경 이미지 완벽 제어"에 대해 상세히 파헤쳐 보겠습니다!
'StyleSheet > CSS' 카테고리의 다른 글
| [CSS] Display (0) | 2026.07.28 |
|---|---|
| [CSS] 타이포그래피(Typography) (0) | 2026.07.28 |
| [CSS] Color & Background (0) | 2026.07.28 |
| [CSS] Box Model - 브라우저가 세상을 바라보는 네모난 시선 (0) | 2026.07.28 |
| [CSS] CSS의 탄생 배경과 HTML과의 완벽한 분리 (0) | 2026.07.28 |