ToolPal
여러 모니터에 코드가 표시된 개발 환경

CSS Grid 생성기 가이드 — 2차원 레이아웃을 자신 있게 구성하는 법

📷 Christina Morillo / Pexels

CSS Grid 생성기 가이드 — 2차원 레이아웃을 자신 있게 구성하는 법

CSS Grid의 핵심 개념을 실용적인 예제로 배워보세요. grid-template-columns, fr 단위, repeat(), auto-fill, auto-fit, minmax()를 활용해 포토 갤러리와 대시보드 레이아웃을 직접 만들어봅니다.

2026년 3월 31일9분 소요

Grid를 실제로 익히기까지 걸린 시간

솔직히 말하면, CSS Grid를 훨씬 더 일찍 배웠어야 했는데 한동안 피하고 있었다. Flexbox로 대부분의 레이아웃을 처리할 수 있었고, Grid 문서를 열 때마다 '암묵적 트랙'이나 '명명된 그리드 라인' 같은 용어가 나와서 조용히 탭을 닫곤 했다. 너무 복잡해 보였다.

생각이 바뀐 건 Flexbox로 대시보드 레이아웃을 만들려다 한계에 부딪혔을 때였다. 사이드바, 헤더, 메인 콘텐츠 영역, 푸터가 있는 구조였는데 모든 것을 맞추려고 flex 컨테이너를 세 단계나 중첩해야 했다. 동작은 했지만 디자인이 조금만 바뀌어도 HTML 구조 전체를 뜯어고쳐야 했다. 그때 누군가 Grid를 써보라고 권유했고, 한 시간 만에 같은 레이아웃을 CSS 30줄로 다시 썼다. HTML은 거의 그대로였다.

이게 Flexbox가 할 수 없는 Grid만의 강점이다. HTML 중첩 구조와 상관없이, 컨테이너에서 2차원 레이아웃을 한 번에 정의할 수 있다.

이 가이드는 실무에서 Grid를 매일 쓰는 데 필요한 것들을 다룬다. 핵심 속성, 독특하지만 유용한 함수들, 실제 프로젝트에서 써온 패턴까지. 읽으면서 직접 실험해보고 싶다면 ToolBox Hubs의 CSS Grid 생성기를 열어두길 권한다. 열, 행, 간격을 시각적으로 설정하고 CSS 코드를 바로 확인할 수 있어서 개념을 익히는 데 도움이 된다.


핵심 개념부터 잡기

코드에 들어가기 전에 개념부터 정리하자. CSS Grid는 그래픽 디자이너가 레이아웃 그리드를 생각하는 방식과 비슷하다. 수평선과 수직선을 정의하면 그 선들이 셀을 만든다. 그 셀에 콘텐츠를 배치하거나, 브라우저가 자동으로 배치하게 할 수 있다.

이건 Flexbox와 근본적으로 다른 접근이다. Flexbox는 아이템이 레이아웃을 주도한다. grow, shrink, align 속성을 아이템에 설정해서 배치를 제어한다. Grid는 이걸 뒤집는다. 레이아웃은 컨테이너에 정의되고, 아이템은 그 구조를 따른다.


그리드 정의하기

시작은 간단하다:

.container {
  display: grid;
}

이것만으로는 큰 변화가 없다. 아이템은 기본적으로 한 열에 쌓인다. 핵심은 트랙을 정의하는 데 있다.

grid-template-columns와 grid-template-rows

열과 행의 크기를 정의한다. 값은 트랙 크기를 공백으로 구분해서 나열한다.

.container {
  display: grid;
  grid-template-columns: 200px 400px 200px;
  grid-template-rows: 100px auto 60px;
}

이렇게 하면 세 열(200px, 400px, 200px)과 세 행(100px, 콘텐츠 높이, 60px)이 생긴다. 아이템은 왼쪽에서 오른쪽, 위에서 아래 순서로 배치된다.

px, em, rem, %, vw 등 CSS 길이 단위는 모두 쓸 수 있다. 하지만 Grid가 새로 도입한 단위가 가장 유용하다.


fr 단위

fr은 fraction(분수)의 약자다. 그리드 컨테이너의 사용 가능한 여유 공간을 비율로 나타낸다. 퍼센트보다 훨씬 나은 이유가 있다:

/* 퍼센트 방식 — 직접 계산해야 함 */
.container {
  display: grid;
  grid-template-columns: 25% 50% 25%;
}

