ABAP

아직도 EQUI 직접 조회? — I_Equipment 3단계 #shorts #SAP #ABAP

▶ YouTube에서 보기

개요와 이 글에서 얻어갈 것

SAP S/4HANA의 Plant Maintenance(PM) 영역에서 설비(Equipment)는 보전 계획·작업오더·측정·고장 분석의 출발점이 되는 마스터 데이터입니다. 클래식 EQUI 테이블을 직접 조회하던 방식에서 벗어나, S/4HANA는 I_Equipment를 비롯한 가상 데이터 모델(VDM, Virtual Data Model) 기반 CDS View를 권장합니다. 이 글에서는 EQUI/EQKT/EQUZ로 흩어진 설비 마스터 데이터가 I_Equipment 인터페이스 뷰로 어떻게 통합되며, 자산 위치(Functional Location)와 어떤 방식으로 연결되는지 단계별로 살펴봅니다.

  • EQUI/EQUZ/EQKT 테이블 구조와 I_Equipment의 매핑 관계 이해
  • Functional Location(IFLOT) 연계를 위한 Association 활용
  • 설비 마스터 조회용 Consumption View 작성 패턴 습득
  • 대량 설비 데이터 처리 시 성능·권한·시간의존성 처리 전략

읽기 전에 갖춰두면 좋은 배경

ABAP CDS View의 기본 문법(define view, association, annotation)과 SAP PM 모듈의 설비/기능위치 개념을 어느 정도 알고 있어야 합니다. EQUI·EQUZ가 본 테이블/시간의존 테이블로 분리되어 있다는 점, S/4HANA에서 VDM 계층이 Basic/Composite/Consumption으로 구분된다는 점을 이해하면 진입이 수월합니다. ADT(ABAP Development Tools) 사용 경험이 있다면 예제 코드를 바로 실습해볼 수 있습니다.

환경과 사전 준비 사항

본 글의 예제는 다음 환경을 기준으로 작성했습니다. 릴리스에 따라 일부 필드명과 Association 이름이 다를 수 있으므로, 실제 도입 전에는 ADT의 Data Preview와 Where-Used List로 확인하는 절차를 권장합니다.

  • SAP S/4HANA 2022 또는 2023 (On-Premise) / S/4HANA Cloud Public Edition
  • ABAP Development Tools for Eclipse 3.30 이상
  • SAP NetWeaver AS ABAP 7.57 이상, CDS DDL 지원
  • PM 모듈 활성화 (T-Code IE03로 설비 조회 가능 상태)
  • 권한: S_DEVELOP(CDS 개발), S_RFC, 설비 마스터 조회 권한(S_EQUI)

예제에서 사용할 패키지는 ZPM_ASSET_VDM으로 가정하며, 네이밍은 Z* 커스터머 네임스페이스를 따릅니다.

I_Equipment의 구조와 동작 원리

설비 마스터는 단일 테이블에 모두 들어있지 않습니다. 핵심 키와 기본 분류는 EQUI에, 설치 위치·코스트센터·플랜트와 같은 시간의존 정보는 EQUZ에, 다국어 텍스트는 EQKT에 저장됩니다. I_Equipment는 이 세 가지를 추상화 계층에서 묶어 하나의 비즈니스 엔티티로 제공하는 Interface View입니다.

비유하자면 EQUI는 자동차의 차대번호, EQUZ는 그 차의 현재 등록지·소유주 이력, EQKT는 차종 설명서에 해당합니다. I_Equipment는 이 세 가지를 한 장의 차량등록증처럼 통합해 보여줍니다.

VDM 계층에서 I_* 접두어는 Interface(또는 Basic) View를 의미하며, Reuse 가능한 표준화된 형태로 노출됩니다. I_Equipment는 보통 다음과 같은 Association을 함께 제공합니다.

  • _FunctionalLocationI_FunctionalLocation (설치된 기능위치)
  • _PlantI_Plant (보전 플랜트)
  • _CostCenterI_CostCenter (원가센터)
  • _EquipmentCategoryI_EquipmentCategory (설비 카테고리)
  • _TextI_EquipmentText (다국어 설명)

시간의존(time-dependent) 데이터는 ValidityStartDate/ValidityEndDate를 기준으로 현재 유효한 레코드가 자동 노출되도록 설계되어 있어, 개발자가 직접 EQUZ를 join하여 DATBI를 필터링할 필요가 없습니다. 이 부분이 EQUI 직접 조회 대비 가장 큰 생산성 차이를 만듭니다.

실전 예제 1단계: 기본 조회 Consumption View

가장 단순한 형태로 설비 번호, 설명, 기능위치, 플랜트 정보를 한 번에 조회하는 Consumption View를 만들어 봅니다.

@AbapCatalog.sqlViewName: 'ZCVPMEQUIP01'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Equipment Master with Location'
@VDM.viewType: #CONSUMPTION

