SAP

BAPI vs OData — S/4HANA 전환 5단계 #shorts #SAP #S4HANA

▶ YouTube에서 보기

BAPI와 OData, 무엇이 다른가 — 패러다임 비교

BAPI는 함수 모듈 기반의 RFC 프로토콜 위에서 동작합니다. 호출자는 SAP GUI 프로토콜 계층을 이해하는 커넥터(JCo, NCo 등)를 갖춰야 하고, 파라미터 구조는 ABAP 딕셔너리 타입에 강하게 결합됩니다. 반면 OData는 HTTP/REST 기반의 엔터티 중심 프로토콜입니다. 리소스(EntitySet)를 URL로 식별하고, CRUD를 HTTP 메서드(GET/POST/PATCH/DELETE)로 표현하며, $filter, $select, $top 같은 쿼리 옵션으로 클라이언트가 필요한 데이터만 요청합니다.

비유하자면 BAPI는 "주방에 직접 전화해서 정해진 양식으로 주문하는 방식"이고, OData는 "메뉴판(메타데이터 $metadata)을 보고 표준화된 주문서로 요청하는 방식"입니다. 계약(Contract)이 프로토콜 수준에서 표준화되어 있어 소비자 측 결합도가 낮아지는 것이 핵심 차이입니다.

  • 전송 계층: RFC(전용 포트) vs HTTP/HTTPS(방화벽 친화적)
  • 계약: ABAP 구조체 vs EDMX 메타데이터(자기 기술적)
  • 상태 관리: BAPI_TRANSACTION_COMMIT 명시 호출 vs 요청 단위 LUW(RAP의 경우 프레임워크 관리)
  • 확장 소비자: ABAP 커넥터 필수 vs Fiori, 모바일, 외부 SaaS 등 HTTP만 있으면 소비 가능

왜 지금 전환해야 하는가

SAP S/4HANA(2022/2023 에디션 및 SAP S/4HANA Cloud) 환경에서 SAP은 일반적으로 릴리스된 API(OData, SOAP)를 통한 통합을 권장하고 있습니다. Clean Core 전략에서는 릴리스되지 않은 BAPI·커스텀 RFC에 대한 직접 의존이 업그레이드 리스크로 분류됩니다. 특히 ABAP Cloud 개발 모델에서는 미릴리스 오브젝트 호출 자체가 구문 검사에서 차단됩니다.

또한 Fiori Elements, SAP Build, BTP 통합 시나리오는 모두 OData를 1급 시민으로 취급하므로, BAPI 기반 인터페이스를 유지하면 신규 채널 확장 때마다 별도의 어댑터 계층이 필요해집니다. 전환은 선택이 아니라 기술 부채 상환에 가깝습니다.

현행 BAPI 인터페이스 분석 방법

전환의 첫 작업은 인벤토리 작성입니다. S/4HANA 2023 온프레미스 기준으로 다음 절차를 권장합니다.

  1. 호출 현황 수집: ST03N 워크로드 통계와 STRFCTRACE(또는 SRTCM)로 실제 호출되는 RFC 함수 목록과 호출 주체(외부 시스템 사용자 ID)를 수집합니다.
  2. 파라미터 매핑표 작성: 예제로 사용할 Z_CUSTOM_DELIVERY_FETCH가 IMPORT로 고객번호·기간을 받고 TABLES로 납품 목록을 반환한다면, 각 필드를 OData 엔터티 속성 후보와 1:1로 매핑합니다.
  3. 트랜잭션 경계 확인: 조회형(GetList/GetDetail)인지 변경형(Create/Change + Commit)인지 분류합니다. 조회형은 CDS 뷰로 대체가 쉽고, 변경형은 RAP Behavior 또는 언매니지드 구현이 필요합니다.
  4. 대체 표준 API 탐색: SAP Business Accelerator Hub(api.sap.com)에서 동일 도메인의 릴리스된 OData API(예: API_OUTBOUND_DELIVERY_SRV)가 있는지 먼저 확인합니다. 표준으로 커버되면 커스텀 전환 자체가 불필요합니다.

OData 서비스 설계 원칙

BAPI의 함수 시그니처를 그대로 URL로 옮기는 것은 흔한 안티패턴입니다. OData는 동사(함수)가 아니라 명사(리소스) 중심으로 설계해야 합니다.

  • Z_CUSTOM_DELIVERY_FETCHGET /Deliveries?$filter=ShipToParty eq '1000'
  • 헤더-아이템 구조는 Association으로 표현: /Deliveries('80001234')/_Items
  • 순수 조회는 CDS 뷰 + 매니지드 쿼리, BAPI 내부의 복잡한 산출 로직이 필수라면 언매니지드 쿼리(if_rap_query_provider)로 래핑
  • 버전 전략: 서비스 바인딩에 OData V4를 권장(신규 Fiori Elements 기능 대부분이 V4 우선)

구현 기술은 SEGW(레거시 Gateway) 대신 RAP(ABAP RESTful Application Programming Model)를 권장합니다. RAP는 CDS·Behavior Definition·Service Binding이 하나의 스택으로 관리되어 Clean Core 원칙과 정합성이 높습니다.

전환 1단계 — CDS 뷰와 기본 OData 서비스 노출

조회형 BAPI의 SELECT 로직을 CDS 뷰 엔터티로 재구성합니다. ADT(Eclipse) 기준입니다.

