Skip to content

novemberde/serverless-crawler-demo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

29 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Serverless Group First Hands-on Part 2

AWSKRUG Serverless Group์˜ ์ฒซ๋ฒˆ์งธ ํ•ธ์ฆˆ์˜จ Part.2 ์›นํฌ๋กค๋Ÿฌ ๋งŒ๋“ค๊ธฐ์ž…๋‹ˆ๋‹ค.๐Ÿ˜

Part.1์„ ํ•˜์…จ๋‹ค๋ฉด "Cloud9 ์‹œ์ž‘ํ•˜๊ธฐ", "Serverless Framework ์†Œ๊ฐœ", ๊ทธ๋ฆฌ๊ณ  "S3 bucket ์ƒ์„ฑํ•˜๊ธฐ"๋Š” ๋„˜์–ด๊ฐ€๋„ ์ข‹์Šต๋‹ˆ๋‹ค.

Objective

Amazon Web Service ๋ฅผ ํ™œ์šฉํ•˜์—ฌ Serverless architecture๋กœ ์›นํฌ๋กค๋Ÿฌ๋ฅผ ๋ฐฐํฌํ•ฉ๋‹ˆ๋‹ค. ํฌ๋กค๋ง๋œ ๋ฐ์ดํ„ฐ๋Š” DynamoDB์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

AWS Resources

AWS์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ฆฌ์†Œ์Šค๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • Cloud9: ์ฝ”๋“œ ์ž‘์„ฑ, ์‹คํ–‰ ๋ฐ ๋””๋ฒ„๊น…์„ ์œ„ํ•œ ํด๋ผ์šฐ๋“œ ๊ธฐ๋ฐ˜ IDE.
  • Lambda: ์„œ๋ฒ„๋ฅผ ํ”„๋กœ๋น„์ €๋‹ํ•˜๊ฑฐ๋‚˜ ๊ด€๋ฆฌํ•˜์ง€ ์•Š๊ณ ๋„ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ์ปดํ“จํŒ… ์„œ๋น„์Šค. ์„œ๋ฒ„๋ฆฌ์Šค ์•„ํ‚คํ…์ณ์˜ ํ•ต์‹ฌ ์„œ๋น„์Šค.
  • DynamoDB: ์™„๋ฒฝํ•˜๊ฒŒ ๊ด€๋ฆฌ๋˜๋Š” NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„œ๋น„์Šค๋กœ, ์›ํ™œํ•œ ํ™•์žฅ์„ฑ๊ณผ ํ•จ๊ป˜ ๋น ๋ฅด๊ณ  ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ์„ฑ๋Šฅ์„ ์ œ๊ณต.

Cloud 9 ์‹œ์ž‘ํ•˜๊ธฐ

