ABAP

아직도 I_ vs C_ 뷰 헷갈려? 이제 정확히 구분해 #shorts #SAP #ABAP

▶ YouTube에서 보기

개요 및 이 글에서 얻어갈 것

SAP S/4HANA 및 ABAP CDS 기반 개발을 하다 보면 I_SalesOrder, C_SalesOrderTP 같은 접두사가 붙은 CDS View를 자주 만나게 됩니다. 이 두 종류는 이름만 다른 게 아니라 Virtual Data Model(VDM)의 계층 구조에서 완전히 다른 역할을 담당합니다. 이 글에서는 Interface View(I_)와 Consumption View(C_)의 차이, 사용 목적, 그리고 실전에서 어떻게 구분해 만드는지 SalesOrder 시나리오로 살펴봅니다.

  • VDM 3계층(Basic / Composite / Consumption) 구조 이해
  • I_ 뷰와 C_ 뷰의 명명 규칙과 사용 시점 판별
  • Interface View 작성 시 필수 어노테이션 파악
  • Consumption View에서 UI/OData Service 노출 방식 이해
  • 잘못된 계층 참조로 발생하는 트러블 회피

알고 있으면 좋은 사전 지식

ABAP CDS View DDL 문법(define view, association) 기초, ADT(ABAP Development Tools) 사용 경험, 그리고 SAP S/4HANA의 Fiori Elements 또는 OData Service에 대한 개념적 이해가 있으면 훨씬 수월합니다. HANA SQL의 뷰 개념을 알고 있다면 CDS도 유사한 관점으로 접근할 수 있습니다.

환경 및 버전 정보

이 글의 예제는 다음 환경을 기준으로 작성되었습니다.

  • SAP S/4HANA 2022 On-Premise (또는 S/4HANA Cloud, Private Edition 2023 이상 권장)
  • ABAP Platform 2022 (NetWeaver 7.58 기반)
  • ADT(Eclipse) 3.36 이상, Java 17
  • ABAP CDS DDL(Data Definition Language) 사용
  • 참고: SAP Cloud Application Programming Model(CAP)의 CDS와 ABAP CDS는 문법이 유사하지만 이 글은 ABAP CDS 기준입니다.

실습을 위해서는 개발자 권한(S_DEVELOP), 그리고 CDS 뷰 생성 가능한 패키지가 필요합니다. VDM 규칙에 따라 명명 규칙을 따르지 않으면 릴리스 시 검사에서 경고가 발생할 수 있으니, 사내 네임스페이스를 미리 확인해두는 것이 좋습니다.

핵심 개념: VDM 계층과 접두사 규칙

SAP의 Virtual Data Model(VDM)은 데이터베이스 테이블 위에 비즈니스 의미를 부여한 가상 데이터 모델입니다. 물리 테이블을 직접 조회하지 않고, 의미 있는 뷰를 통해 접근하도록 표준화한 구조라고 이해하면 됩니다. VDM은 크게 세 개 계층으로 나뉩니다.

비유로 이해하기: VDM을 3층짜리 상가 건물로 생각해보세요. 1층(Basic)은 원자재 창고, 2층(Composite)은 조립 공장, 3층(Consumption)은 매장(쇼윈도)입니다. 고객(UI, 리포트)은 3층 매장만 방문하고, 절대 창고로 들어가지 않습니다.

  • Basic Interface View (I_): 물리 테이블에 가장 가까운 계층. 테이블 조인, 코드 변환, 필드 리네이밍 정도만 수행. 재사용 가능한 원자적 데이터 모델.
  • Composite Interface View (I_): 여러 Basic View를 조합하여 좀 더 풍부한 데이터 셋을 만드는 계층. 여전히 접두사는 I_.
  • Consumption View (C_): 특정 소비 시나리오(Fiori 앱, Analytical Query, OData Service 등)에 맞춰 최적화된 최상위 계층. UI 어노테이션, Value Help, Search 설정 등이 붙습니다.

구분의 핵심은 "누가 사용하는가" 입니다. I_ 뷰는 다른 개발자/뷰가 소비하고, C_ 뷰는 UI 또는 외부 서비스가 소비합니다. 그래서 Interface View는 재사용성과 안정성이 최우선이고, Consumption View는 특정 화면·리포트의 요구사항에 특화되어 있습니다.

또 하나 중요한 원칙: Consumption View는 반드시 Interface View를 통해서만 데이터를 참조해야 합니다. C_ 뷰에서 물리 테이블(예: vbak)이나 다른 C_ 뷰를 직접 select하는 것은 VDM 규칙 위반입니다.

실전 코드 3단계

1단계 — Basic Interface View 만들기

가장 아래 계층부터 시작합니다. Sales Order 헤더 테이블(vbak)을 기반으로 하는 Basic Interface View입니다. 이 뷰는 필드 리네이밍과 기본 association만 담당합니다.

@AbapCatalog.sqlViewName: 'ZISALESORDER'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Sales Order - Basic Interface View'
@VDM.viewType: #BASIC
@Analytics.dataCategory: #DIMENSION
@ObjectModel.representativeKey: 'SalesOrder'

define view Z_I_SalesOrder
  as select from vbak
{
  key vbak.vbeln           as SalesOrder,
      vbak.erdat           as CreationDate,
      vbak.ernam           as CreatedByUser,
      vbak.auart           as SalesOrderType,
      vbak.vkorg           as SalesOrganization,
      vbak.kunnr           as SoldToParty,
      vbak.netwr           as NetAmount,
      vbak.waerk           as TransactionCurrency
}

