이 글에서 다루는 내용
ECC에서 S/4HANA로 넘어온 회계 담당자와 ABAP 개발자가 가장 먼저 마주치는 변화는 "테이블이 다 어디 갔지?"라는 당혹감입니다. 이 글은 ACDOCA 기반 Universal Journal이 ECC 회계 구조를 어떻게 바꿨는지 3가지 관점(테이블 통합, FI-CO 통합, 리포팅 방식)으로 정리하고, 실제 CDS View와 ABAP 예제로 회계 리포트를 만드는 과정을 단계별로 보여줍니다.
- ECC의 집계/인덱스 테이블이 사라진 이유와 ACDOCA의 구조 이해
- FI와 CO가 하나의 원장으로 합쳐지면서 달라진 계정 체계 파악
- ACDOCA 직접 조회 → CDS View 집계 → 권한 제어까지 3단계 실전 예제 작성
- BSEG·GLT0 등 레거시 테이블 호환성 함정 회피
미리 알아두면 좋은 것
ECC 기준 FI 전표 구조(BKPF 헤더 + BSEG 라인)와 원가센터·손익 개념을 알고 있으면 비교 포인트가 명확해집니다. ABAP Open SQL 기본 문법과 CDS View의 DEFINE VIEW ENTITY 구문을 한 번이라도 작성해 본 경험이 있다면 예제 코드를 그대로 따라 할 수 있습니다.
환경과 준비물
이 글의 예제는 다음 환경을 기준으로 작성했습니다.
- SAP S/4HANA 2023 On-Premise (2021 이상이면 대부분 동일하게 동작하며, S/4HANA Cloud Public Edition에서는 릴리스된 CDS 인터페이스 뷰 사용이 권장됩니다)
- ABAP Development Tools(ADT) — CDS View Entity 작성용. SE80에서는 CDS 편집이 불가능합니다
- 권한: ACDOCA 조회를 위한 개발/QA 시스템 접근, 트랜잭션
SE16H또는 ADT Data Preview - 비교 확인용으로 ECC 6.0 EhP 시스템이 있다면 GLT0, COEP 테이블을 함께 열어보는 것을 권장합니다
일반적으로 프로덕션 ACDOCA는 수억 건 이상이므로, 예제 실행은 반드시 개발 시스템에서 진행하세요.
핵심 개념 — ECC 대비 3가지 변화
Universal Journal을 한 문장으로 비유하면 "여러 부서가 각자 쓰던 장부를 하나의 초대형 엑셀 시트로 합친 것"입니다. ECC 시절에는 같은 전표 하나가 FI 원장(FAGLFLEXA), 관리회계(COEP), 자산회계(ANEP), 자재원장(MLIT)에 각각 따로 기록됐고, 월말마다 이들을 맞추는 조정(reconciliation) 작업이 필요했습니다. S/4HANA에서는 이 모든 라인이 ACDOCA 단일 테이블에 기록됩니다.
변화 1: 집계·인덱스 테이블의 제거. ECC는 디스크 DB 성능 한계 때문에 GLT0(총계정 합계), BSIS/BSAS(미결/반제 인덱스), COSS/COSP(CO 합계) 같은 중복 테이블을 미리 만들어 뒀습니다. HANA 인메모리 컬럼 스토어에서는 수억 건 집계가 실시간으로 가능하므로 이 테이블들이 물리적으로 사라지고, 기존 프로그램을 위한 Compatibility View(예: V_GLT0)로 대체됐습니다. 데이터는 한 곳에만 존재하고, 합계는 조회 시점에 계산됩니다.
변화 2: FI-CO의 실질적 통합. ECC에서 별도 마스터였던 2차 원가요소(secondary cost element)가 S/4HANA에서는 G/L 계정 마스터(계정 유형 S)로 통합됐습니다. 배부·정산 같은 CO 내부 거래도 ACDOCA에 전표로 기록되므로, ECC의 조정원장(reconciliation ledger)과 KALC 같은 조정 트랜잭션이 필요 없어졌습니다. 회계 관점에서 FI 손익과 CO 손익이 "원천에서부터" 일치합니다.
변화 3: 리포팅 패러다임의 전환. ECC 리포트가 "미리 집계된 테이블을 읽는 방식"이었다면, S/4HANA는 CDS View로 ACDOCA를 조회 시점에 집계하는 방식입니다. ACDOCA는 원장(RLDNR), 회사코드(RBUKRS), 계정(RACCT), 원가센터(RCNTR), 손익센터(PRCTR), 세그먼트까지 350개 이상의 필드를 한 라인에 담고 있어, 어떤 차원으로든 즉시 드릴다운이 가능합니다. Fiori의 재무 앱 대부분이 이 구조 위에서 동작합니다.
실전 코드 3단계
1단계 — ACDOCA 기본 조회로 구조 감 잡기
먼저 특정 회사코드의 당기 손익 계정 라인을 직접 조회해 봅니다. ECC에서 BSEG + COEP를 각각 읽던 것이 SELECT 한 번으로 끝납니다.
" S/4HANA 2023: 0L(주원장) 기준 손익 라인 조회 예제
SELECT rldnr, rbukrs, gjahr, belnr, docln,
racct, " G/L 계정 (원가요소 통합)
rcntr, " 원가센터
prctr, " 손익센터
hsl " 회사코드 통화 금액 (부호 포함)
FROM acdoca
WHERE rldnr = '0L'
AND rbukrs = '1000'
AND gjahr = '2026'
AND koart = 'S' " 계정 유형: G/L
INTO TABLE @DATA(lt_lines)
UP TO 100 ROWS.
주의할 점: ECC BSEG의 차대변 구분(SHKZG)과 달리 ACDOCA의 금액 필드(HSL/KSL/TSL)는 부호로 차대변을 표현합니다. 대변이면 음수입니다. 또한 DOCLN은 6자리라 BSEG의 BUZEI(3자리)와 매핑이 1:1이 아닐 수 있습니다.
2단계 — CDS View로 월별 원가센터 손익 리포트 만들기
실무 시나리오: 경영지원팀이 "원가센터별 월별 비용 집계"를 요청했습니다. ECC라면 COSS/COSP를 읽었겠지만, S/4HANA에서는 CDS View로 온더플라이 집계를 만듭니다.
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: '원가센터 월별 비용 집계'
define view entity ZFI_CC_MONTHLY_EXP
as select from acdoca
{
key rldnr as Ledger,
key rbukrs as CompanyCode,
key rcntr as CostCenter,
key fiscyearper as FiscalYearPeriod,
racct as GLAccount,
@Semantics.amount.currencyCode: 'CompanyCodeCurrency'
sum( hsl ) as AmountInCoCodeCrcy,
rhcur as CompanyCodeCurrency
}
where rldnr = '0L'
and koart = 'S'
and rcntr is not initial
group by rldnr, rbukrs, rcntr, fiscyearper, racct, rhcur
이 뷰를 소비하는 ABAP 리포트에는 에러 처리와 로깅을 넣습니다.
TRY.
SELECT costcenter, fiscalyearperiod,
SUM( amountincocodecrcy ) AS total_exp
FROM zfi_cc_monthly_exp
WHERE companycode = @p_bukrs
AND fiscalyearperiod BETWEEN @lv_from AND @lv_to
GROUP BY costcenter, fiscalyearperiod
INTO TABLE @DATA(lt_report).
IF lt_report IS INITIAL.
go_log->add_msg( iv_type = 'W'
iv_text = |{ p_bukrs } 기간 내 집계 대상 없음| ).
ENDIF.
CATCH cx_sy_open_sql_db INTO DATA(lx_db).
go_log->add_msg( iv_type = 'E' iv_text = lx_db->get_text( ) ).
RAISE EXCEPTION TYPE zcx_fi_report EXPORTING previous = lx_db.
ENDTRY.
3단계 — 프로덕션 대비: 권한 제어와 성능
프로덕션에서는 두 가지가 필수입니다. 첫째, DCL(Access Control)로 회사코드 권한을 뷰 레벨에서 강제합니다. 이렇게 하면 뷰를 어디서 소비하든 F_BKPF_BUK 권한이 자동 적용됩니다.
@EndUserText.label: '회사코드 권한 제어'
@MappingRole: true
define role ZFI_CC_MONTHLY_EXP {
grant select on ZFI_CC_MONTHLY_EXP
where ( CompanyCode ) = aspect pfcg_auth(
F_BKPF_BUK, BUKRS, ACTVT = '03' );
}
둘째, 성능입니다. ACDOCA 조회는 항상 RLDNR, RBUKRS, GJAHR(또는 FISCYEARPER)를 WHERE에 포함해 파티션 프루닝이 동작하게 하는 것이 일반적인 권장 사항입니다. SELECT *는 350개 이상 컬럼을 모두 읽으므로 컬럼 스토어 이점을 갉아먹습니다. 마지막으로 CDS 테스트 더블 프레임워크로 집계 로직을 검증합니다.
METHOD test_monthly_aggregation.
cl_cds_test_environment=>create(
i_for_entity = 'ZFI_CC_MONTHLY_EXP' )->insert_test_data(
i_data = lt_mock_acdoca ).
SELECT SINGLE amountincocodecrcy
FROM zfi_cc_monthly_exp
WHERE costcenter = 'CC1000'
INTO @DATA(lv_sum).
cl_abap_unit_assert=>assert_equals( act = lv_sum exp = 70 ).
ENDMETHOD.
자주 걸리는 함정과 FAQ
Q1. BSEG는 완전히 사라졌나요? 아닙니다. BSEG는 S/4HANA에서도 물리 테이블로 남아 있는 "엔트리 뷰"이고, ACDOCA가 총계정원장 뷰입니다. 다만 BSIS/BSAS/BSID/BSAD 같은 인덱스 테이블은 Compatibility View로만 존재하므로, 신규 개발에서 이들을 조회하면 내부적으로 ACDOCA를 읽어 성능이 기대와 다를 수 있습니다.
Q2. ECC에서 옮겨온 Z 리포트가 GLT0을 읽는데 왜 동작하나요? 마이그레이션 시 Compatibility View가 같은 이름으로 리다이렉트해 주기 때문입니다. 동작은 하지만 조회 시점 집계가 매번 일어나므로, 대량 조회 프로그램은 CDS 기반으로 재작성하는 것이 권장됩니다.
Q3. CO 문서만 뽑고 싶은데 COEP를 조회해도 되나요? 실적 라인은 ACDOCA로 이동했고 COEP에는 통계·특수 항목만 남습니다. 실적은 ACDOCA에서 CO_BELNR(CO 문서번호) 필드로 추적하는 편이 정확합니다.
Q4. 금액이 ECC 리포트와 부호가 반대로 나옵니다. SHKZG 기반 로직을 그대로 이식했을 가능성이 큽니다. ACDOCA는 부호 있는 금액이므로 IF shkzg = 'H'. hsl = hsl * -1. 같은 변환 코드를 제거해야 이중 반전이 없어집니다.
이어서 보면 좋은 주제
Universal Journal 구조를 이해했다면 다음 주제로 확장해 보세요. 시뮬레이션·관리 조정용 Extension Ledger, 예측 회계를 담는 ACDOCP 테이블, SAP이 제공하는 릴리스된 인터페이스 뷰 I_JournalEntryItem 기반 개발, 그리고 Fiori 앱 "Trial Balance"와 임베디드 애널리틱스가 자연스러운 다음 코스입니다. 그룹 결산까지 본다면 Group Reporting의 ACDOCU도 같은 설계 철학을 공유합니다.
더 읽어볼 자료
댓글 0
아직 댓글이 없습니다.