Cloud9 ์€ ํ•˜๋‚˜์˜ IDE์ž…๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€๋งŒ ์ด์ „์˜ ์„ค์น˜ํ˜• IDE์™€๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ์„ค์น˜ํ˜• IDE๋Š” ๋กœ์ปฌ PC์— ํ”„๋กœ๊ทธ๋žจ์„ ์„ค์น˜ํ•˜๋˜๊ฐ€ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ์‹์ด์—ˆ๋‹ค๋ฉด, Cloud9์€ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์‹คํ–‰๊ฐ€๋Šฅํ•œ ๋ชจ๋“  OS์—์„œ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๋งจ ์ฒ˜์Œ Cloud9์€ AWS ๋‚ด์—์„œ๊ฐ€ ์•„๋‹Œ ๋ณ„๋„์˜ ์„œ๋น„์Šค๋กœ ์ œ๊ณต๋˜์—ˆ์Šต๋‹ˆ๋‹ค. AWS์— ์ธ์ˆ˜๋œ ์ดํ›„ Cloud9์€ AWS์˜ Managed Serviceํ˜•ํƒœ๋กœ ๋ฐ”๋€Œ์—ˆ๊ณ , AWS์˜ ์„œ๋น„์Šค์™€ ๊ฒฐํ•ฉํ•˜์—ฌ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•ด์กŒ์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ ํŽธ์ง‘๊ณผ ๋ช…๋ น์ค„ ์ง€์› ๋“ฑ์˜ ํ‰๋ฒ”ํ•œ IDE ๊ธฐ๋Šฅ์„ ์ง€๋‹ˆ๊ณ  ์žˆ๋˜ ๋ฐ˜๋ฉด์—, ํ˜„์žฌ๋Š” AWS ์„œ๋น„์Šค์™€ ๊ฒฐํ•ฉ๋˜์–ด ์ง์ ‘ Lambda ์ฝ”๋“œ๋ฅผ ๋ฐฐํฌํ•˜๋˜๊ฐ€, ์‹ค์ œ๋กœ Cloud9์ด ์‹คํ–‰๋˜๊ณ  ์žˆ๋Š” EC2์˜ ์ปดํ“จํŒ… ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œ์ผœ์„œ ๋กœ์ปฌ PC์˜ ์‚ฌ์–‘์— ์ข…์†๋˜์ง€ ์•Š์€ ๊ฐœ๋ฐœ์„ ํ•  ์ˆ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋ฉด Cloud9 ํ™˜๊ฒฝ์„ ์‹œ์ž‘ํ•ด๋ด…์‹œ๋‹ค.

Cloud 9 Console์— ์ ‘์†ํ•ฉ๋‹ˆ๋‹ค.

์•„๋ž˜์™€ ๊ฐ™์€ ํ™”๋ฉด์—์„œ Create Environment ๋ฒ„ํŠผ์„ ๋ˆ„๋ฆ…๋‹ˆ๋‹ค.

c9-create

Name๊ณผ Description์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.

  • Name: ServerlessHandsOn
  • Description: Serverless hands-on in AWSKRUG Serverless Group

c9-create-name

Configure Setting์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•ฉ๋‹ˆ๋‹ค.

  • Environment Type: EC2
  • Instance Type: T2.micro
  • Cost Save Setting: After 30 minutes
  • Network Settings: Default

c9-conf

๋ชจ๋“  ์„ค์ •์„ ๋งˆ์ณค๋‹ค๋ฉด Cloud9 Environment๋ฅผ ์ƒ์„ฑํ•˜๊ณ  Open IDE๋ฅผ ํ†ตํ•ด ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์— ์ ‘์†ํ•ฉ๋‹ˆ๋‹ค.

์ ‘์†ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ™”๋ฉด์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ํ˜„์žฌ Environment name
  2. EC2์—์„œ ๋ช…๋ น์–ด๋ฅผ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋Š” Terminal
  3. Lambda Functions
    • Local Functions: ๋ฐฐํฌ๋˜์ง€ ์•Š์€ ํŽธ์ง‘์ค‘์ธ Functions
    • Remote Functions: ํ˜„์žฌ ์„ค์ •ํ•ด๋†“์€ Region์— ๋ฐฐํฌ๋œ Lambda Functions
  4. Preferences

c9-env

ํ˜„์žฌ ap-southeast-1 region์— Cloud9 Environment๋ฅผ ๋ฐฐํฌํ–ˆ์œผ๋ฏ€๋กœ Default Region์ด ap-southeast-1์œผ๋กœ ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. Preferences(์„ค์ • ํ™”๋ฉด)์—์„œ ap-northeast-2(Seoul Region)์œผ๋กœ ๋ฐ”๊พธ์–ด์ค๋‹ˆ๋‹ค.

  • Preferences > AWS Settings > Region > Asia Pacific(Seoul)

c9-region

์„ค์ •์„ ๋งˆ์นœ ๋‹ค์Œ Node.js ๋ฒ„์ „์„ ์˜ฌ๋ ค์•ผํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ(2018-06-30) ์ œ๊ณตํ•˜๋Š” node์˜ ๋ฒ„์ „์ด 6.10์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋ณดํ†ต์€ nvm์„ ๋”ฐ๋กœ ์„ค์น˜ํ•ด์•ผํ•˜์ง€๋งŒ Cloud9์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ณ„๋„์˜ nvm ์„ค์น˜๋Š” ํ•„์š”์—†์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์˜ ๋ช…๋ น์–ด๋ฅผ terminal์— ์ž…๋ ฅํ•˜์—ฌ node์˜ ๋ฒ„์ „์„ 8.10์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

