안녕하세요! 프론트엔드 개발자 양성 과정 강사입니다. CSS Grid 레이아웃을 깊이 있게 공부하고 계시군요! MDN 공식 문서를 통해 꼼꼼히 학습하시는 모습이 정말 훌륭합니다.
요청하신 대로 원본 문서의 내용을 하나도 빠짐없이, 이해하기 쉬운 구어체로 번역해 드릴게요. 중간중간 실무에서 어떻게 쓰이는지, 그리고 여러분이 헷갈리기 쉬운 부분에 대해 제 경험을 담은 보충 설명(팁)도 듬뿍 추가했습니다. 자, 그럼 시작해 볼까요?
이전 가이드들에서 우리는 그리드 트랙을 정의하여 생성된 라인 위에 아이템을 배치하는 방법과, 이름이 지정된 템플릿 영역을 사용하여 아이템을 배치하는 방법을 살펴보았어요. 이번 가이드에서는 우리가 '이름이 지정된 라인(named lines)'을 사용할 때 이 두 가지 개념이 어떻게 함께 맞물려 작동하는지 살펴볼 거예요.
라인에 이름을 지정하는 기능은 정말 엄청나게 유용합니다. 하지만 이 이름과 트랙 크기 지정이 결합될 때 그리드 문법이 조금 헷갈리게 느껴질 수도 있어요. 몇 가지 예제를 직접 실습해 보면서 따라오시면, 개념이 훨씬 명확해지고 다루기도 쉬워질 테니 걱정 마세요!
💡 강사의 팁:
현업에서도 그리드 라인이 많아지면 숫자(1, 2, 3...)만으로 위치를 기억하기가 매우 어렵습니다. "여기가 4번 라인이었나, 5번 라인이었나?" 헷갈리기 쉽죠. 이럴 때 라인에 직관적인 이름을 붙여두면 유지보수성이 크게 향상됩니다. 꼭 마스터해야 할 핵심 기술이에요!
grid-template-rows와 grid-template-columns 속성을 사용하여 그리드를 정의할 때, 그리드 내의 라인 중 일부 또는 전체에 이름을 할당할 수 있습니다. 이를 시각적으로 보여드리기 위해 라인 기반 배치 가이드에서 만들었던 기본적인 레이아웃을 다시 가져와 볼게요. 다만 이번에는 숫자가 아닌 이름이 지정된 라인을 사용하여 그리드를 생성해 보겠습니다.
* {
box-sizing: border-box;
}
.wrapper {
border: 2px solid #f76707;
border-radius: 5px;
background-color: #fff4e6;
}
.wrapper > div {
border: 2px solid #ffa94d;
border-radius: 5px;
background-color: #ffd8a8;
padding: 1em;
color: #d9480f;
}
그리드를 정의할 때, 우리는 대괄호([]) 안에 라인의 이름을 지정합니다. 이름은 여러분이 원하는 대로 자유롭게 지을 수 있어요. 여기서는 컨테이너의 시작과 끝을 나타내는 이름을 행(row)과 열(column) 모두에 정의해 볼 겁니다. 아래 예제에서 중앙에 위치할 그리드 블록의 시작 행과 열의 이름은 모두 content-start로 지정하고, 끝나는 행과 열의 이름은 모두 content-end로 지정했습니다.
.wrapper {
display: grid;
grid-template-columns: [main-start] 1fr [content-start] 1fr [content-end] 1fr [main-end];
grid-template-rows: [main-start] 100px [content-start] 100px [content-end] 100px [main-end];
}
우리가 그리드의 모든 라인에 일일이 이름을 지어줄 필요는 없어요. 레이아웃의 핵심이 되는 주요 라인에만 이름을 지정해도 충분합니다.
이렇게 라인에 이름이 부여되고 나면, 그리드 아이템을 배치할 때 라인 번호(1, 2, 3...) 대신 우리가 정의한 이름을 바로 사용할 수 있게 됩니다.
.box1 {
grid-column-start: main-start;
grid-row-start: main-start;
grid-row-end: main-end;
}
.box2 {
grid-column-start: content-end;
grid-row-start: main-start;
grid-row-end: content-end;
}
.box3 {
grid-column-start: content-start;
grid-row-start: main-start;
}
.box4 {
grid-column-start: content-start;
grid-column-end: main-end;
grid-row-start: content-end;
}
<div class="wrapper">
<div class="box1">One</div>
<div class="box2">Two</div>
<div class="box3">Three</div>
<div class="box4">Four</div>
</div>
라인 기반 배치의 다른 모든 기능들은 기존과 완전히 동일하게 작동합니다. 그리드 레이아웃에서 우리는 각 숫자형 라인에 '별칭(alias name)'을 부여한 셈이고, 그리드 아이템에서는 숫자가 아닌 그 별칭을 참조하게 된 것뿐이에요.
이런 방식으로 라인에 이름을 지정하는 것은 반응형 웹 디자인(responsive design)을 만들 때 엄청난 빛을 발합니다. 미디어 쿼리(media query) 안에서 각 개별 그리드 아이템들의 위치(숫자)를 일일이 수정할 필요 없이, 컨테이너의 그리드 속성 하나만 쓱 업데이트해주면 모든 레이아웃이 마법처럼 다시 정렬되거든요!
💡 강사의 팁:
화면 크기(모바일/태블릿/데스크탑)에 따라 디자인이 확확 바뀌어야 할 때, 아이템마다grid-column: 1 / 3하던 것을 미디어 쿼리에서grid-column: 1 / 2로 바꾸는 작업은 정말 고역입니다. 하지만 이름을 써두면 아이템 자체의 CSS는 그대로 둔 채로 부모(.wrapper)의 라인 정의만 변경하면 되니 코드가 훨씬 깨끗해집니다.
때로는 하나의 라인에 두 개 이상의 이름을 부여하고 싶을 때가 있을 거예요. 예를 들어 어떤 라인이 사이드바의 끝(sidebar-end)이면서 동시에 메인 콘텐츠의 시작(main-start)을 의미할 수 있겠죠. 이렇게 하려면 대괄호 안에 이름들을 넣고 그 사이에 공백(띄어쓰기)을 두면 됩니다. 예를 들면 [sidebar-end main-start] 처럼요. 이렇게 정의하고 나면, 두 이름 중 어떤 것으로든 해당 라인을 참조할 수 있습니다.
앞서 라인의 이름을 지을 때 여러분이 원하는 이름으로 자유롭게 지을 수 있다고 말씀드렸죠. 이 이름은 개발자가 직접 정의하는 <custom-ident> 타입입니다. 단, 이름을 지을 때는 CSS 명세서에 사용되어 혼동을 줄 수 있는 단어(예: span 등)는 피해야 합니다. 식별자(Idents)에는 따옴표를 사용하지 않아요.
이름은 마음대로 지을 수 있지만, 만약 어떤 영역을 둘러싼 라인들의 이름 끝에 -start 와 -end 라는 접미사를 붙이게 되면 (위의 예제에서 했던 것처럼요), 그리드 시스템이 정말 똑똑하게도 메인 이름을 딴 그리드 영역(grid area)을 암시적으로 자동 생성해 줍니다!
위의 예제를 다시 살펴볼까요? 우리는 행과 열 모두에 content-start 와 content-end 라는 라인을 만들었어요. 이 말은 즉, 시스템이 알아서 content 라는 이름의 그리드 영역을 만들어 준다는 뜻입니다. 이제 우리는 원한다면 어떤 요소든 그 content 영역에 바로 꽂아 넣을 수 있습니다.
* {
box-sizing: border-box;
}
.wrapper {
border: 2px solid #f76707;
border-radius: 5px;
background-color: #fff4e6;
}
.wrapper > div {
border: 2px solid #ffa94d;
border-radius: 5px;
background-color: #ffd8a8;
padding: 1em;
color: #d9480f;
}
위에서 정의했던 것과 똑같은 그리드를 다시 선언한 후, 이번에는 단일 아이템을 암시적으로 생성된 content 라는 이름의 영역에 배치해 보겠습니다.
.wrapper {
display: grid;
grid-template-columns: [main-start] 1fr [content-start] 1fr [content-end] 1fr [main-end];
grid-template-rows: [main-start] 100px [content-start] 100px [content-end] 100px [main-end];
}
.thing {
grid-area: content;
}
<div class="wrapper">
<div class="thing">I am placed in an area named content.</div>
</div>
우리가 명시적으로 grid-template-areas 속성을 써서 영역을 그린 적이 없는데도, 이름이 지정된 라인들이 우리를 위해 알아서 영역을 척척 만들어 낸 것이죠!
💡 강사의 팁:
이-start,-end네이밍 규칙은 꼭 알아두셔야 하는 CSS Grid의 '숨겨진 필살기' 같은 거예요. 라인 이름만 규칙에 맞춰 잘 지어주면 영역은 공짜로 얻어지는 셈이니까요! 타이핑을 확 줄여주는 정말 고마운 기능입니다.
우리는 지금까지 이름이 지정된 라인이 어떻게 영역을 만들어내는지 보았습니다. 그런데 놀랍게도 이 원리는 반대로도 작동합니다! 이름이 지정된 템플릿 영역(Named template areas)을 만들면, 그 영역은 여러분이 아이템을 배치할 때 사용할 수 있는 이름이 지정된 라인을 자동으로 만들어냅니다.
그리드 템플릿 영역 가이드에서 만들었던 레이아웃을 가져와서, 영역에 의해 생성된 라인들을 어떻게 사용할 수 있는지 한 번 살펴볼게요.
이 예제에서는 overlay 라는 클래스를 가진 <div> 를 추가했습니다. 먼저 grid-area 속성을 통해 각 요소의 영역 이름을 지정하고, 부모 요소의 grid-template-areas 에서 전체 레이아웃을 그립니다. 우리가 만든 영역의 이름들은 다음과 같아요.
hd (헤더)ft (푸터)main (메인 콘텐츠)sd (사이드바)이렇게 선언하기만 해도, 시스템은 우리에게 다음과 같은 열(column) 및 행(row) 라인 이름들을 선물해 줍니다.
hd-start / hd-endsd-start / sd-endmain-start / main-endft-start / ft-end아래 첨부된 이미지를 보시면 이름이 지정된 라인들을 한눈에 확인할 수 있습니다. 여기서 주목할 점은 어떤 라인은 두 개의 이름을 가질 수도 있다는 거예요. 예를 들어 sd-end 와 main-start 는 사실상 동일한 열의 라인을 가리키고 있죠.

