시각화 구성요소를 사용하여 커스텀 시각화 빌드

이 튜토리얼은 숙련된 JavaScript 개발자를 대상으로 하며 기능 프로그래밍 기법에 익숙하다고 가정합니다.

이 예시에서는 일부 브랜드의 분기별 가상 판매 정보와 관련된 쿼리로 시작합니다. 먼저 특정 브랜드에 대한 쿼리를 필터링한 후 판매 분기별로 결과를 피벗합니다. 예시는 다음 표를 참조하세요.

주문 생성 분기 측정기준을 피벗하는 브랜드별 주문 수에 대한 쿼리 결과

그런 다음 시각화 구성요소를 사용하여 지난 분기 동안 각 브랜드 제품의 추세를 보여주는 커스텀 시각화를 만들어 보겠습니다. 그 결과, 다음 예시와 같이 테이블 내에 중첩된 일련의 스파크라인으로 구성된 새로운 종류의 시각화가 생성됩니다.

브랜드별 행이 있는 테이블과 각 행에 분기별 주문 수를 보여주는 삽입된 스파크라인 시각화가 표시된 커스텀 빌드 시각화

이 예시는 커스텀 시각화를 만드는 방법을 보여주고 React 애플리케이션 내에서 Looker API를 사용하기 위한 몇 가지 권장사항을 보여줍니다.

Looker 구성요소로 맞춤설정된 시각화를 빌드하려면 설정이 요구사항을 충족하는지 확인한 후 다음 단계를 수행합니다.

  1. Explore에서 쿼리를 빌드하고 qid 값 복사
  2. 커스텀 시각화 구성요소에 데이터 전달
  3. CustomVis 구성요소 빌드
  4. 정규화된 데이터 변환
  5. 변환된 데이터를 CustomVis에 삽입
  6. 커스텀 시각화 생성

임베디드 애플리케이션 또는 확장 프로그램을 위한 커스텀 시각화를 원하는 경우 시각화 구성요소를 사용하여 커스텀 시각화를 빌드하는 것이 적합합니다. Looker 인스턴스에서 Looker 사용자가 커스텀 시각화를 사용할 수 있도록 하려면 visualization 문서 페이지의 안내를 따르세요. 커스텀 시각화를 개발하여 Looker Marketplace에 업로드하려면 Looker Marketplace용 커스텀 시각화 개발 문서 페이지의 안내를 따르세요.

요구사항

시작하기 전에 몇 가지 요소가 필요합니다.

  • Looker 인스턴스에 대한 액세스 권한이 있어야 합니다.
  • 확장 프로그램 프레임워크에서 빌드하든 독립 실행형 React 애플리케이션에서 빌드하든 상관없이 Looker의 API로 인증하고 Looker SDK 객체에 액세스할 수 있어야 합니다. 자세한 내용은 Looker API 인증 또는 확장 프로그램 프레임워크를 참조하세요.
  • Looker 시각화 구성요소 NPM 패키지@looker/components-data NPM 패키지를 설치했는지 확인합니다. 시각화 구성요소 패키지 설치 및 사용에 대한 자세한 내용은 GitHubNPM에서 제공되는 README 문서에서 찾을 수 있습니다.

1단계: Explore에서 쿼리 빌드 및 쿼리 ID 복사

이 예시에서는 시간 경과에 따라 추적하는 브랜드에 대해 분기별 가상의 판매 정보를 사용합니다.

피벗은 쿼리 결과를 그룹화하는 기본 제공되는 방법이므로 이 데이터를 피벗합니다. Explore에서 Looker의 기본 시각화 유형 중 하나를 사용하여 쿼리를 실행하고 데이터 차트를 만들 수 있습니다. 차트는 많은 정보를 제공하지만 각 브랜드 제품의 추세를 한눈에 파싱하기는 어렵습니다.

주문 생성 분기 측정기준을 피벗하는 브랜드별 주문 수에 대한 쿼리 결과 차트

간단한 시각화 렌더링 예시와 같이 다음 단계는 Explore의 URL 표시줄에서 qid 값을 복사하는 것입니다. 이 예시의 경우 qid 값은 Uijcav7pCA4MZY2MompsPZ이지만 이 값은 테스트 인스턴스에만 적용됩니다. 다른 경우에는 값이 달라집니다.

2단계: 커스텀 시각화 구성요소에 데이터 전달