@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Delivery Header - Interface View'
define view entity ZI_DeliveryHeader
  as select from likp
{
  key vbeln     as DeliveryId,
      lfart     as DeliveryType,
      kunnr     as ShipToParty,
      wadat_ist as ActualGoodsIssueDate,
      erdat     as CreationDate
}

서비스 정의와 바인딩으로 즉시 OData 엔드포인트가 생성됩니다.

@EndUserText.label: 'Delivery Migration Service'
define service ZUI_DELIVERY_MIG {
  expose ZC_DeliveryHeader as Deliveries;
}

Service Binding에서 OData V4 - Web API를 선택하고 Publish하면 /sap/opu/odata4/... 경로로 GET Deliveries가 동작합니다. BAPI의 필터 파라미터는 클라이언트의 $filter로 자연스럽게 대체됩니다.

전환 2단계 — 커스텀 로직 래핑과 에러 처리

기존 Z_CUSTOM_DELIVERY_FETCH에 단순 SELECT로 환원되지 않는 가공 로직이 있다면, 언매니지드 쿼리로 과도기적 래핑을 합니다. 이때 예외 변환과 로깅을 반드시 넣습니다.

CLASS zcl_delivery_query DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES if_rap_query_provider.
ENDCLASS.

CLASS zcl_delivery_query IMPLEMENTATION.
  METHOD if_rap_query_provider~select.
    DATA lt_result TYPE STANDARD TABLE OF zs_delivery_result.
    DATA(lv_top)  = io_request->get_paging( )->get_page_size( ).
    DATA(lv_skip) = io_request->get_paging( )->get_offset( ).

    TRY.
        CALL FUNCTION 'Z_CUSTOM_DELIVERY_FETCH'
          EXPORTING iv_max_rows = lv_top + lv_skip
          TABLES    et_delivery = lt_result
          EXCEPTIONS no_data = 1 comm_failure = 2 OTHERS = 3.
        IF sy-subrc > 1.
          RAISE EXCEPTION NEW zcx_delivery_query( subrc = sy-subrc ).
        ENDIF.
        DELETE lt_result TO lv_skip.
        io_response->set_total_number_of_records( lines( lt_result ) ).
        io_response->set_data( lt_result ).
      CATCH cx_root INTO DATA(lx_err).
        zcl_delivery_log=>write_error( lx_err ).
        RAISE EXCEPTION NEW zcx_delivery_query( previous = lx_err ).
    ENDTRY.
  ENDMETHOD.
ENDCLASS.

전환 3단계 — 성능·보안·테스트를 갖춘 프로덕션 구성

운영 투입 전 세 축을 마감합니다.

성능 — 매니지드 쿼리로 완전히 이관되면 $select·$top이 DB 푸시다운되므로, 2단계의 래핑 클래스는 중간 산출물로 보고 최종적으로 CDS 계산 필드·테이블 함수로 로직을 내재화하는 것을 권장합니다.

보안 — CDS 접근 제어(DCL)로 BAPI 시절의 AUTHORITY-CHECK를 대체합니다.

@EndUserText.label: 'Delivery Access Control'
@MappingRole: true
define role ZI_DELIVERYHEADER {
  grant select on ZI_DeliveryHeader
    where (ShipToParty) = aspect pfcg_auth( ZV_SHIPTO, KUNNR, ACTVT = '03' );
}

테스트 — ABAP Unit으로 쿼리 구현을 검증하고, 통신 사용자 기준의 통합 테스트를 CI에 포함합니다.

CLASS ltc_delivery_query DEFINITION FINAL FOR TESTING
  DURATION SHORT RISK LEVEL HARMLESS.
  PRIVATE SECTION.
    METHODS empty_result_returns_ok FOR TESTING.
ENDCLASS.

CLASS ltc_delivery_query IMPLEMENTATION.
  METHOD empty_result_returns_ok.
    DATA(lo_double) = cl_osql_test_environment=>create(
      i_dependency_list = VALUE #( ( 'LIKP' ) ) ).
    lo_double->destroy( ).
  ENDMETHOD.
ENDCLASS.

운영 전환 전 검증 체크리스트

자주 겪는 문제 세 가지를 먼저 짚습니다.

  • Q. 전환 후 외부 시스템이 여전히 RFC를 호출한다? — 병행 운영 기간을 두고 STRFCTRACE로 잔여 호출이 0이 된 것을 확인한 뒤 함수 모듈을 폐기하세요.
  • Q. OData 응답이 BAPI보다 느리다? — 언매니지드 래핑 단계에서 전체 조회 후 메모리 필터링을 하는 경우가 대부분입니다. 페이징·필터를 소스 조회 시점에 반영했는지 확인하세요.
  • Q. 403 Forbidden이 발생한다? — DCL 조건과 통신 사용자 PFCG 권한 값이 어긋난 경우입니다. STAUTHTRACE로 체크 대상 권한 오브젝트를 확인하세요.

최종 체크리스트: (1) 잔여 RFC 호출 0건 확인, (2) V4 메타데이터 프리즈 및 소비자 공지, (3) DCL·PFCG 권한 회귀 테스트, (4) 부하 테스트에서 $top 기본값 강제 여부, (5) /IWFND/ERROR_LOG 모니터링 체계 구축.

댓글 0

아직 댓글이 없습니다.