본문으로 바로가기

CSS 레이아웃 정리: Flexbox vs Grid·subgrid 비교

2026.03.302026.07.10 수정31분 읽기

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

목차

CSS 레이아웃은 웹 개발에서 가장 많이 막히는 부분 중 하나입니다. Flexbox와 Grid 둘 다 배웠는데 막상 코딩할 때 어느 것을 써야 할지 모르겠다면,
이 가이드가 명확한 기준을 드립니다.

이 글은 Flexbox와 Grid의 핵심 개념, 둘의 정확한 차이, 실무 패턴 레시피,
subgrid·container queries 같은 최신 기능, Tailwind CSS 대응, 그리고 성능 고려사항까지 한 번에 정리합니다.

Flexbox vs Grid: 한 줄 요약#

  • Flexbox: 한 방향(행 또는 열) 정렬에 강한 1차원 레이아웃
  • Grid: 가로·세로 2차원 배치에 강한 2차원 레이아웃

실무에서는 둘을 함께 씁니다. Grid로 전체 페이지 구조를 잡고,
Flexbox로 각 컴포넌트 내부를 정렬하는 패턴이 가장 일반적입니다.

비교 항목FlexboxGrid
차원1차원(row 또는 column)2차원(row + column)
콘텐츠 우선콘텐츠 크기 기준컨테이너 크기 기준
명시적 트랙없음grid-template-rows/columns
항목 위치순서대로자유롭게 배치 가능
권장 용도네비게이션·버튼 그룹·카드 내부페이지 전체·갤러리·대시보드

Flexbox 핵심 개념#

.container {
  display: flex;
  flex-direction: row;      /* 기본값: 가로 방향 */
  justify-content: center;  /* 주축 정렬 */
  align-items: center;      /* 교차축 정렬 */
  gap: 16px;                /* 자식 요소 간격 */
}

주축(Main axis)과 교차축(Cross axis)#

flex-directionrow면 주축은 가로, 교차축은 세로입니다. column이면 반대.

flex-direction: row →  주축 = 가로(좌→우)
                       교차축 = 세로(상→하)

flex-direction: column → 주축 = 세로
                         교차축 = 가로

justify-content 값별 동작#

결과
flex-start시작 정렬(기본값)
flex-end끝 정렬
center가운데 정렬
space-between양 끝에 붙이고 사이 균등 분배
space-around각 요소 양옆에 균등 여백
space-evenly모든 간격 동일

align-items 값별 동작#

결과
stretch교차축 전체 채움(기본값)
flex-start교차축 시작
flex-end교차축 끝
center교차축 가운데
baseline텍스트 베이스라인 정렬

Flexbox가 적합한 경우#

  • 네비게이션 바(아이템들을 한 줄에 배치)
  • 버튼 그룹(아이콘 + 텍스트 정렬)
  • 카드 내부 레이아웃
  • 수직·수평 중앙 정렬
  • 아이템 수가 동적으로 변하는 리스트
/* 수직·수평 완벽 중앙 정렬 — 가장 깔끔한 방법 */
.center {
  display: flex;
  justify-content: center;
  align-items: center;
}

flex 단축 속성#

자식 요소의 크기 제어:

.item {
  flex: 1 1 0;
  /* flex-grow: 1 (남은 공간 분배) */
  /* flex-shrink: 1 (부족하면 줄이기) */
  /* flex-basis: 0 (기본 크기) */
}

.fixed {
  flex: 0 0 200px;  /* 200px 고정, 늘어나거나 줄지 않음 */
}

CSS Grid 핵심 개념#

.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);  /* 3열 균등 분배 */
  grid-template-rows: auto;
  gap: 24px;
}

fr 단위란?#

fr(fractional unit)은 남은 공간을 비율로 나누는 단위입니다.

grid-template-columns: 1fr 2fr 1fr;
/* 전체를 4등분 → 왼쪽 1/4, 가운데 2/4, 오른쪽 1/4 */

