FEInterview Prep

css · high priority

반응형 디자인 — *Viewport · Media Query · Container Query · Fluid*

*디바이스 다양성* 을 *하나의 마크업* 으로 받아내는 표준 도구 4 종

intermediate 난이도4시간토스당근카카오네이버배민라인쿠팡
시작 전
이해도
매우 낮음

학습 개요

탄생 배경

쉬운 설명

복잡한 개념을 실생활 비유로 설명합니다.

*옷장에 옷이 한 벌* — 어느 몸에든 맞춰 입기

반응형 디자인은 *체형이 다른 사람들에게 같은 옷 한 벌을 맞춰 입히는 일* 과 같습니다. *Viewport meta* 는 옷을 입을 *사람의 실제 치수를 알려주는 첫 단계* 입니다 — 이 단계가 빠지면 모바일 브라우저는 *데스크톱 마네킹* 으로 가정해 옷을 입혀 버립니다. *Media Query* 는 *체형 큰 분류* (S/M/L/XL) 에 따른 *완전히 다른 재단* 을 준비하는 일이고, *Container Query* 는 *같은 옷이 다른 옷장 (컨테이너)* 에 들어갔을 때 옆 옷들과 어울리도록 *자기 자리에 맞춰 자동으로 늘어나거나 줄어드는 옷* 입니다. *Fluid (`clamp`)* 는 *S → M → L → XL 의 단계적 변화 사이에 자연스러운 그라데이션* 을 만드는 도구입니다. 옷이 SS 와 MM 사이의 어떤 몸이든 *어색함 없이* 맞도록. *Logical Properties* 는 *왼손잡이 / 오른손잡이 / 위에서 아래로 입는 사람* 모두에게 *방향 독립적* 으로 작동하는 옷 — 글로벌 시장의 의무복입니다.

핵심 개념

*viewport meta 가 없으면* 모바일 반응형은 시작도 못 한다

모바일 브라우저는 *기본적으로* 페이지를 *데스크톱 폭 (보통 980px)* 으로 가정해 *축소 렌더링* 한다. 미디어 쿼리도 *그 가짜 폭* 으로 평가된다. <meta name="viewport" content="width=device-width, initial-scale=1"> 한 줄로 *논리 폭 = 디바이스 폭* 으로 맞춰야 미디어 쿼리가 *실제 폭* 으로 평가된다.

*표준 viewport 메타*html
1<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
주요 *상대 단위* — 무엇을 기준으로 잡는가
단위기준대표 용례
%*부모* 의 해당 속성폭/높이 비율 레이아웃
em*요소 자신* 의 폰트 크기인접 컴포넌트 비례 (간격, 아이콘)
rem*루트 (html)* 의 폰트 크기글로벌 스케일링 (사용자 글자 크기 존중)
vw / vh*뷰포트* 의 1%히어로 섹션, 풀스크린 모달
svh / lvh / dvh모바일 *주소창 동적* 고려한 vh 계열모바일 풀 스크린 (100dvh)
%로 padding/margin*부모의 inline-size**비율 박스* 트릭 (지금은 aspect-ratio 권장)

`100vh` 의 *모바일 함정*

iOS Safari·Android Chrome 의 *주소창이 펼쳐졌을 때 vs 접혔을 때* 뷰포트 높이가 달라진다. 100vh 는 *큰 쪽 (lvh)* 으로 평가되어 *주소창이 펼쳐진 동안* 페이지가 잘린다. *100dvh (Dynamic Viewport Height)* 는 *현재 보이는 영역* 으로 동적으로 따라간다 — 풀스크린 레이아웃의 표준 정답.

*Logical properties*

margin-inline-start, padding-block-end, inline-size, block-size 등. *글쓰기 방향 (LTR/RTL/세로)* 에 따라 자동으로 매핑되는 *방향 독립 속성*. 국제화 (i18n) 가 있는 서비스에선 *기본값* 으로 채택.

