UI5

직접 참조 없이 — EventBus 2줄로 앱 연결 #shorts #SAP #UI5

▶ YouTube에서 보기

UI5 컴포넌트 간 통신의 문제

SAP UI5 앱에서 서로 다른 뷰 또는 컴포넌트 간에 데이터를 주고받아야 할 때, 컨트롤러를 직접 참조하거나 모델을 공유하는 방식은 강한 결합(Tight Coupling)을 만듭니다. EventBus는 컴포넌트 간 직접 참조 없이 이벤트를 발행/구독하는 느슨한 결합 패턴입니다.

직접 참조 방식 — 잘못된 패턴

// 잘못된 패턴: 다른 컨트롤러를 직접 참조
// MasterController에서 DetailController 메서드 직접 호출
onItemSelect: function(oEvent) {
  const oItem = oEvent.getSource();
  const orderId = oItem.getBindingContext().getProperty("orderId");

  // Detail 컨트롤러를 직접 찾아서 호출 — 강한 결합
  const oDetailController = this.getOwnerComponent()
    .getRootControl()
    .byId("detailView")
    .getController();

  oDetailController.loadOrder(orderId);  // 직접 호출
}
// Master가 Detail의 내부 구조를 알아야 함
// Detail이 바뀌면 Master도 수정 필요

EventBus로 느슨한 결합 구현

// MasterController — 이벤트 발행 (publish)
onItemSelect: function(oEvent) {
  const oItem = oEvent.getSource();
  const sOrderId = oItem.getBindingContext().getProperty("orderId");

  // EventBus로 이벤트 발행 — Detail이 누구인지 알 필요 없음
  const oEventBus = this.getOwnerComponent().getEventBus();
  oEventBus.publish(
    "OrderApp",          // 채널 (namespace)
    "orderSelected",     // 이벤트 이름
    { orderId: sOrderId } // 데이터 페이로드
  );
  // 2줄로 끝
}
// DetailController — 이벤트 구독 (subscribe)
onInit: function() {
  // EventBus 구독 등록
  const oEventBus = this.getOwnerComponent().getEventBus();
  oEventBus.subscribe(
    "OrderApp",           // 채널
    "orderSelected",      // 이벤트 이름
    this._onOrderSelected, // 핸들러
    this                  // 컨텍스트
  );
},

_onOrderSelected: function(sChannel, sEvent, oData) {
  const sOrderId = oData.orderId;
  this._loadOrderDetail(sOrderId);
},

_loadOrderDetail: function(sOrderId) {
  const oModel = this.getView().getModel();
  oModel.read(`/OrderSet('${sOrderId}')`, {
    success: (oData) => {
      const oDetailModel = new JSONModel(oData);
      this.getView().setModel(oDetailModel, "detail");
    }
  });
},

// 반드시 onExit에서 구독 해제
onExit: function() {
  const oEventBus = this.getOwnerComponent().getEventBus();
  oEventBus.unsubscribe(
    "OrderApp",
    "orderSelected",
    this._onOrderSelected,
    this
  );
}

EventBus 채널 설계 전략

// 채널은 앱 또는 기능 도메인으로 구분
const oEventBus = this.getOwnerComponent().getEventBus();

// 주문 도메인 이벤트
oEventBus.publish("Orders", "created", { orderId: "SO-001" });
oEventBus.publish("Orders", "cancelled", { orderId: "SO-001", reason: "고객 요청" });
oEventBus.publish("Orders", "statusChanged", { orderId: "SO-001", newStatus: "CONFIRMED" });

// 공통 앱 이벤트
oEventBus.publish("App", "userLoggedOut", {});
oEventBus.publish("App", "languageChanged", { lang: "ko" });
oEventBus.publish("App", "themeChanged", { theme: "sap_fiori_3" });

복수 구독자 시나리오

// 하나의 이벤트를 여러 컨트롤러가 동시에 구독 가능
// 주문 생성 이벤트 → 재고 뷰, 요약 뷰, 알림 뷰가 각각 업데이트

// InventoryController
oEventBus.subscribe("Orders", "created", this._updateInventory, this);

// SummaryController
oEventBus.subscribe("Orders", "created", this._refreshSummary, this);

// NotificationController
oEventBus.subscribe("Orders", "created", this._showNotification, this);

// 이벤트 발행 한 번으로 세 곳이 동시에 반응
oEventBus.publish("Orders", "created", { orderId: "SO-001", amount: 50000 });

SAP Fiori Launchpad 크로스 앱 통신

// Launchpad에서 여러 앱 간 통신은 CrossApplicationNavigation 또는
// sap.ui.getCore().getEventBus() 사용 (글로벌 EventBus)

// 글로벌 EventBus (컴포넌트 경계를 넘어 통신)
const oGlobalBus = sap.ui.getCore().getEventBus();
oGlobalBus.publish("GlobalApp", "cartUpdated", { itemCount: 5 });

// 단, 글로벌 EventBus는 채널 이름 충돌 주의
// 앱별로 고유한 채널 이름 사용 권장
// 예: "com.mycompany.salesapp.Orders"

EventBus vs 모델 공유 선택 기준

  • EventBus: 일회성 액션, 한 방향 알림, 느슨한 결합이 중요한 경우
  • 공유 모델: 여러 뷰가 동일 데이터를 실시간으로 공유해야 하는 경우
  • EventBus + 공유 모델 조합: 이벤트 발생 → 공유 모델 업데이트 → 뷰 자동 갱신

공식 문서

UI5 EventBus API는 ui5.sap.com EventBus API에서 확인하세요. 컴포넌트 통신 패턴은 UI5 Best Practices 가이드에서 다룹니다.

댓글 0

아직 댓글이 없습니다.