포인트는 @VDM.viewType: #BASIC 어노테이션입니다. 이는 이 뷰가 VDM에서 어떤 계층인지 명시하는 필수 표식이며, 릴리스 검사에서도 확인합니다. 필드명은 기술적 컬럼명(VBELN)이 아닌 비즈니스 의미의 이름(SalesOrder)으로 바꿔주는 것이 관례입니다.

2단계 — Composite Interface View + Consumption View 조합

이제 헤더와 아이템을 결합한 Composite Interface View를 만들고, 이를 Fiori 앱에서 소비할 Consumption View로 노출합니다. 실무에서는 로깅과 예외 케이스도 함께 고려합니다.

@AbapCatalog.sqlViewName: 'ZISOWITHITEM'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Sales Order with Item Totals'
@VDM.viewType: #COMPOSITE
@Metadata.ignorePropagatedAnnotations: true

define view Z_I_SalesOrderWithItems
  as select from Z_I_SalesOrder as SO
  association [0..*] to Z_I_SalesOrderItem as _Item
    on $projection.SalesOrder = _Item.SalesOrder
{
  key SO.SalesOrder,
      SO.CreationDate,
      SO.SoldToParty,
      SO.NetAmount,
      SO.TransactionCurrency,
      _Item
}

그리고 이를 소비하는 Consumption View입니다. UI 어노테이션이 붙기 시작한다는 점에 주목하세요.

@AbapCatalog.sqlViewName: 'ZCSOOVERVIEW'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Sales Order Overview - Consumption'
@VDM.viewType: #CONSUMPTION
@OData.publish: true
@UI.headerInfo: {
  typeName: 'Sales Order',
  typeNamePlural: 'Sales Orders',
  title: { value: 'SalesOrder' }
}

define view Z_C_SalesOrderOverview
  as select from Z_I_SalesOrderWithItems
{
  @UI.lineItem: [{ position: 10, label: 'Order No.' }]
  @UI.identification: [{ position: 10 }]
  key SalesOrder,

  @UI.lineItem: [{ position: 20, label: 'Sold-To' }]
  SoldToParty,

  @UI.lineItem: [{ position: 30, label: 'Net Amount' }]
  @Semantics.amount.currencyCode: 'TransactionCurrency'
  NetAmount,

  @Semantics.currencyCode: true
  TransactionCurrency
}

차이점이 뚜렷하게 보이시나요? Interface View는 데이터의 형태에 집중하고, Consumption View는 화면 표현·서비스 노출에 집중합니다. C_ 뷰에서 @OData.publish: true@UI.* 어노테이션이 등장한 것이 결정적 차이입니다.

3단계 — 프로덕션 관점: 권한, 성능, 테스트

실제 운영 환경에서는 다음 요소가 반드시 반영되어야 합니다. Consumption View에서 @AccessControl.authorizationCheck: #CHECK를 지정하고, 별도의 DCL(Data Control Language)로 접근 제어를 정의합니다.

@EndUserText.label: 'DCL for Sales Order Overview'
@MappingRole: true

define role Z_C_SalesOrderOverview {
  grant select on Z_C_SalesOrderOverview
    where SalesOrganization =
      aspect pfcg_auth ( V_VBAK_VKO, VKORG, ACTVT = '03' );
}

성능 관점에서는 Interface View 계층에서 인덱스가 걸린 키 필드 위주로 조인을 설계하고, Consumption View에서는 필요한 필드만 명시적으로 select하는 편이 유리합니다. 단위 테스트는 ABAP Unit + CDS Test Double Framework(CL_CDS_TEST_ENVIRONMENT)를 사용해 각 계층별로 검증합니다.

자주 겪는 실수와 트러블슈팅

Q1. Consumption View에서 직접 물리 테이블을 select해도 되나요?
문법적으로는 가능하지만 VDM 규칙 위반입니다. Release Check에서 경고가 뜨며, 유지보수 시 테이블 스키마 변경이 UI까지 직접 파급됩니다. 반드시 Interface View를 경유하세요.

Q2. I_ 뷰에 @UI 어노테이션을 붙여도 동작하는데요?
동작은 하지만 재사용성을 심각하게 해칩니다. 특정 화면에 종속된 어노테이션이 Interface View에 붙으면 다른 소비자가 사용할 때 의도치 않은 UI 힌트를 상속받습니다.

Q3. @VDM.viewType 어노테이션을 빠뜨리면 어떻게 되나요?
컴파일 자체는 성공하지만 VDM Analyzer 도구나 릴리스 체크에서 경고가 발생합니다. 또한 다른 개발자가 이 뷰의 계층을 즉시 파악하기 어려워지므로 팀 협업에도 마이너스입니다.

Q4. Composite View와 Consumption View의 경계가 모호할 때는?
"이 뷰의 소비자가 다른 CDS 뷰인가, UI/OData Service인가?"를 물어보세요. 답이 전자면 Composite(I_), 후자면 Consumption(C_)입니다.

Q5. 접두사만 바꾸면 되는 건가요?
아닙니다. 명명 규칙은 표식에 불과하며, 실제로는 어노테이션, 참조 대상, 재사용 목적이 모두 계층에 맞아야 합니다.

확장해볼 만한 주제

  • RAP(RESTful ABAP Programming Model)에서 Behavior Definition과 Projection View(P_) 활용
  • Analytical Cube View(@Analytics.dataCategory: #CUBE)와 Query View 설계
  • CDS Access Control(DCL)을 활용한 다층 권한 모델
  • Released CDS View 확인 방법(@API.state 어노테이션과 SAP Business Accelerator Hub)
  • Extension View, Transactional View, Metadata Extension의 역할 구분

댓글 0

아직 댓글이 없습니다.