시작하려면 Explore URL에서 가져온 qid 값을 Query 구성요소에 전달하고 인증된 SDK 객체를 DataProvider에 전달합니다.

import React, { useContext } from 'react'
import { ExtensionContext } from '@looker/extension-sdk-react'
import { DataProvider } from '@looker/components-data'
import { Query } from '@looker/visualizations'

export const MyReactApp = () => {
  const { core40SDK } = useContext(ExtensionContext)

  return (
    <DataProvider sdk={core40SDK}>
      <Query query='Uijcav7pCA4MZY2MompsPZ'></Query>
    </DataProvider>
  )
}

다음으로, Visualization 구성요소를 통해 네이티브 Looker 시각화를 렌더링하는 대신 CustomVis라는 자체 커스텀 구성요소를 빌드합니다.

Query 구성요소는 모든 React 요소를 하위 요소로 수락할 수 있으며 config, data, fields, totals 값을 속성으로 전달하여 자체 시각화 구성요소를 렌더링합니다. 모든 관련 데이터를 속성으로 수신할 수 있도록 CustomVisQuery의 하위 요소로 렌더링합니다.

import React, { useContext } from 'react'
import { ExtensionContext } from '@looker/extension-sdk-react'
import { DataProvider } from '@looker/components-data'
import { Query } from '@looker/visualizations'
import { CustomVis } from '../path/to/MyCustomVis'

export const MyReactApp = () => {
  const { core40SDK } = useContext(ExtensionContext)

  return (
    <DataProvider sdk={core40SDK}>
      <Query query='Uijcav7pCA4MZY2MompsPZ'>
        <CustomVis />
      </Query>
    </DataProvider>
  )
}

3단계: CustomVis 구성요소 빌드

이제 CustomVis 구성요소를 빌드해 보겠습니다. Query 구성요소에서 상속된 속성은 config, fields, data, pivots, totals입니다.

  • config는 스파크라인의 선 두께, 산점도 점 크기 및 모양과 같이 차트에서 데이터를 렌더링해야 하는 모든 방법을 설명합니다.
  • fields는 쿼리에서 반환된 측정값 및 측정기준 값에 대한 추가 메타데이터(예: 값의 형식 지정 방법 또는 각 축의 라벨 지정)를 저장합니다.
  • data는 쿼리에서 반환된 키/값 응답입니다.
  • pivots는 쿼리가 피벗되는 측정기준을 설명합니다.
  • totals는 테이블 기반 시각화에 사용할 Looker의 행 합계를 참조합니다.

Table 구성요소를 삽입하여 수정되지 않은 속성을 테이블 시각화에 전달할 수 있습니다.

import React from 'react'
import { Table } from '@looker/visualizations'

export const CustomVis = ({ config, fields, data, pivots }) => {
  return <Table config={config} data={data} fields={fields} pivots={pivots} />
}

이렇게 하면 SDK에서 직접 반환되는 데이터를 이해할 수 있습니다. 렌더링된 응답에는 분기별로 그룹화되거나 피벗된 결과가 있는 모든 브랜드에 대한 행이 있습니다.

4단계: 정규화된 데이터 변환

이 피벗된 데이터를 중첩된 스파크라인으로 렌더링하려면 모든 측정 값을 격리하고 하위 차트에 전달합니다. 다음 차트에서는 단일 행의 관련 데이터가 강조표시되어 하위 시각화를 통해 축소 및 렌더링할 데이터를 보여줍니다.

두 번째 행의 주문 수가 강조표시된 데이터 결과 차트

이를 위한 커스텀 변환을 만듭니다. 다음은 이 시나리오와 관련된 예시입니다. 자체 데이터는 파싱해야 합니다.


import React from 'react'
import { Table, Sparkline } from '@looker/visualizations'

// we assign this value to a constant to ensure that fields and data
// objects remain in sync.
const NESTED_DATA_KEY = 'orderCount'