define view ZC_PmEquipmentOverview
  as select from I_Equipment as Equip

  association [0..1] to I_FunctionalLocation as _FuncLoc
    on $projection.FunctionalLocation = _FuncLoc.FunctionalLocation

{
  key Equip.Equipment                       as EquipmentId,
      Equip.EquipmentName                   as EquipmentName,
      Equip.EquipmentCategory               as EquipmentCategory,
      Equip.TechnicalObjectType             as ObjectType,
      Equip.MaintenancePlant                as Plant,
      Equip.FunctionalLocation              as FunctionalLocation,
      _FuncLoc.FunctionalLocationName       as FunctionalLocationDesc,
      Equip.ValidityStartDate               as ValidFrom,
      Equip.ValidityEndDate                 as ValidTo,

      _FuncLoc
}

핵심 포인트는 I_FunctionalLocation과의 association을 통해 EQUZ 조인 없이도 설비가 설치된 기능위치명을 한 번에 가져온다는 점입니다. _FuncLoc를 SELECT 절에 노출하면 상위 뷰나 OData 서비스에서 다시 expand해서 사용할 수 있습니다.

실전 예제 2단계: 다국어 텍스트와 분류 결합

실무에서는 설비의 한국어/영어 설명, 카테고리 텍스트, 코스트센터 정보까지 묶어서 리포팅 백엔드로 사용하는 경우가 많습니다. 이때는 추가 association과 텍스트 조인을 함께 활용합니다.

@AbapCatalog.sqlViewName: 'ZCVPMEQUIP02'
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Equipment Reporting Composite'
@VDM.viewType: #COMPOSITE
@ClientHandling.algorithm: #SESSION_VARIABLE

define view ZC_PmEquipmentReport
  with parameters
    p_Language : abap.lang
  as select from I_Equipment as Equip

  association [0..*] to I_EquipmentText      as _Text
    on  $projection.EquipmentId = _Text.Equipment
    and _Text.Language          = $parameters.p_Language

  association [0..1] to I_CostCenter         as _CostCenter
    on  $projection.CostCenter        = _CostCenter.CostCenter
    and $projection.ControllingArea   = _CostCenter.ControllingArea

  association [0..1] to I_FunctionalLocation as _FuncLoc
    on  $projection.FunctionalLocation = _FuncLoc.FunctionalLocation

{
  key Equip.Equipment                  as EquipmentId,
      Equip.EquipmentCategory          as Category,
      Equip.MaintenancePlant           as Plant,
      Equip.FunctionalLocation         as FunctionalLocation,
      Equip.CostCenter                 as CostCenter,
      Equip.ControllingArea            as ControllingArea,
      Equip.ManufacturerPartNmbr       as PartNumber,
      Equip.ManufacturerOfAsset        as Manufacturer,

      cast(_Text.EquipmentName as abap.char(60))
                                       as EquipmentDescription,
      _CostCenter.CostCenterName       as CostCenterName,
      _FuncLoc.FunctionalLocationName  as LocationName,

      case when Equip.ValidityEndDate >= $session.system_date
           then 'A'
           else 'I'
      end                              as ActiveFlag,

      _Text,
      _CostCenter,
      _FuncLoc
}

이 단계에서 주의할 점은 다음과 같습니다.

  • 파라미터 기반 언어 처리: $session.system_language 대신 p_Language로 명시적으로 전달하면 다국어 BI 리포트에서 재사용성이 올라갑니다.
  • 유효성 플래그: 시간의존 종료일이 시스템 일자 이전이면 비활성으로 표시해 후속 분석 뷰에서 필터링이 쉬워집니다.
  • 로깅: 호출부 ABAP에서는 cl_bali_log_db_writer 또는 cl_demo_output으로 조회 결과 건수를 기록해 운영 중 추적성을 확보합니다.

실전 예제 3단계: 운영용 보안·성능 강화

실 운영 환경에서는 권한, 인덱스 활용, 데이터 캐싱을 고려해야 합니다. 아래는 DCL(Data Control Language)로 플랜트 단위 권한을 적용하고, ABAP에서 페이지네이션으로 호출하는 패턴입니다.

@EndUserText.label: 'Auth for Equipment Report'
@MappingRole: true

define role ZC_PM_EQUIPMENT_AUTH {
  grant select on ZC_PmEquipmentReport
    where (Plant) = aspect pfcg_auth(I_TPLA, WERKS, ACTVT = '03');
}
CLASS zcl_pm_equipment_reader DEFINITION
  PUBLIC FINAL CREATE PUBLIC.

  PUBLIC SECTION.
    TYPES: BEGIN OF ty_equip,
             equipment_id  TYPE equnr,
             description   TYPE char60,
             plant         TYPE werks_d,
             location_name TYPE pltxt,
           END OF ty_equip,
           tt_equip TYPE STANDARD TABLE OF ty_equip WITH EMPTY KEY.

    METHODS read_equipment
      IMPORTING iv_plant    TYPE werks_d
                iv_language TYPE sy-langu DEFAULT sy-langu
                iv_page     TYPE i        DEFAULT 1
                iv_size     TYPE i        DEFAULT 200
      RETURNING VALUE(rt_equip) TYPE tt_equip
      RAISING   cx_sy_open_sql_db.
