Firebase에서 제공하는 서버리스(Serverless) 백엔드 서비스로, 개발자가 서버를 직접 관리하지 않고 클라우드에서 자동으로 확장 가능한 코드를 실행할 수 있도록 도와준다.
Firebase Cloud Functions에서는 두 가지 트리거 방식을 제공한다.
onCall()
async (data, context) => {}
export const getBillingKey = regionalFunctions.https.onCall(
async (data: { authKey: string; customerKey: string }, context) => {
const { authKey, customerKey } = data;
...
return { success: true, billingKey };
}
);
const getBillingKey = httpsCallable<
{ authKey: string; customerKey: string },
{ billingKey: string }
>(functions, 'getBillingKey');
const result = await getBillingKey({ authKey, customerKey });
onRequest()
async (req, res) => {}
const functions = require("firebase-functions");
exports.helloWorld = functions.https.onRequest((req, res) => {
res.send("Hello, World!");
});
import { getFunctions, httpsCallable } from "firebase/functions";
const functions = getFunctions();
const addMessage = httpsCallable(functions, 'helloWorld');
await helloWorld();
구분 | onCall | onRequest |
---|---|---|
호출 방식 | 클라이언트의 firebase.functions() 를 통해 호출 | 표준 HTTPS 클라이언트 (fetch , Axios 등) 사용 |
보안 처리 | Firebase 인증 및 보안 규칙 자동 처리 | ⚠️ CORS 설정 필요 |
사용 목적 | Firebase와의 간편한 통합 | 일반적인 HTTP 엔드포인트 |
⚠️ CORS 문제
- onCall: CORS 설정 불필요 (Firebase가 자동 처리)
- onRequest: Express와 유사하게 별도의 CORS 설정 필요
Firebase Function은 Firebase Emulator를 통해 테스트해볼 수 있다.
아래는 Firebase Emulator로 Function을 테스트 하는 과정이다.
Firebase CLI 설치:
npm install -g firebase-tools
Firebase 로그인:
firebase login
Firebase 프로젝트 초기화:
firebase init
import * as functions from "firebase-functions";
export const helloWorld = functions.https.onRequest((req, res) => {
res.send("Hello, World!");
});
import * as functions from "firebase-functions";
export const addMessage = functions.https.onCall((data, context) => {
return { text: `Message received: ${data.text || 'Hello'}` };
});
functions 폴더로 이동:
cd functions
컴파일 실행:
npm run build
functions/src
코드가 functions/lib
로 변환됨firebase.json
){
"functions": {
"source": "functions"
},
"emulators": {
"functions": {
"port": 5001
}
}
}
firebase emulators:start
http://127.0.0.1:5001/{프로젝트ID}/{지역}/{함수이름}
Firebase Cloud Functions는 Google Cloud의 Pub/Sub와 통합되어 스케줄링 작업을 수행할 수 있다.
// 매일 자정에 실행되는 스케줄링 함수
exports.accountcleanup = onSchedule("every day 00:00", async (event) => {
// 비활성 사용자 조회
const inactiveUsers = await getInactiveUsers();
// 비활성 사용자 삭제
const promisePool = new PromisePool(
() => deleteInactiveUser(inactiveUsers),
MAX_CONCURRENT
);
await promisePool.start();
logger.log("User cleanup finished");
});
Next.Js를 사용해서 프로젝트를 진행하던 중 프론트엔드 개발자와 협업이 필요해서, Cloud Function을 API Document로 작성할 수 있는지 찾아보았다.
필자는 다음과 같은 방법으로 Cloud Function을 문서화했다.
function/src/**.js
: Cloud Function에 JSDoc 주석 작성scripts/swagger-config.js
: swagger-jsdoc 설정 (OpenAPI 정보, apis 경로 등)scripts/generate-swagger.js
: 위 설정을 사용해 swagger.json 생성하는 스크립트 작성package.json
에 스크립트 추가npm run generate:swagger
로public/swagger.json
파일 생성src/app/swagger/page.tsx
: Swagger UI 페이지 작성- 브라우저에서 확인
아래와 같은 프로젝트 구조를 적용해서 Swagger를 적용했다.
project/
│
├─ firebase.json // Firebase 프로젝트 설정 (emulator, hosting, functions 등)
│
├─ next.config.js // Next.js 설정
│
├─ public/
│ └─ swagger.json // JSDoc → Swagger 변환 후 생성되는 최종 문서 (배포 시 포함)
│
├─ scripts/
│ ├─ swagger-config.js // swagger-jsdoc 설정 (OpenAPI 정보, apis 경로 등)
│ └─ generate-swagger.js // 위 설정을 사용해 swagger.json 생성하는 스크립트
│
├─ src/
│ └─ app/ // Next.js 13+ App Router
│ ├─ api-doc/
│ │ └─ page.tsx // Swagger UI 페이지 (use client 또는 dynamic import)
│ └─ page.tsx // 예시: 메인 페이지
│
└─ functions/
├─ package.json // Firebase Functions 전용 package.json
├─ tsconfig.json // Functions TS 설정
└─ src/
├─ index.ts // Firebase Functions entry
├─ (여러 API 모듈).ts
└─ ... // 기타 파일들
/**
* @swagger
* /addMessage:
* post:
* summary: "메시지 추가 API"
* description: "Firebase Database에 메시지를 추가합니다."
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* text:
* type: string
* description: "추가할 메시지"
* responses:
* 200:
* description: "메시지 추가 성공"
*/
export const addMessage = functions.https.onCall((data, context) => {
const text = data.text || "Default message";
return { text: `Message received: ${text}` };
});
// scripts/swagger-config.js
module.exports = {
// OpenAPI 기본 설정
definition: {
openapi: '3.0.0',
info: {
title: 'My Firebase Functions API',
version: '1.0.0',
},
},
// API 정의 경로
apis: ['functions/src/**/*.{ts,js}'],
};
// scripts/generate-swagger.js
const fs = require('fs');
const swaggerJsdoc = require('swagger-jsdoc');
const config = require('./swagger-config.js');
const swaggerSpec = swaggerJsdoc(config);
// Next.js 앱의 public 폴더에 swagger.json을 생성
const outputPath = './public/swagger.json';
fs.writeFileSync(outputPath, JSON.stringify(swaggerSpec, null, 2));
console.log(`✅ Swagger JSON 생성 완료: ${outputPath}`);
프로젝트 루트의 package.json
에 아래 스크립트를 추가:
{
"scripts": {
"generate:swagger": "node scripts/generate-swagger.js",
"dev": "next dev"
}
}
// src/app/swagger/page.tsx
'use client';
import React from 'react';
import SwaggerUI from 'swagger-ui-react';
import 'swagger-ui-react/swagger-ui.css';
export default function ApiDocPage() {
return (
<div style={{ minHeight: '100vh' }}>
{/* public 폴더의 swagger.json은 /swagger.json으로 접근합니다 */}
<SwaggerUI url="/swagger.json" />
</div>
);
}
npm run generate:swagger
firebase emulators:start
브라우저에서 `http://localhost:{포트}/swagger`로 접속하여 API 문서를 확인.
firebase authentication을 적용한 firebase function을 swagger로 테스트하고 싶다면 다음과 같이 swagger-config.ts
를 수정해주면 된다.
module.exports = {
// OpenAPI 기본 설정
definition: {
openapi: '3.0.0',
info: {
title: 'My Firebase Functions API',
version: '1.0.0',
},
servers: [
{
url: 'http://localhost:5003/wedeoio/asia-northeast3', // 실제 local function url
},
],
// 추가: 보안 스키마 설정
components: {
securitySchemes: {
bearerAuth: {
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT', // Firebase ID 토큰도 결국 JWT 구조
},
},
},
// 추가: 전역 보안 적용 (모든 엔드포인트에 bearerAuth 요구)
security: [
{
bearerAuth: [],
},
],
},
apis: ['functions/src/**/*.{ts,js}'],
};
// 프론트 코드
const userCredential = await _auth.signInWithEmailAndPassword(auth, email, password);
// 로그인 성공 시, userCredential.user에서 ID 토큰 가져오기
const token = await userCredential.user.getIdToken(/* forceRefresh */ true);