News

AQ 실전 5/5 — Text Field Binding: @Semantics.text + @ObjectModel.text.element 완전 정복

▶ YouTube에서 보기
# AQ 실전 5/5 — Text Field Binding: @Semantics.text + @ObjectModel.text.element 완전 정복 ## 1. 왜 코드 필드에 텍스트 연결이 필요한가 SAP 시스템에서 다루는 대부분의 마스터 데이터는 **코드(Code)** 형태로 저장됩니다. Material 번호는 `100-100`, Sales Organization은 `1010`, Plant는 `1710` 같은 식이죠. 데이터베이스 입장에서는 짧은 키 값으로 저장하는 편이 인덱스 성능과 저장 효율 모두에 유리하기 때문입니다. 그러나 최종 사용자가 Fiori Elements 화면에서 `100-100`이라는 숫자만 보면 그 자재가 무엇인지 알 수 없습니다. 사용자는 `Trading Good 01` 같은 **사람이 읽을 수 있는 텍스트(Human-readable Text)** 를 함께 보길 원합니다. 전통적인 ABAP 보고서에서는 SELECT 문을 한 번 더 날려서 MAKT 테이블에서 자재명을 조회하고, 화면에 두 컬럼을 나란히 출력하는 방식으로 처리해왔습니다. CDS Analytics Query에서는 이러한 코드-텍스트 매핑을 **선언적으로(Declaratively)** 처리할 수 있습니다. `@ObjectModel.text.element`와 `@Semantics.text` 두 어노테이션만 정확히 선언하면, Fiori Elements가 자동으로 코드 옆에 텍스트를 표시해주거나, 코드를 숨기고 텍스트만 보여주거나, "코드 (텍스트)" 형태로 결합 표시하는 등 다양한 디스플레이 모드를 지원하게 됩니다. 이번 글에서는 코드 필드와 텍스트 필드를 어떻게 연결하는지, 그리고 여러 코드 필드에 각기 다른 텍스트를 연결하는 패턴까지 정리합니다. **AQ 실전 시리즈의 마지막 회차(5/5)** 이므로, 시리즈 전체 흐름을 마무리하는 의미도 함께 담아 작성합니다. --- ## 2. @ObjectModel.text.element 기초 문법 `@ObjectModel.text.element`는 **"이 코드 필드의 텍스트는 같은 View 안의 어느 필드를 봐라"** 라고 알려주는 어노테이션입니다. 동일한 CDS View 내에서 이미 SELECT 절에 포함된 텍스트 필드를 가리키는 방식이라, 추가적인 JOIN이나 Association 정의 없이 사용 가능합니다. 기본 문법은 다음과 같습니다. ```abap @ObjectModel.text.element: ['MaterialText'] Material, @Semantics.text: true MaterialText ``` 문법 핵심 포인트는 세 가지입니다. - **배열 형태**: `['MaterialText']`처럼 대괄호로 감싸야 합니다. 여러 텍스트 필드를 지정할 수도 있도록 배열 구조로 설계되어 있습니다. - **필드명 일치**: 배열 안에 적는 이름은 SELECT 절에 노출된 필드의 **alias 이름**과 정확히 일치해야 합니다. 대소문자도 그대로 따라야 활성화 단계에서 오류가 발생하지 않습니다. - **선언 위치**: 코드 필드 바로 위에 선언합니다. 빈 줄을 사이에 두면 일부 에디터에서 어노테이션 적용 범위가 모호해질 수 있으니, 주석을 제외하고는 바로 붙여 쓰는 편이 안전합니다. 이 어노테이션은 코드 필드와 같은 행에 텍스트가 함께 들어오는 구조, 즉 **Self-referencing Text** 패턴에 잘 맞습니다. 마스터 데이터가 View 내부에서 이미 JOIN되어 있어 텍스트 컬럼을 동시에 SELECT하는 일반적인 Sales/Material 분석 시나리오와 잘 어울립니다. --- ## 3. @Semantics.text: true 선언 `@ObjectModel.text.element`로 "이쪽을 봐라"라고 가리켰다면, 가리킨 대상 필드 쪽에서는 "내가 텍스트 필드이다"라는 신호를 보내야 합니다. 그 역할을 하는 어노테이션이 `@Semantics.text: true`입니다. ```abap @Semantics.text: true MaterialText ``` 이 한 줄이 누락되면 두 가지 문제가 생깁니다. 1. **활성화 경고**: CDS 활성화 시 `Text element 'MaterialText' must be annotated with @Semantics.text` 같은 경고 또는 오류가 발생할 수 있습니다. 시스템 설정에 따라 활성화 자체가 실패하기도 합니다. 2. **Fiori 동작 불일치**: 활성화는 통과해도, Fiori Elements 런타임에서 텍스트 필드를 일반 컬럼으로 인식해 코드와 텍스트가 별도 컬럼으로 따로 표시되거나, Display Mode 옵션이 비활성화될 수 있습니다. `@Semantics.text: true`는 일종의 **메타데이터 마커**입니다. 분석 엔진과 UI 프레임워크에게 "이 컬럼은 정렬, 필터링, 집계 대상이 아니라 어디까지나 보조 텍스트이다"라는 의미를 전달합니다. 그래서 Analytics Query 결과에서도 텍스트 필드가 자동으로 measure(측정값) 후보에서 제외되고, dimension의 부속 정보로 처리됩니다. 또한 `@Semantics.language` 어노테이션과 함께 사용하면 다국어 텍스트 처리도 가능합니다. 사용자의 로그온 언어에 따라 자동으로 해당 언어의 텍스트가 선택되는 동작이 일반적입니다. --- ## 4. 실전 코드 — ZQ_SalesQuery 전체 예시 시리즈에서 계속 다뤄온 `ZQ_SalesQuery`에 텍스트 바인딩을 적용해보겠습니다. 베이스가 되는 `ZC_SalesData` Composite View가 자재 텍스트와 판매조직 텍스트를 미리 JOIN해서 노출한다고 가정합니다. ```abap @AccessControl.authorizationCheck: #CHECK @EndUserText.label: 'Sales Analytics Query with Texts' @Analytics.query: true @OData.publish: true define view entity ZQ_SalesQuery as select from ZC_SalesData { @AnalyticsDetails.query.axis: #ROWS @ObjectModel.text.element: ['MaterialText'] Material, @Semantics.text: true MaterialText, @AnalyticsDetails.query.axis: #ROWS @ObjectModel.text.element: ['SalesOrgText'] SalesOrganization, @Semantics.text: true SalesOrgText, @AnalyticsDetails.query.axis: #COLUMNS CalendarYear, @DefaultAggregation: #SUM @Semantics.amount.currencyCode: 'Currency' NetAmount, @Semantics.currencyCode: true Currency } ``` 이 View가 활성화되어 Fiori Elements 앱(예: Analytical List Page)에 노출되면, 사용자 화면에는 다음과 같은 동작이 나타납니다. - Material 컬럼을 클릭하면 Display Mode를 선택할 수 있는 옵션이 나타나고, "Text Only", "ID Only", "Text and ID" 중에서 고를 수 있습니다. - 필터 입력 시 자재 코드뿐 아니라 자재명으로도 검색이 가능해집니다. - 정렬은 기본적으로 코드 기준이지만, 디스플레이 설정에 따라 텍스트 기준 정렬도 지원됩니다. - Export to Excel을 수행하면 코드와 텍스트가 함께 내보내져 후속 분석에 유용합니다. 여기에 `@AnalyticsDetails.query.display`를 추가하면 기본 디스플레이 모드까지 강제할 수 있습니다. ```abap @AnalyticsDetails.query.display: #KEY_TEXT @ObjectModel.text.element: ['MaterialText'] Material, ``` `#KEY_TEXT`는 "코드 — 텍스트" 형태로 둘 다 보이게 하고, `#TEXT`는 텍스트만, `#KEY`는 코드만 표시합니다. 운영 환경에서 사용자 페르소나별로 적절한 기본값을 잡아주면 사용성이 크게 향상됩니다. --- ## 5. 다중 코드-텍스트 연결 패턴 실제 보고서에서는 한 화면에 여러 코드 필드가 동시에 등장하는 경우가 많습니다. Material, Sales Organization, Distribution Channel, Plant, Customer 등 각각이 별도의 텍스트를 가집니다. 어노테이션은 코드 필드마다 **독립적으로** 선언하면 됩니다. ```abap @ObjectModel.text.element: ['MaterialText'] Material, @Semantics.text: true MaterialText, @ObjectModel.text.element: ['SalesOrgText'] SalesOrganization, @Semantics.text: true SalesOrgText, @ObjectModel.text.element: ['DistChannelText'] DistributionChannel, @Semantics.text: true DistChannelText, @ObjectModel.text.element: ['PlantText'] Plant, @Semantics.text: true PlantText ``` 이 패턴을 사용할 때는 다음 사항을 권장합니다. - **명명 규칙 일관성**: 코드 필드는 명사(Material), 텍스트 필드는 명사 + Text(MaterialText) 형태로 통일하면 가독성이 좋아집니다. 팀 내 명명 규칙 문서로 관리하면 유지보수가 수월합니다. - **그룹화**: 코드 필드와 그 텍스트 필드는 SELECT 절에서 서로 인접하게 배치하는 편이 좋습니다. 활성화 후 디버깅 시에도 매핑 관계가 한눈에 들어옵니다. - **불필요한 텍스트 제거**: 모든 코드에 텍스트가 필요한 것은 아닙니다. 예를 들어 CalendarYear 같은 시간 차원은 텍스트가 무의미하므로 굳이 추가하지 않습니다. 여러 언어 환경을 지원해야 한다면 베이스 Composite View 단계에서 언어 필터링이 적용된 텍스트를 JOIN해두는 편이 일반적입니다. Query Layer에서는 단순히 노출된 텍스트 필드에 어노테이션만 붙이는 책임을 가집니다. 이런 **계층 분리** 가 시리즈 전반에서 강조해온 Composite-Query 분리 원칙과 잘 맞아떨어집니다. --- ## 6. @ObjectModel.text.association vs @ObjectModel.text.element 비교 두 어노테이션은 이름이 비슷해서 헷갈리기 쉽지만, 작동 방식이 다릅니다. | 항목 | @ObjectModel.text.element | @ObjectModel.text.association | |------|---------------------------|-------------------------------| | 텍스트 소스 | 같은 View 내 다른 필드 | Association으로 연결된 다른 Entity | | 추가 JOIN 필요 | 불필요 (이미 SELECT에 포함) | Association 정의 필요 | | 성능 부담 | 낮음 | Association 호출 시 조회 발생 가능 | | 적합한 시나리오 | Composite View에서 텍스트를 미리 JOIN한 경우 | 별도 Text View가 표준으로 제공되는 경우 | | 다국어 처리 | Composite View에서 처리 | Association 대상 View에서 처리 | 권장 사용 기준은 다음과 같습니다. - **`text.element` 권장 케이스**: Composite View에서 마스터 데이터를 한 번에 평탄화(Flattening)했고, 텍스트가 dataset에 항상 포함되어야 하는 경우. Analytics Query에서 가장 흔하게 쓰이는 방식입니다. - **`text.association` 권장 케이스**: 텍스트 조회가 선택적이며, 사용자가 텍스트 표시를 요청할 때만 조회되도록 lazy loading을 하고 싶은 경우. 또는 SAP가 제공하는 표준 Text View(`I_MaterialText` 등)를 그대로 활용하는 경우. 대용량 분석 시나리오에서는 보통 `text.element` + Composite View 평탄화 조합이 응답 시간 측면에서 안정적인 편입니다. Association 방식은 ALV 같은 트랜잭션성 화면에서 효과적입니다. --- ## 7. 자주 발생하는 오류와 해결법 ### 오류 1: "Text element 'XXX' is not defined" `@ObjectModel.text.element: ['MaterialText']`라고 선언했지만 SELECT 절에 `MaterialText` 필드가 없거나 이름이 다른 경우입니다. 대소문자 차이나 단순 오타가 가장 흔한 원인입니다. SELECT 절의 alias를 다시 확인하고, 베이스 View에서 해당 텍스트 컬럼이 정말 노출되어 있는지 점검해야 합니다. ### 오류 2: "@Semantics.text is missing" 텍스트 필드에 `@Semantics.text: true`를 선언하지 않은 경우입니다. 경고로 끝나는 시스템도 있지만, 일부 릴리스에서는 활성화 실패로 이어집니다. 모든 텍스트 필드에 빠짐없이 어노테이션을 다는 습관이 중요합니다. ### 오류 3: Fiori 화면에 텍스트가 표시되지 않음 활성화는 성공했는데 정작 화면에는 코드만 보이는 경우가 있습니다. 점검 순서는 다음과 같습니다. 1. OData 메타데이터(`$metadata`) 호출 결과에 텍스트 필드가 포함되어 있는지 확인합니다. 2. 텍스트 필드의 `sap:text` 속성이 코드 필드를 가리키는지 확인합니다. 3. Fiori Elements 앱의 Manifest에서 컬럼 설정이 텍스트 표시를 막고 있지 않은지 확인합니다. 4. 캐시 문제일 수 있으므로 `/IWFND/CACHE_CLEANUP`, `/UI2/INVALIDATE_CACHES` 같은 캐시 무효화 트랜잭션을 실행해봅니다. ### FAQ **Q1. 텍스트 필드도 measure로 집계되나요?** A. `@Semantics.text: true`가 선언되어 있으면 일반적으로 집계 대상에서 제외됩니다. 차원 필드의 보조 정보로 취급됩니다. **Q2. 한 코드에 두 개 이상의 텍스트를 매핑할 수 있나요?** A. 배열이므로 문법상 가능하지만, 실제 Fiori Elements가 다중 텍스트를 어떻게 렌더링하는지는 컨트롤별로 다릅니다. 일반적으로는 첫 번째 항목이 우선 사용됩니다. **Q3. 베이스 테이블의 텍스트를 그대로 가져와도 되나요?** A. 됩니다. 다만 다국어 처리, NULL 처리, 성능 등을 고려하면 Composite View 단계에서 한 번 가공해서 노출하는 편이 안정적입니다. --- ## 8. AQ 실전 시리즈 마무리 다섯 편에 걸친 Analytics Query 실전 시리즈가 이번 글로 마무리됩니다. 다시 한 번 큰 그림을 정리하면 다음과 같습니다. - **1편 — Analytics Query 기본 구조**: `@Analytics.query: true`를 시작점으로, Composite View와 Query View의 역할 분리, `@OData.publish`를 통한 외부 노출까지 이어지는 기본 아키텍처를 다뤘습니다. - **2편 — Row/Column Axis 설정**: `@AnalyticsDetails.query.axis: #ROWS`와 `#COLUMNS`로 피벗 보고서의 행/열을 선언하는 패턴, 그리고 `#FREE` 축으로 사용자 인터랙션을 허용하는 방식을 정리했습니다. - **3편 — Display & Aggregation**: `@AnalyticsDetails.query.display`로 코드/텍스트 표시 모드를 제어하고, `@DefaultAggregation`으로 SUM/AVG/MIN/MAX 같은 기본 집계 동작을 지정하는 방법을 다뤘습니다. - **4편 — Currency & Unit Semantics**: `@Semantics.amount.currencyCode`, `@Semantics.quantity.unitOfMeasure`로 통화/단위를 명시해 Fiori에서 자동 포맷팅이 이뤄지도록 하는 패턴을 정리했습니다. - **5편 (이번 글) — Text Field Binding**: `@ObjectModel.text.element`와 `@Semantics.text: true`로 코드-텍스트 매핑을 선언적으로 처리하는 마지막 퍼즐을 맞췄습니다. 이 다섯 가지 어노테이션 패턴을 조합하면 ABAP 코드 한 줄 작성하지 않고도 **Fiori 친화적인 분석 보고서**를 구축할 수 있습니다. 핵심은 "Composite View에서 데이터를 깨끗하게 평탄화하고, Query View에서 어노테이션으로 사용자 경험을 선언한다"는 계층 분리 원칙입니다. 이 원칙만 지키면 새로운 KPI나 차원을 추가할 때도 영향 범위를 좁게 유지할 수 있고, 테스트와 유지보수가 한결 수월해집니다. 운영 환경에 적용할 때는 다음 체크리스트를 권장합니다. - Composite View와 Query View의 책임 경계가 명확한가 - 모든 amount/quantity 필드에 단위/통화 어노테이션이 붙어 있는가 - 모든 code 필드에 텍스트 매핑이 적절히 연결되어 있는가 - Authorization, Currency Conversion 등 보안/규정 요건이 반영되었는가 - 성능 측면에서 Aggregation Push-down이 정상 작동하는지 ST05/SAT로 검증했는가 CDS Analytics Query는 단순한 SQL 조회 도구가 아니라, **분석 의도를 메타데이터로 표현하는 선언적 모델링 언어**에 가깝습니다. 어노테이션 하나하나가 Fiori, OData, Analytics Engine, Authorization Framework 등 여러 컴포넌트에 신호를 보내며, 그 조합으로 풍부한 사용자 경험이 만들어집니다. 시리즈에서 다룬 패턴들이 실제 SAP S/4HANA 또는 BTP ABAP Environment 프로젝트에서 견고한 분석 레이어를 설계하는 출발점이 되길 바랍니다. 다음 시리즈에서는 Analytics Query 위에 얹는 **Custom Analytical Query (KQUERY)**, **Multidimensional Report**, **SAC Live Connection** 같은 상위 분석 도구로 시야를 넓혀가는 주제를 다룰 예정입니다. 이번 시리즈를 끝까지 따라와주신 분들께 감사드리며, 여러분의 ABAP 분석 모델링 여정에 좋은 디딤돌이 되었기를 바랍니다.

댓글 0

아직 댓글이 없습니다.