$ sudo yum groupinstall 'Development Tools'
$ nvm install 8.10
Downloading https://nodejs.org/dist/v8.10.0/node-v8.10.0-linux-x64.tar.xz...
######################################################################## 100.0%
Now using node v8.10.0 (npm v5.6.0)

# 8.10์„ default๋กœ ์‚ฌ์šฉํ•˜๊ธฐ
$ nvm alias default 8.10

Cloud9 ์„ค์ •์„ ์™„๋ฃŒํ•˜์˜€์Šต๋‹ˆ๋‹ค.

serverless framework main

Serverless Framework ๋ฉ”์ธ์— ๋‚˜์™€์žˆ๋Š” ์†Œ๊ฐœ๋ฌธ๊ตฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

Serverless is your toolkit for deploying and operating serverless architectures. Focus on your application, not your infrastructure.

์œ„ ๋‚ด์šฉ์„ ๋ฒˆ์—ญํ•œ ๋‚ด์šฉ์€ "Serverless๋Š” ์„œ๋ฒ„ ์—†๋Š” ์•„ํ‚คํ…์ฒ˜๋ฅผ ๋ฐฐ์น˜ํ•˜๊ณ  ์šด์˜ํ•˜๊ธฐ ์œ„ํ•œ ํˆดํ‚ท์ž…๋‹ˆ๋‹ค. ์ธํ”„๋ผ๊ฐ€ ์•„๋‹Œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ง‘์ค‘ํ•ฉ๋‹ˆ๋‹ค." ์ž…๋‹ˆ๋‹ค. ์ด์ฒ˜๋Ÿผ Serverless framework๋Š” Serverless architecture๋ฅผ ์šด์˜ํ•˜๊ธฐ ์œ„ํ•œ ํˆด์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋ฉด serverless framework๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ํ™˜๊ฒฝ์€ ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”?

node.js๊ฐ€ ์„ค์น˜๋˜์–ด ์žˆ๋Š” ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

open source๋กœ ๊ธฐ์—ฌํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด https://github.com/serverless/serverless์—์„œ issue์™€ pull request๋ฅผ ๋“ฑ๋กํ•ด์ฃผ์„ธ์š”.

Serverless Framework ์‚ดํŽด๋ณด๊ธฐ

Serverless Framework๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋ช…๋ น์–ด๋“ค์„ ์‚ดํŽด๋ด…์‹œ๋‹ค.

# Serverless Framework๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.
$ npm i -g serverless

# ๋ช…๋ น์–ด๋“ค์„ ํ™•์ธํ•ด๋ด…๋‹ˆ๋‹ค.
$ serverless --help

Commands
* You can run commands with "serverless" or the shortcut "sls"
* Pass "--verbose" to this command to get in-depth plugin info
* Pass "--no-color" to disable CLI colors
* Pass "--help" after any <command> for contextual help

Framework
* Documentation: https://serverless.com/framework/docs/

config ........................ Configure Serverless
config credentials ............ Configures a new provider profile for the Serverless Framework
create ........................ Create new Serverless service
deploy ........................ Deploy a Serverless service
deploy function ............... Deploy a single function from the service
deploy list ................... List deployed version of your Serverless Service
deploy list functions ......... List all the deployed functions and their versions
info .......................... Display information about the service
install ....................... Install a Serverless service from GitHub or a plugin from the Serverless registry
invoke ........................ Invoke a deployed function
invoke local .................. Invoke function locally
logs .......................... Output the logs of a deployed function
metrics ....................... Show metrics for a specific function
package ....................... Packages a Serverless service
plugin ........................ Plugin management for Serverless
plugin install ................ Install and add a plugin to your service
plugin uninstall .............. Uninstall and remove a plugin from your service
plugin list ................... Lists all available plugins
plugin search ................. Search for plugins
print ......................... Print your compiled and resolved config file
remove ........................ Remove Serverless service and all resources
rollback ...................... Rollback the Serverless service to a specific deployment
rollback function ............. Rollback the function to the previous version
slstats ....................... Enable or disable stats

