개요 및 이번 글에서 다루는 범위
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
아직 댓글이 없습니다.