개요 및 학습 체크리스트
ABAP Analytical Query(분석 쿼리)는 SAP S/4HANA 및 BTP ABAP Environment에서 Fiori 분석 앱, Embedded Analytics, SAC Live Connection 등에 데이터를 공급하는 핵심 빌딩 블록입니다. 이 글에서는 분석 쿼리의 두 가지 입력 메커니즘인 PARAMETERS와 FILTERS의 차이를 명확히 정리하고, 실무에서 자주 마주치는 패턴과 함정을 단계별 예제로 풀어봅니다.
- PARAMETERS와 FILTERS의 실행 시점과 의미 차이 이해
- MANDATORY, DEFAULT, Value Help 등 PARAMETERS 옵션 적용
- 고정 필터(Fixed Filter)와 변수 바인딩 패턴 구현
- 두 메커니즘을 결합한 다국가/다기간 시나리오 설계
- 성능 최적화와 흔한 ABAP CDS 오류 디버깅
사전 준비 사항
독자는 ABAP CDS View(@AbapCatalog.sqlViewName 또는 CDS View Entity), @Analytics.query: true 어노테이션의 역할, 그리고 Fiori Elements Analytical List Page(ALP)의 동작 흐름에 대한 기본 이해가 필요합니다. ADT(ABAP Development Tools) for Eclipse가 설치되어 있어야 하며, S/4HANA 2021 이상 또는 BTP ABAP Environment 환경을 권장합니다.
환경 및 버전
실습에 사용한 환경은 다음과 같습니다. 분석 쿼리 어노테이션은 릴리즈마다 추가/변경되므로 사용 중인 시스템의 CDS Annotation 카탈로그를 함께 확인하는 것을 권장합니다.
- SAP S/4HANA 2022 FPS02 (또는 BTP ABAP Environment 2305 이상)
- ABAP Development Tools for Eclipse 3.36+
- Cube/Dimension View가 이미 정의되어 있는 상태(예:
I_SalesOrderItemCube유형) - Fiori Elements ALP 또는 Design Studio/SAC를 통한 소비
- 권한 객체:
S_RS_AUTH,S_DEVELOP
버전에 따라 @Consumption.filter.selectionType 옵션이 일부 다르게 동작할 수 있으므로 ADT의 Annotation 도움말로 교차 검증하세요.핵심 개념과 비유
PARAMETERS와 FILTERS는 둘 다 분석 쿼리가 반환할 데이터의 범위를 좁히는 역할을 합니다. 하지만 작동 시점과 사용자 경험이 다릅니다.
- PARAMETERS: 쿼리가 실행되기 전에 반드시 값이 결정되어야 하는 입력값입니다. Fiori 분석 앱을 열면 가장 먼저 뜨는 "파라미터 입력 팝업(Prompt)"이 PARAMETERS에 해당합니다. SQL의 바인드 변수 또는 함수 인자처럼 동작합니다.
- FILTERS: 쿼리 정의 시점에 개발자가 고정으로 박아두는 WHERE 조건, 또는 사용자가 런타임에 필터 패널에서 조정하는 컬럼 필터입니다. ABAP CDS WHERE 절과 사용자 인터랙티브 필터, 두 형태가 모두 포함됩니다.
비유하자면 PARAMETERS는 식당 입장 전 인원수 입력이고, FILTERS는 자리에 앉은 후 메뉴를 고르는 행위에 가깝습니다. 인원수가 결정되지 않으면 자리 배정 자체가 불가하지만, 메뉴 선택은 자리에 앉은 뒤 자유롭게 바꿀 수 있습니다.
또 다른 비교 축은 참조 가능 여부입니다. PARAMETERS는 측정값 계산식이나 변환 공식에서 $parameters.P_Currency처럼 직접 참조할 수 있어 통화 환산, 회계연도 변형 등 "수식의 일부"가 됩니다. 반면 FILTERS는 결과 집합의 차원 값 범위를 제한할 뿐, 계산식에서 직접 변수처럼 쓰기 어렵습니다.
실전 코드 3단계
1단계 — 기본 PARAMETERS 정의
가장 단순한 형태로 회계연도(Fiscal Year)를 PARAMETER로 받는 분석 쿼리입니다. Cube View Z_C_SalesCube가 이미 존재한다고 가정합니다.
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Sales Query by Fiscal Year'
@Analytics.query: true
@OData.publish: true
define view entity Z_Q_SalesByFiscYear
with parameters
P_FiscalYear : fis_jahr,
P_DisplayCurrency : waers
as select from Z_C_SalesCube
{
@AnalyticsDetails.query.axis: #ROWS
CompanyCode,
@AnalyticsDetails.query.axis: #ROWS
CustomerGroup,
@Semantics.amount.currencyCode: 'DisplayCurrency'
@AnalyticsDetails.query.formula: 'NetAmount'
NetAmount,
$parameters.P_DisplayCurrency as DisplayCurrency
}
where FiscalYear = $parameters.P_FiscalYear
핵심 포인트는 두 가지입니다. 첫째, with parameters 절에 정의된 P_FiscalYear는 where 절에서 $parameters.P_FiscalYear로 참조됩니다. 둘째, P_DisplayCurrency는 SELECT 리스트에 노출되어 측정값의 통화 코드로 활용됩니다. 이 쿼리를 Fiori ALP에서 열면 회계연도와 표시 통화를 묻는 프롬프트가 먼저 뜹니다.
2단계 — FILTERS와 MANDATORY/DEFAULT, 에러 처리
실무에서는 PARAMETERS에 기본값과 필수 여부, Value Help, 그리고 고정 필터를 함께 적용하는 경우가 일반적입니다. 또한 잘못된 입력이 들어왔을 때 로깅 가능한 형태로 동작하도록 설계해야 합니다.
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Sales Query - Region Filtered'
@Analytics.query: true
define view entity Z_Q_SalesByRegion
with parameters
@Consumption.defaultValue: 'EUR'
@EndUserText.label: 'Display Currency'
@Consumption.valueHelpDefinition: [{ entity.name: 'I_Currency',
entity.element: 'Currency' }]
P_DisplayCurrency : waers,
@Consumption.defaultValue: '2026'
@EndUserText.label: 'Fiscal Year'
P_FiscalYear : fis_jahr
as select from Z_C_SalesCube
{
@AnalyticsDetails.query.axis: #ROWS
@Consumption.filter.selectionType: #SINGLE
@Consumption.filter.mandatory: true
SalesOrganization,
@AnalyticsDetails.query.axis: #FREE
@Consumption.filter.selectionType: #RANGE
@Consumption.filter.multipleSelections: true
CustomerCountry,
@Consumption.filter.hidden: true
CompanyCode,
@Semantics.amount.currencyCode: 'DisplayCurrency'
NetAmount,
$parameters.P_DisplayCurrency as DisplayCurrency
}
where FiscalYear = $parameters.P_FiscalYear
and SalesDocumentType = 'TA' -- Fixed filter: standard orders only
and DeletionIndicator = '' -- Fixed filter: exclude deleted items
여기서 중요한 차이를 정리하면 다음과 같습니다.
@Consumption.defaultValue로 기본값을 부여하면 사용자가 비워두어도 쿼리가 실행됩니다.@Consumption.filter.mandatory: true는 필드 레벨 필터를 필수로 만들지만, PARAMETERS는 별도의 필수 여부 어노테이션 없이도 기본적으로 필수입니다.SalesDocumentType = 'TA'와 같은 WHERE 절 조건은 사용자가 절대 풀 수 없는 "고정 필터"입니다. 거래 유형, 삭제 플래그 등 비즈니스 규칙 차원에서 절대 흔들리면 안 되는 조건은 이곳에 배치합니다.@Consumption.filter.hidden: true는 사용자에게 노출하지 않지만 백엔드에서는 필터링이 가능한 컬럼을 표현합니다(예: 권한 컨텍스트).
입력값 검증과 로깅이 필요하면 동일 패키지 내 ABAP 클래스에서 cl_dba_log 또는 BAL(Business Application Log)을 사용해 호출 전후 파라미터를 기록할 수 있습니다.
3단계 — 프로덕션 패턴: 성능, 보안, 다국가 시나리오
전사 운영 단계에서는 PARAMETERS와 FILTERS를 결합하여 (1) 사용자별 권한 필터, (2) 다국가/다통화 환산, (3) HANA 옵티마이저가 활용할 수 있는 정적 필터의 세 가지를 모두 만족시켜야 합니다.
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Global Sales - Production Query'
@Analytics.query: true
@VDM.viewType: #CONSUMPTION
define view entity Z_Q_GlobalSalesProd
with parameters
@Consumption.defaultValue: 'USD'
@Consumption.valueHelpDefinition: [{ entity.name: 'I_Currency',
entity.element: 'Currency' }]
P_DisplayCurrency : waers,
@Consumption.defaultValue: 'M'
@EndUserText.label: 'Exchange Rate Type'
P_ExchangeRateType : kurst,
@Environment.systemField: #SYSTEM_DATE
P_KeyDate : vdm_v_key_date
as select from Z_C_SalesCubeWithCurrConv
( P_DisplayCurrency : $parameters.P_DisplayCurrency,
P_ExchangeRateType : $parameters.P_ExchangeRateType,
P_KeyDate : $parameters.P_KeyDate )
{
@Consumption.filter.selectionType: #INTERVAL
@AnalyticsDetails.query.axis: #COLUMNS
FiscalYearPeriod,
@Consumption.filter.selectionType: #HIERARCHY_NODE
@ObjectModel.foreignKey.association: '_SalesOrgHierarchy'
SalesOrganization,
@AnalyticsDetails.query.axis: #ROWS
CustomerGroup,
@Semantics.amount.currencyCode: 'DisplayCurrency'
@AnalyticsDetails.query.formula: 'NetAmount'
@AnalyticsDetails.query.formulaDescription: 'Net Amount in Display Currency'
NetAmountInDispCrcy as NetAmount,
$parameters.P_DisplayCurrency as DisplayCurrency,
/* Association for hierarchy filter */
_SalesOrgHierarchy
}
where CompanyCode in (select CompanyCode from Z_I_UserCompanyAuth)
and DeletionIndicator = ''
이 패턴의 의도는 다음과 같습니다.
- PARAMETERS 세 개를 통화 변환 Cube의 입력으로 전달하여 HANA 레벨에서 환산을 처리합니다. 응용 계층에서 환산하는 것보다 성능이 우수합니다.
@Environment.systemField: #SYSTEM_DATE로 키 날짜의 기본값을 시스템 일자로 자동 설정합니다.- WHERE 절의 서브쿼리는 사용자별 회사코드 권한 테이블과 조인하는 행 수준 보안(Row-Level Security) 역할을 합니다. DCL(
define role)로도 구현 가능하지만 정적 필터로 두면 옵티마이저 친화적입니다. #HIERARCHY_NODE선택 타입은 ALP에서 조직 계층 선택 UI를 자동 제공합니다.
흔한 실수와 트러블슈팅
Q1. 파라미터 값이 NULL로 들어와 쿼리가 0건을 반환합니다. PARAMETERS는 기본적으로 필수이지만 @Consumption.defaultValue가 누락된 채 OData를 통해 호출되면 빈 문자열이 전달될 수 있습니다. CDS 측에서 coalesce로 방어하거나, 소비측에서 항상 값을 전달하는 규약을 둡니다.
Q2. FILTERS로 충분한데 굳이 PARAMETERS를 써야 하나요? 통화 환산, 회계연도 변형, 기준 일자처럼 계산식의 입력이 되어야 하는 값은 PARAMETERS여야 합니다. 단순히 "보기 좋게 사용자가 고를 수 있는 값"은 FILTERS로 충분합니다. PARAMETERS는 프롬프트 강제 노출로 UX를 무겁게 만들기 때문에 신중히 결정해야 합니다.
Q3. 고정 필터를 WHERE에 박았더니 다른 쿼리에서 재사용이 어렵습니다. Cube/Dimension 계층까지 고정 필터를 끌어내리면 의도치 않게 다른 쿼리에도 영향을 줍니다. 일반적으로 권장되는 구조는 Interface View(공통) → Basic View(필터 최소) → Composite/Consumption Query(고정 필터) 순으로, 고정 필터는 가장 위의 쿼리 레벨에 두는 것이 안전합니다.
Q4. ALP에서 파라미터 프롬프트가 매번 떠서 불편합니다. @UI.presentationVariant와 Variant Management로 사용자가 자주 쓰는 파라미터 조합을 저장할 수 있습니다. 또한 @Consumption.defaultValue를 채워주면 "Apply Automatically" 옵션과 결합해 자동 실행이 가능합니다.
Q5. HANA 옵티마이저가 필터를 푸시다운하지 못합니다. 파라미터를 계산 필드 안에 깊게 숨기거나, 좌측 조인의 우측 테이블에 적용하면 푸시다운이 실패합니다. PlanViz로 확인하고, 가능하면 정적인 WHERE 조건으로 옮기거나 베이스 뷰까지 파라미터를 전달하세요.
다음 단계와 관련 주제
이 패턴을 익혔다면 다음 주제로 확장해 보길 권장합니다.
- Input Parameters와 Variables의 차이: SAC Live에서 변수(Variable)는 BW 스타일로, ABAP CDS PARAMETERS는 HANA Calculation View 스타일로 매핑됩니다.
- Restricted Measure와 Calculated Measure: 파라미터를 측정값 수식과 결합하면 동적 KPI 설계가 가능합니다.
- Analytical Privileges와 DCL:
define role기반 보안과 정적 필터의 트레이드오프. - Embedded Analytics와 KPI Modeler: 만든 쿼리를 KPI Tile로 노출하는 절차.
- SAC Live Connection: 동일 쿼리를 SAC에서 호출 시 변수 매핑 처리.
참고 자료
- help.sap.com — Analytical Queries (ABAP CDS)
- help.sap.com — CDS View Entity Parameters
- help.sap.com — Embedded Analytics in S/4HANA
- SAP Community Blogs — ABAP CDS Views 태그
- developers.sap.com — Build an Analytical Query Tutorial
- help.sap.com — Consumption Annotations Reference
핵심 한 줄
PARAMETERS는 쿼리 실행 전 값이 결정되어야 하는 계산 입력값이고, FILTERS는 실행 중 결과 범위를 제한하는 조건이며, 통화 환산처럼 수식이 필요하면 PARAMETERS를 단순 범위 제한이면 FILTERS를 선택하는 것이 일반적으로 권장됩니다.
댓글 0
아직 댓글이 없습니다.