Platform (Beta)
* The Serverless Platform is currently in experimental beta. Follow the docs below to get started.
* Documentation: https://serverless.com/platform/docs/

emit .......................... Emits an event to a running Event Gateway
login ......................... Login or sign up for the Serverless Platform
logout ........................ Logout from the Serverless Platform
run ........................... Runs the Event Gateway and the Emulator

Plugins
AwsConfigCredentials, Config, Create, Deploy, Emit, Info, Install, Invoke, Login, Logout, Logs, Metrics, Package, Plugin, PluginInstall, PluginList, PluginSearch, PluginUninstall, Print, Remove, Rollback, Run, SlStats

์—ฌ๊ธฐ์„œ ์ž์ฃผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋  ๋ช…๋ น์–ด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • create: ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ์‹œ ์‚ฌ์šฉ
  • deploy: ๋ฐฐํฌํ•  ๋•Œ ์‚ฌ์šฉ
  • package: ๋ฐฐํฌ๋  ํŒจํ‚ค์ง€์˜ ๊ตฌ์กฐ๋ฅผ ๋ณด๊ณ ์‹ถ์„ ๋•Œ ์‚ฌ์šฉ
  • invoke: ํŠน์ • handler๋ฅผ ๋™์ž‘์‹œํ‚ฌ ๋•Œ ์‚ฌ์šฉ
  • remove: ๋ฐฐํฌ๋œ ๋ฆฌ์†Œ์Šค๋ฅผ ์ œ๊ฑฐํ•  ๋•Œ ์‚ฌ์šฉ

๊ฐ„๋‹จํ•˜๊ฒŒ ๋กœ์ปฌ์—์„œ serverless ๋ช…๋ น์–ด๋ฅผ ํ…Œ์ŠคํŠธํ•ด๋ด…๋‹ˆ๋‹ค. deploy ๋ช…๋ น์–ด๋Š” ์ถ”ํ›„์— ์‚ฌ์šฉํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

# Global ๋กœ serverless framework ์„ค์น˜
$ npm i -g serverless

# serverless service ์ƒ์„ฑ ํžŒํŠธ ๋ฐ›๊ธฐ
$ serverless create --help
Plugin: Create
create ........................ Create new Serverless service
    --template / -t .................... Template for the service. Available templates: "aws-nodejs", "aws-nodejs-typescript", "aws-nodejs-ecma-script", "aws-python", "aws-python3", "aws-groovy-gradle", "aws-java-maven", "aws-java-gradle", "aws-kotlin-jvm-maven", "aws-kotlin-jvm-gradle", "aws-kotlin-nodejs-gradle", "aws-scala-sbt", "aws-csharp", "aws-fsharp", "aws-go", "aws-go-dep", "azure-nodejs", "fn-nodejs", "fn-go", "google-nodejs", "kubeless-python", "kubeless-nodejs", "openwhisk-java-maven", "openwhisk-nodejs", "openwhisk-php", "openwhisk-python", "openwhisk-swift", "spotinst-nodejs", "spotinst-python", "spotinst-ruby", "spotinst-java8", "webtasks-nodejs", "plugin" and "hello-world"
    --template-url / -u ................ Template URL for the service. Supports: GitHub, BitBucket
    --template-path .................... Template local path for the service.
    --path / -p ........................ The path where the service should be created (e.g. --path my-service)
    --name / -n ........................ Name for the service. Overwrites the default name of the created service. ## "

# node๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ํ…œํ”Œ๋ฆฟ์„ "aws-nodejs" ๋กœ "sample-app" ์ƒ์„ฑํ•˜๊ธฐ
$ serverless create -t "aws-nodejs" -p sample-app

