Search
🌇

Cloud Function (스케줄러)

생성일
2020/09/24 13:59
태그
Firebase
Firebase Cloud Function
속성
속성 1
속성 2
2021/01/30 08:58
Youtube의 Data (실시간 인기 동영상) 를 마음껏 호출하고 쓰고 싶었으나, 할당량이 매우 적어 클라이언트마다 Data API 를 호출하면 순식간에 고갈될 것이 예상되었습니다.
그리하여 중간에 캐시 느낌으로 아래와 같이 구성하려고 합니다.
1.
Cloud Function 에서 5분 주기로 API 호출 및 저장
2.
Response 를 Firebase firestore 에 업데이트
3.
클라이언트에서는 firestore 에 있는 값을 이용
이런식으로 Third-party API 를 이용할 때 외부 장애에 대한 안정성을 다소? 높일 수 있고, API 횟수 제한을 회피 할 수 있는 장점이 있을 것 같습니다

시작

Cloude Function을 이용하기 전 firebase-tools 를 설치 후 프로젝트를 설정합니다
npm install -g firebase-tools // firebase-tools 설치 firebase login // Firebase 콘솔 기능을 사용할 수 있도록 로그인 firebase init functions // Cloud function 기능 활성화
Bash
복사
Conolse 에서 몇가지 질문들 던지지만, 전부 Default 로 설정을 해줍니다
이 과정들을 거치고 나면 아래의 디렉토리 구조가 생성됩니다
myproject +- .firebaserc # 숨김 파일로 무시해주세요 | | +- firebase.json # 프로젝트 설정 | +- functions/ # 실행되는 함수, 구현체들이 있는 디렉토리 | +- .eslintrc.json # lint 룰. 옵셔널 | +- package.json # npm package file | +- index.js # main source file for your Cloud Functions code | +- node_modules/ # directory where your dependencies (declared in # package.json) are installed 출처) Firebase 공식 가이드 문서 (https://firebase.google.com/docs/functions/get-started?hl=ko)
Bash
복사

예제

처음은 역시 어려운 것이니 예제를 이용해 보도록 합니다.
functions/index.js 에 아래 예제를 복붙해봅니다.
예제에서 Key 는 수정해주세요. (유튜브 API Key 발급받기)
var request = require('request'); var api_url = 'https://content.googleapis.com/youtube/v3/search?order=rating&regionCode=kr&key={Youtube API Key}&maxResults=50'; request.get({ url: api_url, headers: { 'Content-Type': 'application/json' } }, function (error, response, body) { console.log(response.statusCode); console.log(body); });
JavaScript
복사
테스트
firebase emulators:start
Bash
복사
위 명령어를 이용하면 작성한 function 을 실행시킬 수 있다고 합니다.
실행해 보면
한번에 되는 것은 없지
Error: Cannot find module 'request'
다행히 익숙한 에러입니다. npm 모듈이 없을 때 발생하는 오류입니다.
npm install request
Bash
복사
request 모듈을 설치하고 에뮬레이터를 다시 실행합니다.
50개의 유튜브 영상 목록을 가져오는데 성공했습니다

Firestore 에 저장하기

위 과정에서 가져온 Youtube ID 들을 Firestore 에 저장합니다
const functions = require('firebase-functions'); const admin = require('firebase-admin'); admin.initializeApp() const firestore = admin.firestore(); var request = require('request'); var api_url = 'https://content.googleapis.com/youtube/v3/search?order=rating&regionCode=kr&key={YOUTEBE_API_KEY}&maxResults=50'; function js_yyyy_mm_dd_hh_mm_ss () { now = new Date(); year = "" + now.getFullYear(); month = "" + (now.getMonth() + 1); if (month.length == 1) { month = "0" + month; } day = "" + now.getDate(); if (day.length == 1) { day = "0" + day; } hour = "" + now.getHours(); if (hour.length == 1) { hour = "0" + hour; } minute = "" + now.getMinutes(); if (minute.length == 1) { minute = "0" + minute; } second = "" + now.getSeconds(); if (second.length == 1) { second = "0" + second; } return year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second; } request.get(api_url, function (error, response, body) { if (response.statusCode == 200) { var res = JSON.parse(body); var videoIDs = res["items"].map((v) => { return v.id }).map((v) => { return v.videoId }).join(','); firestore.collection('content').doc("youtube").set(JSON.parse(JSON.stringify({"ids" : videoIDs, "latest_updated_at": js_yyyy_mm_dd_hh_mm_ss()}))); } });
JavaScript
복사
결과는

10,000 units per day 뿌수기

Youtube API의 limit 은 10,000 per day
1분에 1번씩 호출하면 하루 24 * 60 = 1440 충분히 여유있습니다
"Blaze 요금제" 에서 사용할 수 있다고 합니다.
예제코드
exports.scheduledFunction = functions.pubsub.schedule('every 5 minutes').onRun((context) => { console.log('This will be run every 5 minutes!'); return null; });
JavaScript
복사
여기서 every 5 minute ⇒ every 1 minute 로 변경하고 closure? javascript 에서도 closure 라고 부르나..?
에 위에서 작성한 함수를 넣으면 될 듯 합니다.
종량제도 Blaze 로 바꾸고, firebase console 로 최신으로 업뎃 후 성공

결과

1분마다 업데이트 됨을 확인 할 수 있습니다