FEInterview Prep

css · high priority

CSS Layout — Flexbox · Grid 의 *내부 알고리즘*

*1D 흐름* 과 *2D 격자* 의 분기, `flex-grow/shrink/basis` 와 `fr`·`minmax()` 의 정확한 의미

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

학습 개요

탄생 배경

쉬운 설명

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

*책상 정리 (Flex)* vs *책장 칸막이 (Grid)*

Flexbox 는 *책상 위에 책들을 한 줄로 세우는 일* 입니다. 책 두께(콘텐츠) 에 따라 자동으로 자리가 정해지고, 좁아지면 *비율대로 더 좁혀지며* 들어갑니다. Grid 는 *책장에 칸막이를 먼저 짜고* 그 칸에 어떤 책을 어디에 꽂을지 정하는 일입니다. *어떤 칸은 두 칸을 합쳐* 두꺼운 책을, *다른 칸은 빈 칸으로* 둘 수도 있고, 책의 두께와 무관하게 칸의 모양이 *먼저* 결정됩니다. 책 진열대(컴포넌트 내부) 정렬은 Flex, 서재 전체(페이지) 의 칸 짜기는 Grid — 같은 서재에서 두 도구가 *함께* 일합니다.

핵심 개념

같은 문제를 두 도구로 풀 때 *드러나는 차이*

Flexbox — *콘텐츠 우선*
  • 1차원 — 한 번에 *행 또는 열* 중 하나
  • *콘텐츠 크기* 를 출발점으로 공간을 *분배*
  • 아이템 수가 *런타임에 변함* — 잘 어울림
  • 버튼 그룹·네비게이션·태그 칩 같은 *작은 정렬*
  • gap, space-between, align-items 가 주 도구
1.toolbar {
2 display: flex;
3 align-items: center;
4 gap: 12px;
5}
6.toolbar > .spacer { flex: 1; } /* 공간 채우기 */
Grid — *레이아웃 우선*
  • 2차원 — *행과 열* 을 동시 정의
  • *먼저 격자를 그리고* 거기에 콘텐츠를 *배치*
  • 아이템 수가 *알려져 있고 형태가 정해짐* — 적합
  • 페이지 레이아웃·카드 그리드·대시보드
  • grid-template, fr, minmax, auto-fill/fit 이 주 도구
1.dashboard {
2 display: grid;
3 grid-template-columns: 240px 1fr;
4 grid-template-rows: 64px 1fr;
5 min-height: 100vh;
6}

실무 결정 휴리스틱 — *섞어 쓰는 게 정답*

*페이지 외곽* (사이드바 + 메인) 은 Grid, *섹션 안의 카드 그리드* 도 Grid, *카드 한 장 안의 헤더 + 본문 + 액션* 은 Flex, *툴바 안의 아이콘 정렬* 도 Flex. *둘 중 하나만 골라야 한다* 는 가정 자체가 함정이다.

의사결정 한 줄 가이드

*아이템 사이즈에 따라 줄바꿈만 하면 되면* Flexbox flex-wrap. *행과 열의 정렬이 동시에* 필요하면 Grid. 정렬만이 아닌 *카드 폭 자체가 일관* 돼야 하면 Grid.

동등한 너비 카드 N열

Flex 의 flex: 1 N 개도 가능하지만, *행 수가 바뀌면* 어색해진다. Grid 의 repeat(N, 1fr) 또는 repeat(auto-fill, minmax(...)) 가 *훨씬 안정*.

*콘텐츠가 자기 폭을 결정* 하게 두고 싶다

Flex 의 *기본 동작* 이 정확히 그것 — flex: 0 1 auto (기본) 가 *콘텐츠 크기에서 출발해 부족하면 줄어듦*. Grid 는 *명시적 트랙* 을 쓰는 도구라 의도가 다름.

실무 적용

어떤 상황에서 사용하는가

대시보드 페이지 레이아웃 + *반응형 카드 그리드* + 카드 내부 정렬을 구현하면서, *카드 안의 긴 제목이 컨테이너를 뚫는* 버그도 잡아야 한다.

어떻게 적용하는가

(1) 페이지 외곽은 Grid 의 `grid-template-areas` 로 *헤더 / 사이드바 / 메인 / 푸터* 를 7~8 줄에 표현. 사이드바가 없는 모바일은 `@media` 한 곳에서 영역만 재배치. (2) 카드 그리드는 `grid-template-columns: repeat(auto-fill, minmax(280px, 1fr))` 로 *미디어 쿼리 없이* 반응형. *카드를 적게 넣어도 공간을 꽉 채우고 싶다면* `auto-fit`. *fr 트랙이 콘텐츠로 부푸는 문제* 를 미연에 방지하려면 `minmax(0, 1fr)` 패턴을 기본으로. (3) 카드 내부 (이미지/제목/설명/버튼) 는 *Flex 컬럼* 으로 — 제목과 설명은 자연스러운 흐름, 버튼은 `margin-top: auto` 로 카드 바닥에 붙임. (4) 카드 안 텍스트가 컨테이너를 뚫는 문제는 거의 항상 *flex 자식의 `min-width: auto`* 때문 — 해당 자식에 `min-width: 0` 을 명시하면 정상화. (5) `gap` 으로 간격 통일 (margin 핵 금지). (6) 다크 모드/접근성 검증은 별도 — 이 단계에선 *레이아웃 알고리즘이 의도대로 분배되는지* 만 본다.

