개요 및 이번 예제에서 다룰 내용
SAP S/4HANA의 고정자산(FI-AA) 회계에서 감가상각은 단순히 자산의 가치 하락을 기록하는 것이 아니라, 회계연도 마감과 재무제표 신뢰성을 좌우하는 핵심 프로세스입니다. I_AssetDepreciation은 자산별·감가상각영역(Depreciation Area)별·회계기간(Fiscal Period)별로 계획 감가상각(Planned Depreciation)과 실제 전기된 감가상각(Posted Depreciation)을 동시에 조회할 수 있는 표준 Basic CDS View입니다. 이 글에서는 해당 View의 구조를 해부하고, 계획값과 실제값의 차이(Gap)를 분석하는 실전 시나리오를 단계별로 구현합니다.
- I_AssetDepreciation의 컬럼 구조와 키 필드 이해
- 계획 감가상각 vs 전기 감가상각의 차이 인식
- 월별 차이 분석을 위한 Composite CDS View 작성
- RAP 기반 서비스 노출 및 성능 튜닝 포인트 파악
- 흔히 발생하는 단위(Currency) 불일치 트러블슈팅
먼저 알고 있어야 할 배경
이 글은 ABAP CDS View Entity 기본 문법(define view entity, association, annotation)을 이해하고 있다고 가정합니다. 또한 FI-AA의 핵심 마스터(자산 마스터 ANLA/ANLB, 감가상각영역 T093) 및 ANLC(자산 가치) 테이블 구조에 대한 개념적 이해가 있어야 합니다. SAP S/4HANA 1909 이상에서 도입된 신자산회계(New Asset Accounting) 기준으로 설명합니다.
실습 환경 및 사전 준비
이 글의 예제는 다음 환경에서 검증되었습니다. 시스템 버전이 다를 경우 일부 필드명이나 어노테이션 동작이 다를 수 있으므로 SE11/ADT의 Data Preview로 사전에 확인할 것을 권장합니다.
- SAP S/4HANA 2022 (OP) / S/4HANA Cloud Public Edition 2402
- ABAP Development Tools (ADT) for Eclipse 2023-12 이상
- 권한 객체:
S_ANLA_BUK(Company Code 단위),S_DEVELOP(View 생성) - 샘플 데이터: 최소 1개 회계연도 이상 감가상각 시뮬레이션(AFAR) 또는 실제 전기(AFAB)가 수행된 자산
- 테스트 도구: ADT Data Preview, RAP Service Binding Preview, Postman(OData 조회 시)
S/4HANA Cloud Private Edition에서는 일부 확장 필드(예: 사용자 정의 감가상각영역)가 자동 노출되지 않을 수 있으므로 Custom CDS Extension(
extend view entity) 사용을 권장합니다.
핵심 개념 — 계획값과 전기값은 왜 다른가
고정자산 감가상각을 처음 접하는 개발자가 가장 헷갈리는 부분이 바로 "계획(Planned)"과 "전기(Posted)"의 분리입니다. 회계적 비유로 풀자면, 계획 감가상각은 "이번 달 청구될 예정인 카드 결제액"이고, 전기 감가상각은 "실제로 통장에서 빠져나간 금액"입니다. 둘은 정상적인 경우 일치해야 하지만, 마감 전 미전기, 자산 가치 조정(Write-up/Write-down), 사용자 추가 감가상각 입력 등으로 인해 차이가 생깁니다.
I_AssetDepreciation은 이 두 가지 값을 같은 행에 나란히 제공하는 것이 특징입니다. 데이터 소스 측면에서는 ANLP(자산 감가상각 전기)와 ANEP(자산 라인 아이템)을 조합한 형태이며, 키는 일반적으로 다음과 같이 구성됩니다.
CompanyCode— 회사 코드(BUKRS)MasterFixedAsset— 메인 자산 번호(ANLN1)FixedAsset— 자산 하위 번호(ANLN2)FixedAssetYearOfDepreciation— 감가상각 연도FixedAssetPeriod— 회계 기간(월)DepreciationArea— 감가상각 영역(예: 01=장부, 15=세무, 30=IFRS)
그리고 핵심 수치 필드는 두 쌍으로 나뉩니다.
- 계획 측:
PlannedOrdinaryDeprAmtInCoCodeCrcy,PlannedSpecialDeprAmtInCoCodeCrcy,PlannedUnplndDeprAmtInCoCodeCrcy - 전기 측:
OrdinaryDeprAmountInCoCodeCrcy,SpecialDeprAmountInCoCodeCrcy,UnplndDeprAmountInCoCodeCrcy
도식으로 표현하면 다음과 같은 흐름입니다.
[자산 마스터 ANLA] --(취득가)--> [감가상각 시뮬레이션 AFAR]
|
v
[Planned Depreciation]
|
(월별 전기 프로그램 AFAB)
v
[Posted Depreciation]
|
I_AssetDepreciation = 두 값 + Delta
여기서 Delta(차액)는 별도 필드로 제공되지 않으므로, 다음 예제에서 직접 계산 필드로 만들어 분석할 것입니다.
실전 예제 1단계 — 기본 조회로 구조 파악
먼저 가장 단순한 형태로 회사 코드와 회계연도만으로 자산별 감가상각 데이터를 추출합니다. 목적은 컬럼 분포와 데이터 양 감을 잡는 것입니다.
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Asset Depreciation - Basic Read'
define view entity ZC_AssetDeprBasic
as select from I_AssetDepreciation
{
key CompanyCode,
key MasterFixedAsset,
key FixedAsset,
key FixedAssetYearOfDepreciation,
key FixedAssetPeriod,
key DepreciationArea,
PlannedOrdinaryDeprAmtInCoCodeCrcy as PlannedOrdinaryAmt,
OrdinaryDeprAmountInCoCodeCrcy as PostedOrdinaryAmt,
CompanyCodeCurrency
}
ADT에서 Data Preview를 실행해 보면, 한 자산이 12개 행(1월~12월)으로 분리되어 나오는 것을 확인할 수 있습니다. 만약 한 자산에 대해 감가상각영역이 3개(장부/세무/IFRS) 설정되어 있다면 한 회계연도당 36개 행이 생성됩니다. 이 점이 성능 설계의 출발점입니다.
실전 예제 2단계 — 계획 대 실제 차이 분석(실무 시나리오)
월말 마감 담당자가 "이번 달 계획대로 전기되지 않은 자산만 골라내고 싶다"고 요청하는 경우가 빈번합니다. 이때 핵심은 (1) 차액 계산 필드 추가, (2) 차액이 0이 아닌 행만 필터, (3) 자산 마스터 정보(설명, 자산 클래스)를 조인하는 것입니다.
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Depreciation Gap Analysis'
@Metadata.allowExtensions: true
define view entity ZC_DeprGapAnalysis
as select from I_AssetDepreciation as Depr
association [0..1] to I_FixedAsset as _Asset
on $projection.CompanyCode = _Asset.CompanyCode
and $projection.MasterFixedAsset = _Asset.MasterFixedAsset
and $projection.FixedAsset = _Asset.FixedAsset
{
key Depr.CompanyCode,
key Depr.MasterFixedAsset,
key Depr.FixedAsset,
key Depr.FixedAssetYearOfDepreciation,
key Depr.FixedAssetPeriod,
key Depr.DepreciationArea,
_Asset.FixedAssetDescription as AssetName,
_Asset.AssetClass as AssetClass,
Depr.PlannedOrdinaryDeprAmtInCoCodeCrcy as PlannedAmt,
Depr.OrdinaryDeprAmountInCoCodeCrcy as PostedAmt,
@Semantics.amount.currencyCode: 'CompanyCodeCurrency'
cast( Depr.PlannedOrdinaryDeprAmtInCoCodeCrcy
- Depr.OrdinaryDeprAmountInCoCodeCrcy
as abap.curr(23,2) ) as DeprGapAmt,
case when Depr.OrdinaryDeprAmountInCoCodeCrcy = 0
and Depr.PlannedOrdinaryDeprAmtInCoCodeCrcy <> 0
then 'NOT_POSTED'
when abs( Depr.PlannedOrdinaryDeprAmtInCoCodeCrcy
- Depr.OrdinaryDeprAmountInCoCodeCrcy ) > 0.01
then 'MISMATCH'
else 'OK'
end as GapStatus,
Depr.CompanyCodeCurrency,
_Asset
}
where Depr.DepreciationArea = '01'
여기서 두 가지 설계 포인트를 짚어봅니다. 첫째, cast로 차액을 abap.curr(23,2)로 명시적으로 변환하여 OData 출력 시 통화 형식 오류를 예방합니다. 둘째, case 식으로 상태 코드(NOT_POSTED/MISMATCH/OK)를 부여하여 프런트엔드(Fiori Elements)에서 색상 표시나 필터링을 쉽게 할 수 있게 했습니다. 0.01의 허용치는 반올림 오차에 대비한 일반적인 임계값입니다.
실전 예제 3단계 — 프로덕션 준비(성능·검증·서비스 노출)
운영에서 자산이 수만 건이 넘는 회사 코드를 다룰 때는 위 View를 그대로 노출하면 응답이 느려집니다. 다음 세 가지를 함께 적용합니다.
- 연도/회사코드 파라미터화로 인덱스 효과 극대화
- RAP Service Definition + Service Binding으로 OData V4 노출
- ABAP Unit으로 차액 계산 로직 회귀 검증
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Depr Gap Analysis - Parameterized'
define view entity ZC_DeprGapByPeriod
with parameters
p_CompanyCode : bukrs,
p_FiscalYear : gjahr
as select from ZC_DeprGapAnalysis
{
key CompanyCode,
key MasterFixedAsset,
key FixedAsset,
key FixedAssetYearOfDepreciation,
key FixedAssetPeriod,
key DepreciationArea,
AssetName,
AssetClass,
PlannedAmt,
PostedAmt,
DeprGapAmt,
GapStatus,
CompanyCodeCurrency
}
where CompanyCode = $parameters.p_CompanyCode
and FixedAssetYearOfDepreciation = $parameters.p_FiscalYear
이어서 OData 서비스를 노출합니다.
// Service Definition: ZSD_DEPR_GAP
@EndUserText.label: 'Asset Depreciation Gap Service'
define service ZSD_DEPR_GAP {
expose ZC_DeprGapByPeriod as DeprGap;
}
Service Binding은 ODATA_V4_UI 타입으로 생성하고, Preview에서 p_CompanyCode='1010'&p_FiscalYear=2026 형태로 호출하면 즉시 검증할 수 있습니다. 마지막으로 차액 계산 로직에 대한 단위 테스트는 다음과 같이 ABAP Unit으로 작성합니다.
CLASS ltc_depr_gap DEFINITION FINAL FOR TESTING
DURATION SHORT
RISK LEVEL HARMLESS.
PRIVATE SECTION.
METHODS:
mismatch_should_be_flagged FOR TESTING RAISING cx_static_check.
ENDCLASS.
CLASS ltc_depr_gap IMPLEMENTATION.
METHOD mismatch_should_be_flagged.
SELECT SINGLE GapStatus, DeprGapAmt
FROM zc_deprgapbyperiod( p_companycode = '1010',
p_fiscalyear = '2026' )
WHERE MasterFixedAsset = '000000200001'
AND FixedAssetPeriod = '003'
INTO @DATA(ls_result).
cl_abap_unit_assert=>assert_equals(
exp = 'MISMATCH'
act = ls_result-GapStatus
msg = '3월 자산 200001의 차액 상태가 MISMATCH로 분류되어야 함' ).
ENDMETHOD.
ENDCLASS.
보안 측면에서는 @AccessControl.authorizationCheck: #CHECK를 유지하여 사용자가 권한을 가진 회사 코드만 조회되도록 DCL(Data Control Language)이 자동 적용되게 합니다. 로깅은 RAP의 Application Log 또는 BAL을 활용하여 GapStatus가 NOT_POSTED인 자산 ID를 일별로 수집하는 것을 권장합니다.
흔한 실수와 트러블슈팅 가이드
실무에서 반복적으로 발생하는 문제를 FAQ 형태로 정리합니다.
Q1. 같은 자산인데 합계가 두 배로 나옵니다.
A. 감가상각영역(DepreciationArea) 필터를 누락한 경우가 대부분입니다. I_AssetDepreciation은 영역별로 행이 분리되므로 합계 집계 시 반드시 where DepreciationArea = '01' 같은 조건을 넣거나, 영역별 GROUP BY로 분리해야 합니다.
Q2. PlannedAmt와 PostedAmt가 모두 0인 행이 다수 보입니다.
A. 자산이 해당 기간에 활성 상태가 아니거나(미취득/폐기 후), 감가상각 키(Depreciation Key)가 0000인 경우입니다. I_FixedAsset 또는 I_FixedAssetValuation의 자산 활성화일(AssetCapitalizationDate)과 폐기일을 조인하여 사전 필터링하면 깔끔해집니다.
Q3. OData에서 차액 컬럼이 문자열로 출력됩니다.
A. @Semantics.amount.currencyCode 어노테이션이 누락되었거나 currency 필드가 같은 select list에 포함되지 않은 경우입니다. 통화 필드는 반드시 같은 projection에 포함해야 합니다.
Q4. 권한 검사 후 데이터가 전혀 나오지 않습니다.
A. S_ANLA_BUK(자산 회사 코드)와 S_ANLA_ANK(자산 클래스) 권한 객체가 분리되어 있어, 둘 다 충족하지 못하면 결과가 비어 보입니다. SU53으로 권한 트레이스를 먼저 확인하는 것이 빠릅니다.
Q5. 외화 자산의 환산 금액이 필요합니다.
A. I_AssetDepreciation은 회사 코드 통화(CoCodeCrcy) 외에도 영역 통화(InAreaCrcy) 컬럼을 제공합니다. 환산 로직을 직접 구현하기보다 영역 통화 컬럼을 활용하는 편이 일관성 있고 안전합니다.
이어서 탐구하면 좋은 주제
차액 분석 모델이 안정화되면 다음 주제로 확장하는 것을 권장합니다. 첫째, I_FixedAssetValuation과 결합한 NBV(Net Book Value) 흐름 추적, 둘째, Analytical Query(@Analytics.query: true)로 만들어 SAP Analytics Cloud에서 실시간 대시보드 구성, 셋째, RAP Managed BO를 활용한 차액 자산에 대한 워크플로 트리거 자동화입니다. 또한 신자산회계의 Parallel Ledger와 Depreciation Area 매핑(T093B)을 깊게 이해하면 영역별 차이 원인 분석이 훨씬 쉬워집니다.
도움이 될 외부 자료
- SAP Help Portal — Asset Accounting (FI-AA) in S/4HANA Cloud
- SAP Help Portal — S/4HANA On-Premise: Fixed Asset CDS Views
- SAP Help Portal — ABAP RESTful Application Programming Model
- SAP API Business Hub — Fixed Asset OData Services 카탈로그
- SAP Community — ABAP & CDS 토픽 토론
- SAP Blogs — New Asset Accounting 관련 글 모음
댓글 0
아직 댓글이 없습니다.