Dialog 매번 새로 만든다면? — Fragment 재사용 패턴 #shorts #SAP #UI5
Fragment란 무엇인가
UI5에서 Fragment는 자체 Controller를 갖지 않는 순수 UI 조각입니다. View와 동일한 XML 문법을 사용하지만, 독립적인 컨트롤러가 없기 때문에 호출하는 View의 Controller에 이벤트 핸들러를 위임합니다. Dialog, Popover, 메뉴, 폼 등 여러 화면에서 재사용되거나 조건부로만 등장하는 UI를 분리할 때 적합합니다.
비유하자면 Fragment는 레고 블록입니다. 한 번 만들어 두면 어떤 View에서도 Fragment.load()로 불러와 끼워 맞출 수 있습니다.
Dialog를 Fragment로 분리하는 이유
- View 비대화 방지 — 메인 View XML 안에 Dialog까지 선언하면 파일이 빠르게 길어지고, 초기 렌더 트리에 불필요한 컨트롤이 포함됩니다.
- 재사용성 — 같은 확인 Dialog를 여러 화면에서 호출하는 경우, Fragment 한 개로 일원화할 수 있습니다.
- Lazy loading — 사용자가 버튼을 누른 시점에만 Dialog를 인스턴스화하여 초기 로드 비용을 줄일 수 있습니다.
Fragment 선언 (XML)
루트 엘리먼트는 core:FragmentDefinition이며, 그 안에 sap.m.Dialog를 배치합니다. Dialog의 버튼 press 핸들러는 호출 측 Controller의 메서드를 점(.) 표기로 참조합니다.
<!-- view/fragment/OrderDialog.fragment.xml -->
<core:FragmentDefinition xmlns="sap.m" xmlns:core="sap.ui.core">
<Dialog title="주문 확인" id="orderDialog">
<content>
<Text id="orderMessage" text="{/orderMessage}" />
</content>
<beginButton>
<Button text="확인" press=".onConfirm" />
</beginButton>
</Dialog>
</core:FragmentDefinition>
Controller에서 Fragment 로드 (lazy 패턴)
핵심은 한 번만 로드해서 인스턴스를 보관하는 것입니다. 매번 Fragment.load()를 호출하면 Dialog 인스턴스가 누적되어 메모리 누수와 ID 충돌이 발생할 수 있습니다. 첫 호출 시 생성한 객체를 this._oDialog에 캐싱하고, 이후에는 open()만 호출하는 패턴이 일반적으로 권장됩니다.
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/core/Fragment"
], function (Controller, Fragment) {
"use strict";
return Controller.extend("myapp.controller.Main", {
onOpenDialog: async function () {
if (!this._oDialog) {
this._oDialog = await Fragment.load({
id: this.getView().getId(),
name: "myapp.view.fragment.OrderDialog",
controller: this
});
this.getView().addDependent(this._oDialog);
}
this._oDialog.open();
},
onConfirm: function () {
this._oDialog.close();
}
});
});
addDependent()를 호출하면 Fragment가 View의 모델/생명주기를 자연스럽게 상속받아 별도 모델 바인딩 작업이 줄어듭니다.
Fragment 내 컨트롤 접근 (Fragment.byId)
Fragment.load 시점에 id 옵션으로 View ID를 prefix로 부여하면, 컨트롤 ID가 viewId--orderDialog 형태로 네임스페이스화됩니다. Controller에서는 this.byId()로 안전하게 접근할 수 있습니다.
// View ID prefix가 자동 적용된 경우
var oText = this.byId("orderMessage");
oText.setText("주문이 정상 처리되었습니다.");
// Fragment 전용 ID로 직접 조회하려면
var oDialog = sap.ui.core.Fragment.byId(this.getView().getId(), "orderDialog");
같은 Fragment를 여러 View에서 재사용할 때는 반드시 호출 측 View ID를 prefix로 넘겨야 ID 충돌을 피할 수 있습니다.
핵심 한 줄
Dialog는 매번 새로 만들지 말고, Fragment로 분리한 뒤 Controller에서 Fragment.load()로 한 번만 로드해 캐싱하고 재사용하세요.