HBox, VBox, FlexBox가 생긴 이유
SAPUI5에서 화면을 구성할 때 가장 먼저 마주치는 고민은 "컨트롤을 어떻게 배치할 것인가"입니다. 초창기 UI5는 sap.ui.layout 패키지의 Grid, VerticalLayout, HorizontalLayout 등을 사용했지만, CSS Flexbox 표준이 브라우저에 정착되면서 sap.m.FlexBox와 그 파생 컨트롤인 HBox, VBox가 모바일 친화적 레이아웃 컨테이너로 자리 잡았습니다.
이 글의 목적은 세 컨트롤의 차이를 명확히 구분하고, 판매주문(Sales Order) 관리 화면을 예시로 실무에서 어떤 상황에 어떤 컨테이너를 골라야 하는지 판단 기준을 제시하는 것입니다.
핵심 개념: 세 컨트롤의 관계와 동작 원리
가장 먼저 이해해야 할 점은 HBox와 VBox가 FlexBox의 서브클래스라는 사실입니다.
sap.ui.core.Control
└─ sap.m.FlexBox
├─ sap.m.HBox // direction="Row" 고정
└─ sap.m.VBox // direction="Column" 고정
HBox는 direction이 Row로, VBox는 Column으로 미리 세팅된 FlexBox입니다. 내부적으로 렌더링되는 DOM은 모두 display: flex가 적용된 단일 <div>입니다.
1단계 실전 예제: HBox — 판매주문 헤더 수평 배치
<HBox alignItems="Center" justifyContent="SpaceBetween" class="sapUiSmallMargin">
<items>
<Title text="주문번호: {orderModel>/orderId}" level="H2"/>
<Text text="고객: {orderModel>/customerName}"/>
<ObjectStatus
text="{orderModel>/statusText}"
state="{= ${orderModel>/statusCode} === 'C' ? 'Success' : 'Warning' }"/>
</items>
</HBox>
justifyContent="SpaceBetween"이 세 자식을 양 끝과 중앙으로 균등하게 분배하고, alignItems="Center"가 높이가 다른 컨트롤들을 수직 중앙에 맞춥니다.
2단계 실전 예제: VBox — 라인아이템 수직 스택
<VBox class="sapUiSmallMargin" items="{orderModel>/lineItems}">
<HBox alignItems="Center" justifyContent="SpaceBetween">
<VBox>
<Label text="자재: {orderModel>materialCode}" design="Bold"/>
<Text text="{orderModel>materialName}"/>
</VBox>
<HBox alignItems="Center">
<ObjectNumber number="{orderModel>quantity}" unit="EA"/>
<Button icon="sap-icon://delete" type="Transparent"
press=".onRemoveLine"/>
</HBox>
</HBox>
</VBox>
외곽 VBox는 컬렉션을, 내부 HBox는 각 행의 좌우 분할을 담당합니다.
3단계 실전 예제: FlexBox — 반응형 방향 전환
<FlexBox id="orderLayout"
direction="{device>/layoutDirection}"
wrap="Wrap"
alignItems="Stretch"
renderType="Bare">
<items>
<Panel headerText="고객 정보" width="{device>/panelWidth}">
<VBox>
<Label text="고객번호"/>
<Text text="{orderModel>/customer/id}"/>
</VBox>
</Panel>
<Panel headerText="배송지" width="{device>/panelWidth}">
<VBox>
<Text text="{orderModel>/shipTo/address}"/>
</VBox>
</Panel>
</items>
</FlexBox>
onInit: function () {
const oDeviceModel = new JSONModel({
layoutDirection: sap.ui.Device.system.phone ? "Column" : "Row",
panelWidth: sap.ui.Device.system.phone ? "100%" : "50%"
});
this.getView().setModel(oDeviceModel, "device");
sap.ui.Device.media.attachHandler((mParams) => {
const bPhone = mParams.name === "Phone";
oDeviceModel.setProperty("/layoutDirection", bPhone ? "Column" : "Row");
oDeviceModel.setProperty("/panelWidth", bPhone ? "100%" : "50%");
}, null, sap.ui.Device.media.RANGESETS.SAP_STANDARD);
}
주요 속성 정리
| 속성 | 의미 | 주요 값 |
|---|---|---|
| direction | 주축 방향 | Row, Column, RowReverse, ColumnReverse |
| justifyContent | 주축 정렬 | Start, Center, End, SpaceBetween, SpaceAround |
| alignItems | 교차축 정렬 | Start, Center, End, Stretch, Baseline |
| wrap | 줄바꿈 허용 | NoWrap, Wrap, WrapReverse |
| renderType | DOM 렌더 방식 | Div, Bare, List |
흔한 실수와 트러블슈팅
HBox 자식이 공간을 다 채우지 않을 때는 자식에 <FlexItemData growFactor="1"/>를 추가하면 CSS flex-grow: 1이 적용되어 남는 공간을 차지합니다. VBox 높이가 의도대로 잡히지 않을 때는 fitContainer="true"를 지정하거나 height="100%"를 명시합니다. FlexBox를 중첩할 때 DOM 깊이가 깊어지면 renderType="Bare"로 래퍼 div를 제거해 성능을 개선할 수 있습니다.
판단 기준 정리
단순 수평 배치라면 HBox, 단순 수직 스택이라면 VBox를 사용합니다. 방향을 동적으로 전환하거나 wrap, alignContent를 세밀히 제어해야 할 때는 FlexBox를 직접 사용합니다. 일반적으로 고정된 레이아웃에는 HBox와 VBox가 코드 가독성이 높고, 반응형 요구사항이 생기면 FlexBox로 전환하는 방식이 실용적입니다.
HBox/VBox 이후 살펴볼 컨트롤
FlexBox에 익숙해지면 sap.ui.layout.Splitter(드래그 분할), sap.f.GridContainer(카드 대시보드), sap.m.OverflowToolbar(버튼 자동 접힘)도 함께 익혀두면 반응형 화면 설계가 훨씬 수월해집니다.
댓글 0
아직 댓글이 없습니다.