ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 파이어베이스 Functions 가 무엇이고, 설정/배포/테스트를 한꺼번에 ~!
    개발일지/firebase 2021. 10. 31. 12:00

    안녕하세요 개발하는남자 개남입니다. 

    오늘 정리할 포스트는 파이어베이스 Functions에 대한 것입니다. 

    포스팅에 앞서서 오늘 funtions 를 다루고 배포를 위해 firebase CLI 가 설치되어있어야 하고 프로젝트가 연결되어있어야 합니다. 만일 설정 전이라면 이전 포스팅 파이어베이스 CLI 설정 포스트를 보고 오시면 도움이 되실 것입니다. 

    아래 링크를 클릭 하시면 됩니다. 

     

    파이어베이스 윈도우 환경 CLI 설정 방법

    안녕하세요 개발하는남자 개남입니다. 오늘은 간단하게 윈도우환경에서 파이어베이스 cli를 세팅하는 방법을 기록하려고 합니다. 나아가 cli 를 이용하여 프로젝트를 연결하고 원하는 서비스(fun

    sudarlife.tistory.com


    파이어베이스 Functions 란?

    Firebase 기능과 HTTPS 요청에 의해 트리거 되는 이벤트에 응답하여 백엔드 코드를 자동으로 실행할 수 있는 서버리스 프레임워크입니다. 

    파이어베이스에서 공식 도큐먼트에서 파이어베이스 Functions를 소개하는 부분을 발췌했습니다.

    서버리스라는 용어가 나오는데 서버 + 리스 ( Server + Less )를 의미합니다. 

    쉽게 말해 서버가 필요없다는 뜻입니다.

     

    사용자들에게 좋은 콘텐츠 좋은 서비스를 제공하기 위해서는 데이터 처리, 혹은 유저 간 통신이 이루어지게 될 텐데 그러면서 반드시 필요한 것이 서버입니다. 서버가 없이는 좋은 서비스를 제공하기란 쉽지 않습니다. 단순 유틸 성 앱이 아닌 이상 서버가 있어야 하지요. 

    서버를 구축하고 관리하는 부분이 상당한 리소스를 사용하게 됩니다. 이유는 많은 유저가 몰리면 그만큼의 성능이슈가 발생하지 않도록 확장 관리해줘야 하고 사용자 유저가 없을 때는 많은 비용을 지불하기 힘들기 때문에 축소해서 관리해야 합니다. 즉, 원활한 서비스를 제공하기 위해서는 서버 관리는 필수가 되겠지요...

    물리 서버를 확장 축소를 하는 것은 쉬운 작업이 아니고 금방 처리 되는 문제도 아닙니다. 그래서 이러한 문제를 해결하기 위해 나온 것이 cloud server 가 되겠지요. Aws 나 Google MS처럼 cloud server를 제공하고 그곳에서 서버를 세팅하면 간단한(사실 복잡한....) 세팅으로 서버 리소스를 늘리고 줄이거나 할 수 있으며 aws Auto Scaling을 통해 자동적으로 늘리고 줄이는 기능도 이용할 수 있습니다. 더 나아가 서버 리스 서비스까지 나오게 됩니다. 물리적 server 또는 Cloud server 가 없이도 서버가 있는 것처럼 기능을 제공하는 것입니다.

    (사실 서버가 없을수는 없지만 서비스를 제공하는 업체에서 자동으로 관리가 되기 때문에 사용하는 개발사들은 서버 관리를 전혀 하지 않아도 안전한 서비스를 제공할 수 있다는 의미에서 서버가 없다는 serverless용어가 된 것일 것 같습니다. )  

    사용한 만큼 돈을 지불하는 방식으로 적절하게 사용하면 큰 도움이 될 수 있을 것입니다. 

    하지만 분명 비용은 직접 운영하는 것보다는 많이 들 것으로 예상됩니다 ^^;; 

    진짜 서버 대용으로 Functions 나 Aws Lambda 서비스를 사용하게 되면 나중에 후회 하실 것입니다. (비용이 상당할 것으로 예상합니다.)

     


    그렇다면? 왜 Functions 를 사용할까?

    firebase에 다른 서비스와 쉽게 연계하여 후처리 및 전처리 기능들을 손쉽게 처리할 수 있다는 부분이 가장 강점이 아닐까 생각됩니다. 

    흥미로운 알림의 기타 사용 사례

    데이터베이스 정리 및 유지보수의 기타 사용 사례

    Firebase 클라우드 일괄 작업의 기타 예

    타사 서비스 및 API와 통합하는 다른 방법

     

    파이어베이스 functions를 위와 같은 식의 후처리나 전처리를 목적으로 사용 예제를 제시합니다. 

    완전한 서버를 대체 하여 사용하는 부분에 대해서는 소개하고 있지 않다는 것은 적적하지 못하다는 뜻으로 생각하면 되지 않을까 생각해봅니다. 물론 http 통신을 통해 api 서버처럼 사용 가능합니다. 


     

    프로젝트 Functions 설정 및 테스트 

    원하는 디렉토리(프로젝트)에서 아래 명령어를 통해 초기화 설정을 해줍니다. 

    $ firebase init functions

    진행 여부를 묻는데 y 눌러주면 됩니다. 

    프로젝트 연결을 어떻게 할 것인지 묻는 질문에 지난포스팅에서 만들어줬던 프로젝트를 사용할 것이기 때문에 첫 번째 Use and Existing project를 선택해줍니다. 방향키를 이동해서 다른 설정을 하시기 원하시면 이동하시면 됩니다. 

    프로젝트를 선택해주면 다음으로 어떤 언어로 개발할 것인지 나옵니다. 여기서 Javascript 와 TypeScript를 선택할 수 있는데 javascript 를 선택해주겠습니다.( 자료도 많고, 공식 문서에도 예제가 javascript 를 선택해서 진행하고 있습니다 ) 

    다음으로 EsLint 를 세팅할 것인지와 의존성 관리를 npm으로 진행할 것인지를 묻는 질문이 나오는데 esLint는 익숙하신 분들에게는 추천드리고 아닌 분들은 설정하지 않아도 됩니다. 의존성 관리는 npm으로 진행하도록 하겠습니다. 

     

    프로젝트가 세팅이 완료 되면 해당 폴더 내에 위의 구조로 파일들이 생성되어있음을 확인할 수 있습니다. 

    이제 테스트 해볼 것은 Cloud Storage 트리거를 이용하여 사용자가 이미지를 등록했을 때 이미지를 리사이징 처리하여 섬네일로 사용할 수 있는 방법을 알아보도록 하겠습니다. (이 소스 역시 친절하게 예제 소스를 제공하고 있습니다. )

     

    가장먼저 필요 라이브러리를 package.json 파일에 추가하도록 하겠습니다.

      "dependencies": {
        "firebase-admin": "^9.8.0",
        "firebase-functions": "^3.14.1",
        "child-process-promise": "^2.2.1",
        "mkdirp": "^1.0.3"
      },

    해당 모듈을 받기위해 다음 명령어를 통해 설치하도록 하겠습니다.

    $ npm install
    // 참고로 npm install 은 functions 폴더 안에서 해줘야 합니다.

    index.js 파일에 

    예제 소스를 붙여줍니다. 예제 소스는 아래와 같습니다. 

    const functions = require("firebase-functions");
    const admin = require("firebase-admin");
    const mkdirp = require("mkdirp");
    const spawn = require("child-process-promise").spawn;
    const path = require("path");
    const os = require("os");
    const fs = require("fs");
    
    // Max height and width of the thumbnail in pixels.
    const THUMB_MAX_HEIGHT = 200;
    const THUMB_MAX_WIDTH = 200;
    // Thumbnail prefix added to file names.
    const THUMB_PREFIX = "thumb_";
    
    admin.initializeApp();
    
    
    exports.generateThumbnail = functions.region("asia-northeast3").storage.object().onFinalize(async (object) => {
        const filePath = object.name;
        const contentType = object.contentType; // This is the image MIME type
        const fileDir = path.dirname(filePath);
        const fileName = path.basename(filePath);
        const thumbFilePath = path.normalize(path.join(fileDir, `${THUMB_PREFIX}${fileName}`));
        const tempLocalFile = path.join(os.tmpdir(), filePath);
        const tempLocalDir = path.dirname(tempLocalFile);
        const tempLocalThumbFile = path.join(os.tmpdir(), thumbFilePath);
        // Exit if this is triggered on a file that is not an image.
        if (!contentType.startsWith("image/")) {
          return functions.logger.log("This is not an image.");
        }
        // Exit if the image is already a thumbnail.
        if (fileName.startsWith(THUMB_PREFIX)) {
          return functions.logger.log("Already a Thumbnail.");
        }
        // Cloud Storage files.
        const bucket = admin.storage().bucket(object.bucket);
        const file = bucket.file(filePath);
        const thumbFile = bucket.file(thumbFilePath);
        const metadata = {
          contentType: contentType,
        };
        // Create the temp directory where the storage file will be downloaded.
        await mkdirp(tempLocalDir)
        // Download file from bucket.
        await file.download({destination: tempLocalFile});
        functions.logger.log("The file has been downloaded to", tempLocalFile);
        // Generate a thumbnail using ImageMagick.
        await spawn("convert", [tempLocalFile, "-thumbnail", `${THUMB_MAX_WIDTH}x${THUMB_MAX_HEIGHT}>`, tempLocalThumbFile], {capture: ["stdout", "stderr"]});
        functions.logger.log("Thumbnail created at", tempLocalThumbFile);
        // Uploading the Thumbnail.
        await bucket.upload(tempLocalThumbFile, {destination: thumbFilePath, metadata: metadata});
        functions.logger.log("Thumbnail uploaded to Storage at", thumbFilePath);
        // Once the image has been uploaded delete the local files to free up disk space.
        fs.unlinkSync(tempLocalFile);
        fs.unlinkSync(tempLocalThumbFile);
        // Get the Signed URLs for the thumbnail and original image.
        const results = await Promise.all([
          thumbFile.getSignedUrl({
            action: "read",
            expires: "03-01-2500",
          }),
          file.getSignedUrl({
            action: "read",
            expires: "03-01-2500",
          }),
        ]);
        functions.logger.log("Got Signed URLs.");
        const thumbResult = results[0];
        const originalResult = results[1];
        const thumbFileUrl = thumbResult[0];
        const fileUrl = originalResult[0];
        // Add the URLs to the Database
        await admin.database().ref("images").push({path: fileUrl, thumbnail: thumbFileUrl});
        return functions.logger.log("Thumbnail URLs saved to database.");
    });

    이제 테스트를 위해 해당 소스를 배포 진행을 해보겠습니다. 

     

    $ npm run deploy 
    or
    $ firebase deploy --only functions

    위 명령어를 통해 연결된 프로젝트에 배포를 할수 있습니다.

    기본적으로 region 설정없이 배포를 진행하면 us-central1(아이오와) 지역으로 배포가 됩니다. 

    firebase storage 나 database의 region으로 설정하는 것이 아무래도 좋기 때문에 region 변경을 위해서는 

    .
    .
    exports.generateThumbnail = functions.region("asia-northeast3").storage.object().onFinalize(async (object) => {
    .
    .

    위와 같이 설정 할 수 있습니다.  asia-northeast3는 서울입니다. 

    참고) 리전별 가격이 다르기 때문에 가격은 체크해보시고 구역을 정하는 것이 좋을 것으로 보입니다 

     

    추가적으로 firebase 대부분의 기능은 무료버전으로 사용이 가능하지만 functions를 적용하기 위해서는 업그레이드가 필요합니다. 업그레이드 방법은 간단한 입력 내용을 추가해서 결제할 카드만 추가해주시면 바로 사용 가능합니다. 

     

    이상업이 배포가 완료 되었을때 파이어베이스 콘솔 접속하여 Functions 메뉴에 접근하게 되면

    functions 가 generateThumbnail 잘 등록되어있는 것을 볼 수 있습니다.

    아쉬운 것이 있다면 콘솔내에서 바로 소스를 확인할 수 없다는 점이 아쉬웠습니다. 

     

    자 이제 정상적으로 thumbnail 을 만들어지는지 테스트해보겠습니다. 

     

    원래 사용자들에게 제공될 서비스라면 앱에서 이미지를 등록하는 과정을 진행하겠지만 결국 이미지는 Storage에 등록이 될 것이기 때문에 간단 테스트를 위해 Storage에 직접 파일을 업로드해보도록 하겠습니다. 

     

    업로드가 완료되게 되면 자동적으로 thumb_ (prefix)가 붙어서 새로운 작은 사이즈의 이미지가 생기는 것을 볼 수 있습니다. 

     

    추가적으로 Functions 의 기능들이 잘 동작되는 것을 log로 확인하기 위해서는 Functions > Logs 탭으로 이동하면 로그가 남는 것을 확인할 수 있습니다. 

     


    자 이렇게 원하는 기능들을 추가하여 필요에 따라 구현만 해주고 배포 해주면 만사 오케이입니다 ~! 

    포스팅에서는 간단히 구글에서 제공해주는 예제 소스를 그대로 활용하여 테스트 해보았지만 조만간 개남 유튜브에 파이어베이스 Functions를 활용한 영상을 올릴 예정입니다. 그때에는 앱을 활용해서 등록하는 방법에 대해서 살펴보는 시간을 가져보도록 하겠습니다 ^^

     

    감사합니다~! 

    '개발일지 > firebase' 카테고리의 다른 글

    파이어베이스 윈도우 환경 CLI 설정 방법  (0) 2021.10.30

    댓글

Designed by Tistory.