PostgreSQL용 Cloud SQL을 사용하여 Cloud Run에 JavaScript 애플리케이션 배포

1. 개요

Cloud Run은 HTTP 요청을 통해 호출 가능한 스테이트리스(Stateless) 컨테이너를 실행하는 완전 관리형 서버리스 플랫폼입니다. 이 Codelab에서는 Cloud Run의 Node.js 애플리케이션을 PostgreSQL용 Cloud SQL 데이터베이스에 연결하는 방법을 보여줍니다.

학습할 내용

이 실습에서는 다음 작업을 수행하는 방법을 배웁니다.

  • PostgreSQL용 Cloud SQL 인스턴스 만들기 (Private Service Connect를 사용하도록 구성됨)
  • Cloud SQL 데이터베이스에 연결되는 애플리케이션을 Cloud Run에 배포
  • Gemini Code Assist를 사용하여 애플리케이션에 기능 추가

학습할 내용

  • PostgreSQL용 Cloud SQL 인스턴스 만들기 (Private Service Connect를 사용하도록 구성됨)
  • Cloud SQL 데이터베이스에 연결되는 애플리케이션을 Cloud Run에 배포
  • Gemini Code Assist를 사용하여 애플리케이션에 기능 추가

2. 기본 요건

  1. 아직 Google 계정이 없다면 Google 계정을 만들어야 합니다.
    • 직장 또는 학교 계정이 아닌 개인 계정을 사용합니다. 직장 및 학교 계정에는 이 실습에 필요한 API를 사용 설정할 수 없도록 하는 제한사항이 있을 수 있습니다.

3. 프로젝트 설정

  1. Google Cloud 콘솔에 로그인합니다.
  2. Cloud 콘솔에서 결제를 사용 설정합니다.
    • 이 실습을 완료하는 데 드는 Cloud 리소스 비용은 미화 1달러 미만입니다.
    • 이 실습의 끝에 있는 단계에 따라 리소스를 삭제하면 추가 비용이 발생하지 않습니다.
    • 신규 사용자는 미화 300달러 상당의 무료 체험판을 이용할 수 있습니다.
  3. 새 프로젝트를 만들거나 기존 프로젝트를 재사용합니다.

4. Cloud Shell 편집기 열기

  1. Cloud Shell 편집기로 이동합니다.
  2. 터미널이 화면 하단에 표시되지 않으면 다음과 같이 엽니다.
    • 햄버거 메뉴 햄버거 메뉴 아이콘를 클릭합니다.
    • 터미널을 클릭합니다.
    • 새 터미널을 클릭합니다.Cloud Shell 편집기에서 새 터미널 열기
  3. 터미널에서 다음 명령어를 사용하여 프로젝트를 설정합니다.
    • 형식:
      gcloud config set project [PROJECT_ID]
      
    • 예:
      gcloud config set project lab-project-id-example
      
    • 프로젝트 ID를 기억할 수 없는 경우 다음 안내를 따르세요.
      • 다음을 사용하여 모든 프로젝트 ID를 나열할 수 있습니다.
        gcloud projects list | awk '/PROJECT_ID/{print $2}'
        
      Cloud Shell 편집기 터미널에서 프로젝트 ID 설정
  4. 승인하라는 메시지가 표시되면 승인을 클릭하여 계속 진행합니다. Cloud Shell을 승인하려면 클릭합니다.
  5. 다음 메시지가 표시되어야 합니다.
    Updated property [core/project].
    
    WARNING이 표시되고 Do you want to continue (Y/N)? 메시지가 표시되면 프로젝트 ID를 잘못 입력했을 가능성이 큽니다. N를 누른 다음 Enter를 누르고 gcloud config set project 명령어를 다시 실행해 봅니다.

5. API 사용 설정

터미널에서 API를 사용 설정합니다.

gcloud services enable \
  compute.googleapis.com \
  sqladmin.googleapis.com \
  run.googleapis.com \
  artifactregistry.googleapis.com \
  cloudbuild.googleapis.com \
  networkconnectivity.googleapis.com \
  servicenetworking.googleapis.com \
  cloudaicompanion.googleapis.com