# sample-app์—์„œ ๋ช…๋ น์–ด ์—ฐ์Šตํ•˜๊ธฐ
$ cd sample-app
~/sample-app $ serverless package
Serverless: Packaging service...
Serverless: Excluding development dependencies...

# ์—ฌ๊ธฐ๊นŒ์ง€ ์ง„ํ–‰ํ–ˆ๋‹ค๋ฉด .serverless ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
~/sample-app $ cd .serverless

# ์ƒ์„ฑ๋œ ํŒŒ์ผ์„ ๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Œ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
~/sample-app/.serverless $ ls
cloudformation-template-create-stack.json
cloudformation-template-update-stack.json
sample-app.zip
serverless-state.json

์œ„์— ์ƒ์„ฑ๋œ ํŒŒ์ผ์ด ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€๋Š” ํŒŒ์ผ๋ช…๋งŒ์œผ๋กœ๋„ ์œ ์ถ”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ˜„์žฌ cloudformation์— stack์ด ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ ์Šคํƒ์„ ์ƒ์„ฑํ•œ ๋‹ค์Œ, ์—…๋ฐ์ดํŠธ๋ฅผ ํ•˜์—ฌ ์›ํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ Lambda์— ๋ฐฐํฌ๋˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

serverless-state.jsonํŒŒ์ผ์€ ํ•ด๋‹น ๋ฒ„์ „์˜ serverless application์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ๋‹ด๊ฒจ ์žˆ์Šต๋‹ˆ๋‹ค.

# ๋‹ค์‹œ ์•ฑ์˜ ๋ฃจํŠธ๋””๋ ‰ํ„ฐ๋ฆฌ๋กœ ๋Œ์™€์™€์„œ invoke๋ฅผ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
~/sample-app/.serverless $ cd ..
~/sample-app $ serverless invoke local --function hello
{
    "statusCode": 200,
    "body": "{\"message\":\"Go Serverless v1.0! Your function executed successfully!\",\"input\":\"\"}"
}

S3 Bucket ์ƒ์„ฑํ•˜๊ธฐ

S3๋Š” Object Storage๋กœ ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•˜์ž๋ฉด ํ•˜๋‚˜์˜ ์ €์žฅ์†Œ์ž…๋‹ˆ๋‹ค. ํŒŒ์ผ๋“ค์„ ์—…๋กœ๋“œ / ๋‹ค์šด๋กœ๋“œ ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ AWS์—์„œ ํ•ต์‹ฌ์ ์ธ ์„œ๋น„์Šค ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ๋ฐฉ๋ฉด์œผ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์—ฌ๊ธฐ์„œ๋Š” ์†Œ์Šค์ฝ”๋“œ์˜ ์ €์žฅ์†Œ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

S3์˜ ๋ฉ”์ธ์œผ๋กœ ๊ฐ€์„œ ๋ฒ„ํ‚ท ์ƒ์„ฑํ•˜๊ธฐ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

s3-create-btn.png

์•„๋ž˜์™€ ๊ฐ™์ด ์ž…๋ ฅํ•˜๊ณ  ์ƒ์„ฑ๋ฒ„ํŠผ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  • ๋ฒ„ํ‚ท ์ด๋ฆ„(Bucket name): USERNAME-serverless-hands-on-1 // ์—ฌ๊ธฐ์„œ USERNAME์„ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค. ex) khbyun-serverless-hands-on-1
  • ๋ฆฌ์ „(Region): ์•„์‹œ์•„ ํƒœํ‰์–‘(์„œ์šธ)

s3-create-btn.png

Node.js๋กœ ํฌ๋กค๋ง ์‹œ์ž‘ํ•˜๊ธฐ

ํŒŒ์ผ ํŠธ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

