현록

CSS Flexbox와 Grid 차이

CSS로 여러 요소를 배치할 때 Flexbox와 Grid 중 무엇을 써야 할지 자주 고민하게 된다.
둘 다 간격과 정렬을 다룰 수 있고, 반응형 레이아웃에도 쓸 수 있어서 간단한 예제만 보면 차이가 작아 보인다.

가장 정확한 구분 기준은 한 번에 제어하려는 축의 수다.
Flexbox는 행이나 열 중 한 축을 중심으로 항목을 배치하는 1차원 레이아웃이고, Grid는 행과 열을 함께 설계하는 2차원 레이아웃이다.
이 기준을 먼저 잡으면 속성을 외우기보다 레이아웃의 의도에 맞는 도구를 고를 수 있다.

한 축과 두 축의 차이

Flexbox는 flex-direction으로 주축을 정한다.
기본값인 row에서는 가로가 주축이고 세로가 교차축이다.
column을 사용하면 세로가 주축이 되고 가로가 교차축이 된다.

.container {
  display: flex;
  flex-direction: row;
}

Flexbox가 1차원이라는 말은 교차축 정렬을 못 한다는 뜻이 아니다.
align-items로 교차축을 정렬할 수 있지만, 항목의 크기와 남는 공간을 계산하는 중심은 한 번에 하나의 주축이다.

Grid는 컨테이너에 열 track과 행 track을 함께 정의한다.
항목은 두 방향의 grid line으로 둘러싸인 cell에 놓인다.

.container {
  display: grid;
  grid-template-columns: 1fr 2fr;
  grid-template-rows: auto 1fr;
}

이 코드에서는 두 열의 너비 관계와 두 행의 높이 관계를 같은 레이아웃 안에서 제어한다.
행과 열의 교차점까지 설계해야 하는 화면에서 Grid가 자연스러운 이유다.

Flexbox에 맞는 목록 배치

제목, 작성일, 이동 링크가 한 줄에 놓이는 목록을 생각해 보자.
각 항목 안에서 중요한 것은 왼쪽에서 오른쪽으로 이어지는 한 방향의 배치다.

<ul class="post-list">
  <li class="post-item">
    <a class="post-title" href="/posts/flexbox">Flexbox 정리</a>
    <time datetime="2026-07-03">2026.07.03</time>
    <a class="post-link" href="/posts/flexbox">읽기</a>
  </li>
  <li class="post-item">
    <a class="post-title" href="/posts/grid">Grid 정리</a>
    <time datetime="2026-07-02">2026.07.02</time>
    <a class="post-link" href="/posts/grid">읽기</a>
  </li>
</ul>
.post-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.post-item {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 16px;
  border-bottom: 1px solid #d0d7de;
}

.post-title {
  flex: 1;
}

목록 자체는 위에서 아래로 쌓고, 각 항목 안에서는 가로 한 줄을 정렬한다.
두 곳 모두 한 컨테이너가 한 축의 흐름을 담당하므로 Flexbox의 구조와 잘 맞는다.

flex: 1을 받은 제목은 남는 공간을 차지하고 날짜와 링크는 콘텐츠 크기를 유지한다.
텍스트 길이가 달라지는 콘텐츠 중심 UI에서도 자연스럽게 대응할 수 있다.

flex-wrap의 동작

Flexbox에도 flex-wrap: wrap이 있으므로 여러 행을 만들 수 있다.
그렇다고 Flexbox가 2차원 레이아웃으로 바뀌는 것은 아니다.

.flex-cards {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}

.flex-card {
  flex: 1 1 220px;
}

공간이 부족하면 항목은 다음 flex line으로 넘어간다.
중요한 점은 각 줄이 독립적으로 남는 공간을 계산한다는 것이다.

첫째 줄에 카드가 세 개 있고 둘째 줄에 카드가 두 개라면, 둘째 줄의 두 카드가 첫째 줄의 열 너비와 맞지 않고 더 넓어질 수 있다.
둘째 줄은 첫째 줄의 항목 위치를 열 기준선으로 공유하지 않기 때문이다.