/* fr 방식 — 비율만 지정하면 됨 */
.container {
  display: grid;
  grid-template-columns: 1fr 2fr 1fr;
}

두 방법 모두 같은 레이아웃을 만들지만, fr은 gap을 올바르게 처리한다. 퍼센트를 쓸 때 gap을 추가하면 전체 너비가 100%를 초과해 오버플로가 생긴다. fr은 gap을 먼저 빼고 남은 공간을 분배하기 때문에 계산이 필요 없다.

.container {
  display: grid;
  grid-template-columns: 1fr 2fr 1fr;
  gap: 24px;
  /* 브라우저가 24px gap 두 개를 먼저 빼고
     나머지를 1:2:1 비율로 나눔 */
}

고정 너비와 fr을 함께 쓰는 것도 가능하다. 실제 레이아웃에서 자주 쓰는 패턴이다:

.layout {
  display: grid;
  grid-template-columns: 280px 1fr;
  /* 사이드바는 항상 280px, 콘텐츠는 나머지 전부 */
}

이 패턴 — 고정 사이드바, 유동 콘텐츠 — 은 거의 모든 프로젝트에서 쓰게 된다.


repeat() 함수

같은 너비의 열이 여러 개 필요할 때 일일이 적는 건 번거롭다. repeat()이 이 문제를 해결한다:

/* repeat 없이 */
.grid {
  grid-template-columns: 1fr 1fr 1fr 1fr;
}

/* repeat 사용 */
.grid {
  grid-template-columns: repeat(4, 1fr);
}

repeat(4, 1fr)은 "1fr 너비의 트랙 4개"를 의미한다. 복잡한 패턴 반복도 가능하다:

.grid {
  grid-template-columns: repeat(3, 100px 1fr);
  /* 결과: 100px 1fr 100px 1fr 100px 1fr */
}

하지만 repeat()의 진짜 강력함은 두 가지 특별한 키워드와 결합할 때 드러난다.


auto-fill과 auto-fit

이 부분이 Grid가 '유용한 도구'에서 '마법 같은 도구'로 바뀌는 지점이다. 열 개수를 직접 지정하는 대신, 컨테이너에 맞는 만큼 자동으로 만들라고 지시할 수 있다:

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, 200px);
  gap: 16px;
}

컨테이너 너비에 따라 열 수가 자동으로 조정된다. 넓은 화면에선 5열, 좁은 화면에선 2열이 될 수 있다. 미디어 쿼리 없이.

auto-fillauto-fit의 차이는 미묘하지만 중요하다:

auto-fill은 들어갈 수 있는 만큼 트랙을 만들고 빈 트랙도 유지한다. 아이템이 3개인데 6열이 들어갈 공간이 있다면, 빈 열 3개가 공간을 차지한 채로 남는다.

auto-fit도 트랙을 자동으로 만들지만, 빈 트랙을 너비 0으로 축소한다. 아이템 3개에 6열 공간이 있으면 빈 열이 사라지고 3개 아이템이 늘어나 공간을 채운다.

/* auto-fill: 빈 열이 공간을 차지 */
.fill-grid {
  grid-template-columns: repeat(auto-fill, 200px);
}

/* auto-fit: 아이템이 늘어나 공간 채움 */
.fit-grid {
  grid-template-columns: repeat(auto-fit, 200px);
}

어떤 걸 쓸지는 디자인에 달려 있다. 아이템 크기가 일정해야 하는 포토 갤러리엔 auto-fill이, 아이템이 행을 꽉 채워야 하는 카드 그리드엔 auto-fit이 적합하다.


minmax() 함수

마지막 핵심 요소는 minmax()다. 고정 크기 대신 트랙의 크기 범위를 지정한다. 최솟값과 최댓값 두 가지 인수를 받는다.

.grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(200px, 1fr));
}

이렇게 하면 최소 200px, 최대 1fr인 세 열이 생긴다. 넓은 화면에선 늘어나고, 좁은 화면에선 200px 이하로 줄어들지 않는다.

repeat(), auto-fill/auto-fit, minmax()의 조합은 너무 자주 쓰여서 반응형 그리드의 표준 패턴이 되었다:

.responsive-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 24px;
}