자, 이제 암시적으로 생성된 이 라인 이름들을 사용하여 overlay 요소를 배치하는 것은 앞서 배운 일반적인 라인 기반 배치 방법과 완전히 동일합니다!
* {
box-sizing: border-box;
}
.wrapper {
border: 2px solid #f76707;
border-radius: 5px;
background-color: #fff4e6;
}
.wrapper > div {
border: 2px solid #ffa94d;
border-radius: 5px;
background-color: #ffd8a8;
padding: 1em;
color: #d9480f;
}
.wrapper {
display: grid;
grid-template-columns: repeat(9, 1fr);
grid-auto-rows: minmax(100px, auto);
grid-template-areas:
"hd hd hd hd hd hd hd hd hd"
"sd sd sd main main main main main main"
"ft ft ft ft ft ft ft ft ft";
}
.header {
grid-area: hd;
}
.footer {
grid-area: ft;
}
.content {
grid-area: main;
}
.sidebar {
grid-area: sd;
}
.wrapper > div.overlay {
z-index: 10;
grid-column: main-start / main-end; /* 암시적 라인 이름 사용! */
grid-row: hd-start / ft-end; /* 암시적 라인 이름 사용! */
border: 4px solid rgb(92 148 13);
background-color: rgb(92 148 13 / 40%);
color: rgb(92 148 13);
font-size: 150%;
}
<div class="wrapper">
<div class="header">Header</div>
<div class="sidebar">Sidebar</div>
<div class="content">Content</div>
<div class="footer">Footer</div>
<div class="overlay">Overlay</div>
</div>
이름이 지정된 영역을 통해 라인을 자동으로 생성하고, 또 반대로 이름이 지정된 라인을 통해 영역을 생성할 수 있다는 사실을 알게 되셨죠? 그렇기 때문에 그리드 레이아웃을 짜기 시작할 때, 이름 짓기 전략(naming strategy)을 미리 계획하는 데 약간의 시간을 투자하는 것이 아주 중요합니다. 여러분과 팀원들 모두가 이해할 수 있는 합리적인 이름을 선택하면 레이아웃 코드가 훨씬 직관적이고 읽기 쉬워질 거예요.
만약 그리드의 모든 라인에 완전히 고유한 이름을 부여하고 싶다면, repeat 문법을 사용하지 말고 긴 형태로 일일이 트랙 속성을 정의해야 합니다. 왜냐하면 트랙을 정의할 때 대괄호 안에 이름을 명시해야 하기 때문이죠.
하지만 만약 repeat() 문법을 사용하면서 그 안에 라인 이름을 지정하게 된다면, 동일한 이름을 가진 여러 개의 라인이 생성되게 됩니다. 이 동작은 여러분의 레이아웃 요구사항에 따라 굉장히 유용할 수도 있고, 반대로 엄청 헷갈릴 수도 있어요.
이번 예제에서는 12개의 동일한 너비를 가진 열(column) 그리드를 만들어 보겠습니다. 1fr 이라는 열 트랙 크기를 정의하기 바로 직전에, [col-start] 라는 이름의 라인을 정의할 거예요.
이 말은 즉, 12개의 1fr 너비 열 앞에 각각 col-start 라는 이름이 붙은 라인이 총 12개가 생성된다는 뜻입니다.
* {
box-sizing: border-box;
}
.wrapper {
border: 2px solid #f76707;
border-radius: 5px;
background-color: #fff4e6;
}
.wrapper > div {
border: 2px solid #ffa94d;
border-radius: 5px;
background-color: #ffd8a8;
padding: 1em;
color: #d9480f;
}
.wrapper {
display: grid;
grid-template-columns: repeat(12, [col-start] 1fr);
}
그리드가 생성되었으니 이제 아이템을 배치해 볼 차례입니다. 우리에겐 col-start 라는 똑같은 이름을 가진 여러 개의 라인이 존재합니다. 만약 여러분이 어떤 아이템을 col-start 라인 이후에 시작하도록 배치한다면, 기본적으로 시스템은 가장 첫 번째에 위치한 col-start 라인(이 경우 맨 왼쪽 라인)을 사용합니다.
만약 첫 번째가 아닌 다른 위치의 라인을 지정하고 싶다면 어떻게 해야 할까요? 바로 이름 뒤에 해당 라인이 몇 번째에 있는지를 나타내는 숫자를 함께 적어주면 됩니다.
예를 들어, 첫 번째 col-start 라인부터 다섯 번째 col-start 라인까지 걸쳐지는 아이템을 배치하려면 다음과 같이 작성합니다.
.item1to5 {
grid-column: col-start / col-start 5;
}
또한, 여기서도 여전히 span 키워드를 섞어 쓸 수 있습니다. 아래의 아이템은 7번째 col-start 라인에서 시작해서 3개의 라인을 차지하도록 뻗어나갈(span) 것입니다.
.item7to9 {
grid-column: col-start 7 / span 3;
}
<div class="wrapper">
<div class="item1to5">I am placed from col-start line 1 to col-start 5</div>
<div class="item7to9">I am placed from col-start line 7 spanning 3 lines</div>
</div>
브라우저의 개발자 도구를 열어 이 레이아웃을 확인해 보면 열 라인들이 어떻게 표시되어 있는지, 그리고 우리가 지정한 라인에 맞게 아이템이 어떻게 잘 배치되었는지 선명하게 보일 거예요.

