ABAP

ABAP 개발자 90%가 모르는 I_FixedAsset 활용 #shorts #SAP #ABAP

▶ YouTube에서 보기

개요 및 도입

SAP S/4HANA의 고정 자산 관리(FI-AA) 모듈은 토지, 건물, 기계, 차량 등 기업의 장기 보유 자산을 회계적으로 추적하는 핵심 영역입니다. 이 글에서는 ANLA(자산 마스터 헤더 테이블) 위에 구축된 표준 CDS 뷰인 I_FixedAsset을 깊이 있게 다룹니다. 단순한 SELECT 예제를 넘어, 평가 영역(Depreciation Area) 구조, 회사 코드 단위 분리 키, 자산 서브 넘버 처리, 그리고 Embedded Analytics와 RAP 서비스에 연결하는 실전 패턴까지 단계별로 살펴봅니다.

  • ANLA / ANLB / ANLC 핵심 테이블 구조와 I_FixedAsset 뷰의 매핑 관계 파악
  • 자산 마스터 키(BUKRS + ANLN1 + ANLN2)와 평가 영역(AFABE) 분리 원리 이해
  • I_FixedAsset과 I_FixedAssetValuation 어소시에이션 활용 방법 습득
  • S/4HANA Cloud Public/Private Edition에서의 가용성과 권한 객체 적용
  • 실무 보고서, OData 노출, ABAP RAP BO 컨슈머로 확장하는 패턴 학습

알아두면 좋은 사전 배경

이 글은 ABAP CDS View 기본 문법(define view entity, association, annotation), FI-AA 모듈의 기본 흐름(자산 취득 → 감가상각 → 매각/폐기), 그리고 Eclipse ADT 환경에서의 CDS 개발 경험이 있는 독자를 대상으로 합니다. SE16에서 ANLA, ANLB, ANLC 테이블을 한 번이라도 조회해 본 경험이 있다면 본문 내용을 보다 입체적으로 이해할 수 있습니다.

환경 및 버전 준비물

본문 예제는 다음 환경을 기준으로 검증되었습니다. 사용 중인 시스템에 따라 뷰 가용성과 필드 셋이 다를 수 있으니 사전 확인이 권장됩니다.

  • SAP S/4HANA 2022 (On-Premise FPS02) 또는 S/4HANA Cloud Private Edition 2023
  • ABAP Platform 2022 이상 (define view entity 문법 지원 필요)
  • Eclipse ADT (ABAP Development Tools) 3.34 이상
  • FI-AA 모듈이 활성화된 회사 코드(BUKRS) 최소 1개
  • 권한 객체: S_ANLA_BUK (회사 코드 단위 자산 조회), S_DEVELOP (개발)
  • 테스트 데이터: 평가 영역 01(장부), 15(세무) 최소 2개가 설정된 차트 오브 디프리시에이션
S/4HANA Cloud Public Edition에서는 일부 ANLx 테이블에 직접 접근이 제한되므로, 반드시 I_FixedAsset 및 관련 published CDS 뷰를 통해서만 접근하는 것이 권장됩니다.

핵심 개념 — ANLA, 평가 영역, 그리고 CDS 레이어

FI-AA의 데이터 모델은 "마스터 vs 트랜잭션", "회계 독립 vs 평가 영역 종속"이라는 두 축으로 분리되어 있습니다. 이 구조를 정확히 이해해야 I_FixedAsset이 왜 ANLA만으로 충분하지 않은지, 왜 평가 영역 뷰가 별도로 존재하는지 납득할 수 있습니다.

  • ANLA — 자산 마스터 헤더. 자산 클래스(ANLKL), 취득일(AKTIV), 비활성화일(DEAKT), 코스트 센터, 위치 등 평가 영역과 무관한 속성을 보관합니다. 키는 MANDT + BUKRS + ANLN1(메인 자산 번호) + ANLN2(서브 넘버).
  • ANLB — 평가 영역별 마스터. 동일 자산이라도 장부 감가상각과 세무 감가상각의 내용 연수, 상각 키가 다를 수 있어 AFABE(평가 영역) 키로 분리됩니다.
  • ANLC — 평가 영역별 연도 누계값. 취득가, 누적 상각, 잔존가 등 회계 마감 단위 수치를 담습니다.

