Looker 시각화 구성요소 시작하기

iframe을 사용한 Looker 콘텐츠 임베딩은 개발자가 웹 애플리케이션에 대시보드, Look 또는 Explore를 추가하려고 할 때 사용할 수 있는 방법 중 하나에 불과합니다. 이 튜토리얼에서는 React 앱에 Looker 시각화를 추가하려는 개발자를 위한 또 다른 방법을 제공합니다. 이 튜토리얼은 React 앱 만들기 시작 가이드를 기반으로 하며 Looker 시각화 구성요소를 사용합니다.

이 튜토리얼은 다음 단계에 따라 진행됩니다.

  1. Looker에서 쿼리 슬러그 가져오기
  2. Looker 시각화 구성요소로 React 애플리케이션 만들기
  3. 백엔드 도우미 서비스 만들기
  4. 서버 및 React 앱 시작

Looker에서 쿼리 슬러그 가져오기

Looker에서 수행해야 하는 몇 가지 작업이 있습니다. React 앱이 이에 따라 달라지기 때문입니다.

쿼리 슬러그 가져오기

시각화 구성요소의 제안으로 사용할 쿼리 ID 또는 슬러그가 필요합니다. 이 문서에서는 Explore URL에서 쿼리 슬러그를 가져오는 방법을 설명합니다.

Looker 인스턴스에서 CORS 구성

교차 출처 리소스 공유(CORS)는 임베딩과 동일한 도메인 허용 목록에서 제어됩니다.

자세한 내용은 서명된 임베딩 문서 페이지를 참조하세요.

  1. Looker 인스턴스에서 관리자 > 플랫폼 삽입으로 이동합니다. 이 경우 관리자 권한이 필요합니다.
  2. React 앱은 기본적으로 http://localhost:3000에서 실행됩니다. 이 주소를 삽입된 도메인 허용 목록에 추가하면 Looker에게 앱의 요청을 허용하고 같은 주소를 사용하여 요청에 응답하도록 지시합니다. 앱에서 API 요청을 Looker 인스턴스에 보내므로 이 단계는 필수입니다. 그렇지 않으면 Looker와 앱 간에 통신이 끊깁니다.

React 애플리케이션 만들기

이 데모의 프런트엔드는 React 앱 만들기를 사용하여 단일 페이지 React 애플리케이션을 만듭니다. 데모의 루트 폴더(get-started-viz-components)에서 다음 명령어를 실행하여 앱을 만들고 종속 항목을 설치합니다.

npx create-react-app frontend-react cd frontend-react npm i
@looker/visualizations npm i @looker/components @looker/components-data
styled-components

이러한 명령어를 실행하면 폴더 구조가 다음과 같이 표시됩니다.

폴더 노드 모듈, 공개, src 폴더가 포함되어 있고 파일에서 .gitignore, package-lock.json, package.json을 호출하는 프런트엔드라는 폴더입니다.

package.json 파일을 확인하고 react-dom도 설치되었는지 확인합니다. 그렇지 않으면 npm i react-dom을 실행하여 설치합니다.

이 데모의 package.json은 다음과 같습니다.

