GCP VM Connect to BigQuery using Streamlit (ver. 2025, 06)

Page content

개요

  • VM 만들기 Web UI가 일부 변경됨 (추가 진행하기로 함)
  • VM 생성 및 VS Code 연결
  • VM과 BigQuery 연결

VM 머신 생성

머신 구성

  • 이름과 성능 체크
  • 월별 예상 가격을 체크한다.

Screenshot 2025-06-20 at 7.54.08 PM.png

OS 및 스토리지

  • Ubuntu - Ubuntu 24.04 LTS 방식으로 진행 (x86/64) 방식 선택
  • 디스크 사이즈 : 25GB

Screenshot 2025-06-20 at 8.00.50 PM.png

  • 암호화 : Google 관리 암호화 키 선택

Screenshot 2025-06-20 at 8.02.26 PM.png

데이터 보호

  • 이 부분은 생략하고 넘어간다.

네트워킹

  • 방화벽은 아래와 같이 HTTP & HTTPS 트래픽 허용

Screenshot 2025-06-20 at 8.18.23 PM.png

보안

  • 액세스 범위 : 모든 Cloud API에 대한 전체 액세스 허용

Screenshot 2025-06-20 at 8.17.59 PM.png

VM 생성

  • 다음과 같이 만들기 버튼 클릭

Screenshot 2025-06-20 at 8.20.12 PM.png

고정 IP 할당

  • VPC 네트워크 > IP 주소 클릭

Screenshot 2025-06-20 at 8.24.39 PM.png

  • 오른쪽 끝 작업 하단 메뉴 선택 후 고정 IP 주소로 승급 선택

Screenshot 2025-06-20 at 8.25.35 PM.png

  • 다음과 같이 임의의 이름 지정

    Screenshot 2025-06-20 at 8.27.13 PM.png

방화벽 설정 (프로젝트 배포 위해)

  • VPC 네트워크 탭 왼쪽 메뉴에서 방화벽을 클릭한다.

Screenshot 2025-06-20 at 8.31.38 PM.png

  • 방화벽 > 방화벽 규칙만들기를 순차적으로 클릭한다.

Screenshot 2025-06-20 at 8.32.31 PM.png

  • 방화벽 규칙 이름 : lgu6th-firewall

Screenshot 2025-06-20 at 8.37.35 PM.png

  • 여기에서 대상은 네트워크의 모든 인스턴스 / 소스 IPv4 범위는 0.0.0.0/0 프로토콜은 모두 허용을 클릭한다.

Screenshot 2025-06-20 at 8.39.00 PM.png

  • 생성된 방화벽 확인

Screenshot 2025-06-20 at 8.39.39 PM.png

메타데이터 등록

  • Mac/Linux에서 등록하는 것과 Windows에서 등록하는 것은 다르다.
  • Windows에서 등록하는 방법을 소개한다.

SSH Key 생성하기 - PuTTYgen 사용

  • Windows에서는 PuTTY에서 작성한다.
  • 프로그래밍 검색창에서 PuTTYgen 프로그래밍을 실행한다.

image.png

  • 아래화면에서 Generate 버튼을 클릭한다.

image.png

  • Private Key를 OpenSSH 방식으로 Export 한다.
    • Key Comment에 구글 계정을 입력한다.
    • password도 입력한다.

image.png

  • Conversions > Export OpenSSH Key 선택
    • 파일 이름은 gce2windows로 저장 (바탕화면에 임시로)

image.png

  • Public Key는 모두 복사한다. (ssh-rsa 부터 email.com 까지)
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKq75NoFSBvAEp9kKMbBowW9cLi0e2cSiF8CmaYYa8Xxirm/x+ ... your_gmail@gmail.com

GCP 메타데이터 등록

  • Compute Engine > 메타데이터 클릭

image.png

  • SSH 키 탭에서 SSH 추가

image.png

  • 다음과 같이 SSH 키 입력 후 저장

image.png