const nestSparklines = (data) => {
  return data.reduce((acc, d) => {
    // the first entry is the dimension (brand name), and the rest of the rows are the
    // quarterly sales information we want to pass to the Sparkline.
    const [parentDimension, ...measurePairs] = Object.entries(d)

    // `nonPivotedData` represents a single data row.
    // e.g. [{entry: 1, orderCount: 10}, {entry: 2, orderCount: 15}, ...etc]
    const nonPivotedData: SDKRecord[] = measurePairs.map(([_, value], i) => {
      return { entry: i, [NESTED_DATA_KEY]: value }
    })

    // now for each row in the table we render a Sparkline using the `nonPivotedData`
    // that we built above.
    // E.G. [{products.brand: 'adidas', orderCount: <Sparkline />}]
    return [
      ...acc,
      {
        [parentDimension[0]]: parentDimension[1],
        [NESTED_DATA_KEY]: () => (
          <Sparkline
            height={75}
            data={nonPivotedData}
            fields={{
              measures: [{ name: NESTED_DATA_KEY }],
              dimensions: [],
            }}
          />
        ),
      },
    ]
  }, [])
}

함수는 다음 단계를 사용하여 생성됩니다.

  1. 데이터 세트를 줄여 각 행에서 브랜드 이름을 분기별 주문 데이터에서 격리합니다.
  2. 테이블의 각 행 값을 나타낼 수 있는 측정기준 및 렌더링된 React 구성요소를 포함하도록 각 행을 업데이트합니다.

5단계: 변환된 데이터를 CustomVis에 삽입

이제 새 함수를 사용하여 데이터를 변환하고 출력을 nestedData라는 새 변수에 할당합니다.


export const CustomVis =({
  fields,
  data,
  config,
  pivots,
}) => {
  const nestedData = nestSparklines(data)

  return (
    <Table
      fields={{
        measures: [{ name: NESTED_DATA_KEY, label: 'Orders Count By Quarter' }],
        dimensions: fields.dimensions,
        pivots: [],
      }}
      config={config}
      data={nestedData}
      pivots={pivots}
    />
  )
}

6단계: 커스텀 시각화 생성

변환된 데이터를 삽입하고 차트를 구성한 후에는 각 행에 개별 스파크라인 차트가 포함된 이 테이블 예시처럼 시각화가 표시됩니다.

브랜드별 행이 있는 테이블과 각 행에 분기별 주문 수를 보여주는 삽입된 스파크라인 시각화가 표시된 커스텀 빌드 시각화

위의 시각화를 렌더링하는 데 필요한 코드 전체는 다음과 같습니다.


import React, { useContext } from 'react'
import { ExtensionContext } from '@looker/extension-sdk-react'
import { DataProvider } from '@looker/components-data'
import { Query, Sparkline, Table } from '@looker/visualizations'

// we assign this value to a constant to ensure that fields and data
// objects remain in sync.
const NESTED_DATA_KEY = 'orderCount'
const ROW_HEIGHT = 75

const nestSparklines = data => {
  return data.reduce((acc, d) => {
    // the first entry is the dimension (brand name), and the rest of the rows are the
    // quarterly sales information we want to pass to the Sparkline.
    const [parentDimension, ...measurePairs] = Object.entries(d)

    // `nonPivotedData` represents a single data row.
    // e.g. [{entry: 1, orderCount: 10}, {entry: 2, orderCount: 15}, ...etc]
    const nonPivotedData = measurePairs.map(([_, value], i) => {
      return { entry: i, [NESTED_DATA_KEY]: value }
    })

    // now for each row in the table we render a Sparkline using the `nonPivotedData`
    // that we built above.
    // E.G. [{products.brand: 'adidas', orderCount: <Sparkline />}]
    return [
      ...acc,
      {
        [parentDimension[0]]: parentDimension[1],
        [NESTED_DATA_KEY]: () => (
          <Sparkline
            height={ROW_HEIGHT}
            data={nonPivotedData}
            fields={{
              measures: [{ name: NESTED_DATA_KEY }],
              dimensions: [],
            }}
          />
        ),
      },
    ]
  }, [])
}

const CustomVis = ({ fields, data, pivots, config }) => {
  const nestedData = nestSparklines(data)

  return (
    <Table
      config={config}
      height={500}
      fields={{
        measures: [{ name: NESTED_DATA_KEY, label: 'Orders Count By Quarter' }],
        dimensions: fields.dimensions,
        pivots: [],
      }}
      data={nestedData}
      pivots={pivots}
      defaultRowHeight={ROW_HEIGHT}
    />
  )
}

export const MyReactApp = () => {
  const { core40SDK } = useContext(ExtensionContext)

  return (
    <DataProvider sdk={core40SDK}>
      <Query query='Uijcav7pCA4MZY2MompsPZ'>
        <CustomVis />
      </Query>
    </DataProvider>
  )
}

다음 단계