비유하자면 ANLA는 "차량 자체의 등록증"이고, ANLB는 "보험사별 가입 조건", ANLC는 "보험사별 누적 청구 내역"입니다. 한 대의 차량(ANLA)에 여러 보험(평가 영역)이 묶여 있는 셈입니다.

I_FixedAsset은 ANLA를 기반으로 하되, 코드성 필드들을 텍스트와 결합하고 association으로 회사 코드, 자산 클래스, 코스트 센터, 평가 영역 뷰들을 노출합니다. 따라서 I_FixedAsset 단독으로는 취득가나 누적 상각 같은 "금액" 정보가 나오지 않으며, 반드시 _Valuation 또는 I_FixedAssetValuation 어소시에이션을 거쳐야 합니다. 이 분리 원리는 S/4HANA가 평가 영역 다중성을 강제하는 IFRS/로컬 GAAP 병행 결산 요구를 반영한 결과입니다.

Annotation 측면에서 I_FixedAsset은 @VDM.viewType: #BASIC으로 선언되어 있어 직접 분석용으로 쓰기보다는 Composite 뷰의 빌딩 블록으로 사용되는 것이 일반적입니다. 분석용 큐브는 보통 C_FixedAsset 계열을 활용합니다.

실전 예제 1단계 — 회사 코드별 자산 마스터 조회

첫 단계로 특정 회사 코드의 활성 자산 목록을 자산 클래스 텍스트와 함께 가져오는 커스텀 뷰를 만들어 봅니다. 시나리오는 "법인 K100의 차량 자산 인벤토리 추출"입니다.

@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Vehicle Asset Inventory by Company'
@VDM.viewType: #CONSUMPTION
define view entity ZC_VehicleAssetInventory
  as select from I_FixedAsset as Asset

  association [0..1] to I_AssetClass as _Class
    on $projection.AssetClass = _Class.AssetClass

{
  key Asset.CompanyCode,
  key Asset.MasterFixedAsset,
  key Asset.FixedAsset,

      Asset.AssetClass,
      _Class.AssetClassName             as AssetClassDescription,
      Asset.FixedAssetDescription       as AssetName,
      Asset.AdditionalAssetDescription  as AssetLongText,
      Asset.AssetCapitalizationDate     as CapitalizationDate,
      Asset.AssetDeactivationDate       as DeactivationDate,
      Asset.CostCenter,
      Asset.AssetLocation,

      case when Asset.AssetDeactivationDate is initial
             or Asset.AssetDeactivationDate = '99991231'
           then 'A'
           else 'I'
      end                               as ActiveStatus,

      _Class
}
where Asset.AssetClass like '31%'   // 차량 자산 클래스 범위

여기서 MasterFixedAsset은 ANLN1, FixedAsset은 ANLN2(서브 넘버)에 매핑됩니다. 메인 자산 1대당 서브 넘버 0이 기본이며, 부품/액세서리 추가 시 서브 넘버가 증가합니다. 검색 시 두 키를 함께 사용하지 않으면 중복 행이 나타날 수 있으므로 주의해야 합니다.

실전 예제 2단계 — 평가 영역과 결합한 자산 가치 리포트

다음으로 평가 영역 정보를 함께 가져옵니다. 시나리오는 "회사 코드별로 장부(평가 영역 01) 기준 취득가와 누적 상각을 표시하는 월말 리포트"입니다. 단일 평가 영역으로 필터링하여 자산 한 건당 한 행이 나오도록 보장합니다.

