Wednesday, July 19, 2023

Firebase Functions 완벽 가이드: 초보자부터 전문가까지

Firebase Functions 이해 및 기본 설정 방법

Firebase Functions 이해하기

Firebase Functions는 구글이 제공하는 서버리스 아키텍처 기반의 클라우드 함수 서비스로, 복잡한 인프라 구축 과정 없이 백엔드 로직을 구현할 수 있는 기회를 제공합니다.

Firebase Functions 설정하기

Firebase Functions를 사용하기 위해서는 Firebase CLI 설치가 필요합니다. 아래의 순서대로 진행해주세요.

  1. Node.js 설치하기
  2. npm을 통해 Firebase CLI 설치하기
  3. Firebase에 로그인하고 프로젝트 초기화하기

// Node.js와 npm 설치 확인하기
$ node -v
$ npm -v

// Firebase CLI 설치하기
$ npm install -g firebase-tools

// Firebase에 로그인하고 프로젝트 초기화하기
$ firebase login
$ firebase init functions

클라우드 함수 생성 및 배포하기

기본 설정이 완료되면, index.js 파일을 수정하여 첫 번째 클라우드 함수를 작성하고 배포하는 과정입니다.


// functions/index.js
const functions = require('firebase-functions');

exports.helloWorld = functions.https.onRequest((request, response) => {
  response.send('Hello, World!');
});

// 함수 배포하기
$ firebase deploy --only functions

Firebase Functions에서 다양한 트리거 사용법

HTTP 트리거 사용하기

Firebase Functions는 HTTP 요청에 응답하는 함수를 작성할 수 있습니다. 아래는 onRequest 메서드를 사용한 HTTP 트리거의 예시입니다.


// functions/index.js
const functions = require('firebase-functions');

exports.httpFunction = functions.https.onRequest((request, response) => {
  // 여기에 로직을 작성합니다.
});

Firebase Realtime Database 트리거 사용하기

클라우드 함수를 Realtime Database의 이벤트에 연결할 수 있습니다. 예를 들어, 데이터가 추가되거나 삭제될 때마다 함수가 실행됩니다.


// functions/index.js
const functions = require('firebase-functions');

exports.onDataAdded = functions.database.ref('/path/to/data').onCreate((snapshot, context) => {
  // 데이터가 추가되었을 때 수행되는 작업을 정의합니다.
});

exports.onDataDeleted = functions.database.ref('/path/to/data/{id}').onDelete((snapshot, context) => {
  // 데이터가 삭제되었을 때 수행되는 작업을 정의합니다.
});

Firebase Firestore 트리거 사용하기

Firestore 이벤트에 함수를 연결하여, 문서가 생성, 수정, 삭제될 때마다 함수가 실행됩니다.


// functions/index.js
const functions = require('firebase-functions');

// 문서 생성시 실행
exports.firestoreCreateTrigger = functions.firestore.document('collection/{docId}').onCreate((snap, context) => {
  // 여기에 로직을 작성합니다.
});

// 문서 수정시 실행
exports.firestoreUpdateTrigger = functions.firestore.document('collection/{docId}').onUpdate((change, context) => {
  // 여기에 로직을 작성합니다.
});

// 문서 삭제시 실행
exports.firestoreDeleteTrigger = functions.firestore.document('collection/{docId}').onDelete((snap, context) => {
  // 여기에 로직을 작성합니다.
});

Firebase Functions에서 예외 처리 및 에러 관리하기

예외 처리 및 에러 반환하기

클라우드 함수에서 예외 처리와 에러 관리는 중요합니다. 클라이언트에 적절한 에러 메시지와 HTTP 상태 코드를 반환해야 합니다.


// functions/index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

exports.handleErrors = functions.https.onRequest(async (request, response) => {
  try {
    const data = await fetchData();
    response.send(data);
  } catch (error) {
    console.error(error);
    response.status(500).send('Internal Server Error');
  }
});

async function fetchData() {
  // 여기에서 데이터를 가져오거나 에러를 던질 수 있는 로직을 작성합니다.
}

에러 모니터링 및 로깅하기

Firebase Functions에서 에러와 워닝 메시지를 모니터링하기 위해 Google Cloud Logging을 사용할 수 있습니다.

Google Cloud Logging을 사용하면 다음과 같은 로그 유형을 확인할 수 있습니다:

  • 실행 시작 및 종료
  • 메모리 및 CPU 사용
  • 예외 발생
  • 사용자 정의 로그

재시도 정책 설정하기

특정 함수 호출이 실패할 경우, Firebase Functions는 함수를 자동으로 재시도하도록 설정할 수 있습니다. 이 기능을 사용하려면 함수에 재시도 정책을 명시적으로 추가하세요.


// functions/index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

exports.retryFunction = functions.runWith({
  failurePolicy: {
    retry: {
      maxAttempts: 3,
      minBackoff: '10s',
      maxBackoff: '60s',
      maxDoublings: 2,
    },
  },
}).pubsub.topic('retry-topic').onPublish(async (message) => {
  // 여기에 로직을 작성합니다.
});

Firebase Functions와 Firebase Authentication 연동하기

Firebase Authentication 트리거 사용하기

Firebase Functions는 사용자가 가입되거나 삭제될 때 실행되는 함수를 만들 수 있습니다. 이를 이용해 사용자 관련 데이터를 관리하거나 이메일 등의 환영 메시지를 전송할 수 있습니다.


