데이터 제품 모듈 만들기

자체 비즈니스 로직 및 분석 모델을 정의하려면 커스텀 데이터 제품 모듈을 만드세요. 이렇게 하면 기본 테이블 또는 업스트림 데이터 제품에서 계산을 실행하고 결과를 배포 가능한 데이터 세트로 패키징할 수 있습니다.

기본 요건

수명 주기 관리를 개선하려면 전용 커스텀 네임스페이스에서 커스텀 데이터 제품 모듈을 만드는 것이 좋습니다. 또한 사용하려는 소스 테이블이 데이터 기본 데이터 세트에 있는지 확인합니다.

데이터 제품 모듈 만들기

데이터 제품 모듈 정의에는 다음 단계가 필요합니다.

  • config/config.yaml 파일 내에서 데이터 제품 모듈을 등록합니다. 항목으로 data.modules.products 목록을 확장합니다.
data:
  # Configuration for data foundation and product modules.
  modules:
    # List of data product modules.
    products:
        # Recommended naming for product_module_id:
        # custom_namespace_product_name
      - moduleId:  product_module_id
        # Path of the data product (namespaced).
        modulePath:  custom_namespace.system_type.products.product_name
        # Map of module dependencies.
        dependencyBindings:
          sapModule: erp
          sapModuleCustNS:  foundation_module_id
        # Reference to the target dataset ID.
        dataTargetId: product_target
        # Whether the module is enabled.
        # enabled: true
        # Whether the foundation is external (does not create target dataset).
        # external: false
        # Custom table settings file, relative to 'config/' file directory
        # Recommended path: '{custom_namespace}/{system_type}/products/{product_name}/table_settings.yaml'
        # If omitted, defaults to '../src/data_modules/{custom_namespace}/{system_type}/products/{product_name}/table_settings.default.yaml'
        # tableSettings: "{custom_namespace}/{system_type}/products/{product_name}/table_settings.yaml"
        
  • 기본 tableSettings 파일 (예: src/data_modules/custom_namespace/system_type/products/product_name/table_settings.default.yaml)을 만듭니다.

이 YAML은 테이블 구성과 같은 구체화 및 BigQuery 최적화 세부정보를 제어합니다.

common:
  custom_sales_summary:
    materializationType: "table"
    bigQueryLabels:
      - key: data_class
        value: transactional
    dataformTags: ["custom", "sales", "reporting"]
    partitionDetails:
      column: "created_date"
      partitionType: "date"
      timeGrain: "day"
    clusterDetails:
      columns:
        - "customer_id"
  • 주석 파일을 만듭니다.

주석 파일 tablename.yaml은 각 데이터 제품 출력 아티팩트 (테이블, 뷰)에 대해 생성되며 YAML 형식으로 열과 필드를 설명합니다. 컴파일 중에 빌더는 제품의 annotations/ 폴더 (예: src/data_modules/custom_namespace/system_type/products/product_name/annotations/custom_sales_summary.yaml) 내에서 주석을 자동으로 검색하고 이러한 문자열을 출력 Dataform 스키마 정의에 직접 병합하여 BigQuery 테이블 메타데이터에 보존되도록 합니다.

주석 src/data_modules/custom_namespace/system_type/products/product_name/annotations/tablename.yaml 파일의 형식은 다음과 같습니다.

description: "Description of the table or view purpose"
fields:
  - name: "customer_id"                     # column name
    description: "Customer identifier"      # column description
  - name: "column2"
    description: "Description of Column 2"
  - name: "column3"
    description: "Description of Column 3"
  • 데이터 제품 폴더 src/data_modules/custom_namespace/system_type/products/product_name/에서 유형, 카테고리, 테이블, 모듈 종속 항목을 유지하면서 manifest.yaml 파일을 만듭니다. 매니페스트 파일은 다음 형식을 따릅니다.
displayName: Sales Performance Summary
description: Sales performance analytical data product.
category: product
type: generic
builder: sap_product     # Automatically resolves to the global SapProductBuilder fallback
dependencies:
  sapModule:
    modulePath: cortex.sap.foundations.sap
    supportedVersions:
      - ecc
      - s4

데이터 제품 모듈 예시

항공편 예시의 네임스페이스 sap_bookingdatamodel에서 flights_usd 데이터 제품을 구현하는 단계는 다음과 같습니다.

  • config/config.yaml 파일 내에서 데이터 제품 모듈을 등록합니다. 항목으로 data.modules.products 목록을 확장합니다.
data:
  modules:
    products:
      - moduleId: sap_bookingdatamodel_flights_usd
        modulePath: sap_bookingdatamodel.sap.products.flights_usd
        dependencyBindings:
          sapModule: erp
          sapModuleCustNS: sap_bookingdatamodel
        dataTargetId: product_target
  • 다음으로 콘텐츠가 포함된 src/data_modules/sap_bookingdatamodel/sap/products/flights_usd/manifest.yaml을 만듭니다.
displayName: Flights USD
description: Flight scheduling and pricing USD data product.
category: product
type: generic
dependencies:
  sapModule:
    modulePath: cortex.sap.foundations.sap
    supportedVersions:
      - ecc
      - s4
    tables:
      common:
        - tcurr
  sapModuleCustNS:
    # Type of the dependent Module.
    # use cortex.sap.foundations.sap if you followed "Configure multiple instances of a data foundation module"
    # https://docs.cloud.google.com/cortex/docs/deployment-configuration#multiple-data-foundation-instances
    modulePath: cortex.sap.foundations.sap
    # use sap_bookingdatamodel.sap.foundations.sap if you are connecting to custom-data foundation module:
    # https://docs.cloud.google.com/cortex/docs/extensibility-guide-data-foundation
    #modulePath: sap_bookingdatamodel.sap.foundations.sap
    supportedVersions:
      - ecc
      - s4
    tables:
      common:
        - sflight
