ABAP

AUFK vs I_ServiceOrderItem — CDS 전환법 #shorts #SAP #ABAP

▶ YouTube에서 보기

1. I_ServiceOrderItem이 필요한 배경

SAP ECC 시절 서비스 오더 데이터를 다루려면 개발자는 AUFK(오더 마스터), AFIH(유지보수 오더 헤더), AFKO, AFPO 같은 테이블을 직접 조인해야 했습니다. 테이블 이름 자체가 독일어 약어라 가독성이 떨어지고, 아이템 레벨 정보를 얻기 위해 4~5개 테이블을 엮는 일이 일상이었습니다.

S/4HANA(1809 이후, 특히 2020~2023 릴리스와 S/4HANA Cloud)에서는 이런 물리 테이블 접근 대신 VDM(Virtual Data Model) 기반의 릴리스된 CDS View를 사용하는 것이 권장됩니다. 서비스 오더 아이템 영역의 인터페이스 뷰가 바로 I_ServiceOrderItem입니다. 이 글에서는 AUFK 직접 조회 방식의 한계를 짚고, I_ServiceOrderItem으로 전환할 때 얻는 이점과 실전 코드를 단계별로 살펴봅니다.

  • AUFK 기반 레거시 조회의 구조적 문제 이해
  • I_ServiceOrderItem의 필드·Association 구조 파악
  • ABAP SELECT와 리포트 구현에 즉시 적용

2. AUFK 직접 조회의 한계

AUFK를 직접 읽는 방식에는 세 가지 대표적인 문제가 있습니다.

  1. 복잡한 조인 체인 — 오더 헤더는 AUFK, 아이템·오퍼레이션은 AFKO/AFVC/AFPO, 파트너는 IHPA 등 최소 3~5개 테이블 조인이 필요합니다. 조인 조건을 하나만 틀려도 데이터가 중복되거나 누락됩니다.
  2. 권한·클라이언트 처리 누락 — 물리 테이블 SELECT는 권한 체크(AUTHORITY-CHECK)를 개발자가 직접 구현해야 합니다. CDS View는 DCL(Access Control)이 뷰에 결합되어 있어 조회 시점에 권한이 일반적으로 자동 반영됩니다.
  3. S/4HANA 데이터 모델 변경 리스크 — S/4HANA Service(구 CRM Service 통합) 환경에서는 서비스 트랜잭션 저장 구조 자체가 ECC의 CS 모듈과 다릅니다. AUFK에 의존한 코드는 마이그레이션 시 대량 수정 대상이 되지만, 릴리스된 CDS View는 SAP이 내부 구조 변경을 흡수해 주는 안정적 계약(contract) 역할을 합니다.

비유하자면 AUFK 직접 조회는 건물 배선을 직접 뜯어 전기를 끌어오는 방식이고, I_ServiceOrderItem은 벽에 규격화된 콘센트를 꽂는 방식입니다. 내부 배선(물리 테이블)이 바뀌어도 콘센트 규격(뷰 인터페이스)은 유지됩니다.

3. I_ServiceOrderItem CDS View 구조

I_ServiceOrderItem은 VDM 계층 중 Interface View(I_ 접두어)에 해당하며, 서비스 오더의 아이템 단위 데이터를 표준화된 필드명으로 노출합니다. 헤더 뷰 I_ServiceOrder와 키(ServiceOrder)로 연결되고, 컨슈머는 물리 저장 테이블이 무엇인지 알 필요가 없습니다.

구조를 도식으로 정리하면 다음과 같습니다.

[C_* Consumption View / Fiori App]
        ↑ 소비
[I_ServiceOrder] ──(_Item)──> [I_ServiceOrderItem]
        ↑ 추상화                     │ _Product, _ServiceOrder 등 Association
[물리 저장 테이블 — SAP 내부 관리 영역]

확인 방법: ADT(Eclipse)에서 I_ServiceOrderItem을 열어 Release Contract(예: C1 — Use in Cloud Development)와 릴리스 상태를 점검하는 것이 좋습니다. 릴리스에 따라 필드 구성이 다를 수 있으므로 실제 시스템에서 Active 버전을 기준으로 개발하세요.

4. 핵심 필드 상세 분석

필드의미실무 포인트
ServiceOrder서비스 오더 번호(헤더 키)I_ServiceOrder와 조인 키
ServiceOrderItem아이템 번호복합 키의 두 번째 요소
Product서비스/자재 제품 IDMATNR 대체 개념, _Product로 상세 접근
ServiceOrderItemCategory아이템 범주서비스·부품·경비 구분 로직에 활용
RequestedQuantity / RequestedQuantityUnit요청 수량/단위수량 집계 시 단위 혼합 주의
NetAmount / TransactionCurrency순금액/통화통화 참조 필드가 이미 어노테이션으로 연결됨
ServiceOrderItemIsCompleted완료 여부AUFK 상태(JEST/TJ02) 해석 로직을 대체

특히 상태 필드가 중요합니다. 레거시에서는 오더 상태를 알기 위해 JEST/TJ02T를 추가 조인하고 상태 코드를 해석해야 했지만, 인터페이스 뷰는 ...IsCompleted 같은 시맨틱 필드로 이미 가공해 제공합니다.

5. 기본 SELECT 예제

1단계 기본 예제입니다. 특정 제품이 포함된 미완료 서비스 오더 아이템을 조회합니다.

REPORT zsvc_item_basic.

CLASS lcl_svc_reader DEFINITION.
  PUBLIC SECTION.
    METHODS get_open_items
      IMPORTING iv_product      TYPE string
      RETURNING VALUE(rt_items) TYPE TABLE OF i_serviceorderitem
                                     WITH EMPTY KEY.
ENDCLASS.