반응형 Grid 패턴: auto-fit vs auto-fill#

화면 크기에 맞춰 자동으로 열 수 조정:

/* auto-fill: 가능한 만큼 열 자리를 만듦(빈 자리 유지) */
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));

/* auto-fit: 빈 자리를 채워 늘림(아이템이 큰 폭으로 늘어남) */
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));

이 한 줄로 카드 그리드가 화면 크기에 따라 자동으로 1열, 2열, 3열로 바뀝니다. 미디어 쿼리 없이 반응형 완성.

차이auto-fillauto-fit
빈 자리유지(여백 발생)채워서 늘림
권장일반 그리드항상 최대 너비 활용

Grid가 적합한 경우#

  • 카드 갤러리, 상품 목록
  • 신문 스타일 레이아웃(제목 + 본문 + 사이드바)
  • 대시보드(다양한 크기의 위젯 배치)
  • 헤더 + 사이드바 + 본문 + 푸터 페이지 구조
  • 폼(label + input 정렬)
/* 사이드바 + 본문 + 광고 3열 레이아웃 */
.page {
  display: grid;
  grid-template-columns: 240px 1fr 300px;
  gap: 32px;
}

grid-template-areas: 가독성 좋은 방법#

.layout {
  display: grid;
  grid-template-columns: 240px 1fr 300px;
  grid-template-rows: 80px 1fr 60px;
  grid-template-areas:
    "header header  header"
    "nav    main    aside"
    "footer footer  footer";
}
.header { grid-area: header; }
.nav    { grid-area: nav; }
.main   { grid-area: main; }
.aside  { grid-area: aside; }
.footer { grid-area: footer; }

이 방식은 디자이너가 그린 와이어프레임을 그대로 코드로 옮길 수 있어 직관적입니다.

CSS subgrid: 중첩 그리드 정렬#

자식 요소가 부모 그리드의 트랙을 그대로 사용하는 기능입니다
(2023년부터 모든 주요 브라우저 지원).

.parent {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
}
.child {
  display: grid;
  grid-template-columns: subgrid;  /* 부모의 3열 그대로 사용 */
}

카드 그리드에서 모든 카드의 제목·이미지·버튼이 같은 라인에 정렬되어야 할 때 유용합니다.

Container Queries: 반응형의 새 차원#

미디어 쿼리는 화면 크기 기준이지만,
Container Query는 부모 컨테이너 크기 기준입니다(2023년부터 모든 주요 브라우저 지원).

.card-container {
  container-type: inline-size;
  container-name: card;
}

@container card (min-width: 400px) {
  .card {
    display: grid;
    grid-template-columns: 200px 1fr;
  }
}

같은 카드 컴포넌트가 사이드바 안에서는 세로로, 메인 영역에서는 가로로 자동 배치됩니다. 컴포넌트 단위 반응형 디자인이 가능해졌습니다.

자주 쓰는 패턴 레시피#

1. 헤더: 로고 + 네비 + 버튼#

header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 24px;
}

2. 카드 그리드(반응형)#

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 20px;
}
body {
  display: grid;
  grid-template-rows: auto 1fr auto;  /* 헤더 / 본문(남은 공간) / 푸터 */
  min-height: 100vh;
}

4. 아이콘 + 텍스트 인라인 정렬#

.icon-text {
  display: flex;
  align-items: center;
  gap: 8px;
}

5. 폼 정렬(2열 그리드)#

.form {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 12px 16px;  /* 행 간격 12px, 열 간격 16px */
  align-items: center;
}

6. 갤러리(Pinterest 스타일·masonry)#

CSS grid-template-rows: masonry(2024년 실험적 기능, 점진적 도입 중) 또는 JavaScript 라이브러리(Masonry, Isotope) 사용.

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  grid-auto-rows: 200px;
  gap: 12px;
}
.tall   { grid-row: span 2; }
.wide   { grid-column: span 2; }

7. Holy Grail 레이아웃#

전통적인 헤더-사이드바-본문-푸터 패턴:

.page {
  display: grid;
  grid-template-columns: 200px 1fr 200px;
  grid-template-rows: 60px 1fr 60px;
  grid-template-areas:
    "header  header header"
    "nav     main   aside"
    "footer  footer footer";
  min-height: 100vh;
}

Tailwind CSS 대응표#

Tailwind를 사용한다면 유틸리티 클래스로 바로 적용할 수 있습니다.

CSSTailwind
display: flexflex
justify-content: centerjustify-center
align-items: centeritems-center
gap: 16pxgap-4
display: gridgrid
grid-template-columns: repeat(3, 1fr)grid-cols-3
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr))grid-cols-[repeat(auto-fill,minmax(250px,1fr))]
flex-direction: columnflex-col
flex-wrap: wrapflex-wrap
flex: 1 1 0flex-1

성능 고려사항#

레이아웃 비용#

  • Flexbox와 Grid는 모두 GPU 가속을 받지 않습니다(레이아웃은 CPU)
  • 자주 변경되는 애니메이션은 transform 사용(GPU)
  • will-change 남용 금지(메모리 사용)

큰 그리드 성능#

/* 1만 개 아이템 그리드는 가상 스크롤(Virtual Scroll) 권장 */
/* 그리드 자체보다 DOM 노드 수가 성능 병목 */

리액트에서는 react-window, react-virtualized 같은 라이브러리로 가상 스크롤 구현.

자주 묻는 질문#

Q. Flexbox만 써도 되지 않나요? Grid를 굳이 배워야 하나요?

A. 간단한 1차원 정렬은 Flexbox로 충분합니다. 하지만 복잡한 2차원 레이아웃, 불규칙한 크기의 그리드는 Grid가 훨씬 간결합니다. 둘 다 알아두면 상황에 맞게 선택할 수 있습니다.

Q. Internet Explorer도 지원해야 하나요?

A. IE는 2022년 6월 서비스 종료됐습니다. 현재 Flexbox와 Grid는 모든 주요 브라우저에서 완벽히 지원됩니다.

Q. gapmargin의 차이는?

A. gap은 그리드·플렉스 컨테이너 내부 자식들 사이에만 적용됩니다. 첫 번째와 마지막 요소 바깥에는 여백이 생기지 않아 깔끔합니다. margin은 모든 방향에 적용되어 끝 요소에도 여백이 생깁니다.

Q. 동적인 콘텐츠가 있는 카드 높이를 맞추려면?

A. Grid 컨테이너의 자식들은 자동으로 같은 행에서 같은 높이가 됩니다. Flexbox는 align-items: stretch(기본값)로 같은 효과 가능.

Q. subgrid는 언제 쓰나요?

A. 카드 컴포넌트 내부의 제목·본문·버튼이 다른 카드들과 같은 라인에 정렬되어야 할 때 가장 유용합니다.

Q. Container Query와 미디어 쿼리 중 무엇을 써야 하나요?

A. 페이지 전체 레이아웃은 미디어 쿼리(뷰포트 기준),
컴포넌트 단위 반응형은 Container Query 사용. 같은 카드가 사이드바 안과 메인 영역에서 다르게 보여야 한다면
Container Query가 답입니다.

Q. CSS 그리드와 테이블 차이는?

A. <table>은 표 데이터를 위한 시맨틱 태그입니다. 레이아웃 용도로 <table>을 쓰는 것은 접근성·시맨틱 측면에서 안티패턴. CSS Grid가 정답입니다.

CSS 레이아웃 도구 활용#

CSS 레이아웃 도구에서 Flexbox·Grid 모드 선택,
열 수·간격·정렬 방향을 클릭으로 설정하면 CSS 코드가 자동 생성됩니다.

디자인 작업이 더 필요하다면 색상 팔레트 가이드, 그라디언트 가이드, 색상 대비 접근성, 박스 쉐도우 가이드도 함께 참고하세요.

이런 글도 읽어보세요

전체 글 보기

관련 도구