본문 바로가기
개발인생/BI(Business Intelligence)

태블로(tableau) 대시보드를 내 웹사이트에 노출하기

by jeje.91 2023. 3. 3.
반응형

지난번 태블로(tableau) REST API를 Python과 연동하는 방법에 대해 알아봤습니다.

 

태블로 Rest API 연동(with python)

태블로(Tableau)는 데이터 시각화 및 분석 툴로 유명합니다. 태블로를 사용하면 다양한 형식의 데이터를 시각화하고 대시보드를 만들어 데이터 인사이트를 도출할 수 있습니다. 태블로는 REST API를

senslife.tistory.com

 

API 연동을 활용해 대시보드 목록을 구현했습니다.

 

이제 상세 페이지로 들어가면 실제 대시보드를 출력해야 하는데 이는 public 대시보드일 경우에는 태블로의 공유 기능으로 코드만 붙여 넣으면 바로 출력이 가능하지만 private 일 경우에는 token이 필요합니다. 이 토큰은 jwt 방식으로 생성해야 하고 태블로에서 클라이언트ID와 시크릿을 발급 받아 토큰에 담아줘야 합니다. 먼저 시크릿을 발급받기 위한 과정을 진행해 보겠습니다.

 

1. 연결된 앱 추가하기

클라이언트 ID를 생성하기 위해서는 "연결된 앱" 메뉴에서 할 수 있습니다. 이는 먼저 태블로 클라우드에서 왼쪽 하단에 "설정" 메뉴로 들어가보겠습니다.

 

그러면 몇 개의 탭이 보이는 페이지가 나타나는데 여기서 "연결된 앱" 탭을 클릭합니다.

 

지금은 연결된 앱이 없으니 새로 추가해보겠습니다. "새 연결된 앱" SelectBox를 클릭해 "직접 신뢰"를 선택합니다.

 

그러면 "연결된 앱 만들기"라는 창이 뜨게 됩니다. 여기서 저희는 앱 이름만 적고 "만들기" 버튼을 클릭해보겠습니다.

 

이제 클라이언트 ID가 생성됐습니다. 클라이언트 ID 항목 위에는 '암호 없음'이라고 있을 겁니다. 오른쪽에 "새 암호 생성" 버튼을 클릭하겠습니다.

 

"암호를 생성했습니다."라는 알림과 함께 이렇게 암호 ID와 마스킹 처리된 값이 나타나게 됩니다.

 

이제 마지막 설정입니다. 연결된 앱으로 돌아오면 이렇게 목록이 생긴것을 볼 수 있습니다. 아직은 상태 값이 "사용 안 함"으로 되어 있으므로 이를 사용으로 바꿔보겠습니다.

동작 항목에 "..."을 클릭한 후 "사용"을 선택하겠습니다. 

 

이제 상태 값이 "사용"으로 변경된 것을 확인할 수 있습니다.

 

여기까지 클라이언트 ID 생성과 설정이 끝났습니다. 이제 python 을 활용해서 jwt 토큰을 생성하고 대시보드를 출력해보겠습니다.

 

 

2. 태블로 대시보드 출력

먼저 환경변수 파일에 아래와 같이 변수들을 설정하겠습니다. 위에서 발급받은 값들을 추가하면 되고 {사이트 ID}는 클라우드 url을 보면 site 세그먼트 옆의 값이니 참고해주세요.

TABLEAU_URL=https://prod-apnortheast-a.online.tableau.com
TABLEAU_USER={사용자 계정}
TABLEAU_SITE_ID={사이트 ID}
TABLEAU_CONNECTED_APP_CLIENT_ID={클라이언트 ID}
TABLEAU_CONNECTED_APP_SECRET_ID={암호 ID}
TABLEAU_CONNECTED_APP_SECRET_KEY={암호 값}

 

본격적인 코드를 작성하기에 앞서 jwt를 사용하기 위한 PyJWT 패키지를 설치하겠습니다.

$ pip install PyJWT

 

jwt 토큰을 생성하고 대시보드 url을 설정하는 함수를 작성했습니다.

import jwt
import uuid
from datetime import datetime, timedelta


# jwt 토큰 생성 함수
def generate_jwt_token(client_id: str, secret_id: str, secret_key: str, user: str) -> str:

    # 암호화 알고리즘
    algorithm = 'HS256'
    
    # payload 전송 데이터 설정
    payload = {
        'iss': client_id,
        'exp': datetime.utcnow() + timedelta(minutes=5),
        'jti': str(uuid.uuid4()),
        'aud': 'tableau',
        'sub': user,
        'scp': ['tableau:views:embed', 'tableau:metrics:embed']
    }
    
    # headers 데이터 설정
    headers = {
        'kid': secret_id,
        'iss': client_id
    }
    return jwt.encode(payload, secret_key, algorithm=algorithm, headers=headers)


# 대시보드 호출을 위한 url 설정 함수
def get_view_url(server_url: str, site_id: str, content_url: str) -> str:
    # content_url 형식이 {workbook}/sheets/{sheet_id} 로 되어 있다.
    [workbook, sheet_id] = content_url.split('/sheets/')
    return f'{server_url}/t/{site_id}/views/{workbook}/{sheet_id}'

 

 

views.py 파일에서 상세 페이지를 랜더링 하는 함수를 작성합니다. 생성된 jwt 토큰과 url을 template으로 넘겨줍니다.

# views.py

def show(request, id):
    # view 데이터 조회
    view = get_object_or_404(Views, id=id)

    # jwt 생성
    token = generate_jwt_token(
        settings.TABLEAU_CONNECTED_APP_CLIENT_ID,
        settings.TABLEAU_CONNECTED_APP_SECRET_ID,
        settings.TABLEAU_CONNECTED_APP_SECRET_KEY,
        settings.TABLEAU_USER,
    )

    # 대시보드 url 설정
    view_url = get_view_url(
        settings.TABLEAU_URL,
        settings.TABLEAU_SITE_ID,
        view.content_url,
    )
    
    return render(request, 'tableau/show.html', {'token': token, 'view_url': view_url})

 

show.html 로 넘겨받은 token과 url을 아래의 코드와 같이 넣어줍니다.

{% extends 'base.html' %}

{% block content %}
        <div class="row">
            <tableau-viz id='tableau-viz'
                         src='{{ view_url }}'
                         width='1920'
                         height='915'
                         hide-tabs
                         toolbar='bottom'
                         token="{{ token }}" <!-- jwt 토큰을 넣어준다 -->
            ></tableau-viz>
        </div>
        <script type='module'
                src='{{ TABLEAU_URL }}/javascripts/api/tableau.embedding.3.latest.min.js'></script>
{% endblock %}

 

코드가 정상적으로 작동된다면 아래와 같이 대시보드가 출력되는 것을 확인할 수 있습니다.

반응형

댓글