FaaS ๊ธฐ๋ณธ ๋™์ž‘ ์›๋ฆฌ๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•˜์—ฌ IBM Cloud functions web GUI๋ฅผ ํ†ตํ•ด web service๋ฅผ ๋งŒ๋“ค์–ด ๋ณด์ž.

Step Summary

  • Functions GUI๋ฅผ ํ†ตํ•ด action, trigger, sequence, rule ์ƒ์„ฑ ๋ฐ Database read/write ๋ฅผ ์‹ค์Šตํ•œ๋‹ค.
  • http endpoint ์ƒ์„ฑ
  • Guestbook Frontend service์™€ ์—ฐ๊ฒฐ

 

[1st: Action, Trigger, Sequence, Rule ์ƒ์„ฑ]

์ด๋ฒˆ ์‹ค์Šต์œผ๋กœ Functions์—์„œ cloudant db์— data๋ฅผ ์–ด๋–ป๊ฒŒ ์“ฐ๊ณ  ์ฝ๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ๋‹ค.
1.ย ย ย ย  create Functions and action
functions๋Š” ๊ณ„์ •๋‹น ํ•˜๋‚˜ ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ๋‹ค.
ย 
Action์„ ์ƒ์„ฑํ•œ๋‹ค.
์™ผ์ชฝ Action -> createย Action
ย 
actionย name:prepare-entry-for-save
ย 
2.ย ย ย ย  code ์ˆ˜์ •
์™ผ์ชฝ์˜ Code menu๋ฅผ ํ†ตํ•ด Code edit๋ฅผ ํ•  ์ˆ˜ ์žˆ๋‹ค.
ํ•ด๋‹น action์— function์„ ์ฝ”๋”ฉ ํ•œ ํ›„ save๋ฅผ ๋ˆ„๋ฅธ๋‹ค.
ย 

์ฐธ๊ณ ์†Œ์Šค.
/** * Prepare the guestbook entry to be persisted */
function main(params)
{
ย  if (!params.name || !params.comment)
  {
ย ย ย  return Promise.reject({ error: 'no name or comment'}); 
ย  } 
ย  return { 
ย ย ย ย ย ย ย ย ย  doc: { createdAt: new Date(), name: params.name, email: params.email, comment:
params.comment } 
ย  }; 
}
ย 
3.ย ย ย ย  enclosingย sequence
Sequenceย ๋ฅผ ๋งŒ๋“ ๋‹ค.
name:save-geustbook-entry-sequence
 
create& saveํด๋ฆญ
๋ฆฌ์ŠคํŠธ์˜ save-questbook-entry-sequenceํด๋ฆญ

