RAP

Fiori 안 뜨는 이유 — UI vs API 바인딩 차이 #shorts #SAP #RAP

이 글에서 다루는 것

RAP(ABAP RESTful Application Programming Model) 기반으로 서비스를 노출할 때, 개발자가 반드시 마주치는 갈림길이 있습니다. 바로 Service Binding 유형 선택입니다. 같은 Service Definition을 만들었어도, Binding Type을 잘못 고르면 Fiori Elements 앱이 뜨지 않거나, 반대로 외부 API 연동에서 필요 없는 UI 메타데이터가 딸려나가는 문제가 발생합니다. 이 글에서는 UI용 Binding과 API용 Binding의 실제 차이, 내부 동작 방식, 그리고 어떤 상황에 무엇을 골라야 하는지를 실전 예제와 함께 정리합니다.

  • OData V2 UI, V4 UI, V2 Web API, V4 Web API의 4가지 Binding Type 이해
  • Fiori Elements가 요구하는 어노테이션·메타데이터 종속성 파악
  • 외부 시스템 통합 시나리오에서 API Binding 선택 기준
  • Binding별 URL 패턴과 SAP Gateway 등록 방식 차이
  • 실제 프로젝트에서 자주 발생하는 오류 대응

미리 알고 있어야 할 개념

이 글은 RAP의 기본 구조(Behavior Definition, Behavior Implementation, Service Definition)를 한 번이라도 만들어본 개발자를 대상으로 합니다. CDS View, Projection View, 그리고 ABAP Development Tools(ADT)에서 Service Binding 아티팩트를 생성하는 절차에 익숙해야 합니다. Fiori Elements의 List Report, Object Page 개념과 OData V2/V4 스펙 차이도 어느 정도 알고 있어야 실전 사례 분석이 매끄럽게 이어집니다.

실습 환경과 준비물

실습은 다음 환경을 기준으로 설명합니다. 버전에 따라 메뉴 위치나 지원 Binding Type이 달라질 수 있으므로, 자신의 시스템 릴리스를 먼저 확인하기를 권장합니다.

  • ABAP Platform: SAP S/4HANA 2023 온프레미스 또는 SAP BTP ABAP Environment(Steampunk) 2405 이상
  • 개발 도구: ABAP Development Tools(ADT) for Eclipse 2024-06 이상
  • 테스트 도구: Fiori Elements Preview, SAP Gateway Client(/IWFND/GW_CLIENT), Postman
  • 권한: 개발용 사용자에게 S_DEVELOP, /IWFND/SU_ADMIN(온프레미스 Gateway 등록 시)
  • 참고: BTP ABAP Environment에서는 OData V2 UI만 Fiori Elements Preview에서 완전 지원되며, V4 UI는 별도 Fiori 앱 프로젝트로 실행하는 방식이 일반적입니다

Service Binding의 정체와 4가지 갈래

RAP에서 Service Definition은 "어떤 CDS 엔터티들을 하나의 서비스에 묶을 것인가"를 선언하는 논리적 계약입니다. 여기까지는 프로토콜이 결정되지 않은 상태입니다. Service Binding이 바로 이 논리 계약을 실제 프로토콜(OData V2/V4)과 사용 목적(UI/Web API)에 매핑하는 물리적 어댑터 역할을 합니다.

비유하자면 Service Definition이 "이 매장에서 팔 상품 목록"이라면, Service Binding은 "그 상품을 어떤 매대에, 어떤 포장으로 진열할지"입니다. 매대가 백화점 진열대(UI)냐 도매창고 픽업존(API)이냐에 따라 포장 규격이 완전히 달라집니다.

Binding Type은 크게 네 가지입니다.

  • OData V2 - UI: Fiori Elements V2 앱, SAPUI5 Smart Control 대상. 어노테이션 처리와 draft 지원이 UI 시나리오에 최적화
  • OData V4 - UI: Fiori Elements V4(Fiori 3, Horizon) 대상. UI.v4 어노테이션과 최신 개발 모델 지원
  • OData V2 - Web API: 시스템 간 통합, 레거시 소비자, ETL 도구용. UI 어노테이션 노출 억제
  • OData V4 - Web API: 모던 마이크로서비스 통합, BTP 서비스 소비. JSON 기반, batch 지원

핵심 차이는 세 가지 축에서 나옵니다. 첫째, 노출되는 메타데이터의 범위. UI Binding은 @UI, @Search, @Semantics 등 프론트엔드 렌더링 힌트를 metadata.xml에 포함시킵니다. Web API Binding은 이런 UI 종속 어노테이션을 제거해 순수 데이터 계약만 노출합니다. 둘째, draft handling과 액션의 활성화 방식. UI Binding에서는 draft 활성화 시 SAP Fiori 표준 편집 흐름이 자동 연결됩니다. 셋째, Gateway 등록 및 라우팅 경로. UI/API에 따라 SAP Gateway에서 노출되는 서비스 그룹과 시스템 alias가 다를 수 있습니다.

