개요와 이 글에서 얻어갈 것
SAP 표준 CDS 뷰는 SAP가 소유한 자산이라 직접 수정하면 업그레이드 시 충돌이 발생합니다. 그렇다고 같은 데이터에 컬럼 한두 개를 더 붙이려고 새 뷰를 통째로 복제하면 유지보수가 악몽이 됩니다. 이 글에서는 원본을 건드리지 않고 필드와 행을 확장하는 EXTEND VIEW 구문을 PurchaseOrder 시나리오를 중심으로 다룹니다.
핵심 개념 — EXTEND VIEW는 무엇을 확장하는가
EXTEND VIEW를 비유하자면, 표준 CDS 뷰는 봉인된 상자이고 그 상자에 SAP가 미리 뚫어 놓은 "확장 슬롯"이 있다고 생각하면 됩니다. 그 슬롯이 바로 @AbapCatalog.viewEnhancementCategory 어노테이션입니다. 슬롯이 없으면(#NONE) 확장 시도가 컴파일 단계에서 차단됩니다.
슬롯의 종류는 다음과 같습니다.
- #PROJECTION: 기존 SELECT 절에 컬럼을 추가하거나, 이미 정의된 association을 따라가 필드를 가져오는 경우. 가장 자주 쓰임.
- #UNION: 뷰가 UNION으로 구성되어 있고, 확장 시에도 UNION 구조가 유지되어야 하는 경우. 새 컬럼은 모든 UNION 가지에 동일하게 추가됨.
- #NONE: 확장 불가 — 이 경우 EXTEND VIEW로는 손댈 수 없음.
EXTEND VIEW는 원본 SELECT 리스트에 컬럼을 끼워 넣는 작업입니다. 새 뷰를 만드는 것이 아니라 원본 DDL이 활성화될 때 확장 DDL이 함께 합쳐져 하나의 DB 뷰로 컴파일됩니다.
1단계: 기본 PROJECTION 확장
가장 흔한 시나리오는, 구매 발주 헤더 뷰에 고객사에서만 의미가 있는 필드를 붙이는 경우입니다. 원본 뷰에 viewEnhancementCategory가 선언되어 있다고 가정합니다.
// 원본(읽기 전용 가정): I_PurchaseOrder
@AbapCatalog.sqlViewName: 'IPURCHORD'
@AbapCatalog.viewEnhancementCategory: [#PROJECTION]
@EndUserText.label: 'Purchase Order Header'
define view I_PurchaseOrder
as select from ekko
{
key ebeln as PurchaseOrder,
bukrs as CompanyCode,
lifnr as Supplier,
bedat as DocumentDate
}
이 표준 뷰에 사내 승인자 필드를 붙이는 확장 DDL은 다음과 같이 작성합니다.
@EndUserText.label: 'PO Header - Internal Approver Extension'
extend view I_PurchaseOrder with ZE_PurchOrd_Approver
{
// EKKO에 append structure로 추가된 커스텀 필드
zz_internal_approver as ZZ_InternalApprover
}
핵심 포인트는 세 가지입니다. 첫째, extend view <원본명> with <확장명> 형태로 두 개의 이름이 모두 필요합니다. 둘째, 확장 안에서는 key 키워드를 사용할 수 없으며 기존 키 구조는 절대 바꿀 수 없습니다. 셋째, 테이블에 append structure로 컬럼이 이미 존재해야 SELECT가 가능합니다.
2단계: Association 활용과 어노테이션 추가
실무에서는 이미 정의된 association을 따라가 마스터 데이터를 끌어오거나, 새 association을 추가해야 하는 경우가 더 많습니다. 공급사 신용등급을 발주 뷰에 노출하는 예제입니다.
@EndUserText.label: 'PO Header - Supplier Credit Info'
extend view I_PurchaseOrder with ZE_PurchOrd_CreditInfo
association [0..1] to ZI_SupplierCreditScore as _ZzCreditScore
on $projection.Supplier = _ZzCreditScore.Supplier
{
@EndUserText.label: 'Supplier Credit Rating'
_ZzCreditScore.CreditRating as ZZ_SupplierCreditRating,
@EndUserText.label: 'Credit Score Updated On'
_ZzCreditScore.LastUpdated as ZZ_CreditScoreUpdatedOn,
// 노출용 association도 추가하면 다운스트림에서 활용 가능
_ZzCreditScore
}
새로 만든 association은 원본 뷰의 association 목록에 합쳐집니다. 따라서 같은 이름의 association이 표준에 이미 있다면 활성화 단계에서 충돌 오류가 납니다. 네이밍은 항상 _Zz 접두어 또는 회사 표준 접두어를 사용하세요.
3단계: UNION 확장과 운영 고려사항
UNION으로 구성된 표준 뷰에 새로운 행 집합을 합치고 싶다면 UNION 확장을 사용합니다.
@EndUserText.label: 'Open Document - Internal Workflow Source'
extend view I_OpenBusinessDocument with ZE_OpenDoc_Workflow
{
// 첫 번째 UNION 가지에 컬럼 추가 — 모든 가지에 동일 시그니처 필요
}
union all select from zworkflow_doc
{
workflow_id as DocumentNo,
'WF' as DocType,
amount as NetAmount,
curr as Currency
}
UNION 확장에서는 새 SELECT 절의 컬럼 개수, 타입, 순서가 원본 가지와 정확히 일치해야 합니다. 단 하나라도 어긋나면 활성화가 실패합니다.
프로덕션에서는 다음 사항을 점검하세요.
- 실행 계획: 확장이 추가될 때마다 DB 옵티마이저의 플랜이 달라질 수 있어 HANA Plan Visualizer로 회귀 테스트 권장
- 액세스 권한: 새로 추가한 association이 가리키는 뷰의 DCL을 확인해 권한 누락 검토
- 전송 의존성: 확장은 원본 뷰가 활성화된 시스템에만 전송, 전송 순서를 잘못 잡으면 활성화 오류
자주 마주치는 함정과 FAQ
"View enhancement is not allowed" 오류가 납니다.
원본 뷰의 @AbapCatalog.viewEnhancementCategory가 #NONE이거나 어노테이션이 아예 없는 경우입니다. 이때는 EXTEND VIEW로 접근할 수 없고, RAP 기반이라면 Projection View 레이어에서 확장하는 패턴을 검토합니다.
확장 필드가 SELECT 결과에 안 보입니다.
흔한 원인은 (1) 확장 DDL이 비활성 상태, (2) 외부 도구(Fiori Elements)가 메타데이터를 캐시하고 있음, (3) DCL이 새 필드를 마스킹하고 있음입니다. ADT에서 원본 뷰의 SQL 미리보기(F8)에 확장 컬럼이 보이는지 먼저 확인하세요.
동일한 표준 뷰에 확장을 여러 개 만들 수 있나요?
가능합니다. 다만 컬럼명/association명이 전역적으로 유일해야 하며, 회사 표준 네이밍 컨벤션(예: ZZ_ + 도메인 약어)을 강제하면 안전합니다.
CDS View Entity에서도 같은 방식인가요?
문법은 유사하지만 제약이 다릅니다. View Entity는 extend view entity 키워드와 viewEntityEnhancementCategory 어노테이션을 사용합니다.
응용 패턴 — Metadata Extension과 조합
필드 추가 없이 UI 어노테이션만 덧붙이고 싶다면 EXTEND VIEW 대신 annotate view(Metadata Extension)를 사용하는 것이 더 가볍습니다. 두 가지를 조합해 데이터 필드는 EXTEND VIEW로, 라벨/Fiori 어노테이션은 Metadata Extension으로 관리하면 관심사가 분리되어 유지보수성이 높아집니다.
댓글 0
아직 댓글이 없습니다.