이 글에서 다루는 것
RAP(ABAP RESTful Application Programming Model)에서 Service Binding은 서비스를 실제 소비 가능한 프로토콜로 노출하는 마지막 관문입니다. 그런데 개발자들이 자주 놓치는 부분이 있습니다. 바로 Binding Type을 잘못 골라서 Fiori Elements 앱이 아예 뜨지 않는 경우입니다. Service Definition까지는 완벽하게 만들었는데 Binding Type을 API로 잡아버리면 Preview 버튼조차 나타나지 않습니다. 이 글에서는 UI Binding과 API Binding의 근본적인 차이, 잘못 선택했을 때 나타나는 증상, 그리고 실무에서 어떤 기준으로 골라야 하는지를 SalesOrderMonitor라는 실무 예제로 풀어봅니다.
- Service Binding 4가지 타입(OData V2/V4 × UI/API)의 구조적 차이 이해
- UI Binding과 API Binding의 메타데이터·어노테이션 처리 방식 비교
- Fiori Elements Preview가 안 뜨는 원인 진단법 습득
- 실무 판단 기준(내부 앱 vs 외부 통합) 세우기
- ADT에서 바인딩 생성·활성화 실전 흐름 이해
먼저 알고 있어야 할 것들
이 글은 RAP의 BDef(Behavior Definition), CDS View Entity, Service Definition 개념을 이미 다뤄본 개발자를 대상으로 합니다. Managed/Unmanaged 시나리오 구분, Draft 처리, Projection View의 역할 정도는 익숙해야 합니다. SAPUI5 OData Model이나 Fiori Elements Floorplan(List Report, Object Page)에 대한 최소한의 경험이 있으면 UI Binding 파트를 더 깊이 이해할 수 있습니다.
환경과 준비물
이 글의 예제는 다음 환경 기준으로 검증했습니다. 실제 환경의 릴리즈나 SP 레벨에 따라 다이얼로그 UI가 다르게 보일 수 있으니 유의 바랍니다.
- SAP BTP, ABAP Environment (Steampunk) 또는 S/4HANA 2022 이상(On-Premise ABAP Platform 2022+)
- ABAP Development Tools (ADT) 3.36 이상 — Eclipse 2024-03+
- ABAP Language Version: ABAP for Cloud Development 권장 (BTP 기준)
- SAP Fiori Elements Preview (ADT 내장) 또는 SAP Build Work Zone
- 테스트용 CDS Entity:
ZI_SalesOrderMonitor, Projection:ZC_SalesOrderMonitor
BTP ABAP Environment에서는 Business Catalog와 IAM App 매핑까지 필요할 수 있지만, 이 글은 Binding Type 자체에 집중하므로 Preview 레벨까지만 다룹니다. On-Premise 환경이라면 /IWFND/MAINT_SERVICE가 아니라 Service Binding에서 직접 활성화된다는 점을 기억해 두세요.
Service Binding의 정체와 4가지 얼굴
RAP 스택을 위에서 아래로 훑으면 다음과 같은 계층이 나옵니다.
CDS Data Model (Interface View)
↓
CDS Projection View (Consumption Layer)
↓
Behavior Definition (BDef) — Managed / Unmanaged
↓
Service Definition (SD) — "어떤 엔터티를 노출할까"
↓
Service Binding (SB) — "어떤 프로토콜·타입으로 노출할까"
↓
OData Endpoint (/sap/opu/odata/... 또는 /sap/opu/odata4/...)
Service Definition까지는 무엇을(What) 노출할지 정의하는 단계입니다. 반면 Service Binding은 어떻게(How) 노출할지를 결정합니다. ADT에서 Service Binding을 새로 만들 때 나오는 Binding Type 드롭다운을 보면 다음 4가지가 있습니다.
- OData V2 - UI: Fiori Elements V2 앱용. Draft 처리, Side Effects, 어노테이션 기반 UI 힌트 지원
- OData V4 - UI: Fiori Elements V4 앱용. 최신 Floorplan(예: List Report V4)과 결합
- OData V2 - Web API: 외부 시스템 통합, HTTP 클라이언트 호출용. UI 어노테이션 미노출
- OData V4 - Web API: 최신 OData 표준 기반 API 통합용
가장 큰 오해는 "UI냐 API냐는 그냥 이름만 다른 거 아냐?"입니다. 아닙니다. 두 타입은 런타임에서 처리하는 메타데이터와 노출되는 기능이 근본적으로 다릅니다.
비유하자면 같은 자동차를 만드는데 UI Binding은 완성차(대시보드, 시트, 인포테인먼트까지)로 출고하는 것이고, API Binding은 롤링 섀시(엔진·바퀴·프레임만)로 출고하는 것입니다. Fiori Elements는 대시보드가 없으면 계기판을 그릴 수 없기 때문에 API Binding으로는 앱이 뜨지 않습니다. 반대로 외부 Java 서비스에서 HTTP로만 데이터를 긁어갈 거라면 대시보드는 오히려 낭비입니다.
구체적으로 UI Binding에서만 나오는 것들은 다음과 같습니다.
@UI.lineItem,@UI.headerInfo,@UI.facet같은 UI 어노테이션이$metadata에 노출- Draft 관련 액션(Edit, Activate, Discard)이 자동으로 서비스에 포함
- Value Help(F4)가
com.sap.vocabularies.Common.v1.ValueList로 렌더링 - ADT에서 Preview 버튼 활성화 (Fiori Elements 미리보기)
API Binding은 이런 UI 관련 부가정보를 걷어내고 순수 데이터·CRUD·Function/Action 중심으로 서비스를 노출합니다. Draft 액션이 필요없고 어노테이션 오버헤드가 없기 때문에 응답이 상대적으로 가볍고 외부 시스템에서 사용하기 편합니다.
실전 예제 1단계 — UI Binding으로 Fiori Preview 띄우기
먼저 Projection View와 BDef, Service Definition을 갖췄다고 가정합니다. Service Definition은 단순히 어떤 엔터티를 export할지만 선언합니다. 시나리오는 영업 오더 모니터링 서비스입니다.
@EndUserText.label: 'Sales Order Monitor Service'
define service ZSD_SalesOrderMonitor {
expose ZC_SalesOrderMonitor as SalesOrder;
expose ZC_SalesOrderMonitorItem as SalesOrderItem;
expose ZI_SalesOrderStatusVH as StatusVH;
}
이제 ADT에서 Service Definition을 우클릭 → New Service Binding을 선택합니다. 다이얼로그에서 Binding Type을 OData V4 - UI로 지정합니다. 이름은 ZUI_SB_SO_MONITOR_O4 정도로 짓고 저장·활성화하면 아래와 같이 서비스 URL이 생성됩니다.
Service URL : /sap/opu/odata4/sap/zui_sb_so_monitor_o4/srvd/sap/zsd_salesordermonitor/0001/
Entity Sets :
- SalesOrder
- SalesOrderItem
- StatusVH
Preview Button : Enabled (List Report V4)
Service Binding 에디터 상단의 Preview 버튼을 누르면 브라우저가 열리고 Fiori Elements List Report가 뜹니다. 여기까지가 "정상 케이스"입니다. Projection View에 @UI.lineItem이 붙어 있어야 컬럼이 실제로 렌더링된다는 점만 기억해 두세요.
실전 예제 2단계 — API Binding으로 잘못 만들어서 Preview가 사라지는 상황
여기서 개발자가 자주 하는 실수를 재현해봅니다. 같은 Service Definition으로 두 번째 Binding을 만드는데, 이번엔 OData V4 - Web API를 선택합니다.
* Service Binding 정의 (ADT UI에서 자동 생성되지만 개념적으로)
Name : ZAPI_SB_SO_MONITOR_O4
Binding Type : OData V4 - Web API
Service Def. : ZSD_SalesOrderMonitor
Category : Web API
활성화하면 서비스는 문제없이 뜹니다. URL도 정상적으로 나옵니다.
Service URL : /sap/opu/odata4/sap/zapi_sb_so_monitor_o4/srvd_a2x/sap/zsd_salesordermonitor/0001/
주목할 점은 URL 세그먼트에 srvd가 아니라 srvd_a2x가 붙어있다는 것입니다. A2X는 Application-to-Application eXchange, 즉 시스템 간 통신용이라는 뜻입니다. 그리고 결정적으로 Preview 버튼이 비활성화됩니다. 이 상태에서 이 URL을 Fiori Launchpad 타일에 연결하거나 SAPUI5 앱의 매니페스트 dataSources에 넣으면 다음과 같은 증상이 나타납니다.
// SAPUI5 앱 manifest.json 일부
"dataSources": {
"mainService": {
"uri": "/sap/opu/odata4/sap/zapi_sb_so_monitor_o4/srvd_a2x/sap/zsd_salesordermonitor/0001/",
"type": "OData",
"settings": { "odataVersion": "4.0" }
}
}
// 실행 결과 (Fiori Elements List Report)
// - 화면은 로드되지만 컬럼이 하나도 안 나옴
// - @UI.lineItem 어노테이션이 $metadata 에 포함되지 않기 때문
// - 콘솔: "No lineItem annotation found for entity SalesOrder"
// - Draft edit 시도 시: "DraftRoot action not available"
이 증상이 나오면 십중팔구 Binding Type을 잘못 고른 것입니다. 로깅 관점에서는 브라우저 개발자 도구의 Network 탭에서 $metadata 응답을 열어보고, <Annotations Target="..."> 하위에 UI.LineItem이 있는지 눈으로 확인하는 것이 가장 빠른 진단법입니다. 서버 측에서는 SAP Gateway Runtime Log(/IWFND/ERROR_LOG)가 아니라 RAP Application Log(ADT의 Runtime Errors 뷰)와 Communication Arrangement 로그를 함께 봐야 원인이 명확해집니다.
실전 예제 3단계 — UI와 API를 병렬로 운영하는 프로덕션 패턴
실제 운영 환경에서는 하나의 Service Definition에 대해 UI Binding과 API Binding을 병렬로 만드는 것이 일반적으로 권장됩니다. Fiori 앱은 UI Binding을, 외부 통합은 API Binding을 사용하도록 분리하는 패턴입니다.
* Service Definition은 하나
define service ZSD_SalesOrderMonitor {
expose ZC_SalesOrderMonitor as SalesOrder;
expose ZC_SalesOrderMonitorItem as SalesOrderItem;
expose ZI_SalesOrderStatusVH as StatusVH;
}
* Binding 1 — Fiori Elements용
* Name : ZUI_SB_SO_MONITOR_O4
* Type : OData V4 - UI
* URL : /sap/opu/odata4/sap/zui_sb_so_monitor_o4/srvd/...
* Binding 2 — 외부 시스템 통합용
* Name : ZAPI_SB_SO_MONITOR_O4
* Type : OData V4 - Web API
* URL : /sap/opu/odata4/sap/zapi_sb_so_monitor_o4/srvd_a2x/...
이렇게 분리하면 얻는 이점이 몇 가지 있습니다. 첫째, 보안 분리 측면에서 BTP는 Communication Scenario를 API Binding에만 매핑하고, UI Binding은 Business Catalog 기반 IAM App으로 통제할 수 있습니다. 둘째, 성능 튜닝 측면에서 API Binding은 UI 어노테이션이 없어 $metadata 응답이 상대적으로 가볍기 때문에 대량 배치 통합 시 유리합니다. 셋째, 테스트 격리 측면에서 UI 회귀 테스트(예: wdi5)는 UI Binding을, 통합 테스트(예: Postman / ABAP Unit HTTP 클라이언트)는 API Binding을 사용합니다.
ABAP Unit 스타일의 통합 테스트 스텁을 짜면 다음과 같은 형태가 됩니다.
CLASS ltc_so_monitor_api DEFINITION FINAL FOR TESTING
DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
METHODS:
test_read_sales_order FOR TESTING RAISING cx_static_check.
DATA mo_http_client TYPE REF TO if_web_http_client.
ENDCLASS.
CLASS ltc_so_monitor_api IMPLEMENTATION.
METHOD test_read_sales_order.
" API Binding URL 사용 — Fiori와 무관하게 순수 데이터 검증
DATA(lo_dest) = cl_http_destination_provider=>create_by_url(
i_url = '/sap/opu/odata4/sap/zapi_sb_so_monitor_o4/srvd_a2x/'
&& 'sap/zsd_salesordermonitor/0001/SalesOrder' ).
mo_http_client = cl_web_http_client_manager=>create_by_http_destination( lo_dest ).
DATA(lo_request) = mo_http_client->get_http_request( ).
lo_request->set_header_field( i_name = 'Accept' i_value = 'application/json' ).
DATA(lo_response) = mo_http_client->execute( if_web_http_client=>get ).
cl_abap_unit_assert=>assert_equals(
exp = 200
act = lo_response->get_status( )-code ).
ENDMETHOD.
ENDCLASS.
Transport 관점에서도 두 Binding을 다른 Transport에 담아두면 UI 변경과 API 변경의 릴리즈 주기를 분리할 수 있습니다. 실무에서는 API Binding의 스펙 안정성이 UI보다 훨씬 중요하기 때문에(외부 시스템이 스키마 깨지면 즉시 장애로 이어짐) 이런 분리가 큰 도움이 됩니다.
자주 밟는 함정과 해결법 (FAQ)
Q1. Preview 버튼이 회색으로 비활성화됐어요. — Binding Type이 UI 계열이 아닐 가능성이 큽니다. Service Binding 에디터 상단 헤더의 Binding Type을 확인하세요. Web API로 되어 있다면 새로 UI Binding을 만들거나 삭제 후 재생성해야 합니다. Binding Type은 활성화 후에는 변경 불가이므로 실수하면 다시 만들어야 합니다.
Q2. Fiori Elements 앱이 뜨긴 하는데 컬럼이 하나도 안 보입니다. — 두 가지를 확인하세요. 첫째, Binding Type이 진짜 UI인지. 둘째, Projection View에 @UI.lineItem: [{ position: 10 }] 같은 어노테이션이 실제로 붙어 있는지. 어노테이션은 Interface View가 아니라 Projection(Consumption) View에 붙어야 클라이언트 메타데이터에 반영됩니다. Metadata Extension(.mde)로 분리하는 것도 권장됩니다.
Q3. 외부 팀에서 API를 쓰겠다는데 UI Binding URL을 줘도 되나요? — 동작은 하지만 권장하지 않습니다. UI Binding은 UI 어노테이션이 포함되어 페이로드가 무겁고, Draft 관련 액션이 노이즈로 섞입니다. 그리고 UI Binding은 보통 사용자 로그인 세션(SSO) 전제로 노출되므로 시스템-시스템 통신에서는 인증 방식이 어색합니다. API Binding + Communication Arrangement 조합이 일반적으로 권장됩니다.
Q4. OData V2 UI와 V4 UI 중 뭘 골라야 하나요? — 신규 개발이라면 V4 UI가 기본 선택입니다. 다만 기존 Fiori Elements V2 앱과 결합해야 하거나 특정 V2 전용 어노테이션에 의존한다면 V2 UI가 안전합니다. BTP ABAP Environment의 새 개발은 V4 방향으로 이동하는 흐름이므로 특별한 이유가 없다면 V4를 권장합니다.
Q5. 활성화는 됐는데 브라우저에서 404가 뜹니다. — On-Premise 환경이라면 Service Binding 활성화만으로는 부족하고, ICF 노드(/sap/opu/odata4) 자체가 활성화되어 있어야 합니다. BTP 환경이라면 IAM App 매핑과 Business Catalog가 필요합니다. URL 자체 오타(대소문자 포함)도 흔한 원인입니다.
여기서 더 파고들 만한 주제
Service Binding 선택 감을 잡았다면 다음 주제로 확장해 보세요. 첫째, Metadata Extension(.mde)로 UI 어노테이션을 CDS 본체와 분리해서 UI Binding 전용으로 관리하는 방법. 둘째, Communication Scenario로 API Binding을 외부 클라이언트에 안전하게 노출하는 BTP 표준 방식. 셋째, UI Binding에서만 활성화되는 Draft 라이프사이클과 lock 매커니즘. 넷째, Service Consumption Model(SCM)로 API Binding으로 노출된 서비스를 다른 ABAP 시스템에서 소비하는 방법. 다섯째, Behavior Projection의 use action / use create를 활용해 UI와 API에서 노출 액션을 다르게 가져가는 전략.
더 읽어볼 문서 모음
- SAP Help Portal — Service Binding (ABAP RAP)
- SAP Help Portal — Service Definition and Service Binding 개념 정리
- SAP Help Portal — Developing OData Services with ABAP RAP
- SAP Help Portal — OData Service Types (UI vs Web API)
- SAP Developers — RAP100: Build Fiori Apps with ABAP RESTful Application Programming Model
- SAP Community — ABAP RAP 태그 (현업 이슈 사례 검색용)
- SAPUI5 SDK — OData V4 Model 가이드 (UI Binding 소비 관점)
댓글 0
아직 댓글이 없습니다.