ENDCLASS.

CLASS zcl_pm_equipment_reader IMPLEMENTATION.
  METHOD read_equipment.
    DATA(lv_offset) = ( iv_page - 1 ) * iv_size.

    SELECT EquipmentId,
           EquipmentDescription,
           Plant,
           LocationName
      FROM ZC_PmEquipmentReport( p_Language = @iv_language )
      WHERE Plant      = @iv_plant
        AND ActiveFlag = 'A'
      ORDER BY EquipmentId
      INTO TABLE @rt_equip
      OFFSET @lv_offset
      UP TO @iv_size ROWS.
  ENDMETHOD.
ENDCLASS.

운영 단계에서 권장되는 추가 조치입니다.

  • 인덱스 활용: EQUI~MATNR, EQUZ~SWERK 등 표준 인덱스를 활용할 수 있도록 WHERE 절 컬럼 순서를 맞춥니다.
  • 버퍼링 금지: I_Equipment는 일반적으로 빈번하게 갱신되므로 애플리케이션 단 캐시 사용은 신중해야 합니다.
  • 단위 테스트: cl_osql_test_environment로 EQUI/EQUZ 더블을 만들어 회귀 테스트를 구성합니다.
  • OData 노출: RAP(@ObjectModel.query.implementedBy)로 Service Binding을 만들면 Fiori Elements 리스트 리포트로 즉시 사용 가능합니다.

자주 마주치는 실수와 해결 방법

설비 마스터 CDS를 처음 다루는 개발자가 흔히 겪는 이슈와 대응을 정리합니다.

  • Q1. EQUI에는 있는데 I_Equipment에서 안 보인다? 시간의존 레코드(EQUZ DATBI) 종료일이 지나면 기본 노출에서 빠질 수 있습니다. 이력 분석이 필요하면 I_EquipmentTimeDependent 같은 보조 뷰를 검토합니다.
  • Q2. 기능위치명이 자꾸 NULL이다. Association은 LEFT OUTER로 동작하지만, 설비에 위치가 할당되지 않았을 수 있고, 또는 I_FunctionalLocation 권한이 없을 수도 있습니다. @AccessControl.authorizationCheck: #NOT_REQUIRED로 일시적으로 검증한 뒤 DCL을 보강하세요.
  • Q3. 대량 조회 시 응답이 느리다. SELECT 절에 _FuncLoc 같은 association을 전부 expand하면 join 폭이 커집니다. 필요한 컬럼만 명시적으로 노출하고, 클라이언트에서 page size를 200~500 사이로 제한하는 것이 일반적입니다.
  • Q4. 권한 오류 없이 빈 결과가 나온다. DCL의 PFCG aspect가 사용자 권한 객체와 매칭되지 않으면 결과가 자동 필터링됩니다. SU53으로 누락 권한을 확인하기보다 RSCDS_DCL_TRACE로 DCL 트레이스를 분석하는 편이 정확합니다.
  • Q5. 클라우드 환경에서 EQUI 직접 SELECT가 막혔다. S/4HANA Cloud(Public)에서는 릴리스된 CDS만 사용 가능합니다. I_Equipment가 릴리스 상태인지 ADT의 Released APIs 뷰에서 먼저 확인하고, 그렇지 않으면 Composite/Custom CDS 경로를 검토해야 합니다.

이어서 살펴보면 좋은 주제

설비 마스터를 다뤘다면 자연스럽게 다음 영역으로 확장됩니다. 기능위치 계층 구조를 다루는 I_FunctionalLocation과 그 부모-자식 association, 보전 작업오더의 I_MaintenanceOrder, 측정점/측정값을 다루는 I_MeasuringPoint·I_MeasurementDocument가 대표적입니다. 한 걸음 더 나아간다면 RAP(ABAP RESTful Application Programming Model)로 설비 정보를 조회·변경하는 OData 서비스로 묶고, Fiori Elements Object Page에 기능위치/작업오더 facet을 결합하는 패턴도 고려해볼 만합니다.

더 깊이 들어가기 위한 자료

  • SAP S/4HANA On-Premise 공식 문서 포털
  • ABAP RESTful Application Programming Model 가이드
  • SAP S/4HANA Asset Management 컴포넌트 개요
  • Virtual Data Model(VDM) 디자인 가이드
  • SAP API Business Hub: S/4HANA Cloud APIs
  • SAP Community: ABAP 토픽 페이지
  • ABAP Development Tools for Eclipse 사용자 가이드

댓글 0

아직 댓글이 없습니다.