HTML, CSS

CSS Grid vs Flexbox – 언제 무엇을 써야 할까요? (상세 가이드)

jonbeo 2025. 9. 13. 11:16
반응형

 

 

안녕하세요 😊
이번 포스팅에서는 CSS GridFlexbox를 “어떤 상황에서 무엇을 써야 하는지” 관점에서 깊게 풀어보겠습니다.

두 기술은 모두 강력한 레이아웃 시스템이지만 목적이 다릅니다.

 

초보자 분들도 헷갈리지 않도록,

개념 → 속성 → 실전 패턴 → 선택 체크리스트 → 자주 하는 실수 순서로 차근차근 정리 해보겠습니다.


1) 핵심 요약이 아니라 “핵심 이해”: Grid는 2차원, Flex는 1차원

  • Flexbox1차원(행 또는 열 한 방향) 정렬에 특화되어 있습니다.
    버튼 그룹, 네비게이션 바, 카드 내부 정렬처럼 한 줄 안에서의 배치·정렬·간격 제어에 특히 강합니다.
  • Grid2차원(행 + 열 동시) 레이아웃에 적합합니다.
    페이지 전체 레이아웃, 대시보드, 잡지형 배치처럼 행과 열을 동시에 설계해야 할 때 강력합니다.

한 줄 정렬·정돈 = Flex, 페이지 뼈대·격자 = Grid
이 관점만 먼저 정확히 기억하시면 이후 선택이 쉬워집니다.


2) Flexbox: 1차원 레이아웃의 만능 드라이버

2-1. 컨테이너 vs 아이템(속성 분리 이해)

.container {
  display: flex;          /* Flex 컨테이너 선언 */
  flex-direction: row;    /* 행(row) 기준 배치(기본값) */
  justify-content: space-between; /* 가로(주축) 정렬 */
  align-items: center;    /* 세로(교차축) 정렬 */
  gap: 12px;              /* 아이템 간 간격 */
}

.item {
  flex: 0 0 auto;         /* flex-grow  flex-shrink  flex-basis */
}
  • 컨테이너 속성: display:flex, flex-direction, flex-wrap, justify-content, align-items, gap
  • 아이템 속성: flex, flex-grow, flex-shrink, flex-basis, align-self, order

2-2. 축 이해(주축/교차축)

  • flex-direction: row이면 가로가 주축, 세로가 교차축입니다.
  • flex-direction: column이면 세로가 주축, 가로가 교차축입니다.
    이 관점을 알면 justify-*(주축 정렬) vs align-*(교차축 정렬)의 차이가 명확해집니다.

2-3. 실전 패턴 ①: 네비게이션 바

 
<nav class="nav">
  <div class="logo">Brand</div>
  <ul class="menu">
    <li>Docs</li><li>Blog</li><li>Pricing</li>
  </ul>
  <button class="cta">Sign in</button>
</nav>
.nav { display:flex; align-items:center; justify-content:space-between; padding:12px 16px; }
.menu { display:flex; gap:16px; list-style:none; margin:0; padding:0; }
  • 특징: 수평 정렬 + 간격 + 가운데 맞춤을 한 번에 해결.
    반응형에서는 .menu를 wrap 시키거나, 작은 화면에서 햄버거 메뉴로 교체합니다.

2-4. 실전 패턴 ②: 미디어 오브젝트(아바타 + 텍스트)

 
<div class="media">
  <img src="avatar.jpg" alt="" class="avatar">
  <div class="body">
    <h4>제목</h4>
    <p>설명 텍스트…</p>
  </div>
</div>
.media { display:flex; gap:12px; align-items:flex-start; }
.avatar { width:48px; height:48px; border-radius:50%; flex:0 0 48px; }
.body { flex:1 1 auto; min-width:0; }  /* 긴 텍스트 줄바꿈 대비 */
  • : 긴 텍스트가 있는 영역에는 min-width:0을 줘야 overflow 없이 줄바꿈이 됩니다(자주 빠뜨리는 부분).

2-5. Flex에서 자주 하는 실수

  • flex-basiswidth를 혼용해 레이아웃이 흔들리는 경우가 많습니다.
    우선순위는 flex-basis가 높습니다. 고정 폭이 필요하면 flex: 0 0 200px; 같이 명시하세요.
  • 자식에 overflow 문제가 생기면 부모 또는 자식에 min-width: 0을 고려하세요.
    Flex 컨텍스트에선 이 한 줄이 살리는 경우가 많습니다.

3) CSS Grid: 2차원 레이아웃의 청사진