이렇게 읽으면 된다: "최소 240px 너비의 열을 가능한 한 많이 만들고, 각 열은 동일하게 여유 공간을 채운다." 아이템은 자동으로 줄바꿈된다. 미디어 쿼리도, JavaScript도 필요 없다. 카드 그리드가 급하게 필요할 때 가장 먼저 쓰는 패턴이다.


실전 예제: 포토 갤러리

이 개념이 실제로 어떻게 활용되는지 포토 갤러리를 처음부터 만들어보자.

<div class="gallery">
  <img src="photo-1.jpg" alt="...">
  <img src="photo-2.jpg" alt="...">
  <!-- 사진 더 추가 -->
</div>
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 8px;
}

.gallery img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  display: block;
}

이게 전부다. 그리드가 컨테이너 너비에 맞게 열 수를 자동으로 결정한다. 이미지는 aspect-ratio로 정사각형 비율을 유지하고, object-fit: cover가 잘림을 처리한다. 모바일에선 2열, 넓은 데스크톱에선 6열이 나올 수 있다. 미디어 쿼리 없이 반응형이다.

특정 사진을 강조하고 싶다면 여러 셀에 걸치게 할 수 있다:

.gallery img:first-child {
  grid-column: span 2;
  grid-row: span 2;
}

첫 번째 사진이 2x2 블록을 차지하고 나머지가 그 주위를 채운다. position 트릭도 float도 필요 없다. 순수한 Grid 배치다.


실전 예제: 대시보드 레이아웃

이 예제가 나를 Grid로 완전히 전환시킨 케이스다. 사이드바, 헤더, 메인 콘텐츠, 푸터가 있는 대시보드다.

<div class="dashboard">
  <header class="dash-header">헤더</header>
  <nav class="dash-sidebar">사이드바</nav>
  <main class="dash-main">메인 콘텐츠</main>
  <footer class="dash-footer">푸터</footer>
</div>
.dashboard {
  display: grid;
  grid-template-columns: 260px 1fr;
  grid-template-rows: 60px 1fr 40px;
  grid-template-areas:
    'header header'
    'sidebar main'
    'footer footer';
  min-height: 100vh;
  gap: 0;
}

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

grid-template-areas 속성이 이 레이아웃을 특히 읽기 좋게 만든다. ASCII 아트로 레이아웃을 그리는 것과 비슷하다. 헤더와 푸터는 두 열 모두에 걸쳐 있고, 사이드바는 260px, 메인 콘텐츠는 나머지를 채운다.

반응형 처리도 간단하다:

@media (max-width: 768px) {
  .dashboard {
    grid-template-columns: 1fr;
    grid-template-rows: 60px auto 1fr 40px;
    grid-template-areas:
      'header'
      'sidebar'
      'main'
      'footer';
  }
}

모바일에서는 모든 것이 한 열로 쌓인다. 사이드바가 헤더 아래로 내려온다. 깔끔하다.


CSS Grid 생성기 활용하기

레이아웃을 코드로 짜기 전에 결과를 미리 보고 싶다면 ToolBox Hubs의 CSS Grid 생성기를 열어보자. 열과 행 수를 설정하고, 간격을 조정하고, 열과 행 크기를 시각적으로 구성한 후 정확한 CSS 코드를 바로 복사해 프로젝트에 붙여넣을 수 있다.

특히 grid-template-areas 작업에서 유용하다. 어떤 영역이 어떤 셀에 걸쳐 있는지 시각적으로 확인하는 게 코드만 들여다보는 것보다 훨씬 쉽다. 레이아웃을 한 번 구성하고 CSS를 복사하면 끝이다. 일일이 손으로 작성하는 것보다 빠르고, 레이아웃 아이디어를 빠르게 검증하기에도 좋다.


Grid vs Flexbox: 진짜 답

둘 중 하나를 골라야 한다고 생각하는 사람들이 있는데, 그럴 필요가 없다. 해결하는 문제가 다르다.

Grid를 쓸 때:

  • 행과 열이 서로 정렬되어야 할 때
  • 페이지 전체 구조(헤더, 사이드바, 메인, 푸터)를 잡을 때
  • 아이템이 여러 행 또는 열에 걸쳐야 할 때
  • 컨테이너에서 레이아웃을 정의하고 싶을 때
  • 내부 콘텐츠 영역이 열 기준으로 정렬되어야 하는 카드 그리드를 만들 때

