SAP Fiori Elements — Annotation 기반 List Report & Object Page 완전 가이드



1. 개요 및 학습 목표
SAP Fiori Elements는 어노테이션(Annotation)만으로 표준화된 UI를 자동 생성하는 프레임워크입니다. 별도의 프론트엔드 코드 없이 CDS 뷰와 메타데이터 주석을 정의하면, List Report(목록 보고서)와 Object Page(상세 페이지)가 만들어집니다. 이 가이드에서는 ABAP RESTful Application Programming Model(RAP) 기반 OData V4 서비스에서 어노테이션을 활용하여 실무 수준의 Fiori Elements 앱을 구성하는 전 과정을 다룹니다.
이 튜토리얼을 완료하면 다음을 할 수 있습니다:
- CDS 어노테이션으로 List Report 테이블 컬럼, 필터, 정렬을 정의할 수 있다
- Object Page의 헤더, 패싯, 필드그룹을 구성할 수 있다
- Value Help, Criticality, Action 등 실무 시나리오를 구현할 수 있다
- Side Effects, Draft, Feature Control, Presentation Variant를 적용할 수 있다
- 어노테이션 관련 흔한 오류를 진단하고 해결할 수 있다
2. 선수 지식
이 가이드를 효과적으로 따라가려면 다음 지식이 필요합니다:
- ABAP CDS 뷰 기본 문법 (define view entity, association 등)
- OData 서비스의 기본 개념 (Entity Set, Property, Navigation)
- RAP(RESTful Application Programming Model)의 Behavior Definition 구조에 대한 기초 이해
- SAP Business Technology Platform(BTP) 또는 온프레미스 ABAP 시스템 접속 경험
3. 환경 / 버전 / 준비물
본 가이드는 아래 환경을 기준으로 작성되었습니다. 온프레미스 환경에서도 해당 버전 이상이면 동일하게 적용할 수 있습니다.
| 항목 | 버전 / 에디션 |
|---|---|
| ABAP Platform Cloud | SAP BTP, ABAP Environment (최신) |
| ABAP Platform 온프레미스 | 2022 (AS ABAP 7.57) 이상, 2023 (AS ABAP 7.58) 권장 |
| OData 버전 | V4 (UI5 V4 모델) |
| 개발 도구 | ABAP Development Tools (ADT) in Eclipse, 또는 SAP Business Application Studio |
| UI5 버전 | 1.120 이상 권장 |
준비물: RAP 기반 CDS 뷰 엔티티, Behavior Definition(BDEF), Service Definition 및 Service Binding이 생성되어 있어야 합니다. OData V4 서비스를 미리보기할 수 있는 환경이 갖추어져 있어야 합니다.
4. 핵심 개념
어노테이션이 UI가 되기까지
Fiori Elements의 동작 원리를 건축에 비유하면 이해하기 쉽습니다. 일반적인 웹 앱 개발이 "벽돌을 하나씩 쌓아 집을 짓는 것"이라면, Fiori Elements는 "설계도(어노테이션)만 제출하면 표준 공장(프레임워크)이 집을 자동으로 지어주는 것"입니다.
핵심 흐름은 다음과 같습니다:
CDS View Entity (데이터 모델 + 어노테이션 정의) → OData V4 Metadata ($metadata 문서로 변환) → Fiori Elements Runtime (메타데이터 해석) → SAPUI5 컨트롤 자동 렌더링
이 과정에서 개발자가 작성하는 것은 CDS 어노테이션뿐입니다. 프레임워크가 메타데이터를 읽어 적절한 UI 컨트롤을 배치합니다.
List Report vs Object Page
List Report는 엔티티 목록을 테이블 형태로 보여주는 페이지입니다. @UI.lineItem으로 컬럼을, @UI.selectionField로 필터 바를 정의합니다. Object Page는 개별 엔티티의 상세 정보를 표시하는 페이지로, @UI.headerInfo로 헤더를, @UI.facet으로 섹션 구조를, @UI.fieldGroup과 @UI.identification으로 필드 배치를 제어합니다.
주요 어노테이션 카테고리
- @UI 계열: lineItem, selectionField, headerInfo, facet, fieldGroup, presentationVariant — UI 레이아웃과 동작을 정의
- @Consumption 계열: valueHelpDefinition, semanticObject — Value Help와 네비게이션 연결
- @ObjectModel 계열: text.element, resultSet.sizeCategory — 텍스트 연결 및 드롭다운 제어
- @Semantics 계열: timeZone, currencyCode, unitOfMeasure — 데이터 시맨틱 힌트
5. 실전 코드 3단계
1단계: 기본 예제 — LineItem, SelectionField, HeaderInfo
가장 기본적인 List Report를 만들기 위해 필요한 세 가지 어노테이션입니다. 아래 예제는 Travel(여행) 엔티티 기반입니다.
HeaderInfo — 엔티티의 표시 이름 정의:
@UI: {
headerInfo: {
typeName: 'Travel',
typeNamePlural: 'Travels'
},
presentationVariant: [{
sortOrder: [{ by: 'LocalLastChangedAt', direction: #DESC }],
visualizations: [{ type: #AS_LINEITEM }]
}]
}
typeName은 Object Page 타이틀에, typeNamePlural은 List Report 타이틀에 사용됩니다. presentationVariant는 기본 정렬 순서와 시각화 방식을 지정합니다.
SelectionField — 필터 바 구성:
@UI.selectionField: [{ position: 10 }]
AgencyID;
@UI.selectionField: [{ position: 20 }]
CustomerID;
position 값이 작을수록 필터 바의 왼쪽에 배치됩니다. 자주 사용하는 검색 조건을 낮은 position으로 지정하는 것이 일반적입니다.
LineItem — 테이블 컬럼 정의:
@UI.lineItem: [
{
position: 20,
importance: #HIGH,
label: 'String Property'
}
]
StringProperty;
importance는 화면 폭이 줄어들 때 컬럼 표시 우선순위를 결정합니다. #HIGH는 항상 표시, #MEDIUM은 태블릿 이상, #LOW는 데스크톱에서만 표시됩니다.
2단계: 실무 시나리오 — Value Help, Criticality, Actions
Value Help 연결:
사용자가 필드 값을 선택할 수 있도록 Value Help 엔티티를 연결합니다. additionalBinding으로 관련 필드를 함께 채울 수 있습니다.
@Consumption.valueHelpDefinition: [
{
entity: { name: '/DMO/I_Customer', element: 'CustomerID' }
}
]
CustomerID;
추가 바인딩이 필요한 경우, usage 속성으로 동작을 제어합니다. #RESULT는 선택 결과를 해당 필드에 채우고, #FILTER는 Value Help 목록 자체를 필터링합니다.
@Consumption.valueHelpDefinition: [
{
entity: { name: '/DMO/FSA_I_Criticality', element: 'Code' },
additionalBinding: [{ element: 'Name',
localElement: 'FieldWithCriticality',
usage: #RESULT }]
}
]
CriticalityCode;
선택지가 적은 경우(예: 상태 코드) 드롭다운으로 표시하려면 Value Help 엔티티에 다음 어노테이션을 추가합니다:
@ObjectModel: { resultSet.sizeCategory: #XS }
define view entity /DMO/FSA_I_Criticality
Criticality (색상 강조):
특정 필드의 값에 따라 셀 색상을 변경하여 시각적 상태를 표현합니다. Criticality 값은 0(회색/중립), 1(빨강/에러), 2(노랑/경고), 3(초록/성공)입니다.
@UI.lineItem: [{ position: 80, criticality: 'OverallStatusCriticality' }]
OverallStatus;
Criticality 값은 CDS 뷰에서 계산합니다:
case overall_status
when 'O' then 2 -- 노란색 (Open)
when 'A' then 3 -- 초록색 (Accepted)
when 'X' then 1 -- 빨간색 (Rejected)
else 0 -- 회색 (기본)
end as OverallStatusCriticality,
텍스트 연결과 표시 방식:
ID 필드에 사람이 읽을 수 있는 텍스트를 연결하고, 표시 방식을 제어합니다:
@ObjectModel.text.element: ['AgencyName']
AgencyID,
_Agency.Name as AgencyName,
@UI.textArrangement: #TEXT_ONLY
OverallStatus;
Actions — 테이블 툴바 액션:
List Report 테이블에 사용자 정의 버튼을 추가합니다:
@UI.lineItem: [
{
type: #FOR_ACTION,
label: 'Change Criticality',
dataAction: 'changeCriticality',
position: 10
}
]
LastChangedAt;
BDEF에서 해당 액션을 선언합니다:
action changeCriticality parameter /DMO/FSA_D_ChangeCriticalityP result [1] $self;
인라인 액션(행 내부 버튼)이 필요하면 inline: true를 추가합니다:
@UI.lineItem: [
{
type: #FOR_ACTION,
label: 'Change Progress',
dataAction: 'changeProgress',
inline: true,
emphasized: true,
importance: #HIGH,
position: 100
}
]
LastChangedAt;
Copy 액션은 isCopyAction: true로 지정하며, BDEF에서는 factory action으로 선언합니다:
factory action copyInstance [1];
3단계: 프로덕션 — Side Effects, Draft, Feature Control, Presentation Variant
Side Effects:
사용자가 특정 필드를 변경했을 때 연관 필드를 자동으로 다시 읽어오도록 BDEF에서 선언합니다. 예를 들어 타임존 필드를 바꾸면 타임스탬프 표시가 갱신되어야 합니다:
side effects {
field SAPTimezone affects field IANATimestamp, field IANATimezone;
field Timestamp affects field IANATimestamp;
}
Side Effects를 활용하면 사용자가 저장 전에 즉시 계산 결과를 확인할 수 있어 UX가 크게 개선됩니다.
Draft 지원:
Draft는 사용자가 저장하지 않은 중간 상태를 서버에 보관하는 기능입니다. BDEF에서 with draft를 선언하면 Fiori Elements가 자동으로 Draft 관련 UI(편집/활성화 버튼, 잠금 표시 등)를 생성합니다. 트랜잭션 앱에서는 Draft 적용이 일반적으로 권장됩니다.
Feature Control (필드/액션 활성화 제어):
특정 조건에 따라 필드를 읽기 전용으로 만들거나 액션 버튼을 비활성화할 수 있습니다. 이는 BDEF의 features: instance 선언과 RAP handler의 get_instance_features 메서드로 구현합니다. 예를 들어, 상태가 "승인됨"이면 수정 불가로 처리할 수 있습니다.
Presentation Variant — 기본 정렬과 시각화:
@UI.presentationVariant: [{
sortOrder: [{ by: 'LocalLastChangedAt', direction: #DESC }],
visualizations: [{ type: #AS_LINEITEM }]
}]
Presentation Variant는 List Report가 처음 열릴 때의 기본 정렬 순서와 시각화 유형을 결정합니다. Selection Variant와 결합하면 미리 정의된 필터 조건까지 함께 적용할 수 있습니다.
Object Page Facet 구성:
Object Page의 섹션 구조는 @UI.facet으로 정의합니다. 중첩 구조를 사용하면 탭 안에 여러 컬렉션을 배치할 수 있습니다:
@UI.facet: [
{
parentId : 'Nested',
id : 'TimeAndDate',
label : 'Time and Date',
type : #COLLECTION
},
{
parentId : 'TimeAndDate',
type : #FIELDGROUP_REFERENCE,
targetQualifier: 'TimezoneInput',
label : 'SAP Timezone'
}
]
#COLLECTION 타입이 상위 그룹이 되고, 하위에 #FIELDGROUP_REFERENCE로 필드그룹을 배치합니다. parentId로 부모-자식 관계를 연결합니다.
Intent-Based Navigation:
다른 Fiori 앱으로의 네비게이션을 어노테이션으로 선언합니다:
@Consumption.semanticObject: 'FeatureShowcaseNavigation'
@UI.lineItem: [
{
label: 'Navigate to Target App',
type: #FOR_INTENT_BASED_NAVIGATION,
semanticObjectAction: 'manage',
requiresContext: true
}
]
NavigationID;
6. 흔한 실수 / 트러블슈팅
FAQ 1: LineItem 어노테이션을 추가했는데 컬럼이 테이블에 나타나지 않습니다
position 값이 누락되면 프레임워크가 컬럼 순서를 결정하지 못해 표시되지 않을 수 있습니다. 또한 Metadata Extension 파일을 사용하는 경우, 원본 CDS 뷰가 아닌 Extension 파일에 어노테이션을 작성해야 합니다. 서비스 바인딩을 재활성화(Publish)한 뒤 브라우저 캐시를 삭제하고 다시 확인하세요.
FAQ 2: Value Help 팝업이 열리지 않거나 데이터가 비어 있습니다
@Consumption.valueHelpDefinition의 entity.name이 실제 존재하는 CDS 뷰 엔티티 이름과 정확히 일치하는지 확인하세요. element에 지정한 필드명도 대소문자를 포함하여 정확해야 합니다. additionalBinding의 localElement가 현재 뷰에 실제로 존재하는 필드명인지도 점검해야 합니다.
FAQ 3: Criticality 색상이 전혀 반영되지 않습니다
criticality 속성에 지정한 필드 이름이 CDS 뷰에 실제로 존재해야 합니다. 해당 필드의 데이터 타입은 정수형이어야 하며, 값이 0~3 범위 밖이면 무시됩니다. Criticality 필드를 @UI.lineItem이나 @UI.fieldGroup의 criticality 속성에 문자열(필드명)로 지정해야지, 직접 정수를 넣으면 안 됩니다.
FAQ 4: Side Effects가 동작하지 않습니다
Side Effects는 Draft가 활성화된 엔티티에서만 동작합니다. BDEF에 with draft가 선언되어 있는지 확인하세요. 또한 field 뒤에 오는 필드명은 BDEF의 엔티티에 정의된 필드명과 정확히 일치해야 합니다.
FAQ 5: 액션 버튼을 눌렀는데 "Action not found" 오류가 발생합니다
dataAction에 지정한 액션 이름이 BDEF에 선언된 action 이름과 정확히 같은지 확인하세요. 액션에 파라미터가 필요한 경우 파라미터 구조체가 올바르게 정의되어 있어야 합니다. 서비스 바인딩을 다시 Publish하는 것도 필수입니다.
7. 다음 단계 / 관련 주제
이 가이드에서 다룬 내용을 바탕으로 다음 주제를 탐색해 볼 수 있습니다:
- Analytical List Page: 차트와 테이블을 결합한 분석용 Fiori Elements 플로어플랜
- Overview Page: 여러 데이터 소스를 카드 형태로 한 화면에 표시
- Flexible Programming Model: Custom Section, Custom Column 등 Fiori Elements 위에 커스텀 UI를 추가하는 확장 기법
- SAP Build와 Joule 활용: 저코드 도구와 AI 어시스턴트를 활용한 어노테이션 자동 생성
- Micro Chart, Rating/Progress Indicator: 테이블 셀 안에 차트와 게이지를 표시하는 고급 시각화
8. 참고 자료
- SAP Help — RAP Value Help 제공
- SAP Help — RAP Actions
- SAP Help — Intent-Based Navigation
- SAP Help — ABAP RAP Tables
- GitHub — ABAP Platform Fiori Feature Showcase (SAP 공식 샘플)
- GitHub — openSAP Fiori Elements 학습 자료
- Mindset Consulting — Fiori List Report with CDS Annotations
📌 본 게시물은 AI(Claude)가 공개된 자료를 기반으로 자동 생성한 콘텐츠입니다. 기술 내용의 정확성은 SAP 공식 문서 와 교차 확인하시기 바랍니다.
™ SAP, S/4HANA, ABAP, Fiori, SAP BTP 등은 SAP SE 또는 그 계열사의 등록 상표입니다. 본 사이트는 SAP SE 와 공식적인 관련이 없는 비공식 학습 자료 입니다.
📧 저작권 침해 / 오류 / 콘텐츠 신고: btpstacks.com 의 "문의" 메뉴를 이용해주세요.