승인하라는 메시지가 표시되면 승인을 클릭하여 계속 진행합니다. Cloud Shell을 승인하려면 클릭합니다.

이 명령어를 완료하는 데 몇 분 정도 걸릴 수 있지만 결국 다음과 유사한 성공 메시지가 표시됩니다.

Operation "operations/acf.p2-73d90d00-47ee-447a-b600" finished successfully.

6. 서비스 계정 설정

Cloud SQL에 연결할 수 있는 올바른 권한이 있도록 Cloud Run에서 사용할 Google Cloud 서비스 계정을 만들고 구성합니다.

  1. 다음과 같이 gcloud iam service-accounts create 명령어를 실행하여 새 서비스 계정을 만듭니다.
    gcloud iam service-accounts create quickstart-service-account \
      --display-name="Quickstart Service Account"
    
  2. 다음과 같이 gcloud projects add-iam-policy-binding 명령어를 실행하여 방금 만든 Google Cloud 서비스 계정에 로그 작성자 역할을 추가합니다.
    gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
      --member="serviceAccount:quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
      --role="roles/logging.logWriter"
    

7. Cloud SQL 인스턴스 만들기

  1. Private Service Connect를 사용하여 Cloud Run에서 Cloud SQL로의 네트워크 연결을 허용하는 서비스 연결 정책 만들기
    gcloud network-connectivity service-connection-policies create quickstart-policy \
        --network=default \
        --project=${GOOGLE_CLOUD_PROJECT} \
        --region=us-central1 \
        --service-class=google-cloud-sql \
        --subnets=https://www.googleapis.com/compute/v1/projects/${GOOGLE_CLOUD_PROJECT}/regions/us-central1/subnetworks/default
    
  2. 데이터베이스의 고유한 비밀번호 생성
    export DB_PASSWORD=$(openssl rand -base64 20)
    
  3. gcloud sql instances create 명령어를 실행하여 Cloud SQL 인스턴스 만들기
    gcloud sql instances create quickstart-instance \
        --project=${GOOGLE_CLOUD_PROJECT} \
        --root-password=${DB_PASSWORD} \
        --database-version=POSTGRES_17 \
        --tier=db-perf-optimized-N-2 \
        --region=us-central1 \
        --ssl-mode=ENCRYPTED_ONLY \
        --no-assign-ip \
        --enable-private-service-connect \
        --psc-auto-connections=network=projects/${GOOGLE_CLOUD_PROJECT}/global/networks/default
    

이 명령어를 완료하는 데 몇 분 정도 걸릴 수 있습니다.

  1. gcloud sql databases create 명령어를 실행하여 quickstart-instance 내에 Cloud SQL 데이터베이스를 만듭니다.
    gcloud sql databases create quickstart_db \
      --instance=quickstart-instance
    

8. 신청 준비