{
  "name": "frontend-react",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@looker/components": "^4.0.3",
    "@looker/components-data": "^1.0.0",
    "@looker/sdk": "^22.16.0",
    "@looker/sdk-rtl": "^21.4.0",
    "@looker/visualizations": "^1.1.1",
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^12.1.0",
    "@testing-library/user-event": "^12.4.0",
    "i": "^0.3.7",
    "npm": "^8.19.2",
    "react": "^16.14.0",
    "react-dom": "^16.14.0",
    "react-scripts": "5.0.1",
    "styled-components": "^5.3.6",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

환경 변수 구성

앱의 루트 디렉터리(./frontend-react)에 .env 파일을 만들고 다음 변수를 설정합니다.

REACT_APP_LOOKER_API_HOST=https://your-looker-instance.looker.com
REACT_APP_BACKEND_SERVER=http://localhost:3001/

REACT_APP_BACKEND_SERVER는 API 호출을 Looker에 보내 액세스 토큰을 추출하는 데 사용하는 백엔드 도우미 서비스의 주소입니다.

REACT_APP_LOOKER_API_HOST는 React 앱에서 API 요청을 수신하는 Looker 인스턴스의 주소입니다.

클라이언트 측 SDK 초기화

React 앱은 SDK를 사용하여 API 요청을 Looker 서버에 보냅니다. 이 작업은 프런트엔드에서 수행되므로 다음 도우미를 사용하여 sdk를 초기화할 수 있습니다.

import { Looker40SDK } from '@looker/sdk'
import {
  AuthToken,
  AuthSession,
  BrowserTransport,
  DefaultSettings,
} from '@looker/sdk-rtl'

class SDKSession extends AuthSession {
  // This is a placeholder for the fetchToken function.
  // It is modified to make it useful later.
  async fetchToken() {
    return fetch('')
  }

  activeToken = new AuthToken()
  constructor(settings, transport) {
    super(settings, transport || new BrowserTransport(settings))
  }

  // This function checks to see if the user is already authenticated
  isAuthenticated() {
    const token = this.activeToken
    if (!(token && token.access_token)) return false
    return token.isActive()
  }

  // This function gets the current token or fetches a new one if necessary
  async getToken() {
    if (!this.isAuthenticated()) {
      const token = await this.fetchToken()
      const res = await token.json()
      this.activeToken.setToken(res.user_token)
    }
    return this.activeToken
  }

  // This function authenticates a user, which involves getting a new token
  // It returns a modified object with a new authorization header.
  async authenticate(props) {
    const token = await this.getToken()
    if (token && token.access_token) {
      props.mode = 'cors'
      delete props.credentials
      props.headers = {
        ...props.headers,
        Authorization: `Bearer ${this.activeToken.access_token}`,
      }
    }
    return props
  }
}

// This class sets the fetchToken to use the 'real' address of the backend server.
class SDKSessionEmbed extends SDKSession {
  async fetchToken() {
    return fetch(`${process.env.REACT_APP_BACKEND_SERVER}`)
  }
}

// This creates a new session with the 'real' address of the backend server.
const session = new SDKSessionEmbed({
  ...DefaultSettings,
  base_url: process.env.REACT_APP_LOOKER_API_HOST,
})

// This exports the SDK with the authenticated session
export const sdk = new Looker40SDK(session)

앱에 시각화 삽입

지금까지 시각화의 쿼리 슬러그(이 예시에서는 Jlm4YHPeT3lLGA9UtHjZcA)가 있고 sdk 객체가 인스턴스화되었습니다. 다음 단계에서는 Looker 시각화 구성요소를 사용하여 앱에 시각화를 삽입하고 렌더링합니다.

import { sdk } from '../src/helpers/CorsSession'
import { Query, Visualization } from '@looker/visualizations'
import { DataProvider } from '@looker/components-data'
import { ComponentsProvider } from '@looker/components'

function App() {
  return (
    <>
      <h1>Get started with Looker visualization components</h1>
      <ComponentsProvider>
        <DataProvider sdk={sdk}>
          {/* Change this query slug to match your query slug */}
          <Query query="Jlm4YHPeT3lLGA9UtHjZcA">
            <Visualization />
          </Query>
        </DataProvider>
      </ComponentsProvider>
    </>
  )
}

export default App

프런트엔드가 준비되었습니다. 구성요소를 더 추가하거나 앱에 스타일 지정을 더 추가할 수 있습니다.

백엔드 도우미 서비스 만들기

최종 단계는 프런트엔드에서 호출을 수신할 백엔드 도우미 서비스를 빌드하고 Looker-Node SDK를 사용하여 사용자를 인증하고 액세스 토큰을 추출한 후 프런트엔드로 다시 보내는 것입니다.

편의상 엔드포인트 하나로 노드 서버를 빌드해 보겠습니다. 서버는 express, cors, @looker/sdk-node 종속 항목을 사용합니다. 루트 폴더(get-started-viz-components)에서 시작하여 다음 명령어를 실행할 수 있습니다.

mkdir backend-node
cd backend-node
npm init -y
npm i express cors @looker/sdk-node

백엔드에서 SDK를 인증하려면 looker.ini 파일을 사용합니다. 파일을 채우는 방법에 대한 자세한 내용은 SDK-Node 페이지를 참조하세요. 이러한 명령어를 실행하면 폴더 구조가 다음과 같이 표시됩니다.

node_modules라는 폴더와 looker.ini, package-lock.json, package.json, server.js 파일이 포함된 backend-node라는 폴더입니다.

package.json은 다음과 같아야 합니다.

{
  "name": "looker-embed-backend",
  "version": "1.0.0",
  "description": "Backend helper service for getting started with Looker Viz components",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "author": "Looker",
  "license": "Apache-2.0",
  "dependencies": {
    "@looker/sdk-node": "^22.16.0",
    "cors": "^2.8.5",
    "express": "^4.18.2"
  }
}

다음으로 이 코드를 새 server.js 파일에 추가합니다.

const cors = require('cors')
const express = require('express')
const { LookerNodeSDK } = require('@looker/sdk-node')

const port = 3001
const app = express()
// The following init40 method will authenticate using
// the looker.ini file
const sdk = LookerNodeSDK.init40()

app.use(
  cors({
    origin: '*',
  })
)
app.use(express.json())

app.get('/', async (req, res) => {
  const userId = await sdk.ok(sdk.me('id'))
  const accessToken = await sdk.login_user(userId.id)
  const user = {
    user_token: accessToken.value,
    token_last_refreshed: Date.now(),
  }
  res.json({ ...user })
})

app.listen(port, async () => {
  console.log(`Backend Server listening on port ${port}`)
})

서버 및 React 앱 시작

  • 터미널을 열고 backend-node 폴더로 이동한 후 npm start를 실행합니다.
  • 두 번째 터미널을 연 다음 frontend-react 폴더로 이동하고 npm start를 실행합니다.
  • 백엔드 도우미 서비스와 React 앱이 실행되면 브라우저를 열고 http://localhost:3000/으로 이동하여 애플리케이션에 포함된 시각화를 확인할 수 있습니다.

GitHub의 코드 참조