@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Book Value Report per Asset'
define view entity ZC_AssetBookValueReport
  with parameters
    P_FiscalYear : gjahr,
    P_AreaID     : afabe_d
  as select from I_FixedAsset as Asset

  association [0..*] to I_FixedAssetValuation as _Val
    on  $projection.CompanyCode      = _Val.CompanyCode
    and $projection.MasterFixedAsset = _Val.MasterFixedAsset
    and $projection.FixedAsset       = _Val.FixedAsset

{
  key Asset.CompanyCode,
  key Asset.MasterFixedAsset,
  key Asset.FixedAsset,

      Asset.FixedAssetDescription          as AssetName,
      Asset.AssetClass,
      Asset.AssetCapitalizationDate,

      _Val.DepreciationArea,
      _Val.AcqnAndProdnCostsPostedAmount   as AcquisitionCost,
      _Val.OrdinaryDepreciationPostedAmt   as AccumulatedDepreciation,
      _Val.NetBookValueAmtInAreaCrcy       as NetBookValue,
      _Val.AreaCurrency                    as Currency

}
where _Val.FiscalYear      = $parameters.P_FiscalYear
  and _Val.DepreciationArea = $parameters.P_AreaID

ABAP에서 호출할 때는 다음과 같이 파라미터화된 뷰를 사용합니다. SELECT 단계에서 발생할 수 있는 권한 오류, 빈 결과, 평가 영역 미존재 케이스를 함께 처리합니다.

DATA: lt_report TYPE TABLE OF zc_assetbookvaluereport,
      lv_msg    TYPE string.

TRY.
    SELECT *
      FROM zc_assetbookvaluereport( p_fiscalyear = @lv_year,
                                    p_areaid     = '01' )
      WHERE companycode = @lv_bukrs
      INTO TABLE @lt_report.

    IF sy-subrc <> 0 OR lt_report IS INITIAL.
      lv_msg = |No asset valuation rows for { lv_bukrs } / FY { lv_year }|.
      MESSAGE lv_msg TYPE 'I'.
    ENDIF.

  CATCH cx_sy_open_sql_db INTO DATA(lx_db).
    " 권한 부족 또는 뷰 파라미터 누락
    MESSAGE lx_db->get_text( ) TYPE 'E'.
ENDTRY.

로깅 측면에서는 Application Log(BAL_LOG_CREATE)나 Read-only RAP의 cl_ba_log_writer를 통해 어떤 회사 코드/회계 연도/평가 영역 조합이 호출되었는지 누적 기록하는 것이 운영 단계에서 효과적입니다.

실전 예제 3단계 — OData 노출과 성능/보안 보강

프로덕션 단계에서는 Fiori Elements 또는 외부 시스템 연계를 위해 RAP Read-only Service로 노출합니다. 평가 영역 다중 조회 시 성능과 권한이 핵심 이슈이므로 PFCG 권한 객체 매핑과 인덱스 사용을 함께 점검합니다.

@OData.publish: true
@AccessControl.authorizationCheck: #CHECK
@Search.searchable: true
@EndUserText.label: 'Asset 360 View for Controllers'
define root view entity ZC_Asset360
  as projection on ZC_AssetBookValueReport
{
  key CompanyCode,
  key MasterFixedAsset,
  key FixedAsset,

      @Search.defaultSearchElement: true
      AssetName,
      AssetClass,
      AssetCapitalizationDate,
      DepreciationArea,
      AcquisitionCost,
      AccumulatedDepreciation,
      NetBookValue,
      Currency
}
@EndUserText.label: 'Asset 360 Service'
define service ZUI_ASSET_360 {
  expose ZC_Asset360 as Asset360;
}

보안 측면에서는 DCL(Data Control Language)을 함께 적용하여 사용자가 접근 가능한 회사 코드만 필터링되도록 합니다. PFCG 권한 객체 F_BKPF_BUK 또는 S_ANLA_BUK의 BUKRS 값을 PFCG_AUTH_VALUES로 받아오는 방식이 일반적입니다.

