devlog.

CSS Flexbox vs Grid: 언제 뭘 써야 할까?

·7분 읽기

CSS 레이아웃을 짜다 보면 항상 고민이 생깁니다. "여기는 Flexbox를 써야 할까, Grid를 써야 할까?" 정확한 기준을 모르면 둘 중 하나만 고집하거나, 매번 구글링하게 됩니다. 이 글에서 명확한 선택 기준을 정리합니다.

핵심 차이: 1차원 vs 2차원#

  • Flexbox: 1차원 레이아웃 — 가로 혹은 세로 한 방향으로 아이템 배치
  • Grid: 2차원 레이아웃 — 가로와 세로를 동시에 제어
/* Flexbox: 한 줄(행 또는 열)로 배치 */
.container {
  display: flex;
  flex-direction: row; /* 또는 column */
}

/* Grid: 행과 열을 동시에 정의 */
.container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: auto auto;
}

Flexbox 완전 정복#

주요 속성#

.container {
  display: flex;

  /* 주축 방향 */
  flex-direction: row;           /* → 가로 (기본값) */
  flex-direction: column;        /* ↓ 세로 */

  /* 주축 정렬 */
  justify-content: flex-start;   /* 시작점 (기본값) */
  justify-content: center;       /* 가운데 */
  justify-content: space-between; /* 균등 분배 (양 끝 붙음) */
  justify-content: space-around;  /* 균등 분배 (양 끝 여백) */

  /* 교차축 정렬 */
  align-items: stretch;  /* 늘리기 (기본값) */
  align-items: center;   /* 가운데 */
  align-items: flex-end; /* 끝 */

  /* 줄 바꿈 */
  flex-wrap: nowrap;  /* 한 줄 (기본값) */
  flex-wrap: wrap;    /* 넘치면 다음 줄로 */
}

자식 아이템 속성#

.item {
  /* 늘어남 비율 */
  flex-grow: 1;   /* 남은 공간을 채움 */
  flex-grow: 0;   /* 늘어나지 않음 (기본값) */

  /* 줄어듦 비율 */
  flex-shrink: 1;  /* 필요 시 줄어듦 (기본값) */
  flex-shrink: 0;  /* 줄어들지 않음 */

  /* 기본 크기 */
  flex-basis: 200px; /* 기본 너비/높이 */
  flex-basis: auto;

  /* 단축 속성: grow shrink basis */
  flex: 1;        /* 1 1 0% — 균등 분배 */
  flex: 0 0 200px; /* 고정 크기 */
}

Flexbox 실전 패턴#

/* 1. 수직/수평 완벽 가운데 정렬 */
.center {
  display: flex;
  justify-content: center;
  align-items: center;
}

/* 2. 네비게이션 바 (로고 왼쪽, 메뉴 오른쪽) */
.nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

/* 3. 카드 목록 (균등 분배, 줄 바꿈) */
.card-list {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}
.card {
  flex: 0 0 calc(33.33% - 16px);
}

/* 4. 하단 고정 footer */
.page {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
.content {
  flex: 1; /* 남은 공간 모두 차지 */
}

Grid 완전 정복#

주요 속성#

.container {
  display: grid;

  /* 열 정의 */
  grid-template-columns: 200px 1fr 1fr; /* 고정 + 비율 */
  grid-template-columns: repeat(3, 1fr); /* 3등분 */
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); /* 반응형 */

  /* 행 정의 */
  grid-template-rows: auto 1fr auto;

  /* 간격 */
  gap: 16px;
  column-gap: 16px;
  row-gap: 24px;
}

아이템 배치#

.item {
  /* 열 배치 */
  grid-column: 1 / 3;     /* 1번부터 3번 선까지 (2칸) */
  grid-column: span 2;    /* 현재 위치에서 2칸 차지 */

  /* 행 배치 */
  grid-row: 1 / 3;
}

Grid 실전 패턴#

/* 1. 12컬럼 그리드 */
.grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 16px;
}
.col-6 { grid-column: span 6; }  /* 절반 */
.col-4 { grid-column: span 4; }  /* 1/3 */

/* 2. 페이지 전체 레이아웃 */
.layout {
  display: grid;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
  grid-template-columns: 250px 1fr;
  grid-template-rows: 64px 1fr 48px;
  min-height: 100vh;
}

.header  { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main    { grid-area: main; }
.footer  { grid-area: footer; }

/* 3. 반응형 카드 그리드 */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 24px;
}

언제 무엇을 쓸까?#

상황선택이유
네비게이션 바Flexbox한 줄 수평 정렬
버튼 그룹Flexbox아이템 크기에 따른 유연한 배치
카드 목록Grid행/열 동시 정렬 필요
페이지 레이아웃Grid복잡한 2차원 영역 분할
수직/수평 가운데 정렬Flexbox간결하고 직관적
복잡한 대시보드Grid위젯 크기와 위치 정확히 제어

경험적 규칙: 아이템이 먼저고 레이아웃이 따라간다면 Flexbox, 레이아웃이 먼저고 아이템을 배치한다면 Grid

함께 쓰기#

Flexbox와 Grid는 경쟁이 아니라 보완 관계입니다.

/* Grid로 전체 페이지 구조 잡고 */
.page {
  display: grid;
  grid-template-columns: 250px 1fr;
}

/* Flexbox로 네비 내부 아이템 배치 */
.nav {
  display: flex;
  align-items: center;
  gap: 16px;
}

/* Grid로 카드 목록 */
.posts {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 24px;
}

/* Flexbox로 카드 내부 구조 */
.card {
  display: flex;
  flex-direction: column;
}
.card-content {
  flex: 1;
}

실무에서는 대부분 Grid로 큰 레이아웃을 잡고, Flexbox로 각 컴포넌트 내부를 정렬하는 패턴을 사용합니다.

관련 포스트