*aspect-ratio*

aspect-ratio: 16/9. 별도 padding 트릭 없이 *비율 박스* 를 만든다. 이미지·비디오 컨테이너의 표준.

실무 적용

어떤 상황에서 사용하는가

커머스 메인 — *그리드 (모바일 1열, 태블릿 2열, 데스크톱 4열)*, *상품 카드 컴포넌트가 사이드바와 메인 모두에 등장*, *히어로 배너가 폭에 따라 폰트와 padding 부드럽게*, *아랍어 시장 진출로 RTL 지원 필요*, *모바일 풀스크린 모달*.

어떻게 적용하는가

(1) *전역 그리드* 는 미디어 쿼리 — `grid-template-columns: 1fr` (모바일) → `repeat(2, 1fr)` (≥768px) → `repeat(4, 1fr)` (≥1200px). (2) *상품 카드* 는 컨테이너 쿼리 — 카드 컨테이너에 `container-type: inline-size`, `@container (min-width: 360px)` 에서 padding/font-size 확장. 사이드바 (좁음) 와 메인 (넓음) 에 *같은 카드 마크업* 으로 자동 적응. (3) *히어로 배너* 는 fluid — `font-size: clamp(28px, 4vw + 8px, 64px)`, `padding: clamp(24px, 6vw, 96px)`. (4) *RTL* 은 `padding-inline-start`, `margin-inline-end` 같은 *Logical Properties* 로 통일하고 `<html dir="rtl">` 한 줄로 전체 미러링. (5) *모바일 풀스크린 모달* 은 `100dvh` (Dynamic Viewport Height) — iOS 주소창 펼침/접힘에 따라 *동적으로 따라감*. (6) *touch 타깃* 은 `@media (pointer: coarse)` 에서 `min-height: 44px` 보장. (7) *prefers-color-scheme*·*prefers-reduced-motion* 도 같은 미디어 쿼리 흐름에서 처리. (8) *디버깅* 은 DevTools *Device Mode* + *Container 모드* (Chrome 의 컨테이너 시각화) 로 분기 지점을 확인.

흔한 실수와 안티패턴

  • `viewport meta` 누락 → 모바일에서 *모든 미디어 쿼리가 깨짐*.
  • `100vh` 사용 → iOS 주소창 영역에서 *콘텐츠 잘림*. `100dvh` 또는 *fallback (vh + dvh)* 로.
  • *Desktop-first (`max-width`)* 로 설계 → 작은 화면에서 *큰 스타일 평가 비용* + 모바일 우선 성능 손해.
  • `container-type: size` 를 *이유 없이* 적용 → 자식 *containment* 강제로 의도 외 부수효과.
  • *break point 를 디바이스 통계로* 박음 → 콘텐츠가 *어색한 폭 그대로* 방치. 디자인 깨지는 곳에서 break.
  • `srcset/sizes` 누락 → 모바일에서 *데스크톱 해상도 이미지* 다운로드 → 데이터·LCP 손해.
  • `width`/`height` 미명시 → *CLS* 발생.

흔한 오해

오해

*"모바일 퍼스트는 단지 break point 작성 순서일 뿐"*

교정

*철학과 구현* 의 차이가 더 크다. 모바일 퍼스트는 *작은 화면에서 시작 → 점진적 확장* 의 사고방식이다. 이는 *기본 페이로드 (HTML/CSS/JS) 가 가벼움* 으로 이어지고, *모바일 사용자 우선 성능* 으로 직결된다. 단순 작성 순서가 아니라 *모바일이 1차 사용자라는 가정* 이 핵심.

왜 중요

실제 트래픽의 *60% 이상이 모바일* 인 환경에서 데스크톱부터 짜는 것은 *반대 우선순위* 다.

오해

*"Container Query 는 미디어 쿼리를 완전히 대체할 수 있다"*

교정

