개요 및 학습 체크리스트
ABAP Analytical Query는 ABAP CDS View 위에 분석 메타데이터를 얹어, OLAP 스타일의 집계/슬라이스앤다이스 쿼리를 별도 BW 모델링 없이 노출할 수 있게 해주는 기능입니다. 결과는 OData 서비스 또는 SAP Analytics Cloud, Fiori Elements Analytical List Page(ALP)에서 그대로 소비됩니다. 이번 가이드에서는 S/4HANA 2022 이상 기준으로 Cube View와 Query View를 단계별로 구성하고, 파라미터/필터/노출까지 한 번에 정리합니다.
- Cube View와 Query View의 책임 분리 이해
- @Analytics.dataCategory와 @Analytics.query 어노테이션 적용
- 측정값(Measure)과 차원(Dimension) 모델링
- PARAMETERS와 FILTERS의 차이 식별
- OData 노출 및 Fiori Elements ALP 연결 흐름 파악
사전 필요 역량
ABAP CDS View DDL 문법, ABAP Development Tools(ADT)에서의 DDL Source 생성 경험, 기본적인 SQL의 GROUP BY/집계 함수 이해가 필요합니다. 추가로 S/4HANA에서 OData 서비스를 Service Binding으로 노출해본 경험이 있으면 마지막 단계 진행이 매끄럽습니다. Fiori Elements 카드/ALP 템플릿에 대한 개념을 알고 있으면 시각화 결과를 더 빨리 검증할 수 있습니다.
환경, 버전, 준비물
아래 구성은 일반적으로 권장되는 최소 사양입니다. 회사 정책에 따라 권한과 패키지 구성이 다를 수 있으니 Basis 담당과 사전 협의가 필요합니다.
- SAP S/4HANA 2022 FPS01 이상 또는 ABAP Platform 2023 (Steampunk 포함)
- ABAP Development Tools (ADT) for Eclipse 2024-03 이상
- HANA DB 2.0 SPS06 이상 (Analytic Engine 사용)
- 패키지: 자체 개발 패키지 (예: ZANALYTICS_DEMO)
- 권한: S_DEVELOP (DDLS, DCLS), 데이터 소스 SELECT 권한, /IWFND/MAINT_SERVICE 권한
- Fiori Launchpad 또는 Fiori Elements Preview용 BSP/UI5 런타임
실습 데이터는 표준 EPM 데모 모델(SEPM_I_SALESORDERITEM)을 사용합니다. 데모 데이터가 없으면 SEPM_DG_GENERATOR 트랜잭션으로 생성하세요.
핵심 개념
ABAP Analytical Query는 세 가지 계층으로 동작합니다. 아래 도식처럼 데이터 소스(테이블/뷰) 위에 Cube View가 분석 모델을 정의하고, 그 위에 Query View가 사용자 관점의 집계와 필터를 정의합니다.
[데이터베이스 테이블]
v
[Basic Interface View] -- @Analytics.dataCategory: #FACT 또는 #DIMENSION
v
[Cube View] -- @Analytics.dataCategory: #CUBE (FACT + DIMENSION 결합)
v
[Query View] -- @Analytics.query: true (집계/표시/필터 정의)
v
[OData / SAC / Fiori ALP]
핵심 어노테이션을 다음과 같이 이해하면 좋습니다.
- @Analytics.dataCategory: #DIMENSION: 마스터데이터 성격. 차원 조회에 사용.
- @Analytics.dataCategory: #FACT: 집계 가능한 사실 데이터. 측정값 후보 필드 포함.
- @Analytics.dataCategory: #CUBE: FACT를 중심으로 DIMENSION을 조인한 분석 모델. 측정값(
@DefaultAggregation)을 보유. - @Analytics.query: true: 최종 쿼리 뷰. UI 표시 위치(Rows/Columns), 정렬, 단위 등을 결정.
비유하자면 Cube는 "창고에 잘 정리된 재고 데이터베이스"이고, Query는 "점장이 즉석에서 만드는 매출 리포트 화면"입니다. 창고 구조를 그대로 화면에 보여주지 않고, 점장이 원하는 단위(월별/지역별)로 다시 자르고 합치는 역할을 Query View가 담당합니다.
또한 Analytical Query는 HANA Analytic Engine을 통해 처리되기 때문에 OLAP 특유의 동적 집계, 계층(Hierarchy), 통화/단위 변환, 누적계산 등을 SQL로 직접 구현하지 않고 어노테이션으로 선언할 수 있습니다.
실전 코드 3단계
1단계 — Cube View 만들기
판매 주문 아이템을 사실(FACT)로 사용하고, 제품과 사업장 마스터를 차원으로 결합한 Cube를 정의합니다.
@AbapCatalog.sqlViewName: 'ZIVSALESCUBE'
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Sales Order Cube'
@Analytics.dataCategory: #CUBE
@VDM.viewType: #COMPOSITE
define view ZI_SalesCube
as select from sepm_i_salesorderitem as Item
association [1..1] to ZI_Product as _Product
on $projection.Product = _Product.Product
association [1..1] to ZI_SalesOrg as _SalesOrg
on $projection.SalesOrganization = _SalesOrg.SalesOrganization
{
key Item.SalesOrder,
key Item.SalesOrderItem,
Item.Product,
Item.SalesOrganization,
Item.CreationDate,
@Semantics.currencyCode: true
Item.TransactionCurrency,
@DefaultAggregation: #SUM
@Semantics.amount.currencyCode: 'TransactionCurrency'
Item.GrossAmount,
@DefaultAggregation: #SUM
@Semantics.amount.currencyCode: 'TransactionCurrency'
Item.NetAmount,
@DefaultAggregation: #SUM
Item.Quantity,
_Product,
_SalesOrg
}
핵심 포인트는 @DefaultAggregation: #SUM으로 측정값을 선언하고, 통화 필드에 @Semantics.amount.currencyCode를 연결한 부분입니다. 이 메타데이터 덕분에 Query 단계에서 별도 SUM 구문 없이도 자동 집계가 일어납니다.
2단계 — Query View 작성 (실무 시나리오)
이제 Cube 위에 사용자 관점의 Query View를 만듭니다. "통화 파라미터"로 환산 통화를 받고, 사업장별/월별 매출을 행/열에 배치합니다.
@AbapCatalog.sqlViewName: 'ZQSALESREP'
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Sales Reporting Query'
@Analytics.query: true
@OData.publish: true
define view ZC_SalesQuery
with parameters
P_DisplayCurrency : vdm_v_display_currency,
P_ExchangeRateType: kurst_curc,
P_ExchangeRateDate: vdm_v_key_date
as select from ZI_SalesCube
{
@AnalyticsDetails.query.axis: #ROWS
SalesOrganization,
@AnalyticsDetails.query.axis: #ROWS
@AnalyticsDetails.query.display: #KEY_TEXT
Product,
@AnalyticsDetails.query.axis: #COLUMNS
@AnalyticsDetails.query.totals: #SHOW
CreationDate,
@Semantics.currencyCode: true
@AnalyticsDetails.query.variableSequence: 10
$parameters.P_DisplayCurrency as DisplayCurrency,
@DefaultAggregation: #SUM
@Semantics.amount.currencyCode: 'DisplayCurrency'
@AnalyticsDetails.query.formula: 'CURRENCY_CONVERSION( amount => GrossAmount, source_currency => TransactionCurrency, target_currency => $parameters.P_DisplayCurrency, exchange_rate_date => $parameters.P_ExchangeRateDate, exchange_rate_type => $parameters.P_ExchangeRateType, error_handling => ''SET_TO_NULL'' )'
GrossAmount as GrossAmountInDisplayCrcy,
@DefaultAggregation: #SUM
Quantity
}
where CreationDate >= $session.system_date - 365
실무에서는 보통 에러 처리(error_handling)를 SET_TO_NULL 혹은 KEEP_UNCONVERTED로 설정해 환산 실패 시 전체 쿼리가 던전(0건)으로 떨어지는 것을 방지합니다. 또한 @AnalyticsDetails.query.totals: #SHOW로 합계 행 표시 여부를 명시하면, Fiori ALP에서 합계가 자동 노출됩니다.
3단계 — OData 노출과 Fiori Elements 연결 (프로덕션)
생산 환경에서는 @OData.publish 대신 RAP 스타일의 Service Definition + Service Binding을 사용하는 것이 권장됩니다. 변경 이력 추적과 권한 분리가 명확해지기 때문입니다.
@EndUserText.label: 'Sales Reporting Service Definition'
define service ZUI_SALES_REPORTING {
expose ZC_SalesQuery as SalesReport;
}
" Service Binding (ADT > New > Service Binding)
" Binding Type: OData V4 - UI
" Service Name : ZUI_SALES_REPORTING_O4
" Activate 후 'Preview' 클릭 → Fiori Elements Analytical List Page 자동 생성
UI 측 표현(차트 종류, 기본 KPI)은 Metadata Extension으로 분리합니다.
@Metadata.layer: #CUSTOMER
@UI.chart: [{
qualifier : 'SalesByOrg',
title : 'Gross Sales by Organization',
chartType : #COLUMN,
dimensions : [ 'SalesOrganization' ],
measures : [ 'GrossAmountInDisplayCrcy' ],
measureAttributes: [{ measure: 'GrossAmountInDisplayCrcy', role: #AXIS_1 }]
}]
@UI.presentationVariant: [{
qualifier: 'Default',
sortOrder: [{ by: 'GrossAmountInDisplayCrcy', direction: #DESC }],
visualizations: [{ type: #AS_CHART, qualifier: 'SalesByOrg' }]
}]
annotate view ZC_SalesQuery with
{
@UI.lineItem: [{ position: 10 }]
SalesOrganization;
@UI.lineItem: [{ position: 20 }]
Product;
@UI.lineItem: [{ position: 30 }, { type: #AS_DATAPOINT, valueQualifier: 'GrossKpi' }]
@UI.dataPoint: { qualifier: 'GrossKpi', title: 'Gross Amount' }
GrossAmountInDisplayCrcy;
}
운영 단계에서는 다음 사항을 추가로 점검합니다.
- 권한: DCL(Data Control Language)로
DEFINE ROLE작성, 사용자별 사업장/회사코드 필터 적용. - 성능: Cube 단에서 불필요한 association을 join 하지 않도록
redirect to와@ObjectModel.usageType.serviceQuality: #D를 활용. - 테스트: ADT의 Data Preview에서 파라미터를 다르게 주며 합계/소계 검증, ABAP Unit으로
cl_osql_test_environment기반 단위 테스트 작성. - 모니터링: SQL Monitor (ST12), HANA Plan Visualizer로 분석 엔진 사용 여부 확인.
흔한 실수와 트러블슈팅
운영 프로젝트에서 가장 자주 부딪히는 케이스를 FAQ 형태로 정리했습니다.
- Q1. Query View Preview에서 "Query is not analytical" 오류가 납니다.
A.@Analytics.query: true어노테이션이 누락되었거나, 소스가 Cube(#CUBE)가 아닌 일반 View일 가능성이 큽니다. 소스 View의dataCategory가 #CUBE 또는 #FACT인지, 그리고 측정값에@DefaultAggregation이 모두 지정되었는지 점검하세요. - Q2. 통화 환산 결과가 NULL로만 나옵니다.
A. 환율 테이블(TCURR)에 해당 일자/통화쌍이 없는 경우입니다.error_handling => 'KEEP_UNCONVERTED'로 바꿔 원본 통화값을 유지하거나, 환율 일자를$session.system_date대신 거래일로 변경해 보세요. - Q3. Fiori ALP에서 차트는 보이는데 합계 행이 없습니다.
A. 차원 컬럼에@AnalyticsDetails.query.totals: #SHOW가 설정되어 있는지, 그리고 측정값이 #SUM/#AVG 등 집계 가능한 타입인지 확인해야 합니다.#FORMULA측정값은 합계 계산 방식을 별도로 지정해야 합니다.
PARAMETERS vs FILTERS: 둘 다 결과를 좁히는 역할이지만 동작 시점이 다릅니다. PARAMETERS는 쿼리 실행 전에 사용자에게 입력을 받아 SQL 안의 변수($parameters.xxx)로 들어가므로, 통화 환산처럼 "계산 자체에 영향을 주는 값"에 사용합니다. FILTERS(WHERE 절 또는 UI 필터)는 결과 집합을 사후에 잘라내는 용도이며, 사용자가 화면에서 자유롭게 변경 가능합니다. 일반적으로 필수 입력은 PARAMETERS, 선택적 슬라이싱은 FILTERS로 구성하는 것이 권장됩니다.
다음 단계와 관련 주제
분석 쿼리 기본기를 잡았다면 아래 주제로 확장하기 좋습니다.
- Hierarchy CDS View로 조직/계정 계층 분석 구현
- SAP Analytics Cloud Live Connection으로 분석 쿼리 직결
- RAP Business Object와 Analytical Query의 결합 (CRUD + Reporting)
- KPI Modeler(Fiori Smart Business)로 Cards 노출
- Embedded Analytics 권한 모델 (DCL + PFCG 통합)
참고 자료
- SAP Help — ABAP CDS Analytical Annotations
- SAP Help — Embedded Analytics in S/4HANA
- SAP Help — Analytical Query (Transactional Reporting)
- SAP Developers — Create an Analytical Query with ABAP CDS
- SAP Community — ABAP CDS Views Blog Tag
- SAP Help — Service Definition and Service Binding
핵심 한 줄
Cube View로 사실/차원을 정돈하고 그 위에 @Analytics.query Query View를 얹어 OData로 노출하면, 코드 한 줄 없이 Fiori ALP에서 동작하는 분석 화면이 완성됩니다.
댓글 0
아직 댓글이 없습니다.