ย 
4.ย ย ย ย add
save-guestbook-entry-sequence์— action์„ ํ•˜๋‚˜ ๋” ์ถ”๊ฐ€ ํ•˜๋Š” ๊ณผ์ •
ย 
use public ->cloudant์„ ํƒ
ย 
actions:create-document
binding-name:binding-for-guestbook
new instance ์„ ํƒํ•˜๋ฉด db ์ƒ์„ฑํ•˜๋Š” ์ƒˆ๋กœ์šด ์ฐฝ์ด ๋‚˜ํƒ€๋‚œ๋‹ค.
ย 
5.ย ย ย ย  db create
(์ด๋ฏธ db๊ฐ€ ์žˆ๋‹ค๋ฉด ์„ ํƒํ•ด์„œ ์‚ฌ์šฉํ•ด๋„ ๋œ๋‹ค.) 
ย 
serviceย credential์ƒ์„ฑ or ํ™•์ธ
(serviceย credential์„ ํ†ตํ•ด dbย binding์„ ํ•˜๊ฒŒ ๋œ๋‹ค.)
ย 
new credential
view credential
์ด ํฌ๋ ˆ๋ด๋ด์…œ ์ •๋ณด๋ฅผ sequence์˜ binding์ •๋ณด์— ๊ธฐ๋ก ํ•˜์—ฌ db๋ฅผ action์— ๋ฐ”์ธ๋”ฉ ํ•œ๋‹ค.
์ฃผ์˜:database:guestbook
=>์ด ์ •๋ณด๋Š” cloudant tool์—์„œ db์ƒ์„ฑ์‹œ ๋™์ผํ•˜๊ฒŒ ์ž…๋ ฅ ํ•ด์ค˜์•ผ ํ•œ๋‹ค.
ย 
2๊ฐœ์˜ action์„ย ํ™•์ธ ํ•  ์ˆ˜ ์žˆ๋‹ค.
ย 
6.ย ย ย ย  database์ƒ์„ฑ
๋ฐ”์ธ๋”ฉ ์‹œ์— ์‚ฌ์šฉํ•œย db์ด๋ฆ„๊ณผ ๋™์ผํ•œ database๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
Dashboard์—์„œ ์‚ฌ์šฉํ•  cloudant service ๋ฅผ ์„ ํƒ -> cloudant launch ํด๋ฆญ
ย 
create database
guestbook์ด๋ž€ ์ด๋ฆ„์œผ๋กœ ์ƒ์„ฑ
(์œ„ ์Šคํ…์—์„œ ์ƒ์„ฑํ•œ ๊ฒƒ์€ cloudant service์ด๊ณ ย ์ด step์—์„œ๋Š” ํ•ด๋‹น ์„œ๋น„์Šค ๋‚ด์— database๋ฅผ ๋งŒ๋“œ๋Š”ย ๊ฒƒ์ด๋‹ค. ํ•œ ์„œ๋น„์Šค ์•ˆ์— ์—ฌ๋Ÿฌ๊ฐœ์˜ db๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.)
ย 
7.ย ย ย ย sequence save
db insert๋ฅผ ์ค€๋น„ํ•˜๋Š” function๊ณผ ์‹ค์ œ๋กœ db insert action์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์„ ์กฐํ•ฉํ•ด์„œ ํ•˜๋‚˜์˜ sequence๋ฅผ
๋งŒ๋“ค์—ˆ๋‹ค.
ย 
8.ย ย ย ย  test
change inputํด๋ฆญ ํ›„ ์•„๋ž˜ json data๋ฅผ ๋„ฃ๋Š”๋‹ค.
ย 
์ฐธ๊ณ  ์†Œ์Šค:
{

“name”: “John Smith”,

“email”: “john@smith.com”,

“comment”: “this is my comment”

}

ย 

invoke๋ฒ„ํŠผ ํด๋ฆญ

ย 

cloudant์— data์ €์žฅ๋จ ํ™•์ธ

ย 

ย 

ย 

ย 

ย 

9.ย ย ย ย  db data ์ฝ๊ธฐ

createย action

ย 

name:set-read-input

ย 

์ฐธ๊ณ ์†Œ์Šค:

ย  functionย main(params) {

ย ย ย  return { params: {ย include_docs: true } };

ย  }

ย 

save

10.ย ย ย ย  sequence ์ƒ์„ฑ

enclosing sequenceํด๋ฆญ

ย 

add to sequence

ย 

create

action name:read-guestbook-entires-sequence

ย 

ย 

ย 

๋ฐฉ๊ธˆ ์ƒ์„ฑํ•œ sequence ํด๋ฆญ

ย 

11.sequence์— action ์ถ”๊ฐ€(db)

add

Use public ->cloudant

Actions:list-documents

My bindings: binding-for-guestbookdb

ย 

์ถ”๊ฐ€๋œ actionย ํ™•์ธ

ย 

12.ย 3๋ฒˆ์งธ action ์ถ”๊ฐ€: document๋ฅผ ํŠน์ • format์œผ๋กœ ๋งž์ถ”๋Š” ๊ฒƒ.

action name:format-entries

click create&Add

์„ธ๋ฒˆ์งธ action ์ถ”๊ฐ€๋œ๊ฒƒ ํ™•์ธ

ย 

action code๋ฅผ ์ˆ˜์ •ํ•˜๊ธฐ ์œ„ํ•ด ๋ฐฉ๊ธˆ ์ƒ์„ฑํ•œ ์„ธ๋ฒˆ์งธ action์„ ํด๋ฆญ ํ•œ๋‹ค.