environment
โ””โ”€โ”€ serverless-crawler  : Crawler
    โ”œโ”€โ”€ handler.js  : Lambda์—์„œ triggerํ•˜๊ธฐ ์œ„ํ•œ handler
    โ”œโ”€โ”€ handler.test.js  : Local์—์„œ handler๋ฅผ triggerํ•˜๊ธฐ ์œ„ํ•œ ์Šคํฌ๋ฆฝํŠธ
    โ”œโ”€โ”€ config.yml : serverless.yml์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๋ณ€์ˆ˜
    โ”œโ”€โ”€ package.json
    โ””โ”€โ”€ serverless.yml : Serverless Framework config file

๋จผ์ € ํ„ฐ๋ฏธ๋„์„ ์—ด์–ด serverless-crawler ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  npm ์ดˆ๊ธฐํ™”๋ฅผ ์‹œ์ผœ์ค๋‹ˆ๋‹ค.

ec2-user:~/ $ cd ~/environment
ec2-user:~/environment $ mkdir serverless-crawler && cd ec2-user:~/environment/serverless-crawler $ npm init -y

ํ•„์š”ํ•œ npm module๋“ค์„ installํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ aws-sdk๋Š” ๊ฐœ๋ฐœ์„ ์œ„ํ•ด ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค. Lambda๋Š” aws-sdk๋ฅผ ๊ธฐ๋ณธ์ ์œผ๋กœ ํฌํ•จํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์ œ๋กœ ๋ฐฐํฌํ•  ๋•Œ๋Š” ํฌํ•จ์‹œํ‚ค์ง€ ์•Š์•„์•ผํ•ฉ๋‹ˆ๋‹ค. dev-dependency๋กœ ๋„ฃ์–ด๋‘๋ฉด ๋ฐฐํฌํ•  ๋•Œ ์ œ์™ธ๋ฉ๋‹ˆ๋‹ค.

  • Dependencies
    • cheerio : HTMLํŽ˜์ด์ง€๋ฅผ ํŒŒ์‹ฑํ•˜๊ณ , ๊ฒฐ๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ง‘ํ•˜๊ธฐ ์œ„ํ•œ API๋ฅผ ์ œ๊ณต
    • got : ๋ช‡ MB์— ๋ถˆ๊ณผํ•œ http ์š”์ฒญ์„ ๊ฐ„๋‹จํ•˜๊ฒŒ ํ•˜๋Š” API ์ œ๊ณต
    • dynamoose : DynamoDB๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ๋„๋ก Modelingํ•˜๋Š” ๋„๊ตฌ
  • Dev-Dependencies
    • aws-sdk : AWS ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ SDK
    • serverless : Serverless Framework
$ npm i -S cheerio got dynamoose
$ npm i -D aws-sdk serverless

๊ฐ ํŒŒ์ผ์„ ํŽธ์ง‘ํ•ฉ๋‹ˆ๋‹ค.

serverless-crawler/config.yml

AWS_REGION: ap-northeast-2
STAGE: dev
DEPLOYMENT_BUCKET: USERNAME-serverless-hands-on-1    # USERNAME ์ˆ˜์ • ํ•„์š”!

serverless-crawler/handler.js

const got = require('got');
const cheerio = require('cheerio');
const dynamoose = require('dynamoose');

require('aws-sdk').config.region = "ap-northeast-2";

const PortalKeyword = dynamoose.model('PortalKeyword', {
    portal: {
        type: String,
        hashKey: true
    },
    createdAt: {
        type: String,
        rangeKey: true
    },
	keywords: {
		type: Array
	}
}, {
    create: false, // Create a table if not exist,
});