*보완 관계* 다. *글로벌 레이아웃 (사이드바 토글, 그리드 컬럼 수)* 은 뷰포트 기반이 자연스럽고, *컴포넌트 단위 적응* 은 컨테이너 쿼리가 자연스럽다. 둘 다 함께 쓰는 것이 표준.

왜 중요

뷰포트 = *환경* (디바이스, OS), 컨테이너 = *문맥* (자리). 두 변수는 독립이다.

오해

*"`vw` 는 viewport 의 1% 니까 그냥 폰트에 쓰면 된다"*

교정

*조심해야 한다*. `font-size: 5vw` 단독은 *320px 폭에서 16px, 1920px 폭에서 96px* 로 *너무 작거나 너무 큼*. `clamp(14px, 1vw + 10px, 24px)` 처럼 *상하한* 을 둬야 한다. 게다가 `vw` 만으로 폰트를 정하면 *사용자가 글자 크기를 키워도* 반영되지 않아 *접근성 문제*. `rem` 또는 `clamp` 로 보완.

왜 중요

뷰포트 단위는 *상대적이지만 사용자 폰트 설정과 무관* 하다.

오해

*"Logical Properties 는 RTL 시장에만 의미"*

교정

*표준이 되어가고 있다*. 일본어 세로쓰기, 다국어 디자인 시스템, *방향 독립적인 컴포넌트* 라이브러리 모두 logical properties 가 자연스럽다. 영어권 단독 서비스라도 *학습 비용은 1 회* 로 끝나므로 *기본값* 으로 채택하는 흐름.

왜 중요

CSS WG 가 logical 을 표준 권장으로 미는 방향이고, Tailwind 같은 도구도 logical variants 를 추가 중.

면접 질문

중급토스카카오네이버배민당근

답변 방향 힌트

"뷰포트 vs 컨테이너 폭", "container-type", "재사용 컴포넌트".

반드시 언급할 키워드

  • 미디어 쿼리: *뷰포트* 폭/특성 기준
  • 컨테이너 쿼리: *조상 컨테이너* 폭 기준
  • `container-type: inline-size` 선언이 컨테이너 쿼리의 *전제 조건*
  • 글로벌 레이아웃은 미디어 쿼리, 컴포넌트 적응은 컨테이너 쿼리
  • 같은 카드가 *사이드바와 메인* 에 동시에 놓이는 경우 컨테이너 쿼리가 자연스러움
  • 둘은 *대체 관계가 아닌 보완 관계*

예상 꼬리 질문

  • `container-type: size` 가 자식의 *containment* 를 강제한다는 것은 어떤 부작용을 낳을 수 있나요?
  • 컨테이너 쿼리를 *지원하지 않는 구형 브라우저* 에 어떻게 폴백을 깔 수 있을까요?

자기 점검

`<meta name="viewport">` 가 누락되면 *모바일에서* 어떻게 되는가?

기대 키워드

데스크톱 폭 가정축소 렌더링미디어 쿼리 깨짐

자주 하는 오해

*"없어도 미디어 쿼리는 작동한다"* — viewport 메타가 없으면 *가짜 폭 (보통 980px)* 으로 평가된다.

`100vh` 와 `100dvh` 의 차이는?

기대 키워드

Dynamic Viewport Height주소창모바일

자주 하는 오해

*"같은 값이다"* — 모바일 주소창이 펼쳐졌을 때 vh 와 dvh 가 다르다.

`container-type` 의 *기본 권장 값* 은?

기대 키워드

`inline-size`

자주 하는 오해

*"`size` 가 더 강력하니 좋다"* — size 는 자식 containment 강제로 부수효과가 크다.

Fluid 의 핵심 함수 *세 가지* 를 답하라.

기대 키워드

`clamp``min``max`

자주 하는 오해

*"clamp 만 알면 충분"* — `min(90%, 1200px)` 같은 패턴이 폭 상한에 자주 쓰인다.

학습 자료