Flexbox를 쓸 때:

  • 아이템이 한 행이나 한 열에 있을 때
  • 아이템이 콘텐츠 크기에 맞게 자체 사이즈를 조정해야 할 때
  • 내비게이션 링크, 버튼, 폼 인풋을 인라인으로 배치할 때
  • 아이템이 줄바꿈되지만 행 간 정렬은 중요하지 않을 때

실제 프로젝트에선 둘 다 쓴다. Grid는 페이지 골격을 잡고, Flexbox는 컴포넌트 내부 — 내비게이션 바, 카드 안의 버튼 그룹, 폼 레이아웃 — 를 처리한다. 경쟁 관계가 아니라 보완 관계다.

가장 기억하기 쉬운 기준: "Grid는 레이아웃을 위해, Flexbox는 정렬을 위해." 단순화된 표현이지만 대부분의 경우에서 올바른 선택으로 이끌어준다.


브라우저 지원과 실제 주의사항

Grid는 2017년부터 모든 주요 브라우저에서 완전히 지원된다. 벤더 접두사도, 폴리필도 필요 없다. 그냥 쓰면 된다.

유일한 예외는 IE 11이다. IE 11은 이전 버전의 명세를 기반으로 -ms- 접두사를 사용하는 구현을 갖고 있어, 현대 Grid 문법과 대부분 호환되지 않는다. IE 11 사용자가 여전히 의미 있는 비율이라면 Grid 사용 시 신중하게 접근하거나 대체 스타일을 준비해야 한다.

IE 11을 지원하지 않는다면 — 솔직히 이제 대부분의 경우가 그렇다 — Grid는 아무 제약 없이 프로덕션에서 쓸 수 있다.

한 가지 더 언급할 속성: subgrid. 자식 그리드가 부모 그리드의 트랙 정의를 상속받아 함께 참여할 수 있게 해주는 기능인데, 중첩된 콘텐츠를 정렬할 때 유용하다. Safari와 Chrome 모두 2023년에 지원을 추가했고, 2026년 초 현재 주요 브라우저에서 안정적으로 지원된다. 구형 브라우저를 지원해야 하는 프로젝트라면 구체적인 대상 브라우저를 확인해보자.


실무에서 자주 쓰는 속성들

여러 프로젝트에서 Grid를 써오면서 가장 많이 쓰게 된 속성들이다:

/* 기본 정의 */
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
grid-template-rows: auto;

/* 복잡한 레이아웃을 위한 영역 이름 지정 */
grid-template-areas: 'header' 'sidebar main' 'footer';

/* 아이템 배치 */
grid-column: span 2;
grid-row: span 2;

/* 또는 명시적 배치 */
grid-column: 1 / 3; /* 1번 선에서 시작, 3번 선에서 끝 */
grid-row: 2 / 4;

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

암묵적 그리드 속성(grid-auto-rows, grid-auto-columns)도 알아두면 좋다. 명시적으로 정의되지 않은 행에 아이템이 자동 배치될 때 grid-auto-rows가 높이를 설정한다:

.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 200px; /* 자동 배치되는 모든 행은 200px 높이 */
}

아이템을 행이 아닌 열 방향으로 자동 배치하고 싶다면 grid-auto-flow: column을 쓰면 된다.


내가 Grid를 이해한 순간

Grid가 더 이상 어렵게 느껴지지 않은 순간은 모든 속성을 외우려는 시도를 멈추고 세 가지를 내면화했을 때였다:

  1. 열과 행은 아이템이 아닌 컨테이너에 정의한다.
  2. fr 단위는 여유 공간을 비율로 분배한다.
  3. repeat(auto-fill, minmax(최솟값, 1fr))이 반응형 그리드의 기본 패턴이다.

나머지 — 영역 이름 지정, 셀 걸치기, 명시적 배치 — 는 필요할 때 찾아보면 된다. 하지만 이 세 가지 개념만 있으면 실무 Grid 사용의 80%는 커버된다.

CSS Grid는 한 번 이해하면 마치 일을 대신 해주는 것처럼 느껴지는 도구다. 2015년에 float나 깊이 중첩된 flexbox로 50줄을 썼을 레이아웃이 이제 Grid로 10줄이면 충분하다. 이건 진짜 생산성 향상이다. 익숙해지고 나면 Grid 이전의 레이아웃 작업이 어떻게 가능했는지 의아해질 것이다.

자주 묻는 질문

이 글 공유하기

XLinkedIn

관련 글