3-1. 핵심 개념

  • 트랙(track): 열(column)과 행(row)을 구성하는 선 사이의 공간
  • 라인(line): 트랙을 구분하는 선(라인 번호/이름으로 위치 지정 가능)
  • 셀(cell): 행×열이 만드는 격자 칸
  • 명시적/암시적 그리드: grid-template-*로 만든 칸은 명시적, 자동 배치로 늘어나는 칸은 암시적

3-2. 기본 문법(가장 많이 쓰는 속성)

 
.grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);        /* 12열 그리드 */
  grid-template-rows: auto;                      /* 행 높이는 내용에 맞춤 */
  gap: 12px;                                     /* 행/열 간격 */
}

.item-a { grid-column: 1 / 4; }                  /* 1~3열 차지 */
.item-b { grid-column: 4 / 13; }                 /* 4~12열 차지 */
  • fr 단위는 남은 공간 비례 분배입니다. 레이아웃 그릴 때 거의 표준처럼 사용합니다.
  • repeat(), minmax(), auto-fit, auto-fill을 익히면 반응형이 매우 쉬워집니다.

3-3. 실전 패턴 ①: 반응형 카드 그리드(미디어쿼리 최소화)

 
.cards {
  display:grid;
  /* 가로 폭이 240px 미만으로 쪼개지지 않도록 최소폭 보장 */
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap:16px;
}
  • 화면이 넓으면 칼럼 수가 늘고, 좁아지면 자동으로 줄어 미디어쿼리 없이도 깔끔한 반응형이 됩니다.

3-4. 실전 패턴 ②: 페이지 뼈대(헤더/사이드/본문/푸터)

 
.layout {
  display:grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header header"
    "aside  main"
    "footer footer";
  min-height: 100dvh;   /* 뷰포트 꽉 채우기 */
  gap: 12px;
}
.header { grid-area: header; }
.aside  { grid-area: aside; }
.main   { grid-area: main; }
.footer { grid-area: footer; }
  • 장점: 구조를 시각적으로 선언(grid-template-areas) → 협업 시 의사소통이 매우 쉬워집니다.
  • 모바일에서는 한 줄 변경으로 1열 레이아웃 변환이 가능합니다.
 
@media (max-width: 768px) {
  .layout {
    grid-template-columns: 1fr;
    grid-template-areas:
      "header"
      "main"
      "aside"
      "footer";
  }
}

3-5. 실전 패턴 ③: 정확한 중앙 정렬

 
.center {
  display:grid;
  place-items:center;   /* align-items + justify-items 동시 설정 */
  min-height: 300px;
}
  • Flex로도 가운데 정렬이 가능하지만, 가로·세로 동시 중앙은 Grid의 place-items:center 한 줄이 가장 깔끔합니다.

3-6. Grid에서 자주 하는 실수

  • 암시적 행 높이: 열만 정의하고 행을 정의하지 않으면, 예상과 다른 암시적 행이 만들어져 카드 높이가 들쭉날쭉할 수 있습니다. 필요 시 grid-auto-rows로 기본 높이(또는 minmax 전략)를 지정하세요.
  • 라인 번호 의존: grid-area 이름을 사용하면 템플릿 변경이 쉬워집니다(라인 번호는 템플릿 변경 시 무너질 수 있음).

4) Grid vs Flex, 무엇을 선택할까? (의사결정 체크리스트)

아래 질문에 “예/아니오”로 답해 보시면 결정이 훨씬 쉬워집니다.

  1. 행과 열을 동시에 설계해야 하나요?
    예 → Grid. 아니오 → 다음 질문.
  2. 한 줄(혹은 한 열)에서 요소를 정렬·분배만 하면 되나요?
    예 → Flex.
  3. 요소의 시맨틱한 영역 이름(헤더/사이드/본문/푸터)이 중요한가요?
    예 → Grid(areas).
  4. 동일한 높이/정렬/간격으로 버튼·뱃지·아이템들을 일렬 배치하나요?
    예 → Flex.
  5. 카드가 화면 폭에 맞춰 ‘자동으로’ 열 개수가 늘었다 줄었다 해야 하나요?
    예 → Grid + auto-fit/minmax.
  6. **내부 콘텐츠 정렬(아바타 옆 텍스트, 태그 줄바꿈 등)**이 주 관심사인가요?
    예 → Flex.

실무에서는 **“페이지 뼈대는 Grid, 내부 정렬은 Flex”**의 혼합 사용이 가장 많습니다.


5) 혼합 사용 레시피(현업에서 바로 쓰는 예)

레시피 A) 대시보드

  • 바깥 뼈대: Grid(헤더/사이드/메인/푸터)
  • 카드 목록: Grid(auto-fit + minmax)
  • 카드 내부 정렬: Flex(아이콘+텍스트, 버튼 그룹)