@MappingRole: true
define role ZC_AssetBookValueReport {
  grant select on ZC_AssetBookValueReport
    where ( CompanyCode ) =
          aspect pfcg_auth( S_ANLA_BUK, BUKRS, ACTVT = '03' );
}

성능 측면에서는 (1) WHERE 절에 항상 BUKRS를 포함시켜 ANLA의 기본 인덱스를 활용, (2) 평가 영역과 FiscalYear를 단일 값으로 고정하여 ANLC의 partition pruning 활성화, (3) 대용량 추출 시에는 패키지 사이즈를 지정한 cursor 기반 SELECT 사용, (4) Embedded Analytics용으로는 @Analytics.dataCategory: #FACT 적용이 권장됩니다. 단위 테스트는 CL_CDS_TEST_ENVIRONMENT를 사용해 ANLA / ANLB / ANLC 더블을 주입하면 평가 영역 분기 로직까지 격리 테스트가 가능합니다.

자주 마주치는 함정과 해결책

실제 프로젝트에서 반복적으로 보고되는 이슈는 데이터 모델에 대한 오해에서 출발하는 경우가 많습니다.

  • 중복 행 문제 — I_FixedAsset과 평가 영역 뷰를 join할 때 DepreciationArea로 필터하지 않으면 자산 1건당 N개의 평가 영역 행이 곱해져 합계가 부풀려집니다. 항상 단일 AFABE 필터를 적용하거나 sum() + group by를 명시해야 합니다.
  • 서브 넘버 누락 — ANLN2='0000'만 조회하는 잘못된 가정이 흔합니다. 부품 자본화로 서브 넘버가 누적되므로, 자산 단위 집계 시에는 ANLN1 기준 group by가 옳습니다.
  • 비활성 자산 노출 — AssetDeactivationDate가 '99991231' 또는 초기값이면 활성, 그 외에는 폐기/매각된 자산입니다. 단순 NOT NULL 체크만으로는 부족합니다.

FAQ. Q1) S/4HANA Cloud Public Edition에서 ANLA 직접 SELECT가 막혔습니다 — Released CDS인 I_FixedAsset, I_FixedAssetValuation 등으로 우회해야 하며, Custom CDS View(KCC)를 통해 확장 필드를 추가할 수 있습니다. Q2) 평가 영역 01에 데이터가 없습니다 — 차트 오브 디프리시에이션 설정(트랜잭션 OADB)에서 회사 코드에 해당 영역이 활성화되어 있는지 확인이 필요합니다. Q3) 권한 객체를 부여했는데도 빈 결과만 나옵니다 — DCL 역할 활성화 여부, S_ANLA_BUK의 ACTVT 03(표시) 부여 여부, 그리고 사용자가 속한 PFCG 역할에 BUKRS 인스턴스 값이 실제로 채워져 있는지를 함께 점검해야 합니다.

이어서 살펴볼 만한 주제

I_FixedAsset 구조를 익혔다면 자연스러운 확장 경로는 다음과 같습니다. 첫째, I_FixedAssetValuationI_AssetPostingDocumentItem을 결합한 트랜잭션 레벨 분석. 둘째, C_FixedAssetValuesQ 큐브를 활용한 Embedded Analytics 대시보드 구성. 셋째, RAP Managed BO로 자산 마스터 변경(Asset Master Change) 시나리오 구현. 넷째, Fiori Elements List Report로 Asset 360 서비스를 시각화하고 Side Panel로 평가 영역별 비교 화면 구성. 다섯째, SAP Datasphere에 I_FixedAsset 기반 Replication Flow를 구성하여 그룹 차원의 자산 분석으로 확장하는 방향입니다.

더 깊이 있는 자료 모음

댓글 0

아직 댓글이 없습니다.