Data Definition
Data Definition
1. Annotation
select from계층 (Interface / Root View)@AbapCatalog.viewEnhancementCategory
- 의미: 다른 개발자가
EXTEND VIEW ENTITY구문을 사용하여 이 CDS 뷰에 필드를 추가하는 등의 구조 확장을 허용할지 정의합니다.- 옵션별 상세 설명:
[#NONE]: 확장 절대 불가. 내부 구조가 복잡하여 임의로 필드가 추가되면 쿼리 성능이 깨지거나 로직이 꼬일 위험이 있는 중요 인터페이스 뷰에 적용합니다.[#PROJECTION_LIST]: 조회 필드(Select List) 확장만 허용. 가장 일반적으로 사용되며, 기본 키(Key)나 구조 자체를 바꾸지 않고 단순 조회용 필드만 맨 끝에 덧붙일 수 있게 합니다.[#UNION]: Union 구조 확장 허용.UNION구문이 들어간 복잡한 CDS 뷰에서 각 쿼리 블록의 필드 리스트를 동시에 확장할 수 있도록 허용합니다.[#PRIVILEGED_ONLY]: 특수 권한 확장만 허용. SAP 시스템이 제공하는 안전한 전용 패키지나 특수 경로를 통해서만 확장이 가능하도록 제한합니다.
@AccessControl.authorizationCheck
- 의미: 데이터 조회 시 DCL(Data Control Language) 파일에 정의된 유저별/행별 접근 권한 오브젝트를 자동으로 체크할지 결정합니다.
- 옵션별 상세 설명:
#NOT_REQUIRED: 권한 체크 생략. 권한 검사가 필요 없는 단순 마스터 코드성 데이터(예: 국가 코드, 통화 코드)를 조회하거나, 이미 백엔드 ABAP 프로그램 로직에서 권한 제어를 별도로 처리할 때 성능 최적화를 위해 사용합니다.#CHECK: 무조건 권한 체크. 급여 데이터, 매출 실적, 고객 개인정보 등 보안이 극도로 중요한 비즈니스 트랜잭션 데이터 레이어에 적용합니다. 대응하는 DCL 파일이 없으면 경고나 에러가 발생할 수 있습니다.#PRIVILEGED_ONLY: 특수 경로만 허용. 일반적인 쿼리 조회가 아닌, 특정 권한이 부여된 클래스나 시스템 내부 프로세스를 통해서만 데이터 접근을 허용하고자 할 때 사용합니다.
@EndUserText.label
- 의미: Eclipse ADT, SE11 화면 등 시스템 전반에서 이 CDS 뷰를 식별할 때 보여주는 대표 이름(Description Text)입니다.
- 사용 기준: 개발하는 모든 CDS 뷰에 무조건 필수적으로 작성 해야 하며, 동료 개발자가 이 뷰의 비즈니스 목적을 바로 이해할 수 있도록 명확하게 작성합니다. (최대 60자)
@Metadata.ignorePropagatedAnnotations
- 의미: 이 CDS 뷰가 참조하는 하위 물리 테이블이나 데이터 엘리먼트(Data Element)에 걸려있는 메타데이터 어노테이션 속성들을 상속받을지 차단할지 제어합니다.
- 옵션별 상세 설명:
true: 상속 차단 및 현재 뷰의 설정만 활성화. 하위 객체들의 복잡한 어노테이션이 섞여 들어와 원치 않는 사이드 이펙트가 발생하거나, 쿼리 분석 및 활성화 속도(Activation Performance)가 느려지는 것을 방지합니다. 최신 CDS View Entity 설계 시 무조건true로 설정하는 것이 글로벌 표준 규격 입니다.false: 상속 허용. 하위 구조나 엘리먼트에 이미 정의되어 있는 UI 속성, 검색 속성, 레이블 정보 등을 그대로 물려받아 재사용하고 싶을 때 제한적으로 사용합니다.
as projection on계층 (Projection View)@Metadata.allowExtensions
- 의미: UI 화면 배치 설정을 담은 별도의 메타데이터 확장 파일(Metadata Extension,
.ddlx)을 분리하여 작성할 수 있도록 허용할지 여부입니다.- 옵션별 상세 설명:
true: UI 파일 분리 허용.@UI.lineItem이나@UI.selectionField같은 Fiori Elements 전용 화면 배치 어노테이션들을 CDS 본문이 아닌 별도 파일로 쪼갤 수 있게 합니다. 코드가 깔끔해지므로 실무 프로젝션 뷰에서는 무조건true로 설정 합니다.false: UI 파일 분리 불허. 모든 UI 관련 어노테이션을 CDS 뷰 본문 내에 필드와 함께 빽빽하게 적어야 합니다. 유지보수성이 떨어지므로 권장하지 않습니다.
@Search.searchable
- 의미: 최종 Fiori Elements 화면의 우측 상단에 전체 텍스트를 검색할 수 있는 전역 검색창(Global Search Bar)을 활성화할지 여부입니다.
- 옵션별 상세 설명:
true: 검색 기능 활성화. 이 설정을 켜고 본문 필드 중 원하는 컬럼에@Search.defaultSearchElement: true를 붙여주면, 사용자가 해당 키워드로 전체 데이터를 검색할 수 있게 됩니다.false: 검색 기능 비활성화. 화면 상단에 전역 검색 필드를 노출하지 않습니다.
@ObjectModel.semanticKey
- 의미: 기술적인 Key(예: UUID 등) 외에, 현업 사용자가 화면에서 인지하는 비즈니스 관점의 실질적인 유니크 키(얼굴 역할 필드)가 무엇인지 정의합니다.
- 구문 형태:
['CarrierId', 'ConnectionId']형태로 대괄호 안에 필드명을 선언합니다. Fiori 화면 이동(Navigation) 시 타이틀이나 오브젝트 페이지의 헤더 영역에 해당 값이 대표로 노출됩니다.
@AccessControl.authorizationCheck (프로젝션 레이어 기준)
- 의미: 백엔드(Root View) 단계와 별개로, 최종 UI 화면으로 넘어가는 최종 길목 에서 사용자의 권한을 한 번 더 검사할지 결정합니다.
- 옵션별 상세 설명:
#CHECK: 화면 진입 시 최종 권한 체크. 백엔드 레이어에서는 개발 편의나 데이터 가공을 위해#NOT_REQUIRED로 풀어두었더라도, 최종 사용자 화면에 뿌려줄 때만큼은 로그인한 유저의 소속 부서나 플랜트 권한에 맞춰 데이터를 필터링해야 할 때 주로 이 값을 선택합니다.#NOT_REQUIRED: 프로젝션 단계에서도 별도의 DCL 권한 검사 없이 백엔드가 넘겨준 데이터를 그대로 화면에 바인딩합니다.
2. Interface View 정의
- 데이터베이스에 존재하는 원시 데이터 를 가장 먼저 읽어와서,
비즈니스 용어에 맞게 필드명을 매핑(Alias)해주는 가공되지 않은 순수 데이터 레이어입니다. as select from뒤에 올 수 있는 것:- 물리 테이블: 데이터가 실제로 저장된 DB 테이블
(예: SAP 스탠다드 테이블/dmo/flight, CBO 투명 테이블ztwbs_task2) - 스탠다드 뷰 / 타 CDS 뷰: SAP가 기존에 만들어 둔 표준 CDS 뷰나
다른 개발자가 가공해 놓은 인터페이스 뷰도 가져와서 재사용 가능
1
2
3
4
5
6
7
8
9
10
11
12
13
define view entity ZI_LDG_FLIGHT as select from /dmo/flight
{
key carrier_id as CarrierId,
key connection_id as ConnectionId,
key flight_date as FlightDate,
@Semantics.amount.currencyCode: 'CurrencyCode'
price as Price,
currency_code as CurrencyCode,
plane_type_id as PlaneTypeId,
seats_max as SeatsMax,
seats_occupied as SeatsOccupied
}
3. Root View 정의
- 인터페이스 뷰(
ZI_LDG_FLIGHT)를 소스로 지정하여select하는 최상위 뷰입니다. - 핵심 역할: RAP(RESTful ABAP Programming) 프레임워크에서 하나의 비즈니스 오브젝트
(BO, 예: 한 장의 전표, 하나의 프로젝트) 구조를 잡을 때
“내가 이 데이터 구조의 대장(최상위 노드)이다”라고 시스템에 선언하는 뷰.
이 루트 뷰를 중심으로 하위에 자식(Child) 뷰들이 구성(Composition)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
define root view entity ZR_LDG_FLIGHT as select from ZI_LDG_FLIGHT
{
key CarrierId,
key ConnectionId,
key FlightDate,
@Semantics.amount.currencyCode: 'CurrencyCode'
Price,
CurrencyCode,
PlaneTypeId,
SeatsMax,
SeatsOccupied,
'https://example.com/Upload_Portal/it/Logo/COMPANY_LOGO.png' as FixedImageUrl
//상수값도 가능(Y,N 테이블등 콤보박스 생성시에 사용)
}
4. Projection View 정의
- 핵심 역할: Root View를 그대로 가져와서 “이 데이터 중 화면(프론트엔드)에 어떤 필드만 보여주고 어떤 기능을 허용할 것인가”를 결정하는 레이어입니다.
- 주요 특징:* 데이터를 새로
select하거나 조인 등 가공하지 않음. - 오직 Fiori Elements 화면 연동을 위한 서비스 계약(
provider contract)을 체결하고,
UI 전용 어노테이션(@UI.lineItem,@UI.selectionField)을 붙여서 화면 레이아웃 설정 - 하나의 Root View를 기반으로 일반 사용자용 프로젝션 뷰, 관리자용 프로젝션 뷰, 모바일 앱용 프로젝션 뷰 등 화면 목적에 따라 여러 개로 쪼개어 만들 수 있는 포장지 역할
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
define root view entity ZP_LDG_FLIGHT
provider contract transactional_query as projection on ZR_LDG_FLIGHT
{
// [필터바 추가] position 번호 순서대로 화면 왼쪽부터 배치됩니다.
// [테이블 컬럼 추가] lineItem이 붙은 필드만 Fiori 테이블에 컬럼으로 나타납니다.
@UI:{
lineItem: [{position: 10, label: 'Airline ID'}]
,selectionField: [{ position: 10}]
,identification: [{ position: 10, label: 'Airline ID' }]
}
key CarrierId,
@UI.lineItem: [{ position: 20, label: 'Connection ID' }]
key ConnectionId,
@UI.selectionField: [{ position: 20 }] // 날짜로도 검색할 수 있게 필터바 배치
@UI.lineItem: [{ position: 30, label: 'Flight Date' }]
key FlightDate,
@Semantics.amount.currencyCode: 'CurrencyCode'
@UI.lineItem: [{ position: 40, label: 'Price' }]
Price,
CurrencyCode,
@UI.lineItem: [{ position: 50, label: 'Plane Type' }]
PlaneTypeId,
@UI.lineItem: [{ position: 60, label: 'Max Seats' }]
SeatsMax,
@UI.lineItem: [{ position: 70, label: 'Occupied Seats' }]
SeatsOccupied
}
Define내 Annotation 정리 (눌러서 열기)
[메인 페이지 - Report Page]
@UI.selectionField: 화면 상단 검색 필터 영역에 입력 창을 띄우는 속성@UI.lineItem: 화면 중앙 데이터 그리드 테이블에 컬럼을 생성하는 속성position: 10, 20, 30...: 숫자가 작을수록 왼쪽(테이블) 또는 앞쪽(필터바)에 우선 배치됨 (보통 10 단위로 설계하여 향후 유지보수 시 사이에 필드를 끼워 넣을 수 있게 함)label: 라벨 지정@UI.identification: 로우 클릭 시 진입하는 상세 페이지(Object Page)의 기본 정보 탭에 값@UI.hidden: 컬럼 목록에는 나오지 않게 하되, 상세 페이지나 내부 로직에서는 쓰고 싶을 때 사용@UI.lineItem을 적지 않아도 동일 [상세 페이지 - Object Page]@UI.facet:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@UI.facet: [
/* --------------------------------------------------
[탭 1] 부모 바구니: 비행기 상세 정보 (위치 10)
-------------------------------------------------- */
{
id: 'GeneralInfo',
type: #COLLECTION,
label: '비행기 상세 정보',
position: 10
},
{
id: 'FlightDetail',
type: #IDENTIFICATION_REFERENCE,
label: '기본 인포',
parentId: 'GeneralInfo',
position: 10
},
/* --------------------------------------------------
[탭 2] 부모 바구니: 금액 정보 (위치 20)
-------------------------------------------------- */
{
id: 'PriceInfo',
type: #COLLECTION,
label: '금액 정보',
position: 20
},
{
id: 'PriceDetail',
type: #FIELDGROUP_REFERENCE,
label: '금액 세부사항',
parentId: 'PriceInfo',
position: 20,
targetQualifier: 'PriceGroup'
}
]
@UI.fieldGroup- 의미: 상세 페이지(Object Page) 내에서 관련된 필드들을 하나의 그룹(구역)으로 묶어서 예쁘게 배치 하고자 할 때 그룹 ID를 지정하는 속성입니다.
- 사용법 및 옵션:
[{ qualifier: 'GeneralInfo', position: 10, label: '만료일자' }]qualifier: 그룹의 고유 고스트 이름(ID)입니다. 나중에 이 ID를 가진 필드들만 한곳에 모여서 화면에 그려집니다.
요약
상세 페이지에만 필드를 보여주고 싶을 때: @UI.lineItem은 적지 않고, @UI.identification 또는 @UI.fieldGroup만 적는다.
- 화면에서 완전히 숨기고 싶을 때:
@UI.hidden: true를 선언한다. - 상세 페이지에 필드를 이쁘게 구획화할 때:
@UI.fieldGroup으로 묶고, 상단에@UI.facet으로 출력할 방을 파준다.
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.