align-content는 여러 flex line을 교차축 안에서 배치하지만, 서로 다른 줄의 항목을 같은 열 track에 맞추지는 않는다.
따라서 줄이 바뀌어도 세로 열이 계속 맞아야 한다면 flex-wrap보다 Grid가 의도에 가깝다.

Grid에 맞는 카드 배치

여러 카드를 같은 열 기준에 맞추는 레이아웃에서는 가로와 세로 관계를 함께 봐야 한다.
Grid는 컨테이너가 열 track을 만들고 모든 행이 그 열 구조를 공유한다.

<section class="card-grid" aria-label="추천 글">
  <article class="card">
    <h2>Flexbox 정리</h2>
    <p>한 축의 정렬과 공간 분배를 정리한 글입니다.</p>
    <a href="/posts/flexbox">읽기</a>
  </article>
  <article class="card">
    <h2>Grid 정리</h2>
    <p>행과 열을 함께 설계하는 방법을 정리한 글입니다.</p>
    <a href="/posts/grid">읽기</a>
  </article>
  <article class="card">
    <h2>반응형 레이아웃</h2>
    <p>화면 너비에 따라 카드 수를 바꾸는 방법입니다.</p>
    <a href="/posts/responsive-layout">읽기</a>
  </article>
</section>
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 16px;
}

.card {
  padding: 20px;
  border: 1px solid #d0d7de;
  border-radius: 12px;
}

minmax(220px, 1fr)은 각 열이 220px보다 작아지지 않으면서 남는 공간을 같은 비율로 나누게 한다.
auto-fit은 들어갈 수 있는 열의 수를 컨테이너 너비에 맞춰 계산한다.
화면이 좁아지면 열 수가 줄어들고 카드가 다음 행으로 이동한다.

Flexbox 예제와 달리 마지막 행의 카드도 앞선 행과 같은 열 track을 기준으로 놓인다.
카드 목록처럼 반복되는 항목의 가로선과 세로선을 맞추는 데 Grid가 편한 이유다.

콘텐츠와 레이아웃의 출발점

축의 수와 함께 보면 좋은 기준은 크기를 어디에서 출발해 결정하는지다.
Flexbox는 항목의 콘텐츠 크기를 바탕으로 늘어나거나 줄어들며 컨테이너의 남는 공간을 분배하는 패턴에 잘 맞는다.
내비게이션, 버튼 묶음, 도구 모음처럼 항목 자체가 흐름을 만드는 UI가 대표적이다.

Grid는 먼저 행과 열이라는 레이아웃 구조를 만들고 항목을 그 구조에 배치하는 패턴에 잘 맞는다.
대시보드, 갤러리, 카드 목록처럼 여러 항목이 공통 기준선을 가져야 하는 UI가 대표적이다.

이 구분도 절대적인 규칙은 아니다.
Grid track은 콘텐츠 크기에 반응할 수 있고, Flexbox에도 고정된 크기를 줄 수 있다.
다만 코드를 계속 보정해야 한다면 처음 선택한 레이아웃 모델이 실제 의도와 맞는지 다시 확인할 단서가 된다.

선택 기준

한 줄 또는 한 열 안에서 항목의 순서, 간격, 정렬을 다루면 Flexbox부터 고려한다.
메뉴, 검색창과 버튼, 프로필 정보, 목록의 한 행이 여기에 해당한다.

행과 열의 기준선을 동시에 맞춰야 하면 Grid부터 고려한다.
카드 모음, 사진 갤러리, 페이지의 주요 영역, 표와 비슷한 대시보드가 여기에 해당한다.

항목이 다음 줄로 넘어가기만 하면 되고 각 줄의 너비 분배가 달라도 괜찮다면 flex-wrap으로 충분하다.
줄이 바뀐 뒤에도 위아래 항목이 같은 열에 정렬되어야 한다면 Grid가 더 적합하다.

항목의 콘텐츠 크기가 배치를 주도하면 Flexbox가 단순한 경우가 많다.
미리 정한 레이아웃 구조가 항목의 위치와 크기를 주도하면 Grid가 단순한 경우가 많다.

함께 사용하는 패턴

Flexbox와 Grid는 둘 중 하나만 선택해야 하는 경쟁 관계가 아니다.
바깥 구조는 Grid로 만들고 각 카드 내부는 Flexbox로 정렬하는 조합이 자주 쓰인다.

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 16px;
}

