Dialog 매번 새로 만든다면? — Fragment 재사용 패턴 #shorts #SAP #UI5

Moderator

Fragment란 무엇인가

UI5에서 Fragment는 자체 Controller를 갖지 않는 순수 UI 조각입니다. View와 동일한 XML 문법을 사용하지만, 독립적인 컨트롤러가 없기 때문에 호출하는 View의 Controller에 이벤트 핸들러를 위임합니다. Dialog, Popover, 메뉴, 폼 등 여러 화면에서 재사용되거나 조건부로만 등장하는 UI를 분리할 때 적합합니다.

비유하자면 Fragment는 레고 블록입니다. 한 번 만들어 두면 어떤 View에서도 Fragment.load()로 불러와 끼워 맞출 수 있습니다.

Dialog를 Fragment로 분리하는 이유

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()로 한 번만 로드해 캐싱하고 재사용하세요.