ABAP

AUFK vs CDS — PM 정비 오더 설비 조회 #shorts #SAP #ABAP

▶ YouTube에서 보기

개요 및 이번 글에서 다루는 범위

I_MaintenanceOrder는 SAP S/4HANA의 PM(Plant Maintenance, 설비관리) 모듈에서 정비 오더(Maintenance Order) 헤더 데이터를 표준 가상 데이터 모델(VDM)로 제공하는 CDS View입니다. 기존 ABAP 기반의 AUFK(Order Master Data) 테이블을 단순 SELECT 하던 방식과 달리, I_MaintenanceOrder는 오더 헤더, 설비(Equipment), 기능위치(Functional Location), 작업장(Work Center) 등 PM 운영에 필수적인 연결 정보를 미리 통합한 형태로 제공합니다. 이 글에서는 I_MaintenanceOrder의 구조, AUFK 테이블과의 관계, 실전 ABAP 조회 패턴, 그리고 설비 마스터(I_Equipment)와의 조인 시나리오를 단계별로 다룹니다.

  • I_MaintenanceOrder의 기본 구조와 AUFK/AFIH 관계 이해
  • 주요 필드(MaintenanceOrder, Equipment, FunctionalLocation, OrderType 등) 의미 파악
  • ABAP SELECT 문으로 정비 오더 헤더 조회
  • I_Equipment와 INNER JOIN으로 설비별 정비 이력 추출
  • 성능 고려와 권장 필터 패턴 적용

사전에 알고 있어야 할 내용

이 글은 ABAP 개발 경험 6개월 이상, CDS View 정의 및 SELECT 문 작성에 익숙한 중급 개발자를 대상으로 합니다. PM 모듈의 기본 용어(정비 오더, 설비, 기능위치, 오더 유형 PM01/PM02 등)와 SAP S/4HANA의 VDM(Virtual Data Model) 계층(I/C/P View) 개념을 알고 있으면 이해가 빠릅니다. ADT(ABAP Development Tools) 또는 SE80에서 CDS View를 열어볼 수 있는 권한이 필요합니다.

환경 및 준비물

이 글의 예제는 다음 환경 기준으로 작성되었습니다.

  • SAP S/4HANA 2022 (FPS02) 이상 권장 — 일부 필드는 1909 이후부터 제공
  • ABAP Platform 2022 또는 ABAP Cloud (RAP 기반)
  • Eclipse + ADT(ABAP Development Tools) 최신 버전
  • PM 모듈 마스터 데이터(EQUI, IFLOT)와 트랜잭션 데이터(AUFK, AFIH)가 적재된 시스템
  • 권한 오브젝트: S_DEVELOP(개발), I_AUART(오더 유형) 조회 권한

S/4HANA Public Cloud 환경에서는 동일한 I_MaintenanceOrder를 Released API로 사용할 수 있지만, 직접 SELECT 대신 Custom CDS View 또는 RAP BO를 통해 접근하는 방식이 권장됩니다. On-Premise에서는 ABAP CDS와 OpenSQL을 통한 직접 조회가 가능합니다.

핵심 개념과 동작 원리

I_MaintenanceOrder를 이해하려면 먼저 SAP의 정비 오더 데이터 구조를 알아야 합니다. 정비 오더 한 건은 본질적으로 세 개의 테이블에 분산 저장됩니다.

  • AUFK — Order Master Data, 모든 오더(생산/정비/내부)의 공통 헤더
  • AFIH — PM Order Header, 정비 오더 전용 헤더(설비/기능위치/우선순위 등)
  • AFKO — Order Header(스케줄 관련, 기본 수량/일정)

이 세 테이블을 매번 JOIN하는 ABAP 코드를 작성하는 것은 비효율적이고 오류가 잦았습니다. I_MaintenanceOrder는 이 통합 작업을 미리 수행한 "I-View(Interface View, Basic View)" 계층으로, AUFK와 AFIH를 INNER JOIN하고 AFKO에서 필요한 필드를 가져와 한 줄짜리 평탄화된 뷰로 제공합니다.

비유하자면, AUFK/AFIH/AFKO는 각자 다른 서랍에 들어있는 정비 오더의 표지/내용물/일정표입니다. 이전에는 개발자가 매번 세 서랍을 직접 열어 짜맞춰야 했지만, I_MaintenanceOrder는 한 권의 완성된 책으로 제본해 책장에 꽂아둔 상태와 같습니다.

