사전 레이아웃
개념

레이아웃

gabury1

화면에 놓일 것들이 어디에 얼마만 한 크기로 자리 잡을지 정하는 일입니다. 그리기 전에 먼저 합니다. 좌표와 크기가 정해져야 그 자리에 색을 칠할 수 있습니다.

상세

빈 방에 가구를 들이기 전에 줄자로 방을 재고 어느 벽에 무엇을 붙일지 종이에 먼저 그립니다. 가구를 실제로 옮기는 일은 그 다음입니다.

레이아웃은 문서에서 만들어진 박스들이 각각 어느 자리에 얼마만 한 크기로 놓일지를 계산하는 단계입니다. CSS(Cascading Style Sheets, 종속형 시트) 2.2 명세는 시각 서식화 모델을 이렇게 적습니다. 문서 트리의 각 요소는 박스 모델에 따라 0개 이상의 박스를 만듭니다. 그리고 이 박스들의 배치는 네 가지가 정합니다.

  • 박스의 치수와 종류
  • 자리잡기 방식. 정상 흐름, 플로트, 절대 위치 지정
  • 문서 트리 안에서 요소끼리의 관계
  • 바깥에서 오는 정보. 뷰포트 크기, 이미지의 고유 치수 등

네 번째 항목은 문서 안에 없는 정보입니다. 보는 창이 얼마나 큰지, 이미지가 실제로 몇 픽셀인지는 문서 트리에 적혀 있지 않습니다. 그래서 문서만 읽어서는 수가 나오지 않습니다.

이 문서가 다루는 레이아웃은 화면에 놓일 것의 기하를 정하는 단계입니다. 메모리나 디스크에서 데이터가 놓이는 자리를 가리키는 같은 낱말은 여기서 다루지 않습니다.

배경

무엇을 보여줄지는 문서가 정합니다. 얼마만 한 자리에 보여줄지는 문서가 정하지 못합니다. 같은 문서를 큰 모니터에서도 보고 작은 창에서도 보기 때문입니다.

CSS 2.2 명세는 연속 매체용 사용자 에이전트가 대개 사용자에게 뷰포트를 제공한다고 적습니다. 뷰포트는 화면 위의 창이나 그에 준하는 보기 영역이고, 사용자는 그것을 통해 문서를 봅니다. 명세는 뷰포트 크기가 바뀌면 사용자 에이전트가 문서의 배치를 바꿀 수 있다고 적습니다. 뷰포트가 문서를 그리는 캔버스보다 작으면 스크롤 수단을 제공하도록 권합니다.

그래서 일의 순서가 갈립니다. 보는 창의 크기가 정해져야 박스의 크기가 정해집니다. 박스의 크기가 정해져야 그 자리에 무엇을 칠할지가 정해집니다. 이 가운데 박스의 크기와 자리를 정하는 일만 따로 떼어 이름을 붙인 것이 레이아웃입니다.

갈래

같은 박스라도 어떤 규칙으로 계산되는지는 그 박스가 들어간 서식화 문맥이 정합니다. 축은 그것 하나입니다.

CSS Display Module Level 3 은 display 속성을 두 갈래로 읽습니다. 바깥 display 유형은 그 박스 자신이 흐름 배치에 어떻게 참여할지를 정합니다. 안쪽 display 유형은 그 박스가 어떤 서식화 문맥을 만들지, 그래서 자손 박스들이 어떤 방식으로 배치될지를 정합니다. 대체 요소가 아닌 경우에 그렇습니다.

블록 서식화 문맥

CSS 2.2 명세는 새 블록 서식화 문맥을 만드는 쪽을 넷으로 적습니다. 플로트, 절대 위치가 지정된 요소, 블록 박스가 아닌 블록 컨테이너, 그리고 overflow 가 visible 이 아닌 블록 박스입니다. 인라인 블록, 테이블 셀, 테이블 캡션이 세 번째에 해당합니다. 다만 overflow 값이 뷰포트로 전파된 경우는 빼고 셉니다.

인라인 서식화 문맥

블록 수준 박스를 하나도 담지 않은 블록 컨테이너 박스가 인라인 서식화 문맥을 만듭니다.

플렉스 서식화 문맥

CSS Flexbox Level 1 은 플렉스 배치가 겉보기에 블록 배치와 비슷하다고 적습니다. 대신 플로트나 단처럼 글과 문서 중심의 속성 상당수가 빠져 있습니다. 그 자리에 공간을 나누고 내용을 정렬하는 도구가 들어갑니다.

명세는 이 계산을 플렉스 배치 알고리즘이라는 이름으로 일곱 단계에 나눠 적습니다. 초기 설정, 줄 길이 결정, 주축 크기 결정, 교차축 크기 결정, 주축 정렬, 교차축 정렬, 유연 길이 해결입니다.

그리드 서식화 문맥

CSS Grid Level 2 는 그리드 배치를 박스와 그 내용의 크기·위치를 제어하는 능력을 가진 배치 모델이라고 적습니다. 각 그리드 트랙에는 크기 함수가 붙습니다. 그 함수가 열이나 행이 얼마나 넓어지거나 높아질 수 있는지를 정합니다. 그에 따라 트랙을 둘러싼 그리드 선 사이가 얼마나 벌어지는지도 정해집니다. 명세는 이 계산을 트랙 크기 결정 알고리즘으로 따로 둡니다.

