Firebase cloud function
Create folder
// e.g.
mkdir recommand_youtube
Firebase ํ๋ก์ ํธ ์์ฑ on Firebase console
Firebase CLI ์ค์น ๋ฐ ์ด๊ธฐํ
npm install -g firebase-tools
Firebase ํ๋ก์ ํธ ์ด๊ธฐํ ์ค์
// login
firebase login
// login ๋ณ๊ฒฝ
firebase logout
firebase login
// check project list
firebase projects:list
// result
โ Preparing the list of your Firebase projects
Project Display Name: recommand-youtube, Project ID: recommand-5e127, Project Number: 155670260747, Resource Location ID: [Not specified]
Project Display Name: refacter, Project ID: refacter, Project Number: 192701994501, Resource Location ID: [Not specified]
// initialize functions
firebase init functions
// Python์ ๋ก์ปฌ์์ ํ
์คํธํ๊ธฐ๊ฐ ์ด๋ ค์
// ๊ทธ๋์ nodejs๋ ํ์ฉํ๋ ๊ฒ์ด ์ง์์ ์ผ๋ก ์ ์ง๋ณด์๊ฐ ํธํ ๊ฒ์ผ๋ก ์๊ฐ ๋จ
functions์ ์ด๊ธฐํ ํ๋ฉด ํ๋ก์ ํธ๋ฅผ ์ ํํ ์ ์๋ค.
๊ทธ๋ฌ๋ ํ์ํ๋ค๋ฉด ํ๋ก์ ํธ ์ ํ
// select the project
firebase use <ํ๋ก์ ํธID>