CLASS lcl_svc_reader IMPLEMENTATION.
  METHOD get_open_items.
    SELECT FROM i_serviceorderitem
      FIELDS serviceorder,
             serviceorderitem,
             product,
             requestedquantity,
             requestedquantityunit,
             netamount,
             transactioncurrency
      WHERE product                     = @iv_product
        AND serviceorderitemiscompleted = @abap_false
      ORDER BY serviceorder, serviceorderitem
      INTO CORRESPONDING FIELDS OF TABLE @rt_items
      UP TO 200 ROWS.
  ENDMETHOD.
ENDCLASS.

조인 없이 SELECT 한 번으로 끝나는 점, 그리고 필드명이 자기 설명적(self-describing)이라는 점이 AUFK 방식과의 결정적 차이입니다.

6. Association 활용 실전 예제

2단계는 Association 경로 표현식(path expression)으로 헤더·제품 정보를 함께 가져오는 실무 시나리오입니다. 결과 검증과 예외 처리를 포함했습니다.

METHOD get_items_with_header.
  TRY.
      SELECT FROM i_serviceorderitem AS item
        FIELDS item~serviceorder,
               item~serviceorderitem,
               item~\_serviceorder-serviceorderdescription AS headerdesc,
               item~\_serviceorder-soldtoparty             AS soldtoparty,
               item~product,
               item~netamount,
               item~transactioncurrency
        WHERE item~\_serviceorder-serviceordertype = @iv_order_type
          AND item~creationdate >= @iv_date_from
        INTO TABLE @rt_result.

      IF sy-subrc <> 0.
        RAISE EXCEPTION NEW zcx_svc_not_found(
          textid = zcx_svc_not_found=>no_items ).
      ENDIF.

    CATCH cx_sy_open_sql_db INTO DATA(lx_db).
      " 로깅 후 상위 계층에 의미 있는 예외로 변환
      zcl_app_log=>get( )->add_error( lx_db->get_text( ) ).
      RAISE EXCEPTION NEW zcx_svc_read_error( previous = lx_db ).
  ENDTRY.
ENDMETHOD.

Association(\_ServiceOrder)을 경로로 사용하면 조인이 필요할 때만(join on demand) 실행됩니다. 헤더 필드를 지우면 조인 자체가 SQL에서 사라지므로, 레거시처럼 "혹시 몰라서" 걸어둔 조인 비용이 발생하지 않습니다.

7. 서비스 오더 아이템 리포트 구현

3단계 프로덕션 수준 예제입니다. 통화별 금액 집계 리포트를 CDS 집계 + 테스트 가능 구조로 구현합니다.

CLASS zcl_svc_item_report DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    TYPES: BEGIN OF ty_sum,
             serviceorder        TYPE i_serviceorderitem-serviceorder,
             transactioncurrency TYPE i_serviceorderitem-transactioncurrency,
             totalamount         TYPE i_serviceorderitem-netamount,
             itemcount           TYPE i,
           END OF ty_sum,
           tt_sum TYPE STANDARD TABLE OF ty_sum WITH EMPTY KEY.

    METHODS summarize
      IMPORTING iv_date_from     TYPE datum
      RETURNING VALUE(rt_summary) TYPE tt_sum.
ENDCLASS.

CLASS zcl_svc_item_report IMPLEMENTATION.
  METHOD summarize.
    " 집계는 DB 레이어로 코드 푸시다운 (S/4HANA 성능 원칙)
    SELECT FROM i_serviceorderitem
      FIELDS serviceorder,
             transactioncurrency,
             SUM( netamount ) AS totalamount,
             COUNT( * )       AS itemcount
      WHERE creationdate >= @iv_date_from
      GROUP BY serviceorder, transactioncurrency
      INTO CORRESPONDING FIELDS OF TABLE @rt_summary.
  ENDMETHOD.
ENDCLASS.

단위 테스트에서는 CDS Test Double Framework(cl_cds_test_environment)로 I_ServiceOrderItem을 목킹하면 실제 데이터 없이 검증할 수 있습니다. 보안 측면에서는 뷰에 결합된 Access Control이 적용되므로, 리포트 레벨에서 별도의 오더 유형 권한 체크가 필요한 경우에만 추가 구현합니다.

자주 겪는 문제 세 가지도 정리합니다.

  • Q. SELECT에서 뷰를 못 찾습니다. — 릴리스/버전에 따라 뷰 제공 여부가 다릅니다. ADT에서 존재 여부와 Released 상태를 먼저 확인하세요.
  • Q. 통화가 섞인 SUM 결과가 이상합니다. — 반드시 TransactionCurrency를 GROUP BY에 포함해 통화별로 집계해야 합니다.
  • Q. 데이터가 0건입니다. — DCL 권한 제한일 가능성이 큽니다. SU53이 아니라 뷰의 Access Control 정의와 사용자 권한 오브젝트를 대조하세요.

8. S/4HANA 환경에서의 최적 적용 포인트

성능 관점에서 I_ServiceOrderItem은 HANA 컬럼 스토어 위에서 동작하므로 레거시처럼 Secondary Index를 고민할 필요가 일반적으로 없습니다. WHERE 조건을 뷰 필드 기준으로 명확히 주고, 집계·필터를 DB로 푸시다운하는 것이 핵심입니다. 또한 이 뷰는 OData 서비스로 노출해 Fiori Elements 리스트 리포트와 바로 연동하거나, RAP(ABAP RESTful Application Programming Model)의 읽기 소스로 활용하기에 적합합니다. 이후에는 I_ServiceOrder 헤더 뷰, 서비스 확인(Confirmation) 관련 뷰, RAP 기반 커스텀 Fiori 앱으로 확장해 보길 권장합니다.

댓글 0

아직 댓글이 없습니다.