VDM 계층 구조에서 I_MaintenanceOrder의 위치는 다음과 같습니다.

[ DB Table ]   AUFK + AFIH + AFKO
      |
[ Basic View ] I_MaintenanceOrder
      |
[ Composite ]  C_MaintenanceOrder_*
      |
[ Consumption] CDS for Fiori App / OData

주요 필드는 다음과 같이 그룹화됩니다.

  • 식별자: MaintenanceOrder(=AUFK-AUFNR), MaintenanceOrderType(=AUFK-AUART)
  • 대상 설비: TechnicalObjectType, TechnicalObject, Equipment(=AFIH-EQUNR), FunctionalLocation(=AFIH-TPLNR)
  • 조직 단위: MaintenancePlant, MaintPlanningPlant, MainWorkCenter
  • 상태/일자: MaintOrderSystemStatus, BasicStartDate, BasicEndDate
  • 우선순위: Priority, ActivityType, MaintenanceActivityType

실전 예제 1단계 — 기본 조회

가장 단순한 시나리오부터 시작합니다. 특정 정비 플랜트(MaintenancePlant)에서 진행 중인 정비 오더 헤더를 조회하는 코드입니다.

REPORT zr_pm_order_basic.
DATA: lt_orders TYPE TABLE OF i_maintenanceorder.
SELECT maintenanceorder,
       maintenanceordertype,
       maintenanceorderdesc,
       equipment,
       functionallocation,
       maintenanceplant,
       basicstartdate,
       basicenddate,
       maintordersystemstatus
  FROM i_maintenanceorder
  WHERE maintenanceplant   = '1000'
    AND maintenanceordertype = 'PM01'
    AND basicstartdate     >= '20260101'
  INTO TABLE @lt_orders
  UP TO 200 ROWS.
LOOP AT lt_orders INTO DATA(ls_order).
  WRITE: / ls_order-maintenanceorder,
           ls_order-equipment,
           ls_order-basicstartdate,
           ls_order-maintordersystemstatus.
ENDLOOP.

이 코드는 기존의 AUFK + AFIH JOIN을 한 줄의 SELECT로 대체합니다. WHERE 조건에서 maintenanceplant와 maintenanceordertype을 함께 주어 인덱스 활용을 유도하는 것이 핵심입니다.

실전 예제 2단계 — 설비 마스터 조인과 예외 처리

실무에서는 정비 오더만 보는 일은 거의 없습니다. I_Equipment와 INNER JOIN하고 조회 실패/빈 결과/권한 부족 상황도 함께 처리합니다.

CLASS zcl_pm_order_reader DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    TYPES: BEGIN OF ty_order_equip,
             order_id       TYPE i_maintenanceorder-maintenanceorder,
             equipment_id   TYPE i_equipment-equipment,
             equip_desc     TYPE i_equipment-equipmentname,
             start_date     TYPE i_maintenanceorder-basicstartdate,
             sys_status     TYPE i_maintenanceorder-maintordersystemstatus,
           END OF ty_order_equip.
    METHODS read_by_plant
      IMPORTING iv_plant         TYPE werks_d
                iv_date_from     TYPE datum
      RETURNING VALUE(rt_result) TYPE STANDARD TABLE OF ty_order_equip
      RAISING   cx_sy_open_sql_db.
ENDCLASS.

CLASS zcl_pm_order_reader IMPLEMENTATION.
  METHOD read_by_plant.
    TRY.
        SELECT mo~maintenanceorder AS order_id,
               eq~equipment        AS equipment_id,
               eq~equipmentname    AS equip_desc,
               mo~basicstartdate   AS start_date,
               mo~maintordersystemstatus AS sys_status
          FROM i_maintenanceorder AS mo
          INNER JOIN i_equipment  AS eq ON mo~equipment = eq~equipment
          WHERE mo~maintenanceplant = @iv_plant
            AND mo~basicstartdate  >= @iv_date_from
            AND mo~equipment       NE ''
          INTO TABLE @rt_result
          UP TO 1000 ROWS.
        IF sy-subrc NE 0.
          MESSAGE |Plant { iv_plant } 정비 오더 없음| TYPE 'S'.
        ENDIF.
      CATCH cx_sy_open_sql_db INTO DATA(lo_ex).
        RAISE EXCEPTION lo_ex.
    ENDTRY.
  ENDMETHOD.