1단계: 기본 UI Binding으로 List Report 띄우기

가장 흔한 시나리오부터 시작합니다. 구매요청(Purchase Requisition) 헤더를 Fiori Elements List Report로 보여주는 케이스입니다. 먼저 Projection View에 UI 어노테이션을 붙입니다.

@AccessControl.authorizationCheck: #CHECK
@Metadata.allowExtensions: true
@Search.searchable: true
@UI.headerInfo: { typeName: 'Purchase Requisition',
                  typeNamePlural: 'Purchase Requisitions',
                  title: { value: 'RequisitionId' } }
define root view entity ZC_PurchaseReqTP
  provider contract transactional_query
  as projection on ZR_PurchaseReq
{
  key RequisitionId,
  @UI.lineItem: [{ position: 10, label: 'Requisition' }]
  @UI.selectionField: [{ position: 10 }]
  @Search.defaultSearchElement: true
      RequisitionId,

  @UI.lineItem: [{ position: 20, label: 'Vendor' }]
      VendorId,

  @UI.lineItem: [{ position: 30, label: 'Total Amount' }]
  @Semantics.amount.currencyCode: 'CurrencyCode'
      TotalAmount,

      CurrencyCode,

  @UI.lineItem: [{ position: 40, label: 'Status' }]
      RequisitionStatus,

  /* Associations */
  _Vendor
}

Service Definition은 단순합니다.

@EndUserText.label: 'Purchase Requisition Service'
define service ZUI_PURCHASE_REQ {
  expose ZC_PurchaseReqTP as PurchaseRequisition;
  expose ZC_VendorVH     as Vendor;
}

이제 Service Binding을 생성할 때 대화상자에서 OData V4 - UI를 선택합니다. Activate 후 "Service URL" 옆의 Preview 버튼을 누르면 Fiori Elements가 렌더링됩니다. 만약 여기서 실수로 "OData V4 - Web API"를 골랐다면 Preview 버튼 자체가 비활성화되고, 별도 UI 프로젝트에서 소비하려 해도 List Report의 컬럼 순서·필터가 자동 생성되지 않습니다.

2단계: Web API Binding으로 외부 통합 채널 만들기

같은 Purchase Requisition 데이터를 이번엔 외부 조달 시스템에 REST로 노출한다고 가정합니다. 이 경우 UI 어노테이션이 metadata에 포함되면 오히려 문서 크기가 커지고, 소비자 측 코드 생성기가 혼란스러워집니다. Service Definition을 분리하는 것이 실무적 정석입니다.

@EndUserText.label: 'Purchase Requisition Web API'
define service ZAPI_PURCHASE_REQ {
  expose ZC_PurchaseReqAPI as PurchaseRequisition;
}

여기서 ZC_PurchaseReqAPI는 UI 어노테이션을 제거한 별도 projection입니다. 필요하다면 노출 필드도 축소합니다.

@AccessControl.authorizationCheck: #CHECK
define root view entity ZC_PurchaseReqAPI
  provider contract transactional_query
  as projection on ZR_PurchaseReq
{
  key RequisitionId,
      VendorId,
      TotalAmount,
      CurrencyCode,
      RequisitionStatus,
      CreatedAt,
      LastChangedAt
}

Binding 생성 시 OData V4 - Web API를 선택합니다. 이렇게 하면 Fiori Preview는 없지만, /sap/opu/odata4/sap/zapi_purchase_req/... 형태의 API 엔드포인트가 활성화되고, HTTP GET/POST에 대한 로깅과 상태 코드 매핑이 서비스 통합 관점에서 깔끔해집니다.

Behavior Implementation에서는 API 소비자를 위한 예외 메시지도 별도로 관리하는 것이 좋습니다.

METHOD validate_vendor.
  READ ENTITIES OF zr_purchasereq IN LOCAL MODE
    ENTITY PurchaseRequisition
      FIELDS ( RequisitionId VendorId )
      WITH CORRESPONDING #( keys )
    RESULT DATA(lt_reqs).

  LOOP AT lt_reqs INTO DATA(ls_req).
    IF ls_req-VendorId IS INITIAL.
      APPEND VALUE #(
        %tky = ls_req-%tky
        %msg = new_message(
                 id       = 'ZPR_MSG'
                 number   = '010'
                 severity = if_abap_behv_message=>severity-error
                 v1       = ls_req-RequisitionId )
        %element-VendorId = if_abap_behv=>mk-on
      ) TO reported-purchaserequisition.

      APPEND VALUE #( %tky = ls_req-%tky ) TO failed-purchaserequisition.
    ENDIF.
  ENDLOOP.
