RAP

Service Definition vs Service Binding — OData 공개 구조 #shorts #SAP #RAP

OData 서비스가 외부에 노출되는 원리

알에이피(RAP) 아키텍처에서 비즈니스 오브젝트를 외부 시스템이나 Fiori 앱에 공개하려면 반드시 두 가지 오브젝트가 필요합니다. 바로 Service Definition과 Service Binding입니다. 많은 개발자가 이 둘을 비슷한 것으로 혼동하거나, Service Binding만 만들면 된다고 생각하는 경우가 있는데, 실제로는 각각이 완전히 다른 역할을 담당합니다.

Service Definition은 "무엇을 노출할 것인가"를 선언하는 계층입니다. 여기에는 어떤 CDS 뷰(엔티티)를 외부에 공개할지, 그리고 공개할 때 어떤 이름으로 노출할지를 정의합니다. Service Binding은 "어떤 프로토콜로, 어느 환경에서 노출할 것인가"를 결정합니다. OData V2인지 V4인지, UI용인지 API용인지를 여기서 선택합니다.

이 두 오브젝트를 분리해서 관리함으로써 동일한 비즈니스 로직을 OData V2 UI 환경과 OData V4 API 환경에 동시에 노출하는 것이 가능해집니다. Service Definition 하나에 Service Binding 여러 개를 연결할 수 있다는 점이 핵심입니다.

Service Definition 작성 방법

Service Definition은 ABAP Development Tools(ADT)에서 "New → Service Definition" 메뉴를 통해 생성합니다. 파일 확장자는 .srvd이며, 네이밍 컨벤션은 보통 ZSD_ 또는 ZSRV_ 접두어를 사용합니다.

아래는 주문 관리 시나리오에서 주문 헤더와 아이템 엔티티를 노출하는 Service Definition 예시입니다.

@EndUserText.label: '주문 관리 서비스 정의'
define service ZSD_SALES_ORDER_SRV {
  expose ZC_SalesOrderHeader as SalesOrderHeader;
  expose ZC_SalesOrderItem   as SalesOrderItem;
  expose ZC_CustomerData     as Customer;
}

expose 키워드 뒤에는 CDS Projection View(소비 뷰)의 이름을 적습니다. as 뒤의 별칭은 OData 서비스에서 외부에 노출되는 엔티티셋 이름이 됩니다. 예를 들어 expose ZC_SalesOrderHeader as SalesOrderHeader라고 하면, OData 메타데이터에서는 SalesOrderHeaderSet이라는 엔티티셋으로 접근하게 됩니다.

주의할 점은 Service Definition에 넣을 수 있는 것은 반드시 Projection View(소비 뷰, 즉 define root view entity 또는 define view entity에서 @AbapCatalog.viewEnhancementCategory가 아닌 projection on으로 시작하는 뷰)여야 한다는 것입니다. Interface View를 직접 넣으면 활성화 오류가 발생합니다.

Service Binding 생성과 프로토콜 선택

Service Definition이 완성되면 그 위에서 우클릭 → "New Service Binding"을 선택하거나, 직접 Service Binding 오브젝트를 생성하면서 연결할 Service Definition을 지정합니다.

Service Binding 생성 시 가장 중요한 선택이 바로 Binding Type입니다.

  • OData V2 - UI: SAP Fiori Elements 기반의 Fiori 앱과 연결할 때 사용합니다. 대부분의 기존 Fiori 앱이 여기에 해당합니다.
  • OData V4 - UI: 최신 Fiori Elements V4 앱이나 TypeScript 기반 UI5 앱과 연결합니다. 더 강력한 필터링과 집계 기능을 지원합니다.
  • OData V4 - Web API: Fiori 앱이 아닌 외부 시스템 연동, REST API 호출 등 API 용도로 서비스를 공개할 때 사용합니다.
  • InA - UI: SAP Analytics Cloud와 연동하는 Analytical 서비스에 사용합니다.

Binding Type을 선택한 뒤 Service Binding을 활성화(Activate)하면, 해당 서비스의 엔드포인트 URL이 자동으로 생성됩니다. 예를 들어 ZSRVB_SALES_ORDER_UI_V4라는 Service Binding을 활성화하면 내부적으로 서비스가 등록되고, Fiori Launchpad나 API 호출 시 접근 가능한 URL이 만들어집니다.