ENDCLASS.

INNER JOIN 시 설비가 없는 오더는 결과에서 제외됩니다. 전체를 보려면 LEFT OUTER JOIN을 사용하세요. cx_sy_open_sql_db 예외를 잡아 DB 장애를 상위로 전파하고, UP TO 1000 ROWS로 메모리를 보호합니다.

실전 예제 3단계 — 프로덕션 패턴(성능, 보안, 테스트)

운영 시스템에서는 권한 체크, 상태 필터링, 대용량 패키지 처리가 필요합니다.

CLASS zcl_pm_order_prod DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    CONSTANTS c_pkg_size TYPE i VALUE 500.
    METHODS fetch_by_status
      IMPORTING iv_plant  TYPE werks_d
                iv_status TYPE string
      EXPORTING et_orders TYPE STANDARD TABLE.
ENDCLASS.

CLASS zcl_pm_order_prod IMPLEMENTATION.
  METHOD fetch_by_status.
    DATA: lt_chunk TYPE TABLE OF i_maintenanceorder.
    CLEAR et_orders.
    AUTHORITY-CHECK OBJECT 'M_AUFK_WBS'
      ID 'ACTVT' FIELD '03'.
    IF sy-subrc NE 0.
      RAISE EXCEPTION TYPE cx_abap_invalid_value.
    ENDIF.
    SELECT maintenanceorder, equipment, functionallocation,
           maintordersystemstatus, basicstartdate, priority
      FROM i_maintenanceorder
      WHERE maintenanceplant      = @iv_plant
        AND maintordersystemstatus LIKE @( |%{ iv_status }%| )
      INTO TABLE @lt_chunk
      PACKAGE SIZE c_pkg_size.
      APPEND LINES OF lt_chunk TO et_orders.
    ENDSELECT.
  ENDMETHOD.
ENDCLASS.

PACKAGE SIZE로 대용량 데이터를 청크 단위로 처리해 메모리 폭주를 방지합니다. maintordersystemstatus는 'I0002 REL' 형식의 복합 문자열이므로 LIKE '%REL%' 패턴을 씁니다. 더 정밀한 필터링이 필요하면 I_SystemStatus와 JOIN하세요.

자주 만나는 실수와 트러블슈팅

Q1. SELECT 결과가 0건입니다. maintenanceplant와 maintenanceordertype 조합이 실제 데이터와 일치하는지 확인하세요. 정비 플랜트(IWERK)와 유지보수계획공장(MaintPlanningPlant)이 다를 수 있습니다. SE16에서 AUFK-AUART, AFIH-IWERK를 직접 확인하세요.

Q2. equipment 필드가 비어있습니다. 기능위치(FunctionalLocation)에만 발행된 오더나 일반 정비 오더는 EQUNR이 빈 값입니다. INNER JOIN하면 이런 오더가 제외되므로 전체 오더가 필요하면 LEFT OUTER JOIN을 사용하세요.

Q3. 운영 조회가 느립니다. 권장 필터 순서: (1) maintenanceplant (2) maintenanceordertype (3) 기간. 설비 ID 단독 조회는 AFIH-EQUNR 인덱스를 명시적으로 유도하세요. ST05 SQL Trace로 실제 실행 계획을 검증하세요. maintordersystemstatus LIKE 조건은 풀스캔 위험이 있으므로 빈도가 높으면 별도 인덱스 추가를 검토하세요.

이어서 살펴보면 좋은 주제

I_MaintenanceOrder를 익혔다면 다음을 확장할 수 있습니다. 첫째, I_MaintenanceOrderOperation으로 작업(Operation) 단위 인력/시간 분析. 둘째, I_MaintNotification으로 정비 통보-오더 연결 관계 분析. 셋째, C_MaintenanceOrderTP를 활용한 Fiori 앱 연동. 넷째, RAP 기반 커스텀 OData 서비스 노출. 다섯째, Embedded Analytics CDS Analytical Query로 MTBF/MTTR 대시보드 구축.

더 깊게 읽어볼 만한 자료

  • SAP S/4HANA On-Premise — Plant Maintenance 컴포넌트 문서
  • help.sap.com — ABAP CDS Development Guide(Released CDS Views)
  • SAP API Business Hub — Maintenance Order API 문서
  • SAP Community — PM/EAM 태그 기술 블로그

댓글 0

아직 댓글이 없습니다.