💡 강사의 팁:
이 방식은 일정한 규칙성을 가진 다단 그리드(Multi-column grid)를 구성할 때 최고입니다.col-start라는 공통 이름을 부여하고 숫자만col-start 3,col-start 6식으로 컨트롤하면 디자인 시안의 그리드 넘버링을 코드에 직관적으로 매핑할 수 있어요.
repeat() 문법에는 단일 트랙 크기 하나만 들어갈 수 있는 것이 아닙니다. 트랙들의 리스트(패턴) 자체를 통째로 반복시킬 수도 있어요!
다음 CSS 코드는 총 8개의 트랙을 가진 그리드를 생성합니다. 좁은 너비(1fr)를 가진 col1-start 라인 뒤에 넓은 너비(3fr)를 가진 col2-start 라인이 번갈아가며 나타나는 패턴을 4번 반복하게 됩니다.
.wrapper {
grid-template-columns: repeat(4, [col1-start] 1fr [col2-start] 3fr);
}
만약 반복 구문 안에서 두 개의 라인이 서로 딱 붙어있게 된다면(인접하게 된다면), 그리드 시스템은 이 두 라인을 병합해버립니다. 이는 반복 없이 트랙을 정의할 때 하나의 라인에 여러 개의 이름을 부여한 것과 똑같은 결과([name1 name2])를 만들어냅니다.
다음 예제는 각각 시작 라인과 끝 라인을 모두 가진 4개의 1fr 트랙을 정의하고 있습니다.
.wrapper {
grid-template-columns: repeat(4, [col-start] 1fr [col-end]);
}
만약 이 코드를 repeat() 표기법을 쓰지 않고 쭉 풀어서 작성한다면 실제로는 아래와 같은 형태가 됩니다. (붙어있는 col-end와 col-start가 하나로 합쳐진 것을 잘 보세요!)
.wrapper {
grid-template-columns: [col-start] 1fr [col-end col-start] 1fr [col-end col-start] 1fr [col-end col-start] 1fr [col-end];
}
트랙 리스트를 사용할 때도 span 키워드를 활용해 원하는 줄 수만큼, 심지어 특정 이름의 라인 개수를 기준으로 영역을 차지하도록 뻗어나갈 수 있습니다.
* {
box-sizing: border-box;
}
.wrapper {
border: 2px solid #f76707;
border-radius: 5px;
background-color: #fff4e6;
}
.wrapper > div {
border: 2px solid #ffa94d;
border-radius: 5px;
background-color: #ffd8a8;
padding: 1em;
color: #d9480f;
}
.wrapper {
display: grid;
grid-template-columns: repeat(6, [col1-start] 1fr [col2-start] 3fr);
}
.item1 {
grid-column: col1-start / col2-start 2;
}
.item2 {
grid-row: 2;
grid-column: col1-start 2 / span 2 col1-start;
}
<div class="wrapper">
<div class="item1">
I am placed from col1-start line 1 to col2-start line 2
</div>
<div class="item2">
I am placed from col1-start line 2 spanning 2 lines named col1-start
</div>
</div>
숫자를 활용한 라인 배치, 이름이 지정된 라인 기반 배치, 그리고 그리드 템플릿 영역까지 다 배우셨습니다! 이제 여러분은 CSS 그리드 레이아웃을 사용해 아이템을 배치하는 다양한 방법의 무기를 갖추게 된 셈이죠.
어쩌면 이 모든 게 너무 복잡하다고 느껴지실 수도 있지만, 겁먹지 마세요. 이 모든 방법을 항상 섞어서 써야 하는 것은 아닙니다. 실무에서는 비교적 단순한 레이아웃을 짤 때 '그리드 템플릿 영역(Named template areas)'을 사용하는 것만으로도 훌륭히 작동합니다. 코드가 레이아웃을 시각적으로 잘 보여주고, 요소들의 위치를 이리저리 옮기기도 아주 직관적이거든요. 반면, 규칙적이고 엄격한 다단 레이아웃(multiple-column layout)을 짤 때는 방금 배웠던 '이름이 지정된 라인(Named lines)' 방식이 강력한 위력을 발휘합니다.
과거에 많이 썼던 Bootstrap(부트스트랩)이나 Foundation 같은 레거시 그리드 시스템들은 기본적으로 12열(12-column) 그리드에 기반을 두고 있어요. 이 프레임워크들은 열 너비의 합이 딱 100%가 되도록 복잡한 계산을 수행하는 무거운 코드를 불러와야 했죠.
하지만 이제 그런 프레임워크들은 필요 없습니다! 완벽한 12열 그리드 "프레임워크"를 위해 우리가 작성해야 할 CSS는 단 세 줄이면 충분합니다.
.wrapper {
display: grid;
gap: 10px;
grid-template-columns: repeat(12, [col-start] 1fr);
}
그리고 이렇게 만든 가벼운 "프레임워크"를 사용해 아주 쉽게 전체 페이지 레이아웃을 짤 수 있습니다.
예를 들어, 헤더와 푸터가 있고 본문이 세 개의 열로 나뉘는 레이아웃(three-column layout)을 만들고 싶다면 다음과 같이 마크업을 작성하면 됩니다.
* {
box-sizing: border-box;
}
.wrapper {
border: 2px solid #f76707;
border-radius: 5px;
background-color: #fff4e6;
}
.wrapper > * {
border: 2px solid #ffa94d;
border-radius: 5px;
background-color: #ffd8a8;
padding: 1em;
color: #d9480f;
}
<div class="wrapper">
<header class="main-header">I am the header</header>
<aside class="side1">I am sidebar 1</aside>
<article class="content">I am the main article</article>
<aside class="side2">I am sidebar 2</aside>
<footer class="main-footer">I am the footer</footer>
</div>
이제 우리가 만든 그리드 레이아웃 프레임워크에 아이템들을 매끄럽게 올려봅시다.
.main-header,
.main-footer {
grid-column: col-start / span 12; /* 전체 12칸 다 차지하기 */
}
.side1 {
grid-column: col-start / span 3; /* 첫 라인부터 3칸 차지하기 */
grid-row: 2;
}
.content {
grid-column: col-start 4 / span 6; /* 4번째 라인부터 6칸 차지하기 */
grid-row: 2;
}
.side2 {
grid-column: col-start 10 / span 3; /* 10번째 라인부터 3칸 차지하기 */
grid-row: 2;
}
개발자 도구의 그리드 하이라이터를 켜보면, 우리가 배치한 아이템들이 그리드 위에서 얼마나 완벽하게 동작하는지 볼 수 있습니다.