ENDMETHOD.

3단계: 운영 환경을 위한 분리·성능·보안 강화

실제 프로덕션에서는 UI Binding과 API Binding을 동시에 유지하되, 서로 다른 인증·모니터링 체계를 붙이는 경우가 많습니다. 다음 세 가지를 권장합니다.

첫째, Service Definition 자체를 분리합니다. 하나의 Definition에 두 Binding을 붙일 수도 있지만, 시간이 지나면 UI 요구사항(추가 어노테이션, value help) 때문에 API 스키마까지 흔들립니다. UI용/API용 projection view를 다르게 가져가고 Definition도 이원화하는 편이 유지보수에 유리합니다.

둘째, API Binding에는 명시적 페이지 크기와 검색 제한을 걸어둡니다.

define behavior for ZR_PurchaseReq alias PurchaseReq
implementation in class zbp_r_purchasereq unique
persistent table zpurchase_req
lock master
authorization master ( instance )
etag master LastChangedAt
{
  field ( numbering : managed, readonly ) RequisitionId;
  field ( readonly ) CreatedAt, LastChangedAt, CreatedBy;

  create;
  update;
  delete;

  determination calculateTotal on modify { field TotalAmount; }
  validation validate_vendor on save { field VendorId; }

  side effects {
    field VendorId affects entity;
  }
}

셋째, API 소비자용 로깅을 Application Log(SLG1)나 BTP ABAP Environment의 Application Log 서비스에 남깁니다. UI Binding은 사용자 세션과 결합돼 있지만, API Binding은 M2M(machine-to-machine) 호출이 대부분이므로 호출 주체와 페이로드 크기를 별도 기록해야 사후 추적이 가능합니다. 성능 관점에서는 Web API Binding에 대해 $batch 사용을 유도하고, UI Binding은 draft 캐시 정책을 검토하는 것이 일반적입니다.

자주 밟는 지뢰와 대응 요령

Q1. Binding은 Activate했는데 Fiori Preview가 빈 화면입니다.

대부분 두 가지 원인 중 하나입니다. Binding Type이 Web API로 선택돼 UI 어노테이션이 노출되지 않았거나, projection view에 @UI.lineItem 어노테이션이 하나도 없어서 List Report가 렌더링할 컬럼을 찾지 못한 경우입니다. Service Binding 편집기의 "Entity Set and Association" 목록에서 엔터티를 선택했을 때 우측에 UI 어노테이션 미리보기가 뜨는지 먼저 확인합니다.

Q2. Web API Binding으로 만들었는데 외부 클라이언트가 metadata에서 UI.LineItem 같은 요소를 여전히 봅니다.

Projection view에 @UI 어노테이션이 그대로 남아 있어서입니다. Web API용 별도 projection을 만들거나, @Metadata.allowExtensions과 metadata extension으로 UI 어노테이션을 UI용 layer로 분리하는 방식이 권장됩니다.

Q3. 온프레미스에서 Binding을 Activate 했는데 Gateway에 서비스가 안 보입니다.

BTP ABAP Environment는 Binding Activate 시 자동 노출되지만, 온프레미스는 /IWFND/MAINT_SERVICE에서 시스템 alias를 지정해 명시적으로 등록해야 하는 경우가 많습니다. OData V4는 /sap/opu/odata4 경로, V2는 /sap/opu/odata 경로를 사용하며, 트랜스포트 요청에 Binding 아티팩트가 포함됐는지도 확인이 필요합니다.

Q4. UI Binding에서 draft가 동작하지 않습니다.

Behavior Definition에 with draft 절과 draft 관련 필드가 선언돼 있는지, 데이터베이스에 draft 테이블이 활성화됐는지 확인합니다. Web API Binding에서는 draft가 의도적으로 노출되지 않는 경우도 있으니 요구사항에 따라 Binding Type을 재검토합니다.

확장하면 좋은 주제들

이 글에서 다룬 Binding 선택 기준을 이해했다면, 다음 주제로 확장해볼 수 있습니다. Service Consumption Model을 활용해 외부 OData를 ABAP 내부에서 소비하는 패턴, RAP Extensibility로 고객이 UI Binding에 필드를 추가하도록 개방하는 방법, 그리고 BTP Destination Service와 결합해 Web API Binding을 API Management 뒤에 두고 rate limiting과 policy를 적용하는 아키텍처가 대표적입니다. Fiori Elements V4에서 @UI.chart, @UI.presentationVariant를 활용한 분석형 리포트 확장도 UI Binding의 강력한 활용처입니다.

더 파고들 때 도움되는 링크

댓글 0

아직 댓글이 없습니다.