흔한 실수와 안티패턴

  • `flex: 1` 만 쓰고 *basis 가 0* 이라는 사실을 잊어 콘텐츠 크기가 무시됨.
  • `min-width: 0` 트릭을 모르고 *flex 자식이 컨테이너를 뚫음*.
  • `fr` 트랙이 *콘텐츠로 부푸는 것* 을 모르고 *다른 트랙을 압박* 받음 → `minmax(0, 1fr)`.
  • `auto-fill` vs `auto-fit` 차이를 모르고 *카드가 적을 때 비어 보임* (또는 그 반대).
  • Flex 의 `gap` 이 모던 브라우저에서 동작함을 모르고 *margin 핵* 유지.
  • `grid-template-areas` 의 *영역명이 자식의 `grid-area` 와 안 맞아* 빈 칸이 생김.

흔한 오해

오해

*"Grid 가 새로 나왔으니 Flexbox 를 쓸 일은 없다"*

교정

*해결 문제가 다르다*. 1차원 정렬에 Grid 를 쓰면 *과한 도구* 다. 콘텐츠 크기 기반 흐름은 Flex 가 더 적합.

왜 중요

Flex 는 *콘텐츠 크기에서 출발*, Grid 는 *명시 격자에서 출발*. 출발점이 다르면 결과의 자연스러움도 다르다.

오해

*"`flex: 1` 은 모든 아이템을 균등 분배"*

교정

*basis 가 0* 으로 강제되어 콘텐츠 크기를 무시하고 *grow 비율로* 균등 분배되는 것일 뿐. 콘텐츠 보존이 필요하면 `flex: auto` (basis: auto) 가 정답.

왜 중요

`flex: 1` 의 단축 풀이는 `1 1 0%` 다. `auto` 와 명백히 다른 동작.

오해

*"Flex 자식은 부모를 뚫지 않는다"*

교정

Flex 자식의 *기본 `min-width: auto`* 가 *내용의 가장 긴 단어/이미지* 라 정상이다. `min-width: 0` 으로 *축소를 허용* 해야 안전하다.

왜 중요

디폴트가 *콘텐츠 보호* 쪽이라 의도치 않은 부풀음이 자주 일어난다 — 거의 모든 큰 코드베이스에 reset 으로 박혀 있다.

오해

*"`fr` 은 백분율과 같다"*

교정

`%` 는 *컨테이너 전체 크기* 의 비율, `fr` 은 *gap 과 고정 트랙을 뺀 남은 공간* 의 비율. 의미가 다르다.

왜 중요

`gap` 이나 고정 사이드바가 들어가면 % 계산은 *직접 빼야* 하지만 fr 은 *자동* 으로 처리.

면접 질문

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

답변 방향 힌트

"basis 0 vs basis auto" 가 핵심.

반드시 언급할 키워드

  • `flex: 1` = `1 1 0%` — basis 0 강제
  • `flex: 1 1 0` 동치
  • `flex: 1 1 auto` — basis 가 *콘텐츠* — 균등이 깨질 수 있음
  • `flex: auto` = `1 1 auto`
  • 균등 분배의 정체: basis 0 + 자유공간 균등 = 결국 *컨테이너 폭의 균등*

예상 꼬리 질문

  • `flex-basis: 0` 과 `flex-basis: 0%` 의 *미묘한 차이* 가 있나요?
  • `flex: none` 은 어떤 상황에 적절한가요?

자기 점검

`flex: 1` 의 *단축 풀이* 를 답하라.

기대 키워드

`1 1 0%`basis 0grow 1shrink 1

자주 하는 오해

*"basis auto"* — `1` 만 쓰면 basis 가 *0* 으로 강제됨.

`auto-fill` 과 `auto-fit` 의 *카드 1 개일 때* 동작 차이를 한 문장으로.

기대 키워드

빈 트랙 유지빈 트랙 접음공간 채움

자주 하는 오해

*"둘이 같다"* — 카드가 적을 때만 차이가 *극명* 하다.

Flex 자식이 부모를 뚫는 가장 흔한 원인과 해결책 한 줄.

기대 키워드

`min-width: auto``min-width: 0`콘텐츠 가장 긴 단어

자주 하는 오해

*"`overflow: hidden` 만 답"* — 가능하지만 *축소 허용* 이 더 정확한 의도.

*미디어 쿼리 없는* 반응형 카드 그리드의 표준 한 줄.

기대 키워드

`repeat(auto-fill, minmax(...))``1fr`

자주 하는 오해

*"미디어 쿼리 없이는 불가능"* — `auto-fill/fit` + `minmax` 가 표준.

학습 자료