일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- login
- 프론트
- Git
- 신상마켓
- javascript
- AWS
- 뷰
- 토이프로젝트
- PWA
- nginx
- express
- 회고록
- plugin
- database
- 정리
- extension
- 로그인
- Docker
- 플러그인
- Firebase
- react-query
- vue
- 배포
- vue login
- 기획
- jwt
- vsCode
- react
- vuex
- 셋팅
- Today
- Total
강디너의 개발 일지
javascript - AWS Lambda 를 이용해서 크롤링하기 본문
기획
멜론 차트를 하루에 한 번 크롤링해서 Firebase Database에 저장
현재 상황
1. Vue.js 를 이용해서 프론트를 만드는 중이다.
2. Firebase Database 를 사용한다.
3. 멜론 차트를 크롤링 하고 싶다 <--- 주 원인
4. 하지만 서버단이 없다 !
어떻게 구현 할까 고민하던 중 회사에서 토이 프로젝트 지원으로 AWS를 가지고 놀아도 된다고 했던 말이 기억나서 EC2에 웹서버 띄우고, 백단에서 크롤링 + 데이터 저장 하려고 했습니다.
이러한 기획을 가지고 데브옵스분께 쪼르르 가서 말씀드렸는데, 그 정도면 Lambda라는 것을 이용해서 하면 더 좋을 거라고(비용이었나?) 하시며 자기도 javascript 베이스로 안 해봤는데 같이 해보자고 하셨습니다.
제가 아는 람다는 화살표인데...
AWS Lambda란 제 입장에서 말하면 AWS에 요청을 보내면 응답을 보내주는 '착한 애'입니다.
EC2 같은 경우 계속 띄워져 있는 애임에 반해서 Lambda는 호출할 때만 응답하기 때문에 비용적에서도 효율이 좋은 애입니다.
AWS Lambda는 서버를 프로비저닝하거나 관리하지 않고도 코드를 실행할 수 있게 해주는 컴퓨팅 서비스입니다. AWS Lambda는 필요 시에만 코드를 실행하며, 하루에 몇 개의 요청에서 초당 수천 개의 요청까지 자동으로 확장이 가능합니다. 사용한 컴퓨팅 시간에 대해서만 요금을 지불하면 되고 코드가 실행되지 않을 때는 요금이 부과되지 않습니다.
자세한 건 아래 블로그에서 보고 많이 응용했습니다.
코드는 제 깃허브에 있습니다.
https://github.com/DinnerKang/study_vue/tree/master/dinner-project
serverless.yml
service: dinner-project
provider:
name: aws
runtime: nodejs12.x
stage: dev
region: ap-northeast-2
deploymentBucket: ${file(./config.js):config.BUCKET_NAME}
deploymentPrefix: ${self:service}
role: arn:aws:iam::${file(./config.js):config.ACCOUNT_NUM}:role/${file(./config.js):config.ROLE_NAME}
usagePlan:
quota:
limit: 5000
offset: 2
period: MONTH
throttle:
burstLimit: 200
rateLimit: 100
functions:
hello:
handler: handler.hello
events:
- http:
path: hello
method: get
- cloudwatchLog: '/aws/lambda/${self:service}'
뭔가 노출하면 안 될 것 같은 이름들은 config.js 파일에 변수명으로 처리했습니다.
리미트 제한도 설정 할 수 있습니다.
handler.js (1/31 수정)
'use strict';
const cheerio = require('cheerio');
const axios = require('axios');
axios.defaults.baseURL = 'https://vue-pwa-776e7.firebaseapp.com';
axios.defaults.headers['Accept'] = 'application/json, text/plain, */*';
module.exports.hello = async (event, ctx, cb) => {
const title = [];
const artist = [];
const result = {};
const rank = 100;
const getHtml = async () => {
try {
return await axios.get('https://www.melon.com/chart/');
} catch (err) {
console.error('axios error', axios);
console.error(err);
}
}
const html = await getHtml();
const $ = cheerio.load(html.data);
for (let i = 0; i < rank; i++) {
$('.ellipsis.rank01 > span > a').each( function(idx){
const title_info = $(this);
const title_info_text = title_info.text();
title[idx] = title_info_text;
})
}
for (let i = 0; i < rank; i++) {
$('.checkEllipsis').each(function(idx){
const artist_info = $(this);
const artist_info_text = artist_info.text();
artist[idx] = artist_info_text;
})
}
for (let i = 0; i < rank; i ++) {
result[i] = {
title: title[i],
artist: artist[i],
}
}
const registDate = String(new Date());
const response = {
statusCode: 200,
body: JSON.stringify({
result,
registDate,
}),
};
cb(null, response);
};
프론트에서 AWS Lambda를 호출했을 때에는 정상 응답을 했는데, 스케줄을 이용해서 호출하니깐 오류가 나는 현상을 발견해서 axios 헤더를 수정하였습니다.
오류 날 때마다 멜론님께서 절 차단한 줄 알고 얼마나 가슴 졸였는지...
firebase database 이용해서 매 시간 스케줄링 해서 저장하려고 했는데... firebase 만 연동하면 오류가 발생하네요... 함수가 안끝나는거 같은데 'ctx.callbackWaitsForEmptyEventLoop = false;' 이 옵션을 써도 종료가 되지 않습니다.
이거 때문에 삽질을 엄청 했는데 찾지 못했네요 ㅠㅠ.. 누가 찾으신분 답좀 알려줘요...
'Javascript > 삽질' 카테고리의 다른 글
Firebase realtime database pagination 삽질기 (0) | 2020.05.25 |
---|---|
Firebase Database CRUD (0) | 2020.02.17 |
Vue - google OAuth2 로그인 및 Youtube 연동 (0) | 2020.01.20 |
javascript - Comma 만들기 (0) | 2019.09.11 |
주니어 개발자의 어뷰징? 대응하기 (0) | 2019.05.31 |