// Service Binding 활성화 후 생성되는 URL 예시
// OData V4 - UI 기준
/sap/opu/odata4/sap/zsrvb_sales_order_ui_v4/srvd/sap/zsd_sales_order_srv/0001/

Service Definition과 Service Binding의 역할 분리가 주는 이점

이 구조를 처음 접하면 "왜 굳이 두 개로 나누나?"라는 의문이 생깁니다. 핵심 이유는 재사용성과 유연성입니다.

하나의 Service Definition에 여러 Service Binding을 연결할 수 있습니다. 예를 들어 ZSD_SALES_ORDER_SRV라는 Service Definition 하나로 아래 세 가지 바인딩을 동시에 유지할 수 있습니다.

// 같은 Service Definition에 연결된 세 가지 바인딩
ZSRVB_SALES_ORDER_V2_UI   → OData V2 - UI   (레거시 Fiori 앱용)
ZSRVB_SALES_ORDER_V4_UI   → OData V4 - UI   (신규 Fiori 앱용)
ZSRVB_SALES_ORDER_V4_API  → OData V4 - Web API (외부 시스템 연동용)

비즈니스 로직(CDS 뷰, 동작 정의)을 수정해도 Service Definition만 공유하므로, 세 바인딩 모두에 자동으로 변경 사항이 반영됩니다. 각 바인딩별로 따로 로직을 관리할 필요가 없습니다.

반대로 특정 바인딩만 접근 권한을 제한하거나 비활성화하는 것도 가능합니다. OData V4 - Web API 바인딩에만 인증 설정을 강화하거나, 특정 바인딩을 임시로 비활성화해도 다른 바인딩에는 전혀 영향이 없습니다.

Preview 기능으로 서비스 즉시 테스트하기

Service Binding을 활성화하면 ADT 화면 우측 패널에 엔티티 목록이 나타납니다. 여기서 엔티티를 선택하고 "Preview" 버튼을 누르면 Fiori Elements 앱이 브라우저에서 바로 실행됩니다. 별도의 Fiori 프로젝트를 만들지 않아도 됩니다.

이 Preview 기능은 개발 중 데이터 확인, 필터 동작 검증, 드릴다운 네비게이션 테스트 등 초기 개발 단계에서 매우 유용합니다. 실제 배포 전에 비즈니스 데이터가 올바르게 노출되는지 빠르게 확인할 수 있습니다.

// ADT Service Binding Preview 동작 흐름
1. Service Binding 열기 → Activate 버튼 클릭
2. Entity List에서 SalesOrderHeader 선택
3. Preview 버튼 클릭
→ 브라우저에서 Fiori List Report 자동 실행
→ 실제 DB 데이터로 OData 호출 테스트 가능

흔히 발생하는 오류와 해결 방법

Service Definition과 Service Binding 작업 중 자주 마주치는 오류들이 있습니다.

첫 번째로 많이 겪는 오류는 "Interface View를 직접 expose했을 때"입니다. expose ZI_SalesOrderHeader처럼 Interface View를 직접 넣으면 활성화 오류가 발생합니다. 반드시 그 위에 Projection View를 만들고 Projection View를 expose해야 합니다.

// 잘못된 방법 — Interface View 직접 expose (오류 발생)
define service ZTEST_SRV {
  expose ZI_SalesOrder as SalesOrder;  -- 활성화 오류
}

// 올바른 방법 — Projection View를 expose
define service ZTEST_SRV {
  expose ZC_SalesOrder as SalesOrder;  -- ZC_ = Projection/Consumption View
}

두 번째는 연관 엔티티(Composition 관계)를 Service Definition에 누락하는 경우입니다. 헤더-아이템 구조에서 헤더만 expose하고 아이템을 빠뜨리면, Fiori 앱에서 드릴다운이 작동하지 않습니다. Composition 관계로 연결된 모든 엔티티를 함께 expose해야 합니다.

// Composition 관계의 모든 엔티티를 함께 expose
define service ZSD_ORDER_SRV {
  expose ZC_OrderHeader as OrderHeader;  -- 루트
  expose ZC_OrderItem   as OrderItem;    -- Composition 자식
  expose ZC_OrderNote   as OrderNote;    -- 추가 Composition 자식
}