.card {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.card-actions {
  display: flex;
  gap: 8px;
  margin-top: auto;
}

바깥 .card-grid는 여러 카드의 행과 열을 책임진다.
안쪽 .card는 제목, 설명, 버튼 영역을 세로 한 축으로 배치한다.
.card-actions는 버튼을 가로 한 축으로 정렬한다.

컨테이너마다 책임지는 축을 따로 판단하면 두 도구를 섞어도 구조가 복잡해지지 않는다.
페이지 전체에 하나의 방식만 고집하기보다 레이아웃 경계마다 다시 선택하는 편이 낫다.

시각적 순서의 주의점

Flexbox의 order와 Grid의 명시적 배치를 사용하면 화면에 보이는 순서를 바꿀 수 있다.
하지만 시각적 순서가 바뀌어도 문서의 소스 순서와 키보드 탐색 순서가 같은 방식으로 바뀌는 것은 아니다.

레이아웃 도구는 의미 없는 HTML 순서를 고치는 용도로 사용하지 않는 편이 안전하다.
먼저 읽기와 탐색에 자연스러운 순서로 HTML을 작성하고, CSS는 그 의미를 유지하는 범위에서 배치에 사용한다.

정리

Flexbox는 행이나 열 중 한 축을 기준으로 항목의 크기와 남는 공간을 분배한다.
줄 바꿈이 생겨도 각 flex line이 독립적으로 계산되므로 여전히 1차원 모델이다.

Grid는 행과 열을 동시에 정의하고 여러 행이 같은 열 track을 공유하게 만든다.
반복 카드처럼 두 방향의 기준선을 맞춰야 하는 레이아웃에 잘 맞는다.

목록의 한 행이나 버튼 묶음은 Flexbox로, 카드 모음이나 페이지 영역은 Grid로 시작하면 선택이 쉬워진다.
실제 화면에서는 바깥 Grid와 안쪽 Flexbox처럼 각 컨테이너의 역할에 맞춰 함께 쓰는 경우가 많다.

참고 자료

관련 포스트
CSS position sticky와 fixed 차이 thumbnail
CSS position sticky와 fixed 차이
CSS position sticky와 fixed의 차이를 스크롤 기준, 문서 흐름, 부모 영역, top과 overflow, 고정 헤더 구현 기준으로 정리합니다.
CSS box-sizing content-box와 border-box 차이 thumbnail
CSS box-sizing content-box와 border-box 차이
CSS box-sizing의 content-box와 border-box 차이를 width 계산식, padding과 border, width 100% overflow, 전역 설정 방법으로 정리합니다.
CSS flex justify-content와 align-items 차이 thumbnail
CSS flex justify-content와 align-items 차이
CSS flex의 justify-content와 align-items 차이를 주축과 교차축, flex-direction, 가운데 정렬, 적용되지 않는 원인을 중심으로 정리합니다.
CSS margin과 padding 차이 thumbnail
CSS margin과 padding 차이
CSS margin과 padding의 차이를 박스 모델, 배경색과 클릭 영역, 전체 크기, margin collapsing, 축약형 작성 순서로 정리합니다.
CSS display block inline inline-block 차이 thumbnail
CSS display block inline inline-block 차이
CSS display의 block, inline, inline-block 차이를 줄바꿈, width와 height, margin 동작, 버튼과 태그 UI 선택 기준으로 정리합니다.
CSS position relative와 absolute 차이 thumbnail
CSS position relative와 absolute 차이
CSS position의 기본값, relative와 absolute의 배치 기준, normal flow 유지 여부, containing block, 부모에 position relative를 주는 이유를 초보자 기준으로 정리합니다.
CSS로 글래스모피즘 구현하기 thumbnail
CSS로 글래스모피즘 구현하기
안녕하세요. 오늘은 CSS로 글래스모피즘 디자인을 구현하는 법을 알아보겠습니다. 개인적으로 애플의 디자인 스타일을 좋아해서 좋은 레퍼런스 소재로 구경을 하는데, 오늘 문득 궁금해진 것이 CSS로 어떻게 글래스모피즘을 구현했느냐였습니다.