레시피 B) 블로그 아티클 레이아웃

  • 본문/TOC(목차) 2열: Grid(1fr / 280px)
  • 목차 항목: Flex(아이콘 + 텍스트 정렬)
  • 반응형: 768px 이하에서 Grid를 1열로 전환

레시피 C) 폼 UI

  • 라벨/입력칸 2열 정렬: Grid(열 템플릿으로 정렬 균일화)
  • 버튼 줄: Flex(우측 정렬 + 간격)

6) 반응형 전략: 미디어쿼리 없이도 우아하게

6-1. Grid의 auto-fit + minmax

 
.grid-auto {
  display:grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 16px;
}
  • 컬럼 “최소 220px, 최대 1fr”로 늘었다 줄었다 → 콘텐츠가 스스로 자리를 찾습니다.

6-2. Flex의 wrap + gap

 
.flex-wrap {
  display:flex;
  flex-wrap:wrap;
  gap:12px;
}
.item { flex: 1 1 220px; } /* 최소 220px, 남으면 늘어나기 */
  • Flex도 wrapflex-basis 조합으로 간단한 카드 그리드를 만들 수 있습니다.
  • 다만, 열 정렬/줄맞춤은 Grid가 더 정확합니다.

7) 접근성·유지보수 관점에서 꼭 알아야 할 점

  1. 시각 순서와 DOM 순서
    • Flex의 order나 Grid의 위치 지정으로 화면 순서를 바꾸더라도 DOM 순서는 변하지 않습니다.
    • 키보드 포커스, 스크린리더는 DOM 순서를 따르므로, 시맨틱과 접근성을 고려해 논리적인 DOM 순서를 유지하시길 권장합니다.
  2. 네이밍(areas)과 협업
    • Grid의 grid-template-areas는 디자이너·기획자와 협업할 때 강력한 커뮤니케이션 도구가 됩니다(“헤더/사이드/메인/푸터”가 코드에 드러남).
  3. 유틸리티화
    • 자주 쓰는 패턴(센터링, 균등 간격, 카드グ리드)을 유틸 클래스로 만들어 두면 유지보수성이 크게 올라갑니다.

8) 자주 묻는 질문(FAQ)

Q1. 단순 2열/3열 카드, Flex로 해도 되나요?
A. 가능합니다. 다만 행 간 높이 맞춤, 간격 균등, 열 정렬이 중요하면 Grid가 더 깔끔합니다.

 

Q2. 카드 높이가 들쭉날쭉해요.
A. Grid면 grid-auto-rows나 내부 카드 레이아웃을 점검하세요. Flex면 자식에 min-width:0/min-height 조정, 이미지 비율(예: aspect-ratio) 고정이 필요할 수 있습니다.

 

Q3. 중앙 정렬은 무엇이 더 쉬운가요?
A. Grid의 place-items:center가 가장 간결합니다. Flex는 justify-content:center + align-items:center 두 줄이 필요합니다.


9) 실전 스니펫 모음(복붙용)

(1) 완전 중앙 정렬(가로+세로)

 
.center {
  display:grid;
  place-items:center;
  min-height: 60vh;
}

(2) 반응형 카드 그리드(미디어쿼리 최소화)

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

(3) 버튼/태그 수평 나열 + 줄바꿈

 
.pills {
  display:flex;
  flex-wrap:wrap;
  gap:8px;
}
.pills > .pill { padding:.4em .8em; border-radius:999px; background:#f2f2f2; }

(4) Holy Grail(헤더/푸터 + 좌측사이드 + 본문)

 
.holy {
  display:grid; min-height:100dvh; gap:12px;
  grid-template-columns: 240px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header header"
    "aside  main"
    "footer footer";
}
.header{grid-area:header;} .aside{grid-area:aside;}
.main{grid-area:main;} .footer{grid-area:footer;}

@media (max-width: 768px){
  .holy{
    grid-template-columns: 1fr;
    grid-template-areas:
      "header" "main" "aside" "footer";
  }
}

10) 마무리: 선택 기준 한 줄 정리(하지만 요약이 아닌 결론)

  • 한 줄·한 방향 정렬, 요소 간 간격·정렬·순서 조절이 핵심이라면 Flex가 가장 빠르고 읽기 쉽습니다.
  • 페이지 뼈대, 격자, 행·열 동시 설계, 반응형 카드 자동 칼럼이 필요하다면 Grid가 정답입니다.
  • 현업에서는 **Grid(바깥 구조) + Flex(내부 정렬)**의 혼합이 가장 실용적이며,
    유지보수성과 접근성까지 고려한 논리적 DOM 순서를 항상 함께 챙기면 좋습니다.
반응형