개요 및 이 글에서 다루는 것
S/4HANA 환경에서 회계 라인 아이템을 조회할 때, 여전히 많은 개발자가 습관적으로 SELECT ... FROM bseg를 작성합니다. 하지만 S/4HANA에서는 이 접근이 매우 위험합니다. BSEG는 여전히 존재하지만, ACDOCA(Universal Journal)라는 새로운 진실의 원천이 도입되었고, 회계 데이터 구조는 CDS 뷰를 통해 노출되는 것이 권장되는 방식입니다. 이 글에서는 I_AccountingDocumentItem CDS 뷰를 중심으로 안전하고 성능 좋은 회계 라인 조회 방법을 정리합니다.
- BSEG 직접 조회가 위험한 이유(클러스터 성격, 인덱스 부재, 권한)
I_AccountingDocumentItem과 ACDOCA의 관계 이해- 실전 SELECT 패턴 3단계(기본, 실무, 프로덕션)
- 필터·조인 최적화와 흔한 실수 회피
먼저 알아둘 배경
이 글은 ABAP OpenSQL 기본 문법과 CDS 뷰 개념(@AbapCatalog.sqlViewName, define view)에 익숙한 개발자를 대상으로 합니다. 전통 ECC의 재무 테이블(BKPF/BSEG)과 S/4HANA의 ACDOCA 차이에 대한 기본 인식이 있으면 이해가 빠릅니다. Eclipse ADT 환경에서 CDS View를 검색·미리보기할 수 있어야 하고, SAT나 SQL Trace(ST05) 기본 사용법을 알고 있다고 가정합니다.
환경 및 준비 사항
본 예제는 다음 환경 기준으로 작성되었습니다.
- SAP S/4HANA 2022 이상 (On-Premise) 또는 S/4HANA Cloud Public/Private Edition
- ABAP Platform 7.57 이상 (Cloud ABAP RAP 지원)
- Eclipse ADT (ABAP Development Tools) 최신 버전
- 대상 CDS 뷰:
I_AccountingDocumentItem(Basic Interface View, 릴리스 상태 C1) - 백엔드 물리 테이블:
ACDOCA(Universal Journal Entry Line Item) - 권한:
S_TABU_DIS또는 CDS Access Control(@AccessControl.authorizationCheck) 대상 권한 오브젝트
참고로 BSEG는 기술적으로는 S/4HANA에서 "투명 테이블"로 재구성되었지만, ABAP 공식 가이드라인상 직접 접근하지 않는 것이 권장됩니다. 대신 I_AccountingDocumentItem이나 파생된 Consumption View(C_*)를 사용해야 합니다.
핵심 개념: 왜 BSEG를 피해야 하는가
ECC 시절 BSEG는 이름은 투명(transparent)처럼 보였지만 실제로는 클러스터 테이블(RFBLG)의 일부였습니다. 이 구조를 도서관에 비유하면 이렇습니다. BSEG는 "책 제목만 검색되는 카탈로그가 없는 창고"에 가깝습니다. 회계 문서 번호(BELNR)를 알면 빠르게 꺼낼 수 있지만, "이번 달 특정 원가센터의 라인을 다 뽑아줘" 같은 요청은 창고 전체를 뒤져야 했습니다.
S/4HANA에서는 BSEG가 투명 테이블로 바뀌었지만, 다음 세 가지 이유로 여전히 직접 SELECT는 위험합니다.
- 인덱스 한계: BSEG의 기본키는
BUKRS/BELNR/GJAHR/BUZEI입니다. 회사코드/문서번호 없이 다른 조건으로 조회하면 풀 스캔에 가까운 비용이 발생합니다. - 진실의 원천 이동: S/4HANA의 회계 라인은 이제
ACDOCA가 중심입니다. BSEG는 호환성을 위해 유지되지만, 신규 필드(예: 세그먼트, 프로핏센터 계층, 확장 원장)의 완전한 뷰는 ACDOCA에만 있습니다. - 권한 검사 부재: 순수
SELECT FROM bseg는 CDS Access Control을 우회합니다.I_AccountingDocumentItem을 사용하면 조직 단위 권한(회사코드, 원장)이 자동으로 적용됩니다.
I_AccountingDocumentItem은 ACDOCA를 기반으로 I_JournalEntryItem과 함께 회계 라인의 표준 인터페이스 뷰 역할을 합니다. Basic Interface View로 분류되며, 이 위에 Composite View(C_*)와 Consumption View가 얹혀 Fiori 앱과 OData 서비스에 노출됩니다. 즉, 커스텀 리포트에서 I_AccountingDocumentItem을 사용하는 것은 표준 앱이 보는 것과 동일한 데이터 모델을 재사용하는 것과 같습니다.
실전 예제 1단계: 기본 조회
가장 단순한 시나리오부터 시작합니다. 특정 회사코드의 특정 회계연도에서 매출 계정(예: 410000번대)에 전기된 라인 아이템을 조회합니다.
REPORT z_read_ar_lines.
SELECT companycode,
accountingdocument,
accountingdocumentitem,
fiscalyear,
glaccount,
amountincompanycodecurrency,
companycodecurrency,
postingdate,
documentreferenceid
FROM i_accountingdocumentitem
WHERE companycode = '1010'
AND fiscalyear = '2026'
AND glaccount LIKE '410%'
AND postingdate BETWEEN '20260601' AND '20260630'
INTO TABLE @DATA(lt_result).
cl_demo_output=>display( lt_result ).
여기서 눈여겨봐야 할 부분은 필드명입니다. BSEG의 BUKRS/BELNR/GJAHR/HKONT가 아니라, 의미론적 이름인 CompanyCode/AccountingDocument/FiscalYear/GLAccount가 사용됩니다. 이는 유지보수성과 가독성 측면에서 큰 이점입니다.
실전 예제 2단계: 실무 시나리오 — 미결/기결 구분과 로깅
실제 정산 리포트에서는 단순 조회 이상이 필요합니다. 미결(open)/기결(cleared) 라인을 구분하고, 발주 참조 문서와 조인하며, 예외 상황을 로깅해야 합니다.
CLASS zcl_ap_line_reader DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES: BEGIN OF ty_ap_line,
company_code TYPE i_accountingdocumentitem-companycode,
doc_number TYPE i_accountingdocumentitem-accountingdocument,
fiscal_year TYPE i_accountingdocumentitem-fiscalyear,
item_number TYPE i_accountingdocumentitem-accountingdocumentitem,
gl_account TYPE i_accountingdocumentitem-glaccount,
supplier TYPE i_accountingdocumentitem-supplier,
amount_lc TYPE i_accountingdocumentitem-amountincompanycodecurrency,
currency TYPE i_accountingdocumentitem-companycodecurrency,
is_cleared TYPE abap_bool,
clearing_doc TYPE i_accountingdocumentitem-clearingaccountingdocument,
END OF ty_ap_line.
METHODS read_open_items
IMPORTING iv_company_code TYPE bukrs
iv_key_date TYPE d
RETURNING VALUE(rt_lines) TYPE STANDARD TABLE OF ty_ap_line
RAISING cx_sy_open_sql_db.
ENDCLASS.
CLASS zcl_ap_line_reader IMPLEMENTATION.
METHOD read_open_items.
TRY.
SELECT companycode AS company_code,
accountingdocument AS doc_number,
fiscalyear AS fiscal_year,
accountingdocumentitem AS item_number,
glaccount AS gl_account,
supplier,
amountincompanycodecurrency AS amount_lc,
companycodecurrency AS currency,
CASE WHEN clearingaccountingdocument = ''
THEN @abap_true
ELSE @abap_false
END AS is_cleared,
clearingaccountingdocument AS clearing_doc
FROM i_accountingdocumentitem
WHERE companycode = @iv_company_code
AND supplier <> ''
AND postingdate <= @iv_key_date
AND ( clearingaccountingdocument = ''
OR clearingdate > @iv_key_date )
INTO TABLE @rt_lines.
CATCH cx_sy_open_sql_db INTO DATA(lx_sql).
MESSAGE lx_sql->get_text( ) TYPE 'E'.
RAISE EXCEPTION lx_sql.
ENDTRY.
ENDMETHOD.
ENDCLASS.
포인트는 ClearingAccountingDocument와 ClearingDate 조합으로 특정 기준일자의 미결 항목을 판정하는 것입니다. BSEG에서 같은 로직을 짜면 AUGBL/AUGDT를 다뤄야 하는데, 필드 의미가 즉시 와닿지 않아 실수하기 쉽습니다.
실전 예제 3단계: 프로덕션 — 성능과 권한을 고려한 집계
대량 데이터를 다루는 월마감 리포트에서는 DB에서 최대한 처리하고 ABAP은 최소만 수행해야 합니다. Analytical 성격의 집계는 CDS Aggregation을 활용하는 것이 권장됩니다.
@AbapCatalog.sqlViewName: 'ZCVGLBALANCE'
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'GL Account Balance by Period'
@VDM.viewType: #COMPOSITE
define view Z_GLAccountBalance
as select from I_AccountingDocumentItem
{
key CompanyCode,
key FiscalYear,
key FiscalPeriod,
key GLAccount,
Ledger,
@Semantics.amount.currencyCode: 'CompanyCodeCurrency'
sum(AmountInCompanyCodeCurrency) as PeriodBalance,
CompanyCodeCurrency
}
where
Ledger = '0L'
group by
CompanyCode, FiscalYear, FiscalPeriod, GLAccount, Ledger, CompanyCodeCurrency;
주의할 세 가지 프로덕션 원칙입니다.
- Ledger 필드 명시: ACDOCA는 확장 원장을 지원합니다.
Ledger = '0L'처럼 리딩 원장을 명시하지 않으면 원장 수만큼 라인이 곱해져 금액이 왜곡됩니다. - Access Control 활성화:
@AccessControl.authorizationCheck: #CHECK로 CDS DCL을 통해 회사코드 권한이 자동 반영됩니다. - 대량 페치 방지:
UP TO n ROWS, 페이지네이션, 또는 CDS Parameter 기반 필터로 결과 셋을 제한합니다.
흔한 실수와 트러블슈팅 FAQ
Q1. 금액이 두 배로 나옵니다.
가장 흔한 원인은 Ledger 필터 누락입니다. 확장 원장(예: 2L, 3L)이 활성화된 시스템에서는 라인이 원장별로 복제됩니다. 반드시 Ledger = '0L' 또는 요구 원장을 명시해야 합니다.
Q2. BSEG에는 있는 필드가 CDS 뷰에 안 보입니다.
Basic Interface View는 표준 필드만 노출합니다. 커스텀 CI 필드(ZZ*)나 확장 필드가 필요하면 두 가지 옵션이 있습니다. (1) Key User Extensibility로 확장하면 자동으로 뷰에 포함될 수 있습니다. (2) 특정 필드가 정말 BSEG에만 있다면 I_OperationalAcctgDocItemCube나 I_JournalEntryItem을 검토합니다.
Q3. HANA인데도 성능이 느립니다.
세 가지를 점검하세요. (1) SELECT * 대신 필요한 컬럼만 지정 — 열 기반 저장인 HANA에서 특히 중요합니다. (2) WHERE 절에 CompanyCode, FiscalYear, PostingDate 중 최소 하나는 리터럴/바인딩 변수로 포함 — Partition Pruning에 유리합니다. (3) ST05로 실제 SQL을 확인해 뷰가 예상대로 푸시다운되는지 검증합니다.
Q4. Cloud ABAP에서 BSEG가 아예 안 보입니다.
정상입니다. Steampunk(ABAP Environment)나 S/4HANA Cloud Public Edition에서는 BSEG 직접 접근이 릴리스되지 않았습니다. 릴리스된 I_AccountingDocumentItem(릴리스 상태 C1) 계열을 사용해야 합니다.
확장해서 탐색할 주제
I_JournalEntryItem과I_OperationalAcctgDocItem차이 — 관리회계·재무회계 뷰 관점- Analytical CDS(
@Analytics.dataCategory: #FACT)로 KPI 큐브 구성 - RAP(RESTful ABAP Programming Model)에서 회계 데이터 노출과 OData v4 서비스 게시
- ACDOCA와 ACDOCP(계획 데이터), ACDOCU(연결) 통합 조회
- SAP Datasphere로 CDS 뷰를 원격 소스로 연동해 회계 통합 분석
더 읽을거리
- SAP Help Portal — S/4HANA On-Premise 문서 홈
- SAP Help — ABAP CDS 개발 가이드
- SAP Help — S/4HANA Cloud Virtual Data Model 개요
- SAP Business Accelerator Hub — CDS View 카탈로그
- SAP Community Blogs — Universal Journal(ACDOCA) 태그
댓글 0
아직 댓글이 없습니다.