세 번째 문제는 Service Binding 활성화 후 URL이 생성됐는데도 "서비스를 찾을 수 없다"는 오류입니다. 이 경우 SOAMANAGER(트랜잭션)나 /IWFND/MAINT_SERVICE에서 서비스가 실제로 등록됐는지 확인해야 합니다. OData V4 기반 서비스는 /IWFND/MAINT_SERVICE 대신 SOAMANAGER 또는 시스템 관리 도구에서 확인합니다.

실전 시나리오 — 구매 요청 서비스 전체 구성

실제 프로젝트에서 구매 요청(Purchase Requisition) 관리 시나리오를 RAP으로 구현하는 경우를 단계별로 정리합니다.

먼저 CDS 레이어에서 Interface View와 Projection View를 정의합니다. Interface View는 데이터베이스 테이블에서 데이터를 읽어오는 기반 뷰이고, Projection View는 외부에 노출할 필드와 어노테이션을 정의합니다.

// 1단계: Projection View (소비 뷰)
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: '구매 요청 소비 뷰'
define root view entity ZC_PurchaseReq
  provider contract transactional_query
  as projection on ZI_PurchaseReq
{
  key PurchaseReqId,
      VendorId,
      @Semantics.amount.currencyCode: 'CurrencyCode'
      TotalAmount,
      CurrencyCode,
      RequestStatus,
      CreatedAt,
      /* Associations */
      _PurchaseReqItem : redirected to composition child ZC_PurchaseReqItem
}
// 2단계: Service Definition
@EndUserText.label: '구매 요청 서비스 정의'
define service ZSD_PURCHASE_REQ_SRV {
  expose ZC_PurchaseReq     as PurchaseReq;
  expose ZC_PurchaseReqItem as PurchaseReqItem;
}
// 3단계: Service Binding 생성 (ADT UI에서 수행)
// - Service Definition: ZSD_PURCHASE_REQ_SRV
// - Binding Type: OData V4 - UI
// - Name: ZSRVB_PURCHASE_REQ_UI_V4
// → Activate 후 Preview로 즉시 테스트

Service Definition 어노테이션 활용

Service Definition 자체에도 어노테이션을 붙여서 서비스 수준의 메타데이터를 제어할 수 있습니다.

@EndUserText.label: '재고 관리 서비스'
@ObjectModel.usageType: {
  serviceQuality: #A,
  sizeCategory: #S,
  dataClass: #MIXED
}
define service ZSD_INVENTORY_SRV {
  expose ZC_InventoryItem    as InventoryItem;
  expose ZC_InventoryStorage as StorageLocation;
  expose ZC_InventoryBatch   as BatchInfo;
}

@ObjectModel.usageType은 서비스 품질, 데이터 크기 범주, 데이터 특성을 명시합니다. 이 어노테이션은 API 카탈로그 관리나 서비스 거버넌스에서 활용됩니다. 실제 서비스 동작에는 영향을 주지 않지만, 엔터프라이즈 환경에서 수백 개의 서비스를 관리할 때 분류 기준이 됩니다.

정리 — Service Definition이 없으면 아무것도 노출되지 않는다

알에이피에서 아무리 완성도 높은 CDS 뷰와 Behavior Definition을 만들어도, Service Definition에서 expose하지 않으면 외부에서 전혀 접근할 수 없습니다. Service Definition은 "공개 허용 목록"이고, Service Binding은 "공개 채널 설정"입니다.

실무 체크리스트를 정리하면 다음과 같습니다.

  • 노출할 엔티티는 반드시 Projection View를 통해 expose한다.
  • Composition 관계의 자식 엔티티도 함께 expose해야 드릴다운이 동작한다.
  • 같은 Service Definition으로 V2/V4/API 등 여러 바인딩을 만들 수 있다.
  • Service Binding 활성화 후 Preview로 즉시 데이터 검증이 가능하다.
  • Interface View를 직접 expose하면 활성화 오류가 발생하니 반드시 Projection View를 사용한다.

Service Definition과 Service Binding의 역할을 명확히 이해하면, RAP 기반 OData 서비스를 훨씬 체계적으로 설계하고 유지보수할 수 있습니다. 단순히 "만들어야 하는 오브젝트"가 아니라, 각각의 책임이 분리된 아키텍처 레이어라는 관점으로 접근해 보세요.

댓글 0

아직 댓글이 없습니다.