# Pub/Sub 메시지를 받아 평탄화 SQL을 깨우는 서버리스 실행자

Pub/Sub 토픽에 들어온 GA4 데이터 도착 메시지를 받아 평탄화 SQL을 실행시키는 서버리스 실행 도구 Cloud Functions를 자판기 비유로 풀어 봅니다. 1세대와 2세대의 차이, Cloud Run과의 관계(메뉴 통합), Hurdlers가 1세대에서 2세대로 옮겨 가는 이유, 실제 동작 흐름과 비용까지 비개발자도 따라올 수 있게 정리합니다.

- 카테고리: BigQuery
- 소요 시간: 약 7분
- 난이도: 입문
- 업데이트: 2026.05.28
- 원문: /wiki/playbook/bigquery-checklist/what-is-cloud-function-and-run

## 목차

- [왜 Cloud Functions가 필요한가](#why)
- [서버리스를 한 문장으로 — ‘쓴 만큼만 내는 자판기’](#serverless)
- [1세대와 2세대 — 우리는 어디로 가는가](#gen-1-vs-2)
- [Cloud Run과는 어떻게 다른가](#vs-cloud-run)
- [GA4 자동화에서 함수가 실제로 하는 일](#what-it-does)
- [비용 — GA4 규모에선 사실상 0원](#cost)
- [자주 묻는 질문](#faq)

[**Pub/Sub**](/wiki/playbook/bigquery-checklist/what-is-pubsub)토픽에 ‘GA4 데이터가 도착했다’는 메시지가 들어오면, 그 메시지를 받아 실제 동작을 수행할 ‘실행 주체’가 필요합니다. Google Cloud에서 이 역할을 맡는 표준 서비스가 **Cloud Functions**입니다. 이 글은 Cloud Functions가 무엇인지·왜 분석 자동화에 잘 맞는지, 그리고 Hurdlers가 **1세대에서 2세대로 옮겨 가는** 이유까지 비개발자도 따라올 수 있게 풀어 봅니다. 구체적인 설정·배선 절차는 **GA4 export 시점에 예약쿼리 업데이트하는 방법**에서 단계별로 다룹니다.

## 왜 Cloud Functions가 필요한가

앞 두 글에서 ‘GA4 데이터 도착 신호를 Pub/Sub 토픽에 넣어 두는’ 흐름까지 짚었습니다. 그 다음 누군가 메시지를 꺼내 보고 ‘**이제 평탄화 SQL을 한 번 돌려야겠다**’는 결정을 내려야 합니다. 이 역할을 맡길 만한 후보가 둘 더 있지만, 둘 다 결정적인 약점이 있어 결국 Cloud Functions로 모이게 됩니다.

| 대안 | 왜 적합하지 않은가 |
| --- | --- |
| 회사 서버에 작은 프로그램을 두고 24시간 켜 두기 | 평소엔 아무 일도 안 하지만 ‘대기 비용’이 매일 청구됨. 서버 관리·OS 업데이트·장애 대응도 사람이 함. |
| 매일 새벽 X시에 자동 실행되는 스크립트 | GA4 데이터 도착 시각 편차를 못 따라감. [Log Router](/wiki/playbook/bigquery-checklist/what-is-log-router)에서 다룬 그 문제. |

반대로 **Cloud Functions**는 ‘평소엔 꺼져 있다가 Pub/Sub 메시지가 오면 깨어나 잠깐 일하고 다시 꺼지는’ 구조라서, 위 두 대안의 약점(대기 비용·서버 관리·시각 편차)을 한 번에 풉니다. 그래서 GA4 자동화의 ‘실행 주체’ 자리는 Cloud Functions가 표준입니다.

## 서버리스를 한 문장으로 — ‘쓴 만큼만 내는 자판기’

Cloud Functions는 ‘**서버리스(serverless)**’ 서비스입니다. 이름은 ‘서버가 없다’가 아니라 **‘서버를 우리가 관리하지 않는다’**는 뜻입니다.

가장 가까운 일상 비유는 자판기입니다.

- **평소엔 조용히 있고** — 손님이 동전을 넣을 때만 깨어남.
- **한 번 작동에 정확한 비용만 청구되고** — 음료 한 캔 값만 받음.
- **여러 명이 동시에 사용해도 자동으로 처리** — 자판기가 여러 대 있는 것처럼 자동으로 늘어났다 줄어듦.

서버리스의 두 장점이 이 비유에 그대로 들어 있습니다.

- **호출당 과금** — 호출이 0이면 청구도 0. GA4 자동화처럼 하루 몇 번 깨어나는 작업은 실질 비용이 거의 없습니다.
- **자동 확장** — 분당 한 번이든 분당 1,000번이든 같은 방식으로 동작합니다.

## 1세대와 2세대 — 우리는 어디로 가는가

Cloud Functions에는 두 세대가 함께 존재합니다. 둘 다 ‘함수 한 개를 올리면 자동으로 깨어나 일한다’는 기본 동작은 같지만, 내부 실행 방식과 한도에서 차이가 있습니다.

| 구분 | Cloud Functions 1세대 | Cloud Functions 2세대 |
| --- | --- | --- |
| 내부 실행 기반 | Google 내부 컴퓨팅 환경 | **Cloud Run 위에서 동작** |
| 한 번 호출 최대 시간 | 9분 | 60분 |
| 동시 요청 처리 | 인스턴스 1개 = 요청 1개 | 인스턴스 1개 = 동시 다중 요청 처리 가능 |
| 이벤트 트리거 | 기본적인 Pub/Sub·Storage·HTTP | 위 + Eventarc 기반 다양한 이벤트(BigQuery·Firestore 변경 등) |
| Console 메뉴 위치 | 기존 Cloud Functions 위치(이력 보존) | Cloud Run 메뉴 안의 ‘함수 작성’ 카드 |

## Cloud Run과는 어떻게 다른가

Cloud Console에서 Cloud Run 메뉴를 열면 Cloud Functions가 그 안에 함께 보입니다. ‘메뉴가 통합됐다’는 말은 여기서 나옵니다 — 다만 두 서비스가 합쳐졌다는 뜻은 아닙니다. 둘은 같은 우산(서버리스 컴퓨팅) 아래 서로 다른 ‘올리는 방식’입니다.

| 기준 | Cloud Functions | Cloud Run |
| --- | --- | --- |
| 올리는 단위 | 코드 파일 한 개(함수 한 개) | 컨테이너 이미지 한 개 |
| Docker 필요? | 아니요 | 네(Dockerfile) |
| 시작 난이도 | 낮음 — Console 폼에 코드만 | 중간 — 이미지 빌드·배포 절차 필요 |
| 자유도 | ‘짧고 단일한 처리’에 최적 | 의존성·런타임 자유도 최대 |
| GA4 자동화에서 | **기본 선택** | 특수 의존성·복잡한 변환이 필요해질 때 |

![Google Cloud Console Cloud Run > 서비스 목록 화면. 좌측 사이드바에 'Cloud Run' 메뉴와 '개요·서비스(선택됨)·작업·작업자 풀·도메인 매핑' 하위 항목이 있다. 상단에는 '컨테이너 배포·작업도 만들기·함수 작성' 버튼이 가로로 정렬되어 있고, 본문 표는 이름·배포 유형·최소 요청 수·리전·인그레스·인증·인그레스 수·최근 배포 시간·배포자·추천 컬럼으로 구성되어 있다. 표에는 일곱 개의 서비스가 나열되어 있는데 '배포 유형' 컬럼에는 Container · Function · Source 같은 서로 다른 배포 방식 라벨이 보이고, 보안상 이름과 배포자 컬럼은 흐릿하게 처리되어 있다.](/wiki-assets/playbook/what-is-cloud-function-and-run/01-cloud-run-services.png)

> **화면 1.** Cloud Console > Cloud Run > 서비스. **배포 유형** 컬럼에 *Container*(직접 빌드한 컨테이너 = Cloud Run 서비스)와 *Function*(코드 파일 한 개 = Cloud Functions 2세대)이 한 표에 함께 나옵니다. ‘메뉴가 통합됐다’는 말은 이 화면을 뜻하지만, 두 서비스는 여전히 별개의 배포 방식입니다.

## GA4 자동화에서 함수가 실제로 하는 일

Cloud Functions(2세대)를 한 번 만들어 두면 매일 다음 흐름이 자동으로 일어납니다.

1. Pub/Sub 토픽에 ‘GA4 데이터 도착’ 메시지가 들어옴 → 함수 자동 호출.
2. 함수가 메시지에서 ‘어느 날짜의 일별 테이블이 들어왔는지’를 꺼냄.
3. ‘실시간용 intraday 테이블이면 무시, 진짜 일별 테이블이면 통과’ 같은 간단한 검사.
4. BigQuery에 미리 저장해 둔 ‘평탄화 SQL(예약 쿼리)’에 ‘지금 한 번 실행해라’ 신호를 보냄.
5. BigQuery가 그 SQL을 즉시 실행해 평탄화 마트를 갱신.

중요한 점 — 함수 안에서 평탄화 SQL을 ‘**직접 실행**’하는 게 아니라, BigQuery에 미리 저장해 둔 SQL에게 ‘**지금 한 번 돌려라**’는 신호만 보낸다는 점입니다. 그래서 함수 코드는 짧게 유지되고, SQL은 BigQuery 안에서 별도로 관리됩니다.

## 비용 — GA4 규모에선 사실상 0원

### Cloud Functions 매월 무료 한도

호출 횟수**200만 호출**

실행 시간(CPU·메모리)**각각 일정 한도까지 무료**

GA4 자동화의 실제 사용량**GA4 속성당 하루 한 번, 한 번 몇 초 이하**

GA4 데이터 도착 신호는 GA4 속성당 하루 한두 건이라, 한 달 합산해도 무료 한도의 0.003%만 씁니다. 결제 카드에 청구액이 발생할 일이 거의 없습니다.

## 자주 묻는 질문

### ‘서버리스’라는 말이 어렵게 느껴집니다. 정확히 무엇이 사라진 거죠?

‘서버 관리 부담’이 사라졌다고 보면 됩니다. 코드가 돌아갈 서버 자체는 Google이 띄우고·유지하고· 확장합니다. 우리는 ‘이 메시지가 오면 이렇게 해 줘’라는 코드만 올리고, 청구는 ‘실제 호출량’ 기준 으로만 받습니다.

### 1세대로 만들어 둔 함수, 지금 당장 옮겨야 하나요?

아닙니다. 1세대 함수는 그대로 안정적으로 동작하며 즉시 옮길 필요는 없습니다. 다만 새로 만드는 자동화는 2세대로 가는 게 표준이고, 1세대 함수에 큰 변경이 생길 때를 ‘마이그레이션 적기’로 잡아 서서히 옮기는 패턴이 일반적입니다.

### Cloud Functions 2세대와 Cloud Run의 경계가 헷갈립니다.

‘2세대 Cloud Functions는 내부적으로 Cloud Run 위에서 돈다’는 한 줄이 핵심입니다. 사용자 입장에선 여전히 ‘함수 한 개를 코드로 올리는’ 경험이고, 그 함수가 실행되는 컨테이너 환경을 Google이 Cloud Run으로 관리해 준다고 이해하면 됩니다. 우리가 직접 Dockerfile을 만들 일이 없습니다.

### 함수가 깨어나는 데 시간이 오래 걸리진 않나요?

처음 깨어날 때 1~3초 정도 걸립니다(‘cold start’). GA4 평탄화 마트는 ‘몇 초 더 늦어져도 무관한 일배치’라 사용자 체감에 영향이 없습니다. 실시간 응답이 중요한 웹 API라면 ‘항상 따뜻하게 유지’ 옵션을 켜는 식으로 보완합니다.

### 함수가 실수로 무한히 호출되면 비용이 폭증하지 않나요?

걱정을 줄이는 두 가지 장치가 있습니다 — ‘**최대 인스턴스 수 제한**’(함수 설정에서 N개로 캡 가능)과 ‘**예산 알림**’(Cloud Billing의 예산/알림). 처음 만들 때 둘 다 켜 두면 사고가 나도 사람이 알아채기 전에 청구액이 폭증할 가능성이 거의 없습니다.

### 함수 안에서 BigQuery 쿼리를 직접 돌려도 되지 않나요?

가능하지만 운영에선 권장하지 않습니다. 함수가 직접 SQL을 들고 있으면 SQL 변경 때마다 함수 코드를 다시 배포해야 하고, 실행 이력·실패 알림도 함수 로그를 봐야 합니다. ‘**SQL은 BigQuery 안에 예약 쿼리로 저장해 두고 함수는 신호만 보낸다**’는 패턴이 변경·관찰을 더 깔끔하게 만들어 줍니다.

## Navigation

- [전체 플레이북 Markdown sitemap](/wiki/playbook/sitemap.md)

### BigQuery

- [BigQuery](/wiki/playbook/bigquery-checklist)
- [BigQuery 온보딩](/wiki/playbook/bigquery-checklist/bigquery-onboarding-guide)
- [BigQuery 인증 설정](/wiki/playbook/bigquery-checklist/how-to-set-up-bigquery-authentication)
- [BigQuery 데이터셋·테이블 설계](/wiki/playbook/bigquery-checklist/bigquery-dataset-and-table-design-guide)
- [BigQuery 쿼리·비용 제어](/wiki/playbook/bigquery-checklist/bigquery-query-and-cost-control-guide)
- [BigQuery 쓰기·MERGE·CDC](/wiki/playbook/bigquery-checklist/bigquery-data-write-and-cdc-guide)
- [BigQuery 코드 예제 모음](/wiki/playbook/bigquery-checklist/bigquery-code-examples)
- [BigQuery로 들어오는 GA4 데이터](/wiki/playbook/bigquery-checklist/what-is-ga4-data-in-bigquery)
- [BigQuery Studio 인터페이스 이해하기](/wiki/playbook/bigquery-checklist/what-is-bigquery-studio-interface)
- [BigQuery 예상 비용](/wiki/playbook/bigquery-checklist/how-to-estimate-bigquery-costs)
- [무료 버전(샌드박스) 해제해야 하는 이유](/wiki/playbook/bigquery-checklist/why-upgrade-from-bigquery-sandbox)
- [GA4 BigQuery 데이터를 왜 평탄화해야 하나](/wiki/playbook/bigquery-checklist/why-flatten-ga4-bigquery-data)
- [Log Router란?](/wiki/playbook/bigquery-checklist/what-is-log-router)
- [Pub/Sub이란?](/wiki/playbook/bigquery-checklist/what-is-pubsub)
- [Cloud Functions이란?](/wiki/playbook/bigquery-checklist/what-is-cloud-function-and-run) (현재 문서)
- [GA4 export 시점에 예약 쿼리 자동 실행하기](/wiki/playbook/bigquery-checklist/how-to-trigger-scheduled-query-on-ga4-export)
- [테이블 정의서는 왜 필요한가](/wiki/playbook/bigquery-checklist/why-table-definition-doc)
- [Event_Flat 테이블 이해하기](/wiki/playbook/bigquery-checklist/what-is-event-flat-table)
- [Item_Performance 테이블 이해하기](/wiki/playbook/bigquery-checklist/what-is-item-performance-table)
