요소 그룹핑 (Element Grouping)
템플릿 요소들을 그룹으로 묶어 함께 배치하는 기능입니다. 같은 그룹의 요소들은 항상 같은 컬럼/페이지에 배치됩니다.
개요
요소 그룹핑은 템플릿의 여러 요소를 논리적으로 묶어서, 한 컬럼이나 페이지에 함께 배치되도록 하는 기능입니다.
| 특징 | 설명 |
|---|---|
| 그룹 단위 배치 | 같은 그룹의 요소들은 항상 같은 컬럼/페이지에 배치 |
| 자동 이동 | 그룹 내 어떤 요소라도 배치 공간이 부족하면 그룹 전체를 다음 컬럼/페이지로 이동 |
| 텍스트 분할 지원 | splittable 텍스트는 분할 허용 (그룹 이동과 무관) |
| 유효성 검증 | 그룹 높이가 페이지 높이를 초과하면 템플릿 오류 반환 |
사용 방법
템플릿에 groupName 지정
{
"elements": [
{
"element_id": "text-1",
"type": "text",
"position": {"x": 40, "y": 20},
"width": 409,
"height": 30,
"text": "$dateStr$",
"groupName": "group1"
},
{
"element_id": "graphic-1",
"type": "graphic",
"imageSource": "pack://siteoforigin:,,,/ebook/images/bar.png",
"position": {"x": 40, "y": 60},
"width": 449,
"height": 2,
"groupName": "group1"
},
{
"element_id": "text-2",
"type": "text",
"position": {"x": 40, "y": 87},
"width": 409,
"height": 150,
"text": "$contents$",
"isDynamic": true,
"splittable": true,
"groupName": "group1"
},
{
"element_id": "photo-1",
"type": "photo",
"fileName": "$imageMain$",
"position": {"x": 40, "y": 250},
"width": 409,
"height": 409,
"groupName": "group2"
}
]
}그룹화 규칙
groupName이라도 중간에 다른 그룹 요소가 있으면 별도 그룹으로 처리됩니다. 요소들은 Y 좌표 순으로 정렬되어 처리되므로, Y 좌표 순서를 올바르게 유지해야 합니다.// 올바른 예시: group1 요소들이 연속됨 → 하나의 그룹
[
{"element_id": "text-1", "y": 20, "groupName": "group1"},
{"element_id": "graphic-1", "y": 60, "groupName": "group1"},
{"element_id": "text-2", "y": 87, "groupName": "group1"}
]
// 잘못된 예시: group1 사이에 group2가 있음 → 2개의 별도 그룹
[
{"element_id": "text-1", "y": 20, "groupName": "group1"}, // group1-1
{"element_id": "graphic-1", "y": 60, "groupName": "group1"}, // group1-1
{"element_id": "photo-1", "y": 150, "groupName": "group2"}, // group2
{"element_id": "text-2", "y": 300, "groupName": "group1"} // group1-2 (별도 그룹!)
]배치 동작
케이스 1: 그룹 전체가 현재 컬럼에 배치 가능
그룹 전체 높이 < 남은 공간 → 모든 요소를 현재 컬럼에 배치합니다.
케이스 2: 그룹 전체가 현재 컬럼에 배치 불가능
그룹 전체 높이 > 남은 공간 → 그룹 전체를 다음 컬럼/페이지로 이동합니다.
케이스 3: splittable 텍스트 분할
그룹 내 splittable 텍스트가 있고 최소 한 줄은 배치 가능 → 텍스트를 분할하여 현재 컬럼과 다음 컬럼에 나누어 배치합니다. 그룹의 다른 요소는 현재 위치 유지.
케이스 4: splittable 텍스트 한 줄도 배치 불가능
그룹 내 splittable 텍스트가 있지만 한 줄도 배치할 공간 없음 → 그룹 전체를 다음 컬럼/페이지로 이동합니다.
오류 처리
그룹 높이가 페이지 높이 초과
조건: splittable 텍스트가 없는 그룹의 전체 높이가 페이지 높이를 초과할 때.
{
"success": false,
"message": "Template error: Group 'group1' height (1200.5px) exceeds page height (1000.8px). Cannot place group."
}해결 방법: 그룹 내 요소 개수 줄이기, 요소 높이 줄이기, 텍스트 요소에 splittable: true 추가.
주의사항
배치 결과에서 제거되는 속성
groupName은 템플릿 작성 시에만 사용되며, 최종 페이지 JSON에는 포함되지 않습니다.splittable, isDynamic, originalHeight도 배치 결과에서 제거됩니다.
X-lane 분리 그룹화
layoutRules.lanes가 정의된 경우, 같은 Y 범위에 있더라도 서로 다른 X-lane에 속하는 요소들은 별도 그룹으로 처리됩니다. 각 레인의 요소들은 독립적인 Y 흐름으로 배치됩니다.
SubGroups (서브그룹)
groupName으로 묶인 그룹 내에 splittable: true 요소가 포함된 경우, non-splittable 요소들은 Y-overlap 기준으로 SubGroup으로 분리됩니다.
// groupName: "dayEntry" 그룹 내 요소들
[
{ "element_id": "teacher-icon", "y": 63, "h": 22 }, // SubGroup A
{ "element_id": "teacher-label", "y": 63, "h": 25 }, // SubGroup A (Y 겹침)
{ "element_id": "teacher-comment", "y": 90, "isDynamic": true, "splittable": true }, // 분리
{ "element_id": "gallery-photos", "y": 280, "isDynamic": true } // SubGroup B
]
// SubGroup A: teacher-icon + teacher-label (Y 범위 겹침 → 함께 배치)
// 분리: teacher-comment (splittable → 개별 배치, 텍스트 분할 가능)
// SubGroup B: gallery-photos (독립 배치)TemplateBaseY 앵커와 그룹 배치
최종 Y = max(anchoredY, sequentialY)
anchoredY = TemplateBaseY + OriginalY + DynamicDelta
sequentialY = CurrentSlotMaxY + spacingDynamicDelta에 대한 자세한 내용은 동적 레이아웃 시스템 문서를 참조하세요.
요약
| 항목 | 설명 |
|---|---|
| 목적 | 관련 요소들을 함께 배치 |
| 사용법 | 템플릿 요소에 groupName 속성 추가 |
| 그룹화 규칙 | Y 좌표 순으로 연속된 같은 groupName 요소들 |
| X-lane 분리 | lanes 정의 시 다른 레인의 요소는 별도 그룹 |
| SubGroups | splittable 포함 그룹에서 non-splittable Y-overlap 서브그룹 분리 |
| 배치 원칙 | 그룹 전체가 들어갈 수 없으면 전체 이동 |
| 텍스트 분할 | splittable 텍스트는 분할 허용 (단, 한 줄도 못 들어가면 그룹 전체 이동) |
| 오류 조건 | splittable 없는 그룹의 높이 > 페이지 높이 |
| 배치 결과 | groupName, splittable, isDynamic, originalHeight 제거됨 |