예시

같은 단계가 웹 엔진에도 있고 네이티브 UI(User Interface, 사용자 인터페이스) 툴킷에도 있습니다. 부르는 이름과 나뉘는 패스 수가 자리마다 다릅니다.

브라우저 렌더링 경로

MDN(Mozilla Developer Network) 의 브라우저 동작 문서는 임계 렌더링 경로의 네 번째 단계가 렌더 트리 위에서 레이아웃을 돌려 각 노드의 기하를 계산하는 일이라고 적습니다. 렌더 트리는 어떤 노드가 표시되는지와 그 계산된 스타일까지만 갖고 있습니다. 치수와 위치는 없습니다. 그래서 브라우저는 렌더 트리의 뿌리에서 시작해 트리를 훑으며 각 객체의 정확한 크기와 위치를 정합니다.

이때 뷰포트 크기를 밑값으로 삼습니다. 배치는 대개 body 에서 시작해 그 자손들의 크기를 요소마다의 박스 모델 속성으로 정해 나갑니다. 치수를 아직 모르는 대체 요소 자리에는 자리표시 공간을 둡니다. 각 노드의 크기와 위치가 처음 정해지는 것을 레이아웃이라 부르고, 그 뒤의 재계산은 리플로라 부릅니다. MDN 은 초기 레이아웃이 이미지 도착 전에 도는 경우를 예로 듭니다. 이때 이미지 치수를 선언하지 않았다면 치수를 알게 되는 시점에 리플로가 한 번 일어납니다.

flowchart TD
    S[스타일] --> L[레이아웃]
    L --> P[페인트]
    P --> C["합성 · 경우에 따라"]

MDN 은 렌더링 단계로 스타일, 레이아웃, 페인트, 그리고 경우에 따라 합성을 듭니다. 페인트는 레이아웃 단계에서 계산된 각 박스를 화면의 실제 픽셀로 바꾸는 일입니다. 문서의 여러 부분이 서로 겹치는 별개 레이어에 그려질 때는 합성이 필요합니다.

크롬의 LayoutNG

크롬의 LayoutNG 문서는 레이아웃 트리를 여전히 두되 주로 레이아웃의 입력과 출력을 붙들어 두는 데 쓴다고 적습니다. 출력으로는 프래그먼트 트리라는 새 불변 객체를 따로 만듭니다.

이 트리의 한 노드에 레이아웃을 돌리는 일은 스타일과 DOM(Document Object Model, 문서 객체 모델)을 입력으로 받습니다. 그리드·블록·플렉스 같은 부모 배치 시스템에서 내려온 제약도 함께 받습니다. 받은 것으로 레이아웃 제약 알고리즘을 돌려 결과를 냅니다.

안드로이드 뷰 시스템

안드로이드 프레임워크는 뷰 트리를 세 번 훑습니다. 측정 패스는 measure(int, int) 에서 돕니다. 프레임워크는 이때 뷰 트리를 위에서 아래로 내려갑니다. 각 뷰가 재귀 도중 치수 명세를 아래로 내려보냅니다. 측정 패스가 끝나면 모든 뷰가 자기 측정값을 갖고 있습니다.

두 번째 패스는 layout(int, int, int, int) 에서 돕니다. 진행 방향은 역시 위에서 아래입니다. 이 패스에서 각 부모는 측정 패스에서 계산된 크기를 써서 자기 자식들을 배치할 책임을 집니다. 그리기는 그 다음입니다. 프레임워크는 트리를 훑어 무효 영역과 겹치는 뷰를 그립니다. 부모를 자식보다 먼저 그립니다. 자식 뒤쪽에 그린다는 뜻입니다. 형제는 트리에 나타난 순서대로 그립니다.

관련 항목

레이아웃 앞뒤 단계

스타일 계산 · 렌더 트리 · 측정 패스 · 페인트 · 래스터화 · 합성 · 리플로 · 첫 유의미 페인트

레이아웃이 속하는 상위 개념

CSS · 렌더링 · 임계 렌더링 경로

기하를 정하는 재료

박스 모델 · 뷰포트 · 초기 컨테이닝 블록 · 고유 치수 · 정상 흐름 · 플로트 · 절대 위치 지정 · 대체 요소 · 캔버스

레이아웃 규칙을 가르는 서식화 문맥

블록 서식화 문맥 · 인라인 서식화 문맥 · 플렉스박스 · 그리드 · 그리드 트랙 · display 속성 · overflow · 테이블

레이아웃 계산이 오가는 엔진 자료구조

DOM · 레이아웃 트리 · 프래그먼트 트리 · 뷰 트리 · 노드

레이아웃 계산을 실제로 도는 엔진과 이를 적은 문서

브라우저 · 크롬 · 안드로이드 · 사용자 에이전트 · MDN · 메인 스레드 · GPU(Graphics Processing Unit, 그래픽 처리 장치)

다른 이름: layout · 레이아웃 계산