B-2: 박스 모델과 기본 스타일링
안녕하세요, 홍순구 튜터입니다. 지난 시간에 우리는 드디어 CSS의 문을 열고, 휑하던 로그인 페이지에 첫 색을 입혔어요. 선택자로 꾸밀 대상을 콕 집어서 배경색을 깔고, 링크를 남색으로 바꾸고, 파란 로그인 버튼까지 만들었죠.
그런데 지난 시간 마지막에 솔직하게 말씀드렸어요. 색은 입혔지만 "배치"는 손도 못 댔다고요. 지금 로그인 페이지를 다시 열어보면, 입력칸들이 서로 다닥다닥 붙어 있고, 폼 전체가 화면 왼쪽으로 쏠려 있을 거예요. 우리가 아는 그 정갈한 인스타그램 로그인 카드 — 입력칸 사이가 시원하게 벌어지고, 버튼은 누르기 좋게 큼직하고, 전체가 깔끔한 흰 상자에 담긴 그 모습과는 아직 거리가 있죠.
오늘 그 거리를 좁힙니다. 비결은 딱 하나, 세상의 모든 화면 요소를 "상자(box)"로 보는 관점이에요. 제목도 상자, 문단도 상자, 입력칸도 상자, 버튼도 상자. 화면에 보이는 모든 것은 사실 네모난 상자고, 그 상자에는 안쪽 여백 · 테두리 · 바깥쪽 여백이라는 겹이 있어요. 이 겹들을 다루는 법을 박스 모델(Box Model) 이라고 부르는데, 오늘의 진짜 주인공이에요.
박스 모델을 손에 넣으면, 거기에 크기를 정하는 단위(px·rem 같은 것들), 색을 더 자유롭게 다루는 법, 글자를 다듬는 타이포그래피를 더해서 — 지난 시간 시작만 해둔 이 base.css를 오늘 제대로 완성합니다.
💡 오늘 수업의 핵심 — "모든 요소를 상자로 보고, 그 여백·크기·색·글자를 다듬어 base.css를 완성한다" 🎯
🎯 학습 목표
- 모든 HTML 요소가 content · padding · border · margin 네 겹의 상자라는 걸 이해하고, 개발자 도구로 직접 확인합니다.
padding(안쪽 여백)으로 요소에 숨통을 틔우고,border(테두리)와margin(바깥쪽 여백)으로 간격을 잡습니다.box-sizing: border-box로 "너비가 왜 안 맞지?"라는 흔한 함정을 해결합니다.- 크기 단위 px · rem · % · vw/dvh의 차이를 알고, 언제 무엇을 쓸지 감을 잡습니다.
- 색을 표현하는 네 가지 방법(hex · rgb · hsl · oklch)을 알고, 2026년 현재 어떤 걸 권하는지 이해합니다.
- 글꼴 크기 · 굵기 · 줄 간격을 다듬는 타이포그래피로 글을 읽기 좋게 만듭니다.
오늘도 외우려 하지 마세요. 이 과목의 최대 장점인 "한 줄 바꾸고 저장하면 화면이 바로 변한다" 가 박스 모델에서 제대로 빛나거든요. 숫자 하나 바꿔서 여백이 벌어지는 걸 눈으로 확인하는 게 오늘의 목표예요. 자, 모든 걸 상자로 보는 눈을 가져볼까요?
Step 1: "모든 요소는 상자다 — 박스 모델 4겹"
CSS를 제대로 다루려면, 먼저 눈을 하나 바꿔야 해요. 화면에 보이는 모든 HTML 요소는 사실 네모난 상자라는 눈이요. 제목 <h2>도 상자, 문단 <p>도 상자, 입력칸도 버튼도 전부 상자예요. 글자만 동동 떠 있는 것처럼 보여도, 그 글자는 보이지 않는 네모 상자 안에 담겨 있어요.
그리고 이 상자는 그냥 한 겹이 아니라 네 겹으로 되어 있어요. 액자에 사진을 넣는 모습을 떠올리면 쉬워요.
┌───────────────────────────────────────────┐
│ margin (바깥 여백) │ ← 액자 주변 벽 공간
│ ┌─────────────────────────────────┐ │
│ │ border (테두리) │ │ ← 액자 틀
│ │ ┌───────────────────────┐ │ │
│ │ │ padding (안쪽 여백) │ │ │ ← 사진과 틀 사이 흰 매트
│ │ │ ┌─────────────┐ │ │ │
│ │ │ │ content │ │ │ │ ← 실제 사진 (글자·이미지)
│ │ │ │ (내용 영역) │ │ │ │
│ │ │ └─────────────┘ │ │ │
│ │ └───────────────────────┘ │ │
│ └─────────────────────────────────┘ │
└───────────────────────────────────────────┘
안쪽에서 바깥으로 읽어볼게요.
- content(내용): 실제 글자나 이미지가 들어가는 한가운데. 액자 속 사진이에요.
- padding(안쪽 여백): 내용과 테두리 사이의 빈 공간. 사진과 액자 틀 사이의 흰 매트지죠. 내용이 답답하지 않게 숨통을 틔워줘요.
- border(테두리): 상자를 두르는 선. 액자 틀이에요.
- margin(바깥 여백): 이 상자와 다른 상자 사이의 거리. 액자와 옆 액자 사이의 벽 공간이에요.
이 네 단어 — content · padding · border · margin — 가 오늘 내내 나와요. 지금 다 외울 필요는 없고, "안에서 바깥으로 내용·안여백·테두리·밖여백" 순서라는 것만 잡아두면 돼요.
개발자 도구로 진짜 상자를 보자
말로만 들으면 와닿지 않으니, 브라우저가 직접 그려주는 상자를 봅시다. 로그인 페이지를 Live Server로 열고 F12를 눌러 개발자 도구를 켜요. Elements 탭에서 로그인 버튼을 클릭해보세요. 그러면 오른쪽 패널 아래쪽에 이런 색색의 네모 그림이 보여요.
┌─ margin ─────────────────────┐ (주황색)
│ ┌─ border ───────────────┐ │ (노란색)
│ │ ┌─ padding ─────────┐ │ │ (초록색)
│ │ │ ┌─ content ───┐ │ │ │ (파란색)
│ │ │ │ 413 x 19 │ │ │ │
│ │ │ └─────────────┘ │ │ │
│ │ └───────────────────┘ │ │
│ └─────────────────────────┘ │
└───────────────────────────────┘
크롬은 박스 모델의 네 겹을 색깔로 구분해서 그려줘요. 파란색이 content, 그 바깥 초록이 padding, 노랑이 border, 주황이 margin이에요. 우리가 방금 그림으로 본 그 구조 그대로죠. 요소를 클릭할 때마다 이 그림이 바뀌니, 앞으로 "이 요소가 왜 이만큼 떨어져 있지?" 싶을 때 여기를 보면 답이 나와요.
🙋 직접 해보세요 — "글자 한 줄도 정말 상자일까?"
개발자 도구 Elements 탭에서 환영 제목 <h2>를 클릭해보세요. 글자뿐인 제목인데도, 박스 모델 그림에 파란 content 영역과 그 위아래 margin이 표시돼요. 제목조차 상자라는 걸 눈으로 확인할 수 있어요. 이번엔 입력칸, 푸터 링크도 하나씩 클릭해보세요. 전부 네모 상자죠?
💡 튜터의 결론: 모든 요소는 content를 가운데 두고 padding → border → margin으로 감싼 네 겹 상자예요. 이 관점만 잡으면, 화면의 간격·테두리·여백이 전부 "상자의 어느 겹을 건드리느냐"의 문제로 보이기 시작해요. 다음 Step부터 한 겹씩 직접 만져봅니다.
Step 2: "안쪽 여백 — padding으로 숨통 틔우기"
가장 먼저 만질 겹은 padding(안쪽 여백) 이에요. 내용과 테두리 사이를 벌려서, 글자가 상자 벽에 딱 붙어 답답해 보이는 걸 막아줘요. 지금 우리 로그인 버튼이 딱 그래요. "로그인" 글자가 버튼 가장자리에 바짝 붙어서 옹색해 보이죠. 여기에 padding을 줘봅니다.
/* instagram-clone-frontend/css/base.css */
.btn-login {
padding: 0.625rem;
/* (배경색·글자색은 지난 시간에 준 그대로) */
}
padding: 0.625rem; 한 줄이면, "로그인" 글자 사방에 여백이 생기면서 버튼이 큼직하고 누르기 좋게 부풀어요. 저장하고 바로 확인해보세요. 글자는 그대로인데 버튼만 커졌죠?
여기서
rem이라는 단위가 처음 보일 거예요. 글자 크기를 기준으로 한 단위인데, Step 5에서 제대로 배워요. 지금은1rem이 보통16px(픽셀) 이라고만 알아두면 충분해요. 그러니0.625rem은 대략 10px쯤 되는 여백이에요.
한 값 · 두 값 — padding 줄여 쓰기
padding은 위·오른쪽·아래·왼쪽 네 방향에 줄 수 있어요. 그런데 매번 네 줄을 쓰면 번거로우니, 값을 몇 개 적느냐로 한 번에 지정하는 방법이 있어요.
padding: 0.625rem; → 네 방향 모두 같은 여백
padding: 0.5rem 0.75rem; → 위아래 0.5 / 좌우 0.75
값을 하나만 쓰면 사방이 똑같고, 둘을 쓰면 "위아래 / 좌우" 순서예요. 우리 네비게이션 메뉴 항목에 이 두 값짜리를 써봤어요.
/* instagram-clone-frontend/css/base.css */
.nav-menu > li {
padding: 0.5rem 0.75rem;
background-color: #efefef;
}
메뉴 글자 주변에 위아래로는 좁게, 좌우로는 넓게 여백이 생기면서, 회색 배경이 깔린 메뉴 항목이 버튼처럼 보기 좋아져요. 여기서 한 가지 눈여겨볼 게 있어요 — padding은 배경색이 깔리는 영역까지 포함해요. 그래서 안쪽 여백을 늘리면 회색 배경도 함께 넓어지죠.
마지막으로 입력칸에도 padding을 줘서 글자 칠 공간을 넓혀요.
/* instagram-clone-frontend/css/base.css */
.form-input {
padding: 0.625rem;
/* (테두리·너비는 다음 Step에서) */
}
입력칸을 클릭해서 글자를 쳐보면, 글자가 칸 왼쪽 벽에 붙지 않고 살짝 안쪽에서 시작해요. 훨씬 편안하죠.
🎯 핵심 멘트: padding은 내용과 테두리 사이의 안쪽 여백이에요. 값 하나면 사방, 두 개면 "위아래 좌우". 배경색이 padding 영역까지 깔린다는 점을 기억하세요 — 그래서 padding은 "내용에 숨통을 틔우는" 도구예요.
Step 3: "테두리와 바깥 여백 — border · margin"
이제 상자의 바깥쪽 두 겹, border(테두리) 와 margin(바깥 여백) 을 만져요.
border — 상자를 두르는 선
테두리는 세 가지를 한 번에 적어요: 두께 · 모양 · 색.
/* instagram-clone-frontend/css/base.css */
.form-input {
padding: 0.625rem;
border: 1px solid #dbdbdb;
border-radius: 4px;
}
border: 1px solid #dbdbdb;를 풀어보면 — 1px(두께 1픽셀) solid(실선) #dbdbdb(연한 회색) 예요. 저장하면 밋밋하던 입력칸에 연한 회색 테두리가 둘러져서, "여기가 입력하는 칸이구나" 하고 또렷하게 보여요.
바로 아래 border-radius: 4px;는 테두리의 모서리를 둥글게 깎아요. 숫자가 클수록 더 둥글어지죠. 4px면 살짝 둥근 정도예요. 인스타그램의 입력칸과 버튼이 딱 이렇게 모서리가 부드럽게 둥글죠.
🙋 직접 해보세요 — "모서리를 얼마나 둥글게?"
border-radius의 4px를 20px로 바꿔 저장해보세요. 입력칸 모서리가 확 둥글어져요. 더 키워서 9999px를 주면? 양 끝이 완전히 동그란 알약 모양이 돼요. 숫자 하나로 모양이 이렇게 바뀌는 걸 직접 확인해보세요. 확인했으면 다시 4px로 되돌리고요.
margin — 상자와 상자 사이 거리
margin은 이 상자와 옆 상자 사이를 벌리는 바깥 여백이에요. padding이 "상자 안쪽"이라면, margin은 "상자 바깥쪽"이죠. 입력칸 위에 살짝 간격을 줘서 라벨과 칸이 붙지 않게 해봐요.
/* instagram-clone-frontend/css/base.css */
.form-input {
width: 100%;
margin-top: 0.25rem;
padding: 0.625rem;
border: 1px solid #dbdbdb;
border-radius: 4px;
background-color: #fafafa;
}
margin-top: 0.25rem;은 "위쪽 바깥 여백만" 살짝 준 거예요. 이렇게 -top · -bottom · -left · -right를 붙이면 한 방향만 지정할 수 있어요. 여기서 같이 들어간 width: 100%;는 입력칸 너비를 부모(폼) 너비에 꽉 맞춘다는 뜻인데, 그래서 입력칸이 라벨 아래로 내려가 세로로 시원하게 쌓여요.
padding과 margin, 뭐가 다를까
둘 다 "여백"이라 헷갈리기 쉬운데, 결정적 차이가 하나 있어요.
padding (안쪽) margin (바깥)
┌────────────────┐ ┌────────────────┐
│░░░░ 배경색 ░░░░│ │ 배경색 없음 │
│░░┌────────┐░░│ │ ┌────────────┐ │
│░░│ 내용 │░░│ │ │ 내용·테두리 │ │
│░░└────────┘░░│ │ └────────────┘ │
└────────────────┘ └────────────────┘
배경색이 padding까지 깔림 margin은 투명 — 배경 안 깔림
padding 영역엔 배경색이 깔리고, margin 영역은 투명해요. 그래서 "글자 주변을 배경색으로 넓히고 싶다" → padding, "옆 요소와 거리를 두고 싶다" → margin, 이렇게 골라 써요.
폼 전체를 흰 카드로 — margin auto의 마법
마지막으로 폼 전체를 감싸봐요. 테두리로 카드처럼 두르고, 바깥 여백으로 다른 요소와 떨어뜨리고요.
/* instagram-clone-frontend/css/base.css */
.login-form {
width: 90%;
max-width: 22rem;
margin: 1.5rem auto;
padding: 1.5rem;
border: 1px solid #dbdbdb;
border-radius: 8px;
background-color: #ffffff;
}
여기서 margin: 1.5rem auto;를 보세요. 두 값이니 "위아래 / 좌우" 였죠. 위아래는 1.5rem, 그리고 좌우는 auto 예요. 좌우 margin을 auto로 주면, 브라우저가 남는 공간을 좌우에 똑같이 나눠줘요. 결과는? 폼이 화면 가로 가운데로 옮겨와요! 왼쪽으로 쏠려 있던 폼이 중앙 정렬되는 거죠.
저장해보면 휑하던 폼이 드디어 정갈한 흰 카드가 돼서 화면 가운데에 놓여요. 지난 시간 마지막에 아쉬웠던 그 모습이 확 달라지죠.
⚠️ 여기까지는 "가로" 가운데예요:
margin auto는 좌우만 가운데로 맞춰요. 화면 세로 정중앙에 딱 띄우거나, 여러 요소를 나란히 배치하는 건 또 다른 도구(Flexbox)가 필요한데, 그건 곧 배워요. 오늘은 "바깥 여백으로 가로 가운데를 맞춘다"까지만.
💡 튜터의 결론: border는 두께·모양·색을 한 줄로 적고(1px solid #dbdbdb), border-radius로 모서리를 둥글려요. margin은 상자 바깥 거리이고 투명하다는 게 padding과의 차이예요. 그리고 margin: ... auto는 블록 요소를 가로 가운데로 보내는 자주 쓰는 기법이에요.
Step 4: "너비 계산의 함정 — box-sizing"
지금부터 CSS 초심자가 거의 100% 한 번은 걸리는 함정을 미리 피해갈게요. 질문 하나로 시작해요. 입력칸에 이렇게 줬다고 해봐요.
width: 100%; ← 너비는 부모에 꽉 맞게
padding: 0.625rem; ← 안쪽 여백
border: 1px solid; ← 테두리
상식적으로는 "너비 100%니까 부모 칸에 딱 맞겠지" 싶죠. 그런데 기본 설정에서는 — 입력칸이 부모보다 살짝 삐져나가요. 가로 스크롤이 생기거나 칸이 오른쪽으로 넘쳐요. 왜 그럴까요?
기본값에서 width는 content(내용) 영역만의 너비예요. padding과 border는 그 위에 더해져요. 그림으로 보면 이래요.
box-sizing: content-box (기본값)
┌──────────────────────────────────────────┐
│ border │ padding │ width: 100% │ ... │
└──────────────────────────────────────────┘
실제 차지 너비 = 100% + padding 좌우 + border 좌우 ← 넘침!
width: 100%로 내용이 이미 부모를 꽉 채웠는데, 거기에 padding과 border 두께가 더 붙으니 총합이 100%를 넘어버리는 거예요. 이게 그 악명 높은 함정이에요.
해결책은 딱 한 줄이에요. box-sizing: border-box 를 켜면, width가 "내용만"이 아니라 "테두리까지 포함한 전체 너비"를 뜻하게 바뀌어요.
box-sizing: border-box
┌──────────────────────────────────────────┐
│ border │ padding │ content │ │
│←──────────── width: 100% ────────────────→│
└──────────────────────────────────────────┘
실제 차지 너비 = 정확히 100% ← 안 넘침!
이제 padding과 border가 width 안쪽으로 들어와서, 아무리 여백·테두리를 줘도 전체 너비는 딱 100%를 지켜요. 그래서 거의 모든 프로젝트가 페이지 첫머리에 이 한 줄을 깔고 시작해요.
/* instagram-clone-frontend/css/base.css */
* {
box-sizing: border-box;
}
여기 *(별표)는 처음 보는 선택자죠. 전체 선택자라고 부르는데, "페이지의 모든 요소"를 한꺼번에 골라요. 그러니 이 규칙은 "모든 요소를 border-box 방식으로 계산하라"는 뜻이에요. 우리 base.css 맨 위에 이미 이 한 줄을 깔아뒀어요. 덕분에 Step 3에서 입력칸에 width: 100% + padding + border를 한꺼번에 줘도 칸이 안 넘치고 부모에 깔끔하게 맞았던 거예요.
⚠️ 호환성 메모:
box-sizing: border-box는 아주 오래전부터 모든 브라우저가 지원하는, 완전히 안정된 기능이에요. 2026년 현재 이 한 줄은 사실상 모든 실무 프로젝트의 표준 출발점이니, 새 CSS 파일을 만들면 습관처럼 맨 위에 깔아두세요.
🎯 핵심 멘트: 기본값(content-box)에서는 width에 padding·border가 더해져 상자가 넘쳐요. * { box-sizing: border-box; } 한 줄이면 width가 테두리까지 포함한 전체 너비가 되어 계산이 직관적으로 맞아떨어져요. 모든 CSS의 첫 줄로 외워두세요.
Step 5: "크기의 단위 — px · rem · % · vw/dvh"
지금까지 여백과 너비에 rem · px · % 같은 단위를 슬쩍슬쩍 써왔죠. 이제 정체를 제대로 밝힐 차례예요. CSS의 크기 단위는 크게 절대 단위와 상대 단위로 나뉘어요.
px — 절대 단위, 변하지 않는 자
px(픽셀)은 화면의 점 하나 크기예요. 16px이라고 하면 어디서나 똑같이 16점이에요. 변하지 않으니 예측하기 쉽죠. 테두리 두께(border: 1px)처럼 "딱 이만큼"이 분명해야 하는 곳에 잘 맞아요.
다만 px의 약점이 하나 있어요. 사용자가 브라우저에서 "글자 크게 보기"를 켜도, px로 고정한 크기는 꿈쩍도 안 해요. 그래서 글자나 여백을 전부 px로만 짜면, 시력이 약한 분이 글자를 키우려 해도 레이아웃이 안 따라와요.
rem — 상대 단위, 글자 크기를 따라가는 자
rem은 페이지 기본 글자 크기를 기준으로 한 배수예요. 브라우저 기본 글자 크기는 보통 16px이라, 1rem = 16px, 0.5rem = 8px, 1.5rem = 24px이 돼요.
핵심은 — 사용자가 기본 글자 크기를 20px로 키우면, 1rem도 따라서 20px이 된다는 거예요. rem으로 짜둔 여백·글자가 사용자 설정에 맞춰 함께 커지죠. 그래서 글자 크기와 여백에는 rem을 기본으로 쓰는 게 2026년 실무의 정석이에요. 우리가 padding·margin·font-size에 rem을 쓴 이유가 이거예요.
기본 글자 16px 환경 사용자가 20px로 키운 환경
1rem = 16px 1rem = 20px (함께 커짐)
1.5rem = 24px 1.5rem = 30px
16px = 16px (고정) 16px = 16px (안 변함)
% — 부모를 기준으로 한 비율
%는 부모 요소를 기준으로 한 비율이에요. width: 90%면 "부모 너비의 90%"죠. 부모가 커지면 따라 커지고 작아지면 따라 작아져서, 화면 크기에 유연하게 반응해요. 우리 폼이 width: 90%에 max-width: 22rem인 건 — "기본은 부모의 90%를 쓰되, 아무리 커도 22rem(약 352px)은 넘지 마라"는 뜻이에요. 좁은 화면에선 90%로 줄고, 넓은 화면에선 22rem에서 멈춰 너무 길어지지 않죠.
vw · dvh — 화면(뷰포트) 기준
vw와 vh는 브라우저 화면 자체를 기준으로 해요. vw는 화면 너비의 1%, vh는 화면 높이의 1%예요. 100vw면 화면 가로 전체죠.
여기에 최근 형제가 생겼어요. 모바일에서 주소창이 스르륵 사라졌다 나타나면 화면 높이가 실시간으로 변하는데, vh는 이 변화를 잘 못 따라가서 화면이 어긋나곤 했어요. 이걸 해결한 게 dvh(dynamic viewport height) 예요. 주소창 상태에 맞춰 실시간으로 화면 높이를 다시 재죠. 모바일에서 "화면에 딱 맞는 전체 높이"가 필요하면 100vh보다 100dvh가 안전해요.
⚠️ 호환성 메모:
dvh를 비롯한 새 화면 단위(dvh·svh·lvh)는 2025년 중반에 모든 주요 브라우저에서 안정적으로 쓸 수 있게 됐어요. 2026년 현재 전 세계 사용자의 약 95%가 지원 브라우저를 쓰고 있으니, 모바일 대응에 안심하고 활용하세요.
💡 튜터의 결론: px는 변하지 않는 절대 단위(테두리처럼 딱 정해야 할 때), rem은 글자 크기를 따라가는 상대 단위(글자·여백의 기본), %는 부모 기준 비율(유연한 너비), vw/dvh는 화면 기준이에요. 외울 필요 없이 "변하면 안 되는 건 px, 사용자 설정을 존중할 건 rem, 화면에 맞출 건 % 와 dvh" 정도로 감만 잡아두세요.
Step 6: "색을 자유롭게 — hex · rgb · hsl · oklch"
지난 시간 #fafafa 같은 색 코드를 쓰면서 "색 표현법은 다음에 제대로"라고 미뤄뒀죠. 이제 그 약속을 지킬 차례예요. CSS에서 같은 색을 적는 방법이 여럿인데, 대표 네 가지를 봐요. 놀랍게도 아래 네 줄은 전부 똑같은 인스타그램 파란색이에요.
color: #0095f6; /* hex — 16진수 */
color: rgb(0, 149, 246); /* rgb — 빨강·초록·파랑 */
color: hsl(204, 100%, 48%); /* hsl — 색상·채도·명도 */
color: oklch(0.67 0.17 245); /* oklch — 2026 추천 */
하나씩 감만 잡아볼게요.
- hex(헥스):
#뒤에 여섯 자리. 앞 두 자리가 빨강, 가운데 둘이 초록, 끝 둘이 파랑의 양이에요. 가장 흔하게 보이는 표기라 우리base.css도 이걸로 통일했어요. 짧고 익숙하지만, 숫자만 봐선 무슨 색인지 가늠하기 어렵죠. - rgb: 빨강·초록·파랑을 0~255로 직접 적어요. hex와 원리는 같은데 10진수라 조금 더 읽기 쉬워요. 투명도를 더하고 싶으면
rgb(0, 149, 246, 0.5)처럼 뒤에 0~1 값을 붙여 반투명하게 만들 수 있어요. - hsl: 색상(Hue) · 채도(Saturation) · 명도(Lightness) 예요. 이건 사람 직관에 가까워요. "같은 파란색인데 더 밝게"가 필요하면 맨 뒤 명도 값만 올리면 되거든요. 색을 미세 조정할 때 편해요.
- oklch: 가장 최신 방식이에요. hsl과 비슷하게 밝기·진하기·색상을 다루는데, 사람 눈이 느끼는 밝기에 더 정확히 맞춰져 있어요. 그래서 "명도를 10% 올렸다"가 어떤 색이든 비슷한 정도로 밝아져서, 색 테마를 일관되게 만들기 좋아요. 2026년 현재 디자인 시스템에서 점점 표준으로 자리 잡고 있어요.
🙋 직접 해보세요 — "정말 같은 색일까?"
base.css의 .btn-login 배경을 #0095f6에서 rgb(0, 149, 246)으로 바꿔 저장해보세요. 버튼 색이 그대로죠? 이번엔 hsl(204, 100%, 48%)로 바꿔도 똑같아요. 표기법만 다를 뿐 같은 색이라는 걸 눈으로 확인할 수 있어요. hsl로 둔 채 명도(마지막 48%)를 70%로 올리면? 같은 파랑이 환하게 밝아져요. 확인했으면 원래 #0095f6으로 되돌리고요.
⚠️ 호환성 메모:
oklch는 2026년 현재 모든 주요 브라우저에서 안정적으로 동작해요(CSS 색상 표준에 정식 포함). 새 프로젝트라면 마음 놓고 써도 되고, 아주 오래된 환경까지 챙겨야 한다면 hex/rgb를 함께 두는 정도면 충분해요.
🎯 핵심 멘트: 같은 색을 hex · rgb · hsl · oklch 네 방법으로 적을 수 있어요. 익숙한 건 hex, 직관적인 건 hsl(명도만 올리면 밝아짐), 2026년 추천은 oklch(사람 눈에 맞는 밝기)예요. 팀에서는 보통 한 표기법으로 통일하니, 우리는 base.css를 hex로 맞췄어요.
Step 7: "글자 다듬기 + base.css 완성"
마지막 겹은 타이포그래피(typography), 글자를 다루는 기술이에요. 지난 시간 font-family(글꼴)와 font-weight(굵기)는 맛봤으니, 오늘은 크기와 줄 간격까지 더해 글을 진짜 읽기 좋게 만들어요.
페이지 전체의 글자 기본값부터 잡아요.
/* instagram-clone-frontend/css/base.css */
body {
font-family: "Apple SD Gothic Neo", "Segoe UI", sans-serif;
font-size: 1rem;
line-height: 1.6;
}
- font-family: 글꼴 목록이에요. 앞 글꼴이 없으면 다음 걸 쓰고, 다 없으면 마지막
sans-serif(고딕 계열)로 넘어가요. 안전망을 깔아두는 거죠. - font-size: 1rem: 기본 글자 크기를
1rem(보통 16px)으로. Step 5에서 배운 rem을 글자에 그대로 적용한 거예요. - line-height: 1.6: 줄 간격이에요. 숫자
1.6은 "글자 크기의 1.6배만큼 줄 높이를 잡아라"는 뜻이라, 글자가 커지면 줄 간격도 비례해서 커져요. 문단이 빽빽하지 않고 숨 쉴 틈이 생겨 읽기 편해져요.
여기에 위계를 더해요. 제목 바로 뒤 안내 문단은 조금 작고 흐리게 해서, 제목과 구분되게요.
/* instagram-clone-frontend/css/base.css */
h2 + p {
color: #8e8e8e;
font-size: 0.9rem;
}
font-size: 0.9rem으로 기본보다 살짝 작게, 색은 연한 회색으로. 제목은 또렷하고 설명은 차분한 자연스러운 위계가 생겨요.
드디어 완성된 base.css
오늘 한 겹씩 쌓아온 결과예요. 박스 모델·단위·색·타이포가 다 들어간 완성본을 두 부분으로 나눠 봅니다. 먼저 바탕과 헤더예요.
/* instagram-clone-frontend/css/base.css */
/* 모든 요소를 border-box로 — 너비 계산을 직관적으로 */
* {
box-sizing: border-box;
}
/* 페이지 바탕 (태그 선택자 + 타이포그래피) */
body {
margin: 0;
background-color: #fafafa;
color: #262626;
font-family: "Apple SD Gothic Neo", "Segoe UI", sans-serif;
font-size: 1rem;
line-height: 1.6;
}
a {
color: #00376b;
text-decoration: none;
}
/* 헤더 네비게이션 (관계 선택자) */
header nav a {
color: #262626;
font-weight: bold;
}
.nav-menu > li {
padding: 0.5rem 0.75rem;
background-color: #efefef;
}
h2 + p {
color: #8e8e8e;
font-size: 0.9rem;
}
이어서 로그인 폼과 입력칸, 버튼이에요.
/* 로그인 폼 — 박스 모델 + 단위 + 타이포 */
.login-form {
width: 90%;
max-width: 22rem;
margin: 1.5rem auto;
padding: 1.5rem;
border: 1px solid #dbdbdb;
border-radius: 8px;
background-color: #ffffff;
& label {
margin-right: 0.5rem;
color: #8e8e8e;
font-weight: bold;
}
}
.form-input {
width: 100%;
margin-top: 0.25rem;
padding: 0.625rem;
border: 1px solid #dbdbdb;
border-radius: 4px;
background-color: #fafafa;
}
#username {
background-color: #efefef;
}
.login-form p:has(input:checked) {
background-color: #e7f3ff;
}
.btn-login {
width: 100%;
margin-top: 0.5rem;
padding: 0.625rem;
border: none;
border-radius: 8px;
background-color: #0095f6;
color: #ffffff;
font-size: 1rem;
font-weight: bold;
}
body에 margin: 0을 준 것도 보이죠? 브라우저가 기본으로 페이지 가장자리에 주는 약간의 여백을 지워서, 배경색이 화면 끝까지 꽉 차게 한 거예요. 이것도 margin을 다루는 한 가지예요.
저장하고 로그인 페이지를 보면 — 연회색 바탕 위에, 가로 가운데 놓인 흰 카드, 그 안에 테두리 두른 입력칸들이 세로로 시원하게 쌓이고, 큼직한 파란 버튼까지. 지난 시간 휑하던 그 페이지가 우리가 아는 인스타그램 로그인 화면에 성큼 가까워졌어요.
🎯 핵심 멘트: font-size는 글자 크기(rem 권장), font-weight는 굵기, line-height는 줄 간격(숫자만 쓰면 글자 크기 배수)이에요. 줄 간격 1.5~1.6은 본문 가독성의 황금비라고 기억해두세요.
마무리
오늘 우리는 화면을 보는 눈을 하나 바꿨어요. 모든 요소는 상자라는 눈이요. 그리고 그 상자의 네 겹을 한 겹씩 직접 만져서, 휑하던 로그인 페이지를 정갈한 카드로 단장하고 base.css를 완성했어요.
오늘 배운 것 한눈에 정리
🎯 하나, 박스 모델 — 모든 요소는 content(내용) · padding(안쪽 여백) · border(테두리) · margin(바깥 여백) 네 겹 상자예요.
🎯 둘, padding은 내용에 숨통을 틔우고 배경색이 깔려요. border는 두께·모양·색을 한 줄로, margin은 상자 바깥 거리(투명)예요. margin: ... auto는 가로 가운데 정렬이고요.
🎯 셋, box-sizing: border-box는 width가 테두리까지 포함하게 만들어, 너비가 넘치는 함정을 막아요. 모든 CSS의 첫 줄.
🎯 넷, 단위 — px(절대), rem(글자 크기 배수, 기본), %(부모 비율), vw/dvh(화면 기준).
🎯 다섯, 색 — hex · rgb · hsl · oklch 네 표기법. 같은 색을 다르게 적을 뿐이고, 2026년 추천은 oklch예요.
🎯 여섯, 타이포 — font-size(rem) · font-weight · line-height(줄 간격, 1.5~1.6).
그런데 아직 "배치"는 절반만 했죠
오늘 margin: ... auto로 폼을 가로 가운데로 옮겼어요. 한 걸음 나아갔죠. 하지만 진짜 인스타그램을 떠올려보면 — 네비게이션 바는 스크롤해도 화면 위에 딱 붙어 있고, 게시물들은 가지런히 세로로 흐르고, 좋아요·댓글 아이콘은 한 줄에 나란히 놓이죠. 이런 "요소들을 원하는 자리에 놓고 흐르게 하는" 일은 박스 모델만으로는 부족해요.
왜냐면 우리는 아직 요소가 화면에서 어떻게 흐르고 쌓이는지를 결정하는 도구를 안 배웠거든요. 상자를 가로로 눕힐지 세로로 세울지, 화면에 고정할지 흐르게 둘지 — 이게 다음 주제예요.
다음 시간 예고
다음 시간엔 상자들을 어떻게 배치하고 흐르게 할지를 배웁니다. 핵심은 display(요소가 한 줄을 통째로 쓸지 글자처럼 옆으로 흐를지 정하는 속성), position(요소를 원래 흐름에서 떼어내 원하는 위치에 고정하는 속성), 그리고 z-index(상자가 겹칠 때 누가 위로 올라올지)예요.
이걸 익히면 — 스크롤해도 따라오는 상단 네비게이션 바를 만들 수 있어요. 인스타그램 맨 위 그 고정된 메뉴 바요. 오늘 상자의 "크기와 여백"을 다뤘다면, 다음 시간은 그 상자를 "어디에 놓을지"예요. 오늘 완성한 base.css 위에, 다음 시간엔 배치를 담당할 새 스타일 파일을 더해갑니다.
오늘 모든 걸 상자로 보는 눈을 얻었으니, 다음 시간엔 그 상자들을 마음대로 배치해봅시다!
과제
[구현] 피드 게시물을 카드로 단장하기
오늘 로그인 폼을 흰 카드로 만든 것처럼, 피드 페이지(feed.html)의 게시물 하나하나(<article>)도 카드로 단장해봐요. base.css에 아래 규칙을 직접 추가하세요.
요구 사항:
- 게시물 카드:
article선택자에background-color(흰색) ·padding·border(연회색 1px) ·border-radius·margin-bottom(게시물 사이 간격)을 줘서 카드 모양으로. 너비는max-width(예:32rem)와margin: ... auto로 가로 가운데 정렬도 해보기. - 사진 설명 다듬기:
figcaption에padding(위아래 약간)과font-size(0.9rem정도), 색을 줘서 사진과 구분되게. - 버튼 여백: 게시물의 "더보기/공유" 버튼(
<button>)에padding을 줘서 누르기 좋게. - 단위는 rem으로: 여백·글자 크기는 가능하면
rem으로 적어보기.
각 규칙을 저장할 때마다 브라우저에서 게시물이 어떻게 변하는지 확인하고, box-sizing: border-box가 이미 깔려 있으니 width에 padding을 더해도 카드가 안 넘치는 걸 직접 보세요.
[탐구] 개발자 도구로 박스 모델 읽기
자주 쓰는 웹사이트 한 곳을 열고 F12 → Elements 탭에서 아무 버튼이나 카드를 클릭해보세요. 오른쪽 패널 아래 박스 모델 그림(파랑·초록·노랑·주황 네모)이 보여요.
확인 항목:
- 그 요소의
padding은 사방이 같은가, 다른가? 숫자는 얼마인가? margin은 어느 방향에 얼마나 들어가 있나?content(파란 영역)의 가로·세로 크기는 얼마인가?- 그 사이트는
box-sizing을border-box로 쓰고 있나? (Computed탭에서box-sizing검색)
관찰한 수치를 3~4줄로 정리하고, "이 사이트는 여백을 넉넉히 쓰는 편인가, 빽빽한 편인가" 한 줄 의견을 덧붙여주세요.
생각해볼 주제
1. 위아래 margin은 왜 "합쳐지지" 않고 큰 쪽만 남을까?
박스 두 개를 세로로 놓고, 위 박스에 margin-bottom: 20px, 아래 박스에 margin-top: 30px을 줬다고 해봐요. 상식적으로는 둘 사이 간격이 20 + 30 = 50px일 것 같죠. 그런데 실제로 재보면 50px이 아니라 30px, 즉 둘 중 큰 값만 남아요. 이걸 margin 상쇄(collapsing)라고 불러요. 왜 브라우저는 두 여백을 더하지 않고 큰 쪽만 남기도록 설계됐을까요? 만약 항상 더해졌다면 문서를 쓸 때 어떤 불편이 생겼을지 상상해보세요.
2. 글자 크기를 px로 박으면 누가 곤란해질까?
font-size를 전부 px로 고정한 사이트와, rem으로 짠 사이트가 있다고 해봐요. 시력이 약해서 브라우저 설정에서 기본 글자 크기를 키운 사용자가 두 사이트를 방문하면, 각각 어떻게 보일까요? "디자인이 정확히 의도대로 나온다"는 px의 장점이, 어떤 사용자에게는 왜 단점이 되는 걸까요? 편리함과 접근성 사이의 선택을 생각해보세요.
3. hex로 충분한데 왜 굳이 oklch를 권할까?
색을 적는 방법이 이미 hex·rgb·hsl로 충분해 보이는데, 2026년 디자인 시스템은 자꾸 oklch를 권해요. "같은 색을 더 밝게/어둡게"를 여러 색에 똑같은 정도로 적용해야 하는 상황(예: 버튼의 기본·호버·눌림 상태 색을 한 세트로)을 떠올려보세요. hsl로 명도만 올렸을 때와, oklch로 밝기를 올렸을 때 결과가 왜 다를 수 있을까요? "사람 눈에 일정하게 보이는 밝기"가 왜 중요한지 생각해보세요.
✅ 예시 답안정답 보기
과제와 생각해볼 주제의 예시답안이에요. 정답이 하나만 있는 건 아니에요. 여백 값이나 색은 여러분 취향대로 골라도 좋아요. 중요한 건 박스 모델의 네 겹을 의도대로 다뤘는가 예요.
🎯 [과제 1 예시답안] 피드 게시물을 카드로 단장하기
핵심 접근
이 과제의 핵심은 오늘 배운 박스 모델 네 겹을 게시물(<article>)에 직접 입혀보는 거예요. 로그인 폼을 흰 카드로 만든 그 방식 그대로, 게시물도 padding(안쪽 숨통) · border(테두리) · margin(게시물 사이 간격)으로 카드처럼 묶으면 돼요. box-sizing: border-box는 이미 base.css 맨 위에 깔려 있으니, width에 padding을 더해도 카드가 넘치지 않아요.
예시 구현
게시물의 "더보기/공유" 버튼은 먼저 HTML에서 클래스를 붙여두면 고르기 편해요.
<!-- instagram-clone-frontend/feed.html — 게시물 버튼 -->
<button type="button" class="post-action" popovertarget="postMenu">⋯ 더보기</button>
<button type="button" class="post-action" command="show-modal" commandfor="shareDialog">공유</button>
이제 base.css 맨 아래에 게시물용 규칙을 추가해요.
/* instagram-clone-frontend/css/base.css 맨 아래에 추가 */
/* 게시물 카드 — 박스 모델 네 겹 */
article {
max-width: 32rem;
margin: 1rem auto;
padding: 1rem;
border: 1px solid #dbdbdb;
border-radius: 8px;
background-color: #ffffff;
}
/* 사진 설명 다듬기 */
article figcaption {
padding: 0.5rem 0;
color: #8e8e8e;
font-size: 0.9rem;
}
/* 게시물 버튼 — 누르기 좋게 */
.post-action {
margin-right: 0.5rem;
padding: 0.5rem 0.75rem;
border: 1px solid #dbdbdb;
border-radius: 4px;
background-color: #fafafa;
}
각 규칙이 하는 일을 짚어볼게요.
article— 게시물 하나하나를 흰 카드로.max-width: 32rem으로 너무 넓어지지 않게 막고,margin: 1rem auto로 가로 가운데에 놓으며 게시물 사이를 위아래1rem씩 벌려요.padding: 1rem으로 안쪽 숨통을 틔우고 테두리로 둘렀어요.article figcaption— 사진 설명을 살짝 작고(0.9rem) 흐린 회색으로, 위아래 padding으로 사진과 띄워요..post-action— 더보기/공유 버튼에 padding을 줘서 누르기 좋게,margin-right로 두 버튼 사이를 벌려요.
저장하면 밋밋하게 나열되던 게시물들이 각각 둥근 흰 카드로 묶이고, 가운데 정렬되어 한결 정돈돼 보여요.
채점 포인트
| 항목 | 확인 내용 |
|---|---|
| padding 적용 | 게시물·버튼 안쪽 여백으로 숨통을 틔웠는가 |
| border 적용 | 두께·모양·색을 한 줄로 적고 모서리를 둥글렸는가 (border-radius) |
| margin 적용 | 게시물 사이 간격(margin-bottom 또는 margin)을 줬는가 |
| margin auto | margin: ... auto로 카드를 가로 가운데로 옮겼는가 |
| 단위 rem | 여백·글자 크기를 가능한 한 rem으로 적었는가 |
| 결과 확인 | 저장 후 카드가 안 넘치는 걸(border-box 효과) 눈으로 봤는가 |
흔한 실수
margin: auto인데 가운데로 안 옴:margin: ... auto로 가로 가운데 정렬이 되려면 그 요소에width나max-width가 있어야 해요. 너비 제한이 없으면 요소가 이미 가로를 꽉 채워서 auto가 밀어줄 공간이 없거든요.padding과margin을 헷갈림: 게시물 "사이" 간격은 바깥 여백margin이고, 게시물 "안쪽" 글자와 테두리 사이는padding이에요. 배경색을 보면 구분돼요 — 배경이 깔리면 padding, 안 깔리면 margin.border값 순서/단위 빠뜨림:border: solid 1px;처럼 색을 빼거나,border: 1 solid #ccc;처럼px를 빼면 안 먹을 수 있어요.두께 모양 색(1px solid #dbdbdb) 세 가지를 다 챙기세요.
실무 개선 포인트 (심화)
지금은 게시물 카드 규칙을 base.css에 이어 붙였어요. 그런데 게시물 사이 간격을 article의 margin으로 주면, 첫 게시물 위에도 margin이 붙어서 헤더와의 간격이 의도보다 벌어질 수 있어요. 실무에서는 이런 "첫/마지막 요소만 여백 빼기"를 다루는 기법이 따로 있는데, 그건 레이아웃을 본격적으로 배우면서 만나요. 지금은 "margin으로 카드 사이를 벌린다"로 충분하고, "첫 카드 여백이 살짝 어색할 수 있다"만 눈여겨봐 두세요.
🎯 [과제 2 예시답안] 개발자 도구로 박스 모델 읽기
핵심 접근
이 과제는 코드를 짜는 게 아니라 읽는 연습이에요. 잘 만든 사이트가 여백을 어떻게 주는지 박스 모델 그림으로 관찰하면, "아, 이만큼이 보기 좋은 여백이구나" 하는 감각이 생겨요. 숫자를 외우는 게 아니라 패턴을 느끼는 과제예요.
분석 가이드
F12 → Elements 탭에서 요소를 클릭하면, 오른쪽 패널 아래에 파랑·초록·노랑·주황 네모 그림이 보여요. 안쪽부터 content(파랑) · padding(초록) · border(노랑) · margin(주황)이에요. 이때 세 가지를 관찰해요.
- padding — 버튼이나 카드의 안쪽 여백이 사방 같은지, 위아래와 좌우가 다른지. 보통 버튼은 "위아래 좁게, 좌우 넓게"가 많아요.
- margin — 요소 사이 간격이 어느 방향에 얼마나 들어가 있는지. 카드 사이 간격이 주로 여기서 나와요.
- box-sizing —
Computed탭에서box-sizing을 검색하면 그 요소가border-box인지 보여요. 요즘 사이트는 대부분border-box예요.
모범 정리 예시
어느 쇼핑몰의 "장바구니" 버튼을 눌러봤어요. 박스 모델 그림을 보니 padding이 위아래
12px, 좌우24px로 좌우가 두 배 넓었어요. 글자가 옆으로 길어서 좌우 여백을 더 준 것 같아요. margin은 오른쪽에만8px이 있어서 옆 버튼과 띄워져 있었고요. content 영역은 가로72px, 세로20px이었어요.Computed탭에서 box-sizing을 찾아보니border-box였어요. 결론: 이 사이트는 버튼에 여백을 넉넉히 주는 편이고, box-sizing은 border-box로 통일돼 있었다.
채점 포인트
| 항목 | 확인 내용 |
|---|---|
| padding 관찰 | 사방이 같은지/다른지, 실제 수치를 읽었는가 |
| margin 관찰 | 어느 방향에 얼마나 들어가는지 확인했는가 |
| content 크기 | 파란 영역의 가로·세로 수치를 읽었는가 |
| box-sizing | border-box인지 Computed 탭에서 확인했는가 |
| 한 줄 의견 | "여백이 넉넉/빽빽" 같은 결론을 냈는가 |
흔한 실수
Styles패널만 보고 박스 모델 그림을 못 찾음: 박스 모델 색깔 그림은 오른쪽 패널을 아래로 스크롤하거나Computed탭 위쪽에 있어요. 스타일 규칙 목록과는 다른 곳에 있어요.px말고 다른 단위로 표시될 거라 기대: 개발자 도구의 박스 모델 그림은 계산된 최종 크기라 항상px로 보여줘요. CSS에rem으로 적었어도 여기선px로 환산돼 나와요.
실무 개선 포인트 (심화)
박스 모델 그림은 "내가 준 여백이 정말 의도대로 들어갔나"를 확인하는 가장 빠른 도구예요. 앞으로 "이 요소가 왜 이만큼 떨어져 있지?", "왜 칸이 넘치지?" 같은 문제를 만나면, 코드를 노려보기 전에 먼저 이 그림을 켜보세요. padding인지 margin인지, border가 width를 밀어내는 건 아닌지 — 눈으로 바로 답이 나와요. 화면을 추측하지 않고 도구로 확인하는 습관이 실력의 시작이에요.
💡 [생각해볼 주제 1 예시답안] 위아래 margin은 왜 "합쳐지지" 않고 큰 쪽만 남을까?
[문제 상황 요약]
위 박스에 margin-bottom: 20px, 아래 박스에 margin-top: 30px을 줬을 때, 둘 사이 간격이 50px이 아니라 30px(큰 쪽)만 남는 현상이에요. 이걸 margin 상쇄(collapsing)라고 불러요. 왜 브라우저는 두 여백을 더하지 않도록 설계됐을까요?
[튜터의 가이드 및 해설]
핵심은 "글이 자연스럽게 흐르도록" 이에요. 문서가 글자로 가득한 상황을 떠올려보세요.
문단(<p>)에는 보통 위아래 여백이 기본으로 붙어 있어요. 문단이 여러 개 연달아 쌓이면, 앞 문단의 아래 여백과 뒤 문단의 위 여백이 맞닿죠. 만약 이 둘이 더해진다면, 문단 사이 간격이 한 문단의 여백보다 두 배로 벌어져요. 글을 쓸 때마다 "어, 왜 이렇게 많이 벌어지지?" 하면서 여백을 일일이 절반으로 줄여야 할 거예요.
그래서 브라우저는 맞닿은 위아래 여백을 더하지 않고 큰 쪽 하나만 남기도록 설계됐어요. "이 요소는 위로 최소 30px은 떨어지고 싶다", "저 요소는 아래로 최소 20px은 떨어지고 싶다" 두 요청 중 더 큰 요청을 들어주면 양쪽이 다 만족하거든요. 덕분에 문단을 아무리 쌓아도 간격이 일정하게 유지돼요.
다만 이게 가끔 함정이 돼요. "20 + 30 = 50일 줄 알았는데 30만 나오네?" 하고 당황하는 거죠. 그리고 이 상쇄는 위아래(세로) margin에서만, 그것도 특정 조건에서만 일어나요. 좌우(가로) margin은 절대 상쇄되지 않고 항상 더해져요. 이 차이를 알아두면 "왜 세로 간격만 예상과 다르지?" 싶을 때 바로 이해돼요.
🎯 면접관을 홀리는 핵심 멘트
"margin 상쇄는 버그가 아니라 의도된 설계예요. 문단처럼 위아래 여백을 가진 요소가 연달아 쌓일 때 간격이 두 배로 벌어지지 않게, 맞닿은 세로 여백을 큰 쪽 하나로 합쳐줘요. 그래서 저는 간격이 예상과 다를 때 가장 먼저 상쇄를 의심하고, 한 방향(예:
margin-top만)으로 여백을 통일하는 식으로 예측 가능하게 관리합니다."
💡 [생각해볼 주제 2 예시답안] 글자 크기를 px로 박으면 누가 곤란해질까?
[문제 상황 요약]
font-size를 전부 px로 고정한 사이트와 rem으로 짠 사이트가 있어요. 시력이 약해서 브라우저 설정에서 기본 글자 크기를 키운 사용자가 둘을 방문하면 각각 어떻게 보일까요? px의 "정확함"이 왜 누군가에겐 단점이 될까요?
[튜터의 가이드 및 해설]
핵심은 "px는 사용자의 글자 크기 설정을 무시한다" 예요.
브라우저에는 "기본 글자 크기"를 키우는 설정이 있어요. 시력이 약한 분들이 자주 쓰죠. 이 설정을 16px에서 24px로 키웠다고 해봐요.
rem으로 짠 사이트는 1rem이 기준 글자 크기를 따라가니까, 기준이 24px이 되면 본문도 함께 커져요. 사용자가 "글자 크게" 했을 때 정말로 글자가 커지죠. 여백도 rem으로 줬다면 같이 늘어나서 레이아웃이 자연스럽게 따라와요.
반면 px로 박은 사이트는 16px이라고 적은 글자가 사용자가 뭘 어떻게 설정하든 그대로 16px이에요. 글자를 키우고 싶어도 안 커져요. 디자이너 입장에선 "내가 의도한 크기가 정확히 나온다"는 게 px의 장점이지만, 글자를 키워야만 읽을 수 있는 사용자에겐 그 정확함이 벽이 돼요.
그래서 2026년 실무의 기본은 글자와 여백엔 rem, 정말 변하면 안 되는 것(테두리 두께 1px 같은)엔 px이에요. "픽셀 단위로 완벽하게"보다 "모든 사용자가 읽을 수 있게"가 더 중요한 가치라고 보는 거죠. 이게 접근성(accessibility)의 기본 정신이에요.
🎯 면접관을 홀리는 핵심 멘트
"글자 크기를 px로 고정하면 사용자가 브라우저에서 글자를 키워도 반응하지 않아서, 저시력 사용자에게 접근성 장벽이 됩니다. 그래서 저는 글자와 여백은 사용자 설정을 따라가는 rem으로 짜고, 테두리처럼 변하면 안 되는 값만 px로 둡니다. '픽셀 완벽함'보다 '모두가 읽을 수 있음'을 우선하는 거죠."
💡 [생각해볼 주제 3 예시답안] hex로 충분한데 왜 굳이 oklch를 권할까?
[문제 상황 요약]
색을 적는 방법이 hex·rgb·hsl로 이미 충분해 보이는데, 2026년 디자인 시스템은 자꾸 oklch를 권해요. 버튼의 기본·호버·눌림 색을 한 세트로 만들 때처럼 "같은 색을 일정하게 밝게/어둡게" 해야 하는 상황에서, hsl과 oklch가 왜 다른 결과를 낼까요?
[튜터의 가이드 및 해설]
핵심은 "사람 눈이 느끼는 밝기와 숫자상의 밝기가 다르다" 예요.
hsl의 명도(Lightness)는 숫자상으로는 고르게 올라가지만, 사람 눈엔 그렇게 안 보여요. 예를 들어 노란색과 파란색에 똑같이 "명도 50%"를 줘도, 노란색이 훨씬 환하게 느껴져요. 그래서 여러 색에 "명도를 똑같이 10% 올려"라고 하면, 어떤 색은 확 밝아지고 어떤 색은 거의 그대로라 — 버튼 색 세트를 만들면 들쭉날쭉해져요.
oklch는 이 문제를 풀려고 만들어졌어요. oklch의 밝기 값은 사람 눈이 느끼는 밝기에 맞춰져 있어서, 어떤 색이든 "밝기를 10% 올려"라고 하면 비슷한 정도로 환해져요. 그래서 파란 버튼, 빨간 버튼, 초록 버튼의 호버 색을 "전부 밝기 +10%"로 한 번에 만들면, 셋 다 일관된 느낌으로 밝아지죠. 색 테마를 체계적으로 굴리기에 훨씬 편해요.
물론 색 하나를 그냥 칠하는 정도면 hex로도 전혀 문제없어요. 우리 base.css도 hex로 통일했고요. oklch의 진가는 여러 색을 규칙적으로 변형하고 관리해야 할 때, 즉 디자인 시스템이나 다크 모드처럼 색을 체계적으로 다룰 때 드러나요. 그래서 "지금 당장 hex를 버려라"가 아니라, "색을 규모 있게 다루기 시작하면 oklch가 답이 된다"고 이해하면 돼요.
🎯 면접관을 홀리는 핵심 멘트
"hsl의 명도는 숫자상으로만 고르고 사람 눈엔 색마다 밝기가 다르게 느껴져서, 여러 색에 같은 변형을 주면 들쭉날쭉해집니다. oklch는 사람 눈에 맞춘 밝기라 '모든 색을 +10% 밝게' 같은 일괄 변형이 일관되게 먹습니다. 그래서 단발 색칠엔 hex로 충분하지만, 버튼 상태나 다크 모드처럼 색을 체계적으로 굴려야 할 땐 oklch를 선택합니다."