exports.crawler = async function (event, context, callback) {
	try {
		let naverKeywords = [];
		let daumKeywords = [];

		const result = await Promise.all([
			got('https://naver.com'),
			got('http://daum.net'),
		]);
		const createdAt = new Date().toISOString();
		
		const naverContent = result[0].body;
		const daumContent = result[1].body;
		const $naver = cheerio.load(naverContent);
		const $daum = cheerio.load(daumContent);

		// Get doms containing latest keywords
		$naver('.ah_l').filter((i, el) => {
			return i===0;
		}).find('.ah_item').each(((i, el) => {
			if(i >= 20) return;
			const keyword = $naver(el).find('.ah_k').text();
			naverKeywords.push({rank: i+1, keyword});
		}));
		$daum('.rank_cont').find('.link_issue[tabindex=-1]').each((i, el) => {
			const keyword = $daum(el).text();
			daumKeywords.push({rank: i+1, keyword});
		});

		// console.log({
		// 	naver: naverKeywords,
		// 	daum: daumKeywords,
		// });

		await new PortalKeyword({
			portal: 'naver',
			createdAt,
			keywords: naverKeywords
		}).save();
		await new PortalKeyword({
			portal: 'daum',
			createdAt,
			keywords: daumKeywords
		}).save();

		return callback(null, "success");
	} catch (err) {
		callback(err);
	}
}

serverless-crawler/handler.test.js

const crawler = require('./handler').crawler;

crawler({}, {}, (err, result) => {
    if(err) return console.error(err);
    console.log(result);
});

serverless-crawler/package.json

...
...
  "description": "AWSKRUG Serverless Group์˜ ์ฒซ๋ฒˆ์งธ ํ•ธ์ฆˆ์˜จ Part.2 ์›นํฌ๋กค๋Ÿฌ ๋งŒ๋“ค๊ธฐ์ž…๋‹ˆ๋‹ค.๐Ÿ˜",
  "main": "index.js",
  "scripts": {  // ์ด ๋ถ€๋ถ„์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
    "test": "node handler.test.js", 
    "deploy": "serverless deploy"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/novemberde/serverless-crawler-demo.git"
  },
  "keywords": [],
  "author": "",
...

serverless-crawler/serverless.yml

service: ServerlessHandsOnPart2

provider:
  name: aws
  runtime: nodejs8.10
  memorySize: 256
  timeout: 30
  stage:  ${file(./config.yml):STAGE}
  region: ${file(./config.yml):AWS_REGION}
  deploymentBucket: ${file(./config.yml):DEPLOYMENT_BUCKET}
  environment:
    NODE_ENV: production
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:DescribeTable
        - dynamodb:Query
        - dynamodb:Scan
        - dynamodb:GetItem
        - dynamodb:PutItem
        - dynamodb:UpdateItem
        - dynamodb:DeleteItem
      Resource: "arn:aws:dynamodb:${opt:region, self:provider.region}:*:*"

functions:
  crawler:
    handler: handler.crawler
    events:
      - schedule: rate(10 minutes)

DynamoDB ํ…Œ์ด๋ธ” ์ƒ์„ฑํ•˜๊ธฐ

DynamoDB๋ฅผ ์„ค๊ณ„ํ•  ์‹œ ์ฃผ์˜ํ•ด์•ผํ•  ์ ์€ FAQ๋ฅผ ์ฐธ๊ณ ํ•˜์‹œ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์ด์ œ DynamoDB์— Todo table์„ ์ƒ์„ฑํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํŒŒํ‹ฐ์…˜ ํ‚ค์™€ ์ •๋ ฌ ํ‚ค๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

  • ํŒŒํ‹ฐ์…˜ํ‚ค(Partition Key): portal
  • ์ •๋ ฌํ‚ค(Sort Key): createdAt

๊ทธ๋Ÿผ DynamoDB Console๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. ํ…Œ์ด๋ธ” ๋งŒ๋“ค๊ธฐ๋ฅผ ํด๋ฆญํ•˜์—ฌ ์•„๋ž˜์™€ ๊ฐ™์ด ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

dynamodb-create

๊ทธ๋Ÿฐ ๋‹ค์Œ์— ๋‹ค์‹œ Cloud9์œผ๋กœ ๋Œ์•„๊ฐ€์„œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ๋Œ๋ ค๋ด…๋‹ˆ๋‹ค.

ec2-user:~/environment/serverless-crawler $ npm test

> [email protected] test/home/ec2-user/environment/serverless-crawler-demo
> node handler.test.js

success

