지금까지 배치와 겹침, 넘침을 다루는 여러 도구를 익혔지만, 정작 실무에서 마주하는 건 늘 비슷한 몇 가지 배치 문제였다. 무언가를 화면 한가운데 두는 일, 헤더와 사이드바와 본문과 푸터로 페이지를 나누는 일, 카드를 격자로 늘어놓는 일, 푸터를 바닥에 붙이는 일이 반복됐다. 이런 흔한 문제들에는 검증된 해법이 있었고, 그 패턴들을 알면 매번 고민하지 않아도 됐다.
이번 편은 실무에서 반복되는 레이아웃 문제들의 정석적인 해법을 다룬다. 요소를 완벽하게 가운데 두는 법, 페이지 전체를 구획으로 나누는 고전적인 골격, 화면 크기에 자동으로 반응하는 카드 격자, 내용이 짧아도 바닥에 붙는 푸터, 그리고 어디에나 재사용할 수 있는 배치 도구까지 살펴본다. 이 패턴들을 손에 익히면 레이아웃 작업이 훨씬 빨라진다.
1. 완벽한 중앙 정렬
요소를 화면 한가운데 두는 것은 가장 흔하면서도 오랫동안 까다로웠던 문제다. 가로 중앙은 비교적 쉬웠지만, 가로와 세로를 동시에 정확히 가운데 두는 건 예전에는 여러 편법을 동원해야 했다. 나는 이 문제로 초보 시절에 정말 많은 시간을 썼다. 지금은 훨씬 간단한 방법이 있어서, 그 시절의 고생이 무색할 정도다.
가장 간결한 방법은 그리드를 이용하는 것이다. 부모를 그리드로 만들고 자식을 가로세로 모두 가운데 두라고 지정하면, 단 한두 줄로 완벽한 중앙 정렬이 완성된다. 나는 이 방법을 알고 나서 중앙 정렬에 더 이상 고민하지 않게 되었다. 부모에 몇 줄만 적으면 그 안의 요소가 정확히 한가운데 놓인다.
플렉스를 이용하는 방법도 있다. 부모를 플렉스로 만들고 주축과 교차축 양쪽으로 가운데 정렬하면 같은 결과를 얻는다. 나는 정렬할 요소가 하나뿐이거나 단순한 경우에는 그리드를, 여러 요소를 한 방향으로 정렬하며 가운데 두는 경우에는 플렉스를 고른다. 둘 다 중앙 정렬을 쉽게 해주므로 상황에 맞게 선택한다.
세로 중앙 정렬을 위해서는 부모가 높이를 가지고 있어야 한다. 부모의 높이가 내용에 딱 맞으면 세로로 가운데 둘 여백 자체가 없기 때문이다. 나는 화면 전체에 무언가를 가운데 두고 싶을 때, 부모의 높이를 화면 높이로 맞춘 뒤 중앙 정렬한다. 세로 정렬이 안 될 때는 대개 부모의 높이가 확보되지 않은 것이 원인이다.
중앙 정렬은 로딩 화면이나 빈 상태 안내처럼 화면 한가운데 메시지를 두어야 할 때 특히 자주 쓴다. 나는 데이터를 기다리는 화면이나 검색 결과가 없을 때의 안내를, 이 중앙 정렬로 화면 한복판에 배치한다. 텅 빈 화면 가운데 놓인 안내는 사용자의 시선을 자연스럽게 모아, 지금 상황을 명확히 전달한다.
예전의 편법들과 비교하면 지금의 중앙 정렬은 놀랍도록 단순하다. 나는 이 변화가 최신 레이아웃 도구들이 실무를 얼마나 편하게 만들었는지를 보여주는 대표적인 예라고 생각한다. 과거의 복잡한 방법을 굳이 알 필요 없이, 검증된 간결한 패턴 하나만 익히면 된다. 도구가 발전하면 오래된 고민들이 이렇게 사라진다.
2. 페이지 전체를 나누는 골격
대부분의 웹 페이지는 비슷한 골격을 갖는다. 위에 헤더, 아래에 푸터, 그 사이에 사이드바와 본문이 나란히 놓이는 구조다. 이 고전적인 배치를 예전에는 여러 요소를 띄우고 정렬하며 힘겹게 만들었다. 나는 이 골격을 그리드로 짜면서, 복잡하던 페이지 구조가 얼마나 간결해질 수 있는지 실감했다.
그리드로 이 골격을 짜는 핵심은 영역에 이름을 붙이는 것이다. 헤더, 사이드바, 본문, 푸터에 각각 이름을 주고, 그 이름들을 시각적인 배치 그대로 배열한다. 나는 이 방식이 코드만 봐도 페이지가 어떻게 생겼는지 그려진다는 점이 마음에 든다. 영역 이름을 배치한 모양이 곧 화면의 모양이니, 구조가 한눈에 드러난다.
이 골격은 반응형과 자연스럽게 어울린다. 좁은 화면에서는 사이드바를 본문 아래로 내리거나 감추고, 넓은 화면에서는 나란히 두도록 영역 배열만 바꾸면 된다. 나는 화면 크기에 따라 영역들의 배치도만 다시 그려서, 하나의 골격이 좁은 화면과 넓은 화면 모두에 대응하게 한다. 배치를 이름으로 다루니 재배열이 쉽다.
이 구조에서 본문 영역이 남은 공간을 모두 차지하게 만드는 것이 중요하다. 헤더와 푸터는 내용에 맞는 높이를 갖고, 본문이 그 사이의 나머지 공간을 채우도록 한다. 나는 본문 영역에 남는 공간을 차지하라고 지정해서, 페이지가 화면을 꽉 채우면서도 각 영역이 제 몫의 크기를 갖게 한다. 공간 분배의 규칙이 명확하면 배치가 견고해진다.
이 골격에서 사이드바의 폭은 고정하고 본문은 유연하게 두는 조합이 흔하다. 사이드바는 일정한 폭을 유지하고, 본문이 남은 공간에 맞춰 늘고 준다. 나는 앞서 다룬 계산 기능이나 유연한 크기 단위를 써서 이 조합을 만든다. 고정된 부분과 유연한 부분을 함께 다루는 것이, 실전 레이아웃에서 가장 자주 마주하는 상황이다.
이 고전적 골격을 한번 제대로 익혀두면 대부분의 페이지 구조에 응용할 수 있다. 나는 새 페이지를 시작할 때 이 골격을 기본 틀로 삼고, 세부만 조정한다. 구획을 나누는 큰 틀은 대개 비슷하므로, 검증된 골격에서 출발하면 매번 처음부터 고민할 필요가 없다. 반복되는 구조를 패턴으로 익혀두는 것이 작업 속도의 비결이다.
3. 화면에 반응하는 카드 격자
카드를 격자로 늘어놓는 것도 아주 흔한 패턴이다. 상품 목록, 글 목록, 갤러리처럼 비슷한 조각을 여러 개 나열하는 상황이다. 예전에는 화면 크기 구간마다 몇 열로 배치할지를 일일이 지정해야 했다. 나는 이 방식이 화면 크기마다 규칙을 새로 써야 해서 번거롭다고 늘 느꼈다. 그런데 훨씬 우아한 방법이 있었다.
그리드에는 화면 크기에 따라 열 수를 자동으로 조절하는 기능이 있다. 각 카드의 최소 폭만 정해두면, 브라우저가 그 폭을 유지하며 화면에 들어갈 수 있는 만큼 열을 자동으로 만든다. 나는 이 기능을 처음 봤을 때, 화면 크기 구간을 하나도 지정하지 않고 완벽한 반응형 격자가 완성되는 데 감탄했다. 규칙 한 줄로 모든 화면에 대응하는 것이다.
이 자동 격자의 원리는 최소 폭과 유연함의 조합이다. 카드가 정해진 최소 폭보다 작아지지 않게 하면서, 남는 공간은 카드들이 나눠 갖게 한다. 그래서 화면이 넓어지면 열이 늘고, 좁아지면 열이 줄면서 카드들이 자연스럽게 재배치된다. 나는 이 조합이 반응형 격자의 가장 우아한 해법이라고 생각한다. 최소한의 규칙으로 최대한의 반응을 얻는다.
다만 이 자동 격자에는 주의할 점이 있다. 카드가 하나뿐일 때, 그 하나가 화면 전체로 늘어나 어색해질 수 있다. 나는 카드 수가 적을 때의 모습도 반드시 확인해서, 하나나 둘만 있을 때 지나치게 늘어나지 않는지 점검한다. 자동 격자는 편리하지만 항목 수가 적은 경우를 놓치면 예상 못 한 모습이 나오기 쉽다.
초소형 화면에서 카드가 화면을 넘치지 않게 하는 것도 챙겨야 한다. 카드의 최소 폭이 화면보다 넓으면 가로로 넘쳐 스크롤이 생긴다. 나는 카드의 최소 폭을 화면 폭과 비교해 더 작은 쪽을 택하게 해서, 아주 좁은 화면에서도 카드가 넘치지 않게 한다. 반응형에서 가로 넘침은 늘 경계해야 할 문제다.
카드 격자는 앞서 다룬 컨테이너 쿼리와 결합하면 더 강력해진다. 각 카드가 자기에게 주어진 폭에 따라 내부 배치를 바꾸게 하면, 격자의 열 수와 카드 내부가 모두 자기 자리에 맞춰 반응한다. 나는 재사용하는 카드를 이렇게 설계해서, 어떤 격자에 놓여도 알아서 적응하게 한다. 바깥 격자와 안쪽 카드가 각자 반응하는 이중 구조가 견고하다.
4. 바닥에 붙는 푸터
내용이 짧은 페이지에서 푸터가 화면 중간에 붕 떠버리는 문제는 오래된 골칫거리다. 내용이 화면을 다 채우지 못하면, 푸터가 내용 바로 아래에 붙어 화면 아래쪽에 빈 공간이 남는다. 나는 내용이 적은 페이지에서 푸터가 어정쩡하게 떠 있는 모습이 늘 거슬렸다. 푸터는 내용이 짧든 길든 바닥에 붙어 있어야 자연스럽다.
이 문제의 해법은 페이지 전체가 최소한 화면 높이만큼은 차지하게 하고, 본문이 남는 공간을 밀어내게 하는 것이다. 그러면 내용이 짧아도 본문이 늘어나 푸터를 바닥으로 밀어내고, 내용이 길면 자연스럽게 아래로 이어진다. 나는 이 방식으로 내용 길이에 상관없이 푸터가 항상 제자리에 있게 만든다. 짧아도 바닥, 길어도 그 아래인 것이다.
이 패턴은 플렉스로도 그리드로도 만들 수 있다. 페이지를 세로 방향으로 쌓되, 본문이 남는 공간을 차지하게 지정하는 것이 핵심이다. 나는 페이지 골격을 짤 때 이 바닥 푸터 처리를 기본으로 넣는다. 나중에 내용이 적은 페이지가 생겨도 푸터가 뜨는 문제를 미리 막아두는 것이다. 예방적으로 넣어두면 나중에 손댈 일이 없다.
이때 화면 높이를 재는 단위 선택이 중요하다. 모바일에서는 주소창 때문에 화면 높이가 변하므로, 앞서 다룬 동적 높이 단위를 쓰면 주소창의 움직임에 관계없이 푸터가 안정적으로 자리 잡는다. 나는 바닥 푸터에 이 동적 단위를 써서, 모바일에서 푸터가 주소창에 가리거나 어긋나는 문제를 함께 해결한다.
바닥 푸터는 사소해 보이지만 사이트의 완성도를 드러낸다. 내용이 적은 페이지에서 푸터가 뜨거나, 반대로 긴 페이지에서 푸터가 내용을 가리면 어설퍼 보인다. 나는 내용의 길이가 다양한 여러 페이지에서 푸터가 일관되게 동작하는지 확인한다. 어떤 페이지에서든 푸터가 제자리를 지키는 것이, 잘 마감된 사이트의 조건이다.
이 패턴은 페이지 골격과 자연스럽게 하나로 묶인다. 앞서 다룬 전체 페이지 골격에 바닥 푸터 처리를 더하면, 헤더와 본문과 푸터가 각자 제 위치에서 화면을 채우는 완결된 구조가 된다. 나는 이 둘을 한 세트로 익혀두고 새 프로젝트마다 재사용한다. 검증된 골격 위에서 세부를 채우는 방식이 안정적이고 빠르다.
5. 재사용하는 배치 도구
반복되는 레이아웃 문제를 매번 새로 풀기보다, 재사용 가능한 배치 도구로 만들어두면 작업이 훨씬 효율적이다. 나는 자주 쓰는 배치들을 이름 붙인 작은 도구로 정리해두고, 필요할 때마다 불러 쓴다. 요소들을 일정 간격으로 세로로 쌓는 도구, 가로로 나열하며 넘치면 줄바꿈하는 도구 같은 것들이다.
가장 유용한 도구는 요소들을 일정한 간격으로 쌓는 것이다. 여러 요소 사이에 균일한 간격을 주는 이 도구 하나면, 문단이나 항목들을 정돈된 간격으로 배열하는 대부분의 상황이 해결된다. 나는 이 쌓기 도구를 거의 모든 곳에서 쓴다. 요소들 사이의 간격을 일관되게 유지하는 것만으로 화면이 훨씬 정돈되어 보이기 때문이다.
가로로 나열하며 넘치면 줄바꿈하는 도구도 자주 쓴다. 태그 목록이나 버튼 무리처럼 여러 조각을 옆으로 늘어놓되, 공간이 부족하면 다음 줄로 넘어가게 하는 것이다. 나는 개수가 유동적인 항목들을 배치할 때 이 도구를 쓴다. 항목이 몇 개든 자연스럽게 줄을 채우고 넘어가니, 개수를 신경 쓰지 않고도 깔끔한 배치를 얻는다.
요소를 양 끝으로 밀어내는 도구도 유용하다. 한쪽에는 제목을, 반대쪽에는 버튼을 두는 것처럼 두 요소를 양 끝에 배치하는 상황이 자주 생긴다. 나는 이런 배치를 도구로 만들어두고, 헤더나 카드의 제목 줄처럼 양 끝 정렬이 필요한 곳마다 재사용한다. 반복되는 배치일수록 도구로 만들어두는 가치가 크다.
이런 배치 도구들은 앞서 다룬 변수와 결합하면 더욱 유연해진다. 간격 값을 변수로 받게 하면, 같은 쌓기 도구라도 상황에 따라 촘촘하거나 넉넉하게 조절할 수 있다. 나는 도구의 핵심 값들을 변수로 열어두어, 하나의 도구가 여러 맥락에 적응하게 한다. 재사용성과 유연함을 함께 갖춘 도구가 진짜 쓸모 있는 도구다.
이렇게 배치를 작은 도구들의 조합으로 다루는 사고방식은 레이아웃을 근본적으로 단순하게 만든다. 복잡한 화면도 결국 쌓기와 나열, 양 끝 배치 같은 기본 도구들의 조합으로 분해되기 때문이다. 나는 새 레이아웃을 마주하면, 그것을 어떤 기본 도구들의 조합으로 볼 수 있을지부터 생각한다. 복잡함을 익숙한 조각들로 나누면 대부분의 배치가 손에 잡힌다.
정리하면 중앙 정렬, 페이지 골격, 반응형 카드 격자, 바닥 푸터, 재사용 배치 도구는 실무에서 끊임없이 반복되는 문제들의 검증된 해법이다. 나는 이 패턴들을 손에 익혀두고 새 작업마다 재사용한다. 흔한 문제를 매번 새로 풀지 않는 것이 숙련의 지름길이다. 다음 편에서는 이런 스타일들을 큰 규모에서 질서 있게 유지하는 방법론과 구조화를 다룬다.