// functions/index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

exports.userCreated = functions.auth.user().onCreate(async (userRecord) => {
  // 새로운 사용자가 가입했을 때 수행되는 작업을 정의합니다.
});

exports.userDeleted = functions.auth.user().onDelete(async (userRecord) => {
  // 사용자가 삭제되었을 때 수행되는 작업을 정의합니다.
});

Firebase Functions에서 사용자 인증 정보 관리하기

Firebase Functions를 사용해 사용자 인증 정보를 가져오거나 수정할 수 있습니다. Firebase Admin SDK를 사용하면 사용자 관리 작업을 처리할 수 있습니다.


// functions/index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

exports.userFunction = functions.https.onRequest(async (request, response) => {
  const uid = request.body.uid;

  try {
    const userRecord = await admin.auth().getUser(uid);
    // 인증 정보를 사용한 작업 (예: 이메일 주소 변경)
    await admin.auth().updateUser(uid, { email: 'new-email@example.com' });
    response.send(userRecord);
  } catch (error) {
    response.status(500).send('Error fetching user data');
  }
});

인증된 요청 처리하기

클라이언트가 인증 토큰과 함께 요청을 보낼 경우, 클라우드 함수에서 토큰을 검증하고 요청을 처리할 수 있습니다.


// functions/index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

exports.authenticatedFunction = functions.https.onRequest(async (request, response) => {
  const authToken = request.header('Authorization');
  if (!authToken) {
    response.status(401).send('Unauthorized');
    return;
  }

  try {
    // Id 토큰을 검증하고 파싱
    const decodedToken = await admin.auth().verifyIdToken(authToken);
    // 인증된 사용자의 UID
    const uid = decodedToken.uid;
    // 인증된 요청을 처리하는 로직을 작성합니다.
    const userData = await processData(uid);
    response.send(userData);
  } catch (error) {
    response.status(401).send('Invalid token');
  }
});

async function processData(uid) {
  // 사용자의 UID를 사용하여 데이터를 처리하고 결과를 반환하는 로직을 작성합니다.
}

Firebase Functions와 Firebase Firestore 연동하기

Firestore 트리거 사용하기

Firebase Functions는 Firestore 데이터베이스의 특정 문서가 생성, 수정, 삭제될 때 실행되는 함수를 만들 수 있습니다. 이를 이용해 데이터 변동에 따른 로직을 처리할 수 있습니다.


// functions/index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

exports.documentCreated = functions.firestore.document('collection/{docId}').onCreate(async (snap, context) => {
  // 문서가 생성되었을 때 실행되는 로직을 작성합니다.
});

exports.documentUpdated = functions.firestore.document('collection/{docId}').onUpdate(async (change, context) => {
  // 문서가 수정되었을 때 실행되는 로직을 작성합니다.
});

exports.documentDeleted = functions.firestore.document('collection/{docId}').onDelete(async (snap, context) => {
  // 문서가 삭제되었을 때 실행되는 로직을 작성합니다.
});

Firebase Functions에서 Firestore 데이터 관리하기

Firebase Functions를 사용해 Firestore 데이터를 읽거나 쓸 수 있습니다. Firebase Admin SDK를 사용하면 데이터베이스 관리 작업을 처리할 수 있습니다.


// functions/index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

exports.firestoreFunction = functions.https.onRequest(async (request, response) => {
  const docId = request.body.docId;
  const db = admin.firestore();

  try {
    // 문서 읽기
    const docSnapshot = await db.collection('collection').doc(docId).get();
    if (!docSnapshot.exists) {
      response.status(404).send('Document not found');
      return;
    }

    // 문서 쓰기
    await db.collection('collection').doc(docId).set({ field: 'value' });
    response.send(docSnapshot.data());
  } catch (error) {
    response.status(500).send('Error accessing Firestore');
  }
});

Firebase Functions와 Firebase Storage 연동하기

Storage 트리거 사용하기

Firebase Functions는 Firebase Storage에 파일이 업로드되거나 삭제될 때 실행되는 함수를 만들 수 있습니다. 이를 이용해 파일 업로드에 따른 로직을 처리할 수 있습니다.


// functions/index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

exports.fileUploaded = functions.storage.object().onFinalize(async (object) => {
  // 파일이 업로드되었을 때 실행되는 로직을 작성합니다.
});

exports.fileDeleted = functions.storage.object().onDelete(async (object) => {
  // 파일이 삭제되었을 때 실행되는 로직을 작성합니다.
});

Firebase Functions에서 Storage 파일 관리하기

Firebase Functions를 사용해 Storage에 저장된 파일에 접근하거나 파일을 삭제할 수 있습니다. Firebase Admin SDK를 사용하면 파일 관리 작업을 처리할 수 있습니다.


// functions/index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

exports.storageFunction = functions.https.onRequest(async (request, response) => {
  const filePath = request.body.filePath;
  const storage = admin.storage();

  try {
    // 파일 읽기
    const file = storage.bucket().file(filePath);
    const downloadUrl = await file.getSignedUrl({ action: 'read', expires: '03-09-2491' });

    // 파일 삭제
    await file.delete();
    response.send({ downloadUrl });
  } catch (error) {
    response.status(500).send('Error accessing Storage');
  }
});

0 개의 댓글:

Post a Comment