(Optional)Google Cloud Platform(GCP) API ํ์ฑํ
- Google Cloud Console (https://console.cloud.google.com) ์ ์
- ํด๋น ํ๋ก์ ํธ ์ ํ
- ์ข์ธก ๋ฉ๋ด์์ โAPI ๋ฐ ์๋น์คโ > โYoutube Data API v3โ ํ์ฑํ > โ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณดโ (Credentials) ์ด๋
- โAPI ํคโ ์น์ ์ ์์ฑ๋ API ํค๊ฐ ํ์๋จ
// GCP secret manager์ key ์ ์ฅ
firebase functions:secrets:set YOUR_SECRET_NAME
// result
firebase functions:secrets:set youtube_key
โ By convention, secret key must be in UPPER_SNAKE_CASE.
? Would you like to use YOUTUBE_KEY as key instead? Yes
? Enter a value for YOUTUBE_KEY [hidden]
โ Created a new secret version projects/155670260747/secrets/YOUTUBE_KEY/versions/1
- Firebase functions์ ์ ๊ทผํ๋
PROJECT_ID@appspot.gserviceaccount.com์ ๊ถํ ์ค์ 
(Optional) OAuth 2.0 ์ค์
- OAuth ๋์ ํ๋ฉด

- ํด๋ผ์ด์ธํธ ๋ง๋ค๊ธฐ
- redirect-uri
-
- OAuth Playground์ฉ:
https://developers.google.com/oauthplayground
- OAuth Playground์ฉ:
- ์์ฒด ์ ํ๋ฆฌ์ผ์ด์
์ฉ: ๊ทํ์ ์ ํ๋ฆฌ์ผ์ด์
์ฝ๋ฐฑ URL

-
- redirect-uri
- Id, ๋ณดํธ ๋น๋ฐ๋ฒํธ ์ ์ฅ
- ๋์ > ํ
์คํธ ์ฌ์ฉ์ ๋ฑ๋ก

- RefreshToken ๊ฐ์ ธ์ค๊ธฐ OAuth 2.0 Playground ์์ RefreshToken ๊ฐ์ ธ์ค๊ธฐ
Google OAuth 2.0 ๋ฆฌํ๋ ์ ํ ํฐ ํ๋ ์๋ฒฝ ๊ฐ์ด๋ 2024 - ์ต์ UI ์ ๋ฐ์ดํธ ๋ฐ์
IDE ํ๊ฒฝ ๊ตฌ์ฑ
Nodejs ํ๊ฒฝ์ผ ๋๋ง ์ ํจ
Run and Debug ์ค์
9229 ํฌํธ ์ค์
๋ณ๋๋ก ํฌํธ๋ฅผ ์ง์ ํ๋ ค๋ฉด Node.js inspect ์ต์ ์ธย
--inspect=ํฌํธ๋ฒํธย ์ฌ์ฉ๋ฒ์ ์ฐธ๊ณ ํด์ผ ํ์ง๋ง ํ์ฌ Firebase CLI๋ ๊ณ ์ ์ผ๋ก 9229 ํฌํธ๋ฅผ ์ฌ์ฉํฉ๋๋ค. by GPT
"configurations": [
// ...
{
"type": "node",
"request": "attach",
"name": "Attach to Functions Emulator",
"port": 9229,
"restart": true,
}
]
Break point ์ค์
์ค์ ํ ํ์ธ
์๋ฎฌ๋ ์ดํฐ ์คํ & VS Code ์คํ
// Emulator
firebase emulators:start --inspect-functions
// VS Code
Run "Attach to Functions Emulator"
Firebase hosting
ํธ์คํ ์ค๋จ
firebase hosting:disable
Google cloud
// login
gcloud auth login
// ํ์ฌ ๋ก๊ทธ์ธ ๊ณ์ ๋ฆฌ์คํธ
gcloud auth list
// ํ๋ก์ ํธ ์ค์
gcloud config set project PROJECT_ID
Vertex AI RAG
- ์ฝํผ์ค ์์ฑ
- ์ฝํผ์ค๋? ๋ง๋ญ์น, ์์ฐ์ธ์ด ์ฐ๊ตฌ๋ฅผ ์ํด ํน์ ํ ๋ชฉ์ ์ ๊ฐ์ง๊ณ ์ธ์ด์ ํ๋ณธ์ ์ถ์ถํ ์งํฉ

- ์ฝํผ์ค๋? ๋ง๋ญ์น, ์์ฐ์ธ์ด ์ฐ๊ตฌ๋ฅผ ์ํด ํน์ ํ ๋ชฉ์ ์ ๊ฐ์ง๊ณ ์ธ์ด์ ํ๋ณธ์ ์ถ์ถํ ์งํฉ
- ๋ฐ์ดํฐ ์ ํ ํ ์์ฑ
- ๋ก์ปฌ ํ์ผ ์ ๋ก๋: ๋ก์ปฌ ํ์ผ์ ํตํด RAG ์ค์ , ์ดํ ๋ก์ปฌ์์ ํ์ผ ์ญ์ ๋๋ ๋ฌด๋ฐฉ
- Google Drive ํ์ผ ์ ํ: ๊ณ์ ์ ๋ฐ์ดํธ ๊ฐ๋ฅํ ๊ฒ
- ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ, ์ค์
- service-<ํ๋ก์ ํธ ๋๋ฒ>@gcp-sa-vertex-rag.iam.gserviceaccount.com

- service-<ํ๋ก์ ํธ ๋๋ฒ>@gcp-sa-vertex-rag.iam.gserviceaccount.com
- Vertex AI Studio์์ ํ ์คํธ - 3๋ฒ ์ฒซ๋ฒ์งธ ๊ทธ๋ฆผ์ ์๋ ๋ฒํผ
Cloud function with RAG
- Google Cloud ํ๋ก์ ํธ ์ค์
# ํ๋ก์ ํธ ์ค์
PROJECT_ID=carenote-ai-474805
LOCATION=europe-west4
gcloud config set project ${PROJECT_ID}
- ํ์ํ API ํ์ฑํ Vertex AI, Cloud Functions, Cloud Build ๋ฑ ํ์ํ API ํ์ฑํ
gcloud services enable \
aiplatform.googleapis.com \
cloudfunctions.googleapis.com \
cloudbuild.googleapis.com \
artifactregistry.googleapis.com \
run.googleapis.com
- Vertex AI RAG Corpus ์ค์
# RAG Corpus๋ ์ด๋ฏธ ์์ฑ๋์ด ์์
RAG_CORPUS_ID=2305843009213693952
RAG_CORPUS_RESOURCE_NAME="projects/${PROJECT_ID}/locations/${LOCATION}/ragCorpora/${RAG_CORPUS_ID}"
- ํ๊ฒฝ ๋ณ์ ์ค์ (.env ํ์ผ)
PROJECT_ID=carenote-ai-474805
PROJECT_NUMBER=16801581551
LOCATION=europe-west4
RAG_CORPUS_ID=2305843009213693952
MODEL_ID=gemini-2.5-flash-lite
- Node.js ํ๋ก์ ํธ ๊ตฌ์ฑ
package.json:
{
"name": "carenote-ai",
"version": "1.0.0",
"main": "index.js",
"type": "module", // ES6 ๋ชจ๋ ์ฌ์ฉ
"dependencies": {
"@google-cloud/functions-framework": "^4.0.0",
"@google-cloud/vertexai": "^1.10.0",
"dotenv": "^17.2.3"
}
}๊ธฐ๋ณธ ์ฝ๋ ๊ตฌ์กฐ: // index.js - Cloud Functions ์ํธ๋ฆฌํฌ์ธํธ import functions from โ@google-cloud/functions-frameworkโ;
// generateDiary ํจ์ ์ ์ functions.http(โgenerateDiaryโ, async (req, res) โ { // CORS, ์ธ์ฆ, ๊ฒ์ฆ ์ฒ๋ฆฌ // RAG ํธ์ถ ๋ฐ ์๋ต });
// ragQuery ํจ์ ์ ์
functions.http(โragQueryโ, async (req, res) โ {
// ์ผ๋ฐ RAG ์ฟผ๋ฆฌ ์ฒ๋ฆฌ
});
Vertex AI RAG ํธ์ถ ํต์ฌ ์ฝ๋: import { VertexAI } from โ@google-cloud/vertexaiโ;
const vertexAI = new VertexAI({ project: PROJECT_ID, location: LOCATION, });
const generativeModel = vertexAI.preview.getGenerativeModel({ model: MODEL_ID, generationConfig: { responseMimeType: โapplication/jsonโ } });
// RAG ์์ฒญ const ragRequest = { contents: [{ role: โuserโ, parts: [{ text: query }] }], tools: [{ retrieval: { vertexRagStore: { ragResources: [{ ragCorpus: RAG_CORPUS_RESOURCE_NAME }], similarityTopK: 5, vectorDistanceThreshold: 0.8 } } }] };
- Cloud Functions ๋ฐฐํฌ
generateDiary ํจ์ ๋ฐฐํฌ
gcloud functions deploy generateDiary
โgen2
โruntime nodejs20
โregion europe-west4
โsource .
โentry-point generateDiary
โtrigger-http
โtimeout 300s
โmemory 512MB
โmin-instances 0
โmax-instances 10
โset-env-vars PROJECT_ID={LOCATION},RAG_CORPUS_ID=${RAG_CORPUS_ID},MODEL_ID=gemini-2.5-flash-lite
โno-allow-unauthenticated
gcloud functions deploy generate-diary \
--gen2 \
--runtime nodejs20 \
--region europe-west4 \
--source . \
--entry-point generateDiary \
--trigger-http \
--timeout 300s \
--memory 512MB \
--min-instances 0 \
--max-instances 10 \
--set-env-vars PROJECT_ID=carenote-ai-474805,LOCATION=europe-west4,RAG_CORPUS_ID=2305843009213693952,MODEL_ID=gemini-2.5-flash-lite \
--no-allow-unauthenticated
ragQuery ํจ์๋ ๋์ผํ ๋ฐฉ์์ผ๋ก ๋ฐฐํฌ ๊ฐ๋ฅ
- ๋ฐฐํฌ ํ ์ค์
IAM ๊ถํ ์ค์ (Cloud Functions Invoker)
gcloud functions add-invoker-policy-binding generateDiary
โmember=โuser:email@domain.comโ
โregion=europe-west4
๋ฐฐํฌ๋ ํจ์ URL
FUNCTION_URL=โhttps://europe-west4-${PROJECT_ID}.cloudfunctions.net/generateDiaryโ
- ํ์ ํ์ผ ๊ตฌ์ฑ
project/ โโโ index.js # Cloud Functions ์ํธ๋ฆฌํฌ์ธํธ โโโ package.json # ์์กด์ฑ ์ ์ โโโ .env # ํ๊ฒฝ๋ณ์ (๋ก์ปฌ ํ ์คํธ์ฉ) โโโ .gcloudignore # ๋ฐฐํฌ ์ ์ธ ํ์ผ โโโ src/ โโโ config/ # Vertex AI ์ค์ โโโ services/ # RAG ํธ์ถ ๋ก์ง โโโ controllers/ # HTTP ์์ฒญ ์ฒ๋ฆฌ
- ์ฃผ์ ํ๊ฒฝ ์ค์ ์์ฝ
- Region: europe-west4 (RAG Corpus์ ๋์ผ ์ง์ญ)
- Runtime: nodejs20
- Memory: 512MB
- Timeout: 300s (RAG ์๋ต ์๊ฐ ๊ณ ๋ ค)
- Authentication: IAM ๊ธฐ๋ฐ (no-allow-unauthenticated)
์ด ์ค์ ์ผ๋ก Vertex AI RAG๋ฅผ Cloud Functions๋ฅผ ํตํด ์๋น์คํ ์ ์์ต๋๋ค.
์ฃผ๊ธฐ์ ์ธ ํ ํฐ ์
๋ฐ์ดํธ ํ์
gcloud auth print-identity-token