웹 에디터 레이아웃 엔진 설계
웹 에디터의 핵심 엔진인 레이아웃 매핑 로직을 분석합니다. 사용자의 직관적인 인터페이스가 어떻게 복잡한 CSS 속성으로 변환되어 브라우저에 렌더링되는지 그 과정을 다룹니다.

웹 기반 디자인 에디터를 개발할 때 가장 도전적인 과제 중 하나는 사용자가 이해하기 쉬운 개념을 브라우저가 이해할 수 있는 CSS 코드로 완벽하게 번역하는 것입니다. 사용자는 픽셀 단위의 정교한 배치뿐만 아니라 부모 컨테이너를 채우거나(Fill) 내용물에 맞게 크기가 조절되는(Fit) 유연한 레이아웃을 기대합니다. 이 글에서는 그 간극을 메우기 위한 레이아웃 엔진의 설계 원칙과 구현 로직을 살펴봅니다.
직관과 기술의 간극
CSS의 Flexbox나 Grid는 강력하지만 그 자체만으로는 에디터 사용자에게 직관적인 도구가 되기 어렵습니다. 사용자가 "이 박스는 부모의 남은 공간을 다 채웠으면 좋겠어"라고 생각할 때 에디터는 내부적으로 다음과 같은 복잡한 질문에 답해야 합니다.
- 부모는 Row 방향인가 Column 방향인가
- 주축(Main Axis)에서의 채우기인가 교차축(Cross Axis)에서의 채우기인가
- 콘텐츠가 넘칠 때 레이아웃이 깨지지 않도록 어떤 최소 크기 제약을 걸어야 하는가
이러한 고민을 해결하기 위해 레이아웃 엔진은 추상화된 정체성을 실제 브라우저 속성으로 변환하는 리졸버를 필요로 합니다.
레이아웃 해석 프로세스
아래 차트는 디자인 시스템의 속성이 실제 렌더링 스타일로 변환되는 흐름을 보여줍니다.
mermaidgraph TD
A[사용자 의도: Fill/Fit 선택] --> B{Layout Metadata}
B --> C[resolveSizeStyle Resolver]
C --> D{부모 방향 판단}
D -- Row --> E[Main: flex-grow / Cross: align-self]
D -- Column --> F[Main: flex-grow / Cross: align-self]
E --> G[최종 CSS Style 주입]
F --> G
G --> H[브라우저 레이아웃 엔진 작동]
핵심 로직: resolveSizeStyle
레이아웃 엔진의 심장은 resolveSizeStyle 유틸리티입니다. 이 함수는 노드의 레이아웃 설정과 부모의 방향 데이터를 입력받아 즉시 적용 가능한 CSSProperties를 반환합니다.
1. 가변적 주축 처리
Fill 모드에서 주축(Main Axis)은 공간을 나누어 갖는 행위입니다. 단순히 width: 100%를 부여하는 것이 아니라 flex-grow와 flex-basis: 0을 조합하여 콘텐츠 크기에 상관없이 균등하게 공간을 분배하도록 구현해야 합니다.
2. 고정적인 교차축 처리
반면 교차축(Cross Axis)에서의 Fill은 부모의 길이에 맞춰 늘어나는 행위이므로 align-self: stretch와 min-width/height: 0의 조합이 사용됩니다.
3. Fit-content의 예외 처리
Fit 모드는 내용물만큼만 크기를 차지하게 합니다. 하지만 에디터 내부에서 빈 컨테이너가 Fit 모드가 되어 0px로 사라지는 것을 방지하기 위해 최소 20px 정도의 플레이스홀더를 유지하는 등 세심한 예외 처리가 필요합니다.
시스템의 이원화: Absolute vs Flow
에디터는 두 가지 상반된 요구사항을 동시에 충족해야 합니다.
- 자유로운 배치(Absolute): 캔버스 어디든 자유롭게 드래그하여 배치할 수 있어야 합니다.
- 질서 있는 배치(Flow): Stack 내부에서 순서대로 정렬되고 크기가 반응형으로 변해야 합니다.
이를 위해 시스템은 드래그 라이브러리(react-rnd)를 사용하는 EditorNodeWrapper와 순수 CSS 레이아웃 엔진을 사용하는 FlowNodeWrapper로 이원화됩니다. 사용자가 위치 속성을 변경하는 순간 엔진은 적절한 래퍼를 교체하며 레이아웃 체계를 매끄럽게 전환합니다.
마치며
웹 에디터의 레이아웃 엔진은 단순히 CSS 속성을 나열하는 것이 아닙니다. 그것은 브라우저의 렌더링 동작을 깊이 분석하고 사용자의 의도를 왜곡 없이 전달하기 위한 치열한 논리적 설계의 산물입니다. 불가능한 동작을 막기 위한 예외 처리와 복잡한 조건 분기가 얽혀 하나의 아름다운 시스템을 완성합니다.
.
.
.
ps. 글은 Claude가 훨씬 잘 쓰는듯