DynamoDB Console์— ๋“ค์–ด๊ฐ€์„œ ์„ฑ๊ณต์ ์œผ๋กœ ํ•ญ๋ชฉ๋“ค์ด ์ƒ์„ฑ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

Cloud9์—์„œ ๋ฐฐํฌํ•˜๊ธฐ

Node๊ฐ€ 8.x๋ฒ„์ „์ด ์„ค์น˜๋˜์–ด ์žˆ์œผ๋ฉด dev-dependency์— ์„ค์น˜๋œ serverless ๋ช…๋ น์–ด๋ฅผ ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์ผ node 6.x๋ฒ„์ „์ด๋ผ๋ฉด Global๋กœ serverless๋ฅผ ์„ค์น˜ํ•˜์—ฌ ์ค๋‹ˆ๋‹ค. ํ˜„์žฌ๋Š” 8.x์˜ ๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์Œ ๋ช…๋ น์–ด๋Š” ๋„˜์–ด๊ฐ€๊ฒ ์Šต๋‹ˆ๋‹ค.

ec2-user:~/environment/serverless-crawler (master) $ npm i -g serverless

์„ค์น˜๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ์œผ๋ฉด ๋ฐฐํฌ๋ฅผ ํ•ฉ๋‹ˆ๋‹ค. package.json์— script์— serverless deploy๋ฅผ ๋„ฃ์–ด ๋‘์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฐฐํฌ๋ฅผ ํ•ฉ๋‹ˆ๋‹ค.

ec2-user:~/environment/serverless-crawler (master) $ npm run deploy

> [email protected] deploy /home/ec2-user/environment/serverless-crawler
> serverless deploy

Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip file to S3 (8.69 MB)...
Serverless: Validating template...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
....................
Serverless: Stack create finished...
Service Information
service: ServerlessHandsOnPart2
stage: dev
region: ap-northeast-2
stack: ServerlessHandsOnPart2-dev
api keys:
  None
endpoints:
  None
functions:
  crawler: ServerlessHandsOnPart2-dev-crawler

์„ฑ๊ณต์ ์œผ๋กœ ๋ฐฐํฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ๋ถ€ํ„ฐ ์ฃผ๊ธฐ์ ์œผ๋กœ DynamoDB์— ๊ฒ€์ƒ‰์–ด ๋žญํ‚น์ด ์Œ“์ž…๋‹ˆ๋‹ค.

๋ฆฌ์†Œ์Šค ์‚ญ์ œํ•˜๊ธฐ

์„œ๋ฒ„๋ฆฌ์Šค ์•ฑ์€ ๋‚ด๋ฆฌ๋Š” ๊ฒƒ์ด ์–ด๋ ต์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•œ Command ํ•˜๋‚˜๋ฉด ๋ชจ๋“  ์Šคํƒ์ด ๋‚ด๋ ค๊ฐ‘๋‹ˆ๋‹ค. Cloud9์—์„œ ์ƒˆ๋กœ์šด ํ„ฐ๋ฏธ๋„์„ ์—ด๊ณ  ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.

$ cd ~/environment/serverless-crawler
$ serverless remove
Serverless: Getting all objects in S3 bucket...
Serverless: Removing objects in S3 bucket...
Serverless: Removing Stack...
Serverless: Checking Stack removal progress...
............
Serverless: Stack removal finished...

DynamoDB Console๋กœ ๋“ค์–ด๊ฐ€์„œ Table์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค. ๋ฆฌ์ „์€ ์„œ์šธ์ž…๋‹ˆ๋‹ค.

Cloud9 Console๋กœ ๋“ค์–ด๊ฐ€์„œ IDE๋ฅผ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค. ๋ฆฌ์ „์€ ์‹ฑ๊ฐ€ํฌ๋ฅด์ž…๋‹ˆ๋‹ค.

S3 Console๋กœ ๋“ค์–ด๊ฐ€์„œ ์ƒ์„ฑ๋œ ๋ฒ„ํ‚ท์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

References

Releases

No releases published

Packages

No packages published