builder: sap_product
  • 다음 단계에서는 참조된 테이블 설정 파일을 만들어 BigQuery의 출력 테이블 또는 뷰의 스키마와 메타데이터를 구성합니다.

사용된 예시에서 콘텐츠가 포함된 src/data_modules/sap_bookingdatamodel/sap/products/flights_usd/table_settings.default.yaml을 만듭니다.

ecc:
  flights_usd:
    materializationType: incremental
    bigQueryLabels:
      - key: data_class
        value: transactional
    dataformTags: [sap, dataproduct, masterdata]
s4:
  flights_usd:
    materializationType: incremental
    bigQueryLabels:
      - key: data_class
        value: transactional
    dataformTags: [sap, dataproduct, masterdata]

  • 데이터 제품 테이블의 주석을 만들어 설명으로 스토리지 스키마를 보강합니다.

사용된 예시에서 콘텐츠가 포함된 src/data_modules/sap_bookingdatamodel/sap/products/flights_usd/annotations/flights_usd.yaml 파일을 만듭니다.

description: "Flight scheduling and pricing information, including currency conversion to USD."
fields:
  - name: "client_mandt"
    description: "Client (Mandant), PK"
  - name: "airline_code_carrid"
    description: "Airline Carrier ID, PK"
  - name: "flight_connection_number_connid"
    description: "Flight Number, PK"
  - name: "flight_date_fldate"
    description: "Flight Date"
  - name: "price_usd"
    description: "Price in USD"
  - name: "price"
    description: "Price in local currency"
  - name: "currency"
    description: "Local currency"
  • 데이터 제품의 비즈니스 로직은 js 또는 sqlx 파일에 저장됩니다.

제공된 예시에서 콘텐츠가 포함된 src/data_modules/sap_bookingdatamodel/sap/products/flights_usd/definitions/flights_usd.js 파일을 만듭니다.

// ___MODULE_CONTEXT___
// ___TABLE_CONFIG___

const moduleConfig = config.product[moduleContext.moduleId];
const sapModuleConfigDatasetId = moduleConfig.sources.sapModule.datasetId;
const sapModuleCustNSConfigDatasetId = moduleConfig.sources.sapModuleCustNS.datasetId;

const materializationType = tableConfig.materializationType || "incremental";

const incremental = require("includes/cortex/incremental.js");
const publish_config = require("includes/cortex/publish_config.js");

const publishConfig = publish_config.getPublishConfig(
   materializationType,
   tableConfig,
   moduleConfig,
   [
       "client_mandt",
       "airline_code_carrid",
       "flight_connection_number_connid",
       "flight_date_fldate"
   ]
);

publish("flight_usd", publishConfig).query(
   (ctx) => `
WITH flight_base AS (
   SELECT
       mandt,
       carrid,
       connid,
       fldate,
       price,
       currency,
       -- Convert flight date string (YYYYMMDD) to an integer to calculate SAP's inverted date key
       CAST(99999999 - CAST(fldate AS INT64) AS STRING) AS inverted_fldate
   FROM   ${ctx.ref(sapModuleCustNSConfigDatasetId, 'sflight')} AS flight
),
ranked_exchange_rates AS (
   SELECT
       f.mandt,
       f.carrid,
       f.connid,
       f.fldate,
       f.price,
       f.currency,
       t.ukurs,
       -- Window function to grab the closest historical exchange rate
       ROW_NUMBER() OVER (
           PARTITION BY f.mandt, f.carrid, f.connid, f.fldate
           ORDER BY t.gdatu ASC
       ) AS latest_rate_rank
   FROM flight_base f
   LEFT JOIN ${ctx.ref(sapModuleConfigDatasetId, 'tcurr')} AS t
     ON f.mandt = t.mandt
    AND t.kurst = 'M'       -- 'M' is the standard SAP default for average exchange rates
    AND t.fcurr = f.currency
    AND t.tcurr = 'USD'
    -- Chronological (rate_date <= flight_date) translates to (t.gdatu >= inverted_fldate)
    AND t.gdatu >= f.inverted_fldate
)

SELECT
   client_mandt,
   airline_code_carrid,
   flight_connection_number_connid,
   flight_date_fldate,
   price,
   currency,
   price_usd,
   CURRENT_TIMESTAMP() AS bq_loaded_at
FROM (
  SELECT
    mandt              AS client_mandt,
    carrid             AS airline_code_carrid,
    connid             AS flight_connection_number_connid,
    PARSE_TIMESTAMP('%Y%m%d', fldate) AS flight_date_fldate,
    price              AS price,
    currency           AS currency,
    -- Currency Conversion Logic
    CASE
       WHEN currency = 'USD' THEN price
       WHEN ukurs IS NULL   THEN NULL -- Handles cases where no exchange rate is found
       -- If UKURS is negative, it's an indirect quotation (1 USD = X Local) -> Divide
       WHEN ukurs < 0       THEN ROUND(price / ABS(ukurs), 2)
       -- If UKURS is positive, it's a direct quotation (1 Local = X USD) -> Multiply
       ELSE ROUND(price * ukurs, 2)
     END AS price_usd
  FROM ranked_exchange_rates
  WHERE latest_rate_rank = 1
)
${incremental.getWhere(ctx, ["flight_date_fldate"])}
`
);

커스텀 네임스페이스 확장 확인

Google Cloud Cortex Framework 데이터 제품 모듈이 성공적으로 생성되었는지 확인하려면 다음 단계를 따르세요.