보시다시피 이게 전부입니다. 우리가 직접 머리를 쥐어짜며 복잡한 퍼센트(%) 여백 계산을 할 필요가 전~혀 없습니다! CSS 그리드 레이아웃 엔진이 알아서 10px의 갭(gutter)을 전체 공간에서 먼저 깔끔하게 빼준 다음, 남은 공간을 1fr 크기의 열 트랙들에 완벽하게 분배해 주니까요.
다음 가이드에서는 이런 배치 속성을 하나도 적어주지 않아도 CSS 그리드 레이아웃이 알아서 똑똑하게 요소들의 자리를 찾아주는 그리드 레이아웃의 자동 배치(auto-placement in grid layout) 기능에 대해 깊게 파헤쳐 보겠습니다.
💡 강사의 마무리 팁:
과거에width: 33.3333%나calc(100% / 12 - 10px)같은 코드를 짜며 눈물 흘렸던 선배 개발자들의 고충이 CSS Grid 덕분에 완전히 사라졌습니다! 프론트엔드 실무 면접에서 레이아웃 구현 능력을 뽐낼 때 Grid를 능숙하게 사용하는 모습은 큰 가산점이 됩니다. 이 가이드 내용을 손에 익을 때까지 충분히 연습해 보세요! 화이팅입니다!
MDN 문서 개선에 참여하기 (Help improve MDN)
MDN 문서 내용이 조금은 딱딱할 수 있는데, 제 설명과 함께하니 조금 더 쉽게 다가오시나요? 코딩하다가 이해가 안 가거나 잘 안되는 부분이 있으면 혼자 앓지 말고 언제든 질문해주세요!