ย 

์†Œ์Šค ์ˆ˜์ • ->save

์ฐธ๊ณ  ์†Œ์Šค:

const md5 = require(‘spark-md5’);

function main(params)
{

ย  return {

ย ย ย  entries:params.rows.map((row) => { return {

ย ย ย ย ย  name:row.doc.name,

ย ย ย ย ย  email:row.doc.email,

ย ย ย ย ย  comment:row.doc.comment,

ย ย ย ย ย  createdAt:row.doc.createdAt,

ย ย ย ย ย  icon: (row.doc.email ? `https://secure.gravatar.com/avatar/${md5.hash(row.doc.email.trim().toLowerCase())}?s=64` :
 null)}})

ย  };

ย 

read-guestbook-entries-sequence๋กœ ๋Œ์•„๊ฐ„๋‹ค.

sequence๋ฅผ saveํ•œ๋‹ค.

ย 

test๋ฅผ ์œ„ํ•ด invoke๋ฅผ ํ•ด๋ณด์ž

ย 

๋‚ด๊ฐ€ ์ €์žฅํ–ˆ๋˜ย John Smith๊ฐ€ ์ž˜ ๋‚˜์˜ค๋Š”๊ฒƒ์„ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ๋‹ค.

ย 

[2nd: HTTP endpoint ์ƒ์„ฑ]

HTTP endpoint๋ฅผ ์ƒ์„ฑํ•จ์œผ๋กœ์จ, cli ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ http request๋ฅผ ํ†ตํ•ด function์„ ์ˆ˜ํ–‰ ํ•  ์ˆ˜ ์žˆ๋‹ค.

1.cloud functions dashboard์—์„œ read-guestbook-entries-sequence๋กœ ์ด๋™ํ•˜์ž.

endpoint ํด๋ฆญ

Enable as Web action ์ฒดํฌ -> save

๊ฐ™์€ ๊ณผ์ •์„ save-guestbook-entry-sequence๋„ ํ•˜์ž.ย 

 

2.API ๋กœ ์ด๋™ํ•˜์ž.

create managed api ํด๋ฆญ

APIs ->Create Managed API

api name:guestbook

base path:/guestbook

create operation

path:/entries

verb:get

action:get-guestbook-entire-sequence

path:/entries

verb:put

action:save-guestbook-entry-sequence

save & expose ํด๋ฆญ

[3rd: Guestbook Frontend ์„œ๋น„์Šค์— functions ์—ฐ๊ฒฐ]

์ƒ์„ฑํ•œ endpoint๋ฅผ ์ด์šฉํ•˜์—ฌ client program์— functions๋ฅผ ์—ฐ๊ฒฐํ•œ๋‹ค.

์™„์„ฑ๋œ ํ•˜๋‚˜์˜ application์„ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ๋‹ค.

1.client interface frontend source ๋ฅผ ๋ฐ›๋Š”๋‹ค. (local pc)

git clone https://github.com/IBM-Cloud/serverless-guestbook.git

2.docs/guestbook.js ๋ฅผ ์—ด์–ด์„œ apiUrl๋ฅผ ๊ต์ฒด ํ•œ๋‹ค.

apiUrl์€ apiexploer ๋ฉ”๋‰ด์—์„œ ํ™•์ธ ๋œ๋‹ค. (guestbook ๋ถ€๋ถ„๊นŒ์ง€๋งŒ )

https://service.us.apiconnect.ibmcloud.com/gws/apigateway/api/7bbe0aa3d0ab81a7ad000000000000000000000002fb36400000ec43323d59363/guestbook

 

์ฐธ๊ณ : Serverless web application and API

 

[Next ย IBM Cloud Functions CLI ์‚ฌ์šฉํ•ด๋ณด๊ธฐ]

ํ† ๋ก  ์ฐธ๊ฐ€

์ด๋ฉ”์ผ์€ ๊ณต๊ฐœ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ•„์ˆ˜ ์ž…๋ ฅ์ฐฝ์€ * ๋กœ ํ‘œ์‹œ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.