HTTP 요청에 응답하는 Node.js 애플리케이션을 준비합니다.

  1. Cloud Shell에서 helloworld라는 새 디렉터리를 만든 다음 해당 디렉터리로 변경합니다.
    mkdir helloworld
    cd helloworld
    
  2. package.json 파일을 모듈로 초기화합니다.
    npm init -y
    npm pkg set type="module"
    npm pkg set main="index.mjs"
    npm pkg set scripts.start="node index.mjs"
    
  3. pg를 설치하여 PostgreSQL 데이터베이스와 상호작용합니다.
    npm install pg
    
  4. 들어오는 HTTP 요청을 수락하도록 express를 설치합니다.
    npm install express
    
  5. 애플리케이션 코드로 index.mjs 파일을 만듭니다. 이 코드는 다음을 실행할 수 있습니다.
    • HTTP 요청 수락
    • 데이터베이스에 연결
    • 데이터베이스에 HTTP 요청 시간을 저장합니다.
    • 지난 5번의 요청 시간을 반환합니다.
    Cloud Shell에서 다음 명령어를 실행합니다.
    cat > index.mjs << "EOF"
    import express from 'express';
    import pg from 'pg';
    const { Pool } = pg;
    
    const pool = new Pool({
      host: process.env.DB_HOST,
      user: process.env.DB_USER,
      password: process.env.DB_PASSWORD,
      database: process.env.DB_NAME,
      ssl: {
        require: true,
        rejectUnauthorized: false, // required for self-signed certs
        // https://node-postgres.com/features/ssl#self-signed-cert
      }
    });
    
    const app = express();
    
    app.get('/', async (req, res) => {
      await pool.query('INSERT INTO visits(created_at) VALUES(NOW())');
      const {rows} = await pool.query('SELECT created_at FROM visits ORDER BY created_at DESC LIMIT 5');
      console.table(rows); // prints the last 5 visits
      res.send(rows);
    });
    
    const port = parseInt(process.env.PORT) || 8080;
    app.listen(port, async () => {
      console.log('process.env: ', process.env);
      await pool.query(`CREATE TABLE IF NOT EXISTS visits (
        id SERIAL NOT NULL,
        created_at timestamp NOT NULL,
        PRIMARY KEY (id)
      );`);
      console.log(`helloworld: listening on port ${port}`);
    });
    
    EOF
    

이 코드는 PORT 환경 변수로 정의된 포트를 리슨하는 기본 웹 서버를 만듭니다. 이제 애플리케이션을 배포할 수 있습니다.

9. Cloud Run에 애플리케이션 배포

  1. 다음과 같이 gcloud projects add-iam-policy-binding 명령어를 실행하여 만들려는 Cloud Run 서비스의 Cloud Run 서비스 계정에 네트워크 사용자 역할을 추가합니다.
    gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
    --member "serviceAccount:service-$(gcloud projects describe ${GOOGLE_CLOUD_PROJECT} --format="value(projectNumber)")@serverless-robot-prod.iam.gserviceaccount.com" \
    --role "roles/compute.networkUser"
    
  1. 아래 명령어를 실행하여 Cloud Run에 애플리케이션을 배포합니다.
    gcloud run deploy helloworld \
      --region=us-central1 \
      --source=. \
      --set-env-vars DB_NAME="quickstart_db" \
      --set-env-vars DB_USER="postgres" \
      --set-env-vars DB_PASSWORD=${DB_PASSWORD} \
      --set-env-vars DB_HOST="$(gcloud sql instances describe quickstart-instance --project=${GOOGLE_CLOUD_PROJECT} --format='value(settings.ipConfiguration.pscConfig.pscAutoConnections.ipAddress)')" \
      --service-account="quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
      --network=default \
      --subnet=default \
      --allow-unauthenticated
    
  2. 메시지가 표시되면 YEnter를 눌러 계속 진행하겠다고 확인합니다.
    Do you want to continue (Y/n)? Y
    

몇 분 후 애플리케이션에서 방문할 URL을 제공합니다.

URL로 이동하여 애플리케이션이 작동하는 모습을 확인합니다. URL을 방문하거나 페이지를 새로고침할 때마다 최근 5회의 방문이 JSON으로 반환됩니다.

10. 축하합니다

이 실습에서는 다음을 수행하는 방법을 알아봤습니다.

  • PostgreSQL용 Cloud SQL 인스턴스 만들기 (Private Service Connect를 사용하도록 구성됨)
  • Cloud SQL 데이터베이스에 연결되는 애플리케이션을 Cloud Run에 배포
  • Gemini Code Assist를 사용하여 애플리케이션에 기능 추가

삭제

이 튜토리얼에서 사용된 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 리소스가 포함된 프로젝트를 삭제하거나 프로젝트를 유지하고 개별 리소스를 삭제하세요. 전체 프로젝트를 삭제하려면 다음을 실행합니다.

gcloud projects delete ${GOOGLE_CLOUD_PROJECT}