VS Code 접속

  • GCE 인스턴스 활성화한다.

image.png

  • 바탕화면에 있던 gce2windows 파일을 .ssh 폴더에 복사 붙이기 할 것이다. (Git-Bash에서 진행)
~/OneDrive/Desktop
$ cp -r gce2windows ~/.ssh/

~/OneDrive/Desktop
$ cd ~/.ssh

~/OneDrive/Desktop
$ ls
Q-tutor.pem  gce2windows  id_rsa.pub   known_hosts.old
config       id_rsa.ppk   known_hosts  openssh
  • VS Code에서는 다음과 같이 진행
  • 먼저 SSH Config 파일 수정
    • Ctrl + Shift + P > Remote-SSH: Open SSH Configuration File… > ~.ssh\config 선택

image.png

image.png

  • 다음과 같이 수정한다.
    • HostName에 있는 포트번호는 GCP에서 발급해준 번호
Host gce2windows
    HostName 34.22.86.213 # 외부 IP 각자 다름
    Port 22
    User yourname
    IdentityFile ~/.ssh/gce2windows
  • 키 생성할 때 만들었던 Password 입력

image.png

  • 접속 여부 확인

image.png

간단한 웹 테스트 (Streamlit & Jupyterlab)

  • Streamlit이 동작하는지 살펴보기 위해 빠르게 라이브러리 설치 진행
  • uv 설치
  • 환경변수 지정 및 터미널 종료 및 재 실행
curl -LsSf https://astral.sh/uv/install.sh | sh
source $HOME/.local/bin/env 
  • requirements.txt 파일
streamlit
jupyterlab
  • 라이브러리 설치
uv pip install -r requirements.txt

Streamlit 웹 배포 체크

  • 간단한 streamlit 파일 작성 (파일명 : app.py)
import streamlit as st

st.title("Hello GCP-Streamlit")
  • 실행 확인

image.png

JupyterLab 웹 배포 체크

  • 다음과 같이 실행한다.
jupyter lab --ip=0.0.0.0 --port=8888 --allow-root
  • 이 때 토큰값은 복사해둔다. 필자는 다음과 같다.
    • 이때 127.0.0.1:8888을 URL에 띄우는 것이 아니다.
    • 여기선 token값 복사를 한다.
http://127.0.0.1:8888/lab?token=297d002ad3c3a76b55db4ed10856609201bd12631ef5efbc

image.png

image.png

빅쿼리 사용 및 연결

  • 빅쿼리 사용 설정을 하기 위해서 잠깐 인스턴스는 중지한다.

BigQuery API 설정

  • API 및 서비스 > 사용 설정된 API 및 서비스를 클릭한다.

image.png

  • BigQuery 검색하기

image.png

  • 아래와 같은 화면이 나오면 사용 버튼 클릭한다.

image.png

  • BigQuery Studio 화면이 나온다.

image.png

  • SQL 쿼리 열고 다음 쿼리
SELECT
  name,
  gender,
  SUM(number) as total
FROM
  `bigquery-public-data.usa_names.usa_1910_2013`
WHERE
  state = 'TX'
GROUP BY
  name, gender
ORDER BY
  total DESC
LIMIT 10;

image.png

  • 데이터 추가 버튼 > 공개 데이터 선택 > 데이터 > 무료 버튼 클릭
  • 무료 데이터 처리

image.png

image.png

image.png

image.png

Local 데이터 업로드

  • 데이터 세트 만들기

image.png

image.png

  • 테이블 만들기

image.png

  • boston 데이터 파일을 준비한다. 1MB 이하의 파일을 준비한다.
  • 테이블을 만들 소스는 업로드에서 가져온다.

image.png

image.png

image.png

image.png

  • 간단하게 쿼리 가져오기
SELECT * FROM `lgu6th.sample_data.boston`;

image.png

BigQuery 관련 라이브러리 설치

  • 이제 VM 다시 생성 후, VS Code에서 연결 후 라이브러리 추가 (requirements.txt)
  • 라이브러리 설치
streamlit
jupyterlab
db-dtypes
google-cloud-bigquery
pandas
matplotlib
  • streamlit 코드 추가
import streamlit as st
import pandas as pd
import numpy as np
from google.cloud import bigquery
import matplotlib.pyplot as plt

client = bigquery.Client()
source_table = "lgu6th.sample_data.boston"
transformed_table = "lgu6th.sample_data.transformed_boston"

st.set_page_config(layout="wide")
st.title("Boston Housing Data - BigQuery 연동 및 표준화 처리")

tab1, tab2, tab3 = st.tabs(["데이터 불러오기", "데이터 변환 및 업로드", "📊 시각화"])

# 데이터 불러오기 탭
with tab1:
    st.subheader("1. 원본 데이터 불러오기")
    if st.button("데이터 불러오기 (BigQuery)"):
        query = f"SELECT * FROM `{source_table}` LIMIT 1000"
        df = client.query(query).to_dataframe()
        st.session_state["original_df"] = df
        st.success("데이터 불러오기 완료")
    
    if "original_df" in st.session_state:
        st.dataframe(st.session_state["original_df"])

# 데이터 변환 탭
with tab2:
    st.subheader("2. 데이터 변환 및 BigQuery 업로드")

    if "original_df" not in st.session_state:
        st.warning("먼저 [데이터 불러오기] 탭에서 데이터를 불러오세요.")
    else:
        if st.button("데이터 표준화 + 로그변환 후 업로드"):
            df = st.session_state["original_df"].copy()
            
            # 로그 변환
            df["LOG_CRIM"] = df["CRIM"].apply(lambda x: np.nan if x <= 0 else round(np.log(x), 4))
            
            # 표준화 (평균 0, 표준편차 1)
            numeric_cols = df.select_dtypes(include=[np.number]).columns.tolist()
            for col in numeric_cols:
                mean = df[col].mean()
                std = df[col].std()
                if std > 0:
                    df[f"{col}_z"] = (df[col] - mean) / std

            st.session_state["transformed_df"] = df  # 변환된 데이터 저장

            # 업로드
            job_config = bigquery.LoadJobConfig(
                write_disposition="WRITE_TRUNCATE",
                autodetect=True,
            )
            job = client.load_table_from_dataframe(df, transformed_table, job_config=job_config)
            job.result()
            st.success("변환 및 업로드 완료")
            st.dataframe(df)

        elif "transformed_df" in st.session_state:
            st.info("이전 변환 결과:")
            st.dataframe(st.session_state["transformed_df"])

# 시각화 탭
with tab3:
    st.subheader("3. 변환된 데이터 시각화 (BigQuery에서 불러오기)")
    
    if st.button("변환된 데이터 시각화"):
        try:
            query = f"SELECT * FROM `{transformed_table}`"
            df_trans = client.query(query).to_dataframe()
            st.session_state["visual_df"] = df_trans  # 시각화용 저장
            st.success("BigQuery에서 불러오기 완료")
        except Exception as e:
            st.error(f"불러오기 실패: {e}")

    if "visual_df" in st.session_state:
        df_trans = st.session_state["visual_df"]
        st.write("데이터 미리보기:")
        st.dataframe(df_trans.head())

        # 시각화
        if "CRIM" in df_trans.columns and "LOG_CRIM" in df_trans.columns:
            fig, ax = plt.subplots()
            ax.hist(df_trans["CRIM"].dropna(), bins=30, alpha=0.5, label="CRIM")
            ax.hist(df_trans["LOG_CRIM"].dropna(), bins=30, alpha=0.5, label="LOG_CRIM")
            ax.set_title("CRIM vs LOG_CRIM Histogram")
            ax.legend()
            st.pyplot(fig)
  • Web 배포 결과 확인

image.png

  • 결과 확인

image.png

VM 종료

  • 테스트가 완료가 되었다면 모두 사용 중지 시킨다.