์ž‘์—… ํ—ˆ๋ธŒ๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ ๊ณต์œ 

Looker์˜ ๊ธฐ๋ณธ ์ œ๊ณต ๋Œ€์ƒ์— ์ฝ˜ํ…์ธ ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ ์™ธ์—๋„ ์ž‘์—…(ํ†ตํ•ฉ์ด๋ผ๊ณ ๋„ ํ•จ)์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์—… ํ—ˆ๋ธŒ ์„œ๋ฒ„๋ฅผ ํ†ตํ•ด Looker์™€ ํ†ตํ•ฉ๋œ ํƒ€์‚ฌ ์„œ๋น„์Šค์— ์ฝ˜ํ…์ธ ๋ฅผ ์ „์†กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€์—์„œ๋Š” Looker ์ž‘์—… ํ—ˆ๋ธŒ ๋˜๋Š” ์ž์ฒด ๋น„๊ณต๊ฐœ ์ž‘์—… ํ—ˆ๋ธŒ ์„œ๋ฒ„์— ์ถ”๊ฐ€ํ•˜๋„๋ก ์š”์ฒญํ•  ์ˆ˜ ์žˆ๋Š” ์ปค์Šคํ…€ ์ž‘์—… ๋นŒ๋“œ ์˜ต์…˜์„ ์•ˆ๋‚ดํ•ฉ๋‹ˆ๋‹ค. ์ด ํŽ˜์ด์ง€์—์„œ๋Š” ๋˜ํ•œ ๋กœ์ปฌ ์ž‘์—… ํ—ˆ๋ธŒ ์„œ๋ฒ„๋ฅผ ๊ฐ€๋™ํ•˜์—ฌ ์ปค์Šคํ…€ ์ž‘์—…์„ ํ…Œ์ŠคํŠธํ•˜๊ฑฐ๋‚˜ ๋น„๊ณต๊ฐœ ์ž‘์—… ํ—ˆ๋ธŒ ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

์ž‘์—…์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋‹ค์Œ ์ค‘ ํ•˜๋‚˜๋ฅผ ์ˆ˜ํ–‰ํ•˜์„ธ์š”.

์ž‘์—…์ด ์ž‘์—… ํ—ˆ๋ธŒ์— ์ถ”๊ฐ€๋˜๋ฉด Looker ๊ด€๋ฆฌ์ž๊ฐ€ ํ•ด๋‹น ์„œ๋น„์Šค์— Looker ์ฝ˜ํ…์ธ ๋ฅผ ์ „์†กํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ž‘์—…์„ ์‚ฌ์šฉ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ Looker ์ž‘์—… ํ—ˆ๋ธŒ๋ฅผ ํ†ตํ•ด Looker์˜ ํ†ตํ•ฉ์„ ์‚ฌ์šฉํ•˜๊ณ  ์ž์ฒด ๋น„๊ณต๊ฐœ ๋˜๋Š” ์ปค์Šคํ…€ ์ž‘์—…์„ ํ˜ธ์ŠคํŒ…ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ์—ฌ๋Ÿฌ ์ž‘์—… ํ—ˆ๋ธŒ๋ฅผ ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ์ž‘์—… ํ—ˆ๋ธŒ์˜ ์ž‘์—…์€ ๊ด€๋ฆฌ์ž ํŒจ๋„์˜ ์ž‘์—… ํŽ˜์ด์ง€์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

Looker ์ž‘์—… ํ—ˆ๋ธŒ

Looker๋Š” Looker์˜ Action API๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ์ž‘์—…์„ ๋…ธ์ถœํ•˜๋Š” ์Šคํ…Œ์ดํŠธ๋ฆฌ์Šค(Stateless) ์„œ๋ฒ„์ธ Looker ์ž‘์—… ํ—ˆ๋ธŒ๋ฅผ ํ˜ธ์ŠคํŒ…ํ•˜๊ณ  ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ์ž‘์—…์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ณด๋‚ด๋Š” ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋Š” Looker ์ธ์Šคํ„ด์Šค๊ฐ€ ์•„๋‹ŒLooker ์ž‘์—… ํ—ˆ๋ธŒ ์„œ๋ฒ„์—์„œ ์ผ์‹œ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค.

Looker๋Š” ์ด๋ฏธ ์—ฌ๋Ÿฌ ์„œ๋น„์Šค์— ํ†ตํ•ฉ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ์กด ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด๋ ค๋ฉด ๊ด€๋ฆฌ ์„ค์ • - ์ž‘์—… ๋ฌธ์„œ ํŽ˜์ด์ง€๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

Looker ์ž‘์—… ํ—ˆ๋ธŒ ์š”๊ตฌ์‚ฌํ•ญ

Looker ์ž‘์—… ํ—ˆ๋ธŒ๋Š” ๋‹ค์Œ ๋ฐฉ์‹์œผ๋กœ API ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ๋ฐ›์„ ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Looker ๋ฐฐํฌ๊ฐ€ ์ด๋Ÿฌํ•œ ์š”์ฒญ์„ ์ˆ˜์šฉํ•  ์ˆ˜ ์—†๊ฑฐ๋‚˜ Looker ์ธ์Šคํ„ด์Šค์— IP ํ—ˆ์šฉ ๋ชฉ๋ก ๊ธฐ๋Šฅ์ด ์‚ฌ์šฉ ์„ค์ •๋œ ๊ฒฝ์šฐ ๋น„๊ณต๊ฐœ Looker ํ†ตํ•ฉ ๋˜๋Š” ์ปค์Šคํ…€ ์ž‘์—…์„ ์ œ๊ณตํ•˜๋„๋ก ๋กœ์ปฌ ์ž‘์—… ํ—ˆ๋ธŒ ์„œ๋ฒ„๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๊ณ ๊ฐ ํ˜ธ์ŠคํŒ… ์ธ์Šคํ„ด์Šค ๊ด€๋ฆฌ์ž๋Š” ๋˜ํ•œ ํŠนํžˆ OAuth ๋ฐ ์ŠคํŠธ๋ฆฌ๋ฐ ์ž‘์—…์„ ์œ„ํ•ด ๋กœ์ปฌ ์ž‘์—… ์„œ๋ฒ„๋ฅผ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Looker ์ธ์Šคํ„ด์Šค์—์„œ Looker ์ž‘์—… ํ—ˆ๋ธŒ ๋„คํŠธ์›Œํฌ๋กœ์˜ ์š”์ฒญ

actions.looker.com์— ๋Œ€ํ•œ ์š”์ฒญ์€ ๋™์  IP ์ฃผ์†Œ๋กœ ๋ณด๋‚ด์ง‘๋‹ˆ๋‹ค. Looker ์ธ์Šคํ„ด์Šค์—์„œ ๋‚˜๊ฐ€๋Š” ์š”์ฒญ์€ ๋‹ค์Œ ์—”๋“œํฌ์ธํŠธ์— ๋„๋‹ฌํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

actions.looker.com/
actions.looker.com/actions/<name>/execute
actions.looker.com/actions/<name>/form

์—ฌ๊ธฐ์„œ name์€ ์ž‘์—…์˜ ํ”„๋กœ๊ทธ๋ž˜๋งคํ‹ฑ ์ด๋ฆ„์ž…๋‹ˆ๋‹ค.

Looker ์‚ฌ์šฉ์ž์˜ ๋ธŒ๋ผ์šฐ์ €์—์„œ Looker ์ž‘์—… ํ—ˆ๋ธŒ ๋„คํŠธ์›Œํฌ๋กœ์˜ ์š”์ฒญ

Looker ์‚ฌ์šฉ์ž์˜ ๋ธŒ๋ผ์šฐ์ €๋Š” ๋‹ค์Œ Looker ์ž‘์—… ํ—ˆ๋ธŒ ์—”๋“œํฌ์ธํŠธ(OAuth์˜ ๊ฒฝ์šฐ)์— ์š”์ฒญ์„ ์ „์†กํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

actions.looker.com/actions/<name>/oauth

์—ฌ๊ธฐ์„œ name์€ ์ž‘์—…์˜ ํ”„๋กœ๊ทธ๋ž˜๋งคํ‹ฑ ์ด๋ฆ„์ž…๋‹ˆ๋‹ค.

Looker ์ž‘์—… ํ—ˆ๋ธŒ ๋„คํŠธ์›Œํฌ์—์„œ Looker ์ธ์Šคํ„ด์Šค๋กœ์˜ ์š”์ฒญ

Looker ์ž‘์—… ํ—ˆ๋ธŒ๋Š” Looker ์ธ์Šคํ„ด์Šค์— ์ŠคํŠธ๋ฆฌ๋ฐ ๊ฒฐ๊ณผ๋ฅผ ์ง€์›ํ•˜๊ฑฐ๋‚˜ OAuth๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ž‘์—…์„ ์š”์ฒญํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ŠคํŠธ๋ฆฌ๋ฐ ์ž‘์—…์„ ํ†ตํ•ด ๋ชจ๋“  ๊ฒฐ๊ณผ๋ฅผ ์ œ๊ณตํ•˜๋Š” ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ž‘์—…์„ ์‚ฌ์šฉ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. OAuth ์ง€์› ์ž‘์—…์€ OAuth 2.0 ํ”Œ๋กœ์šฐ๋ฅผ ํ†ตํ•œ ์‚ฌ์šฉ์ž๋ณ„ ์ธ์ฆ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. Looker ์ž‘์—… ํ—ˆ๋ธŒ๋Š” ์Šคํ…Œ์ดํŠธ๋ฆฌ์Šค(Stateless)์ด๊ณ  ๋ฉ€ํ‹ฐ ํ…Œ๋„ŒํŠธ์ด๋ฉฐ ์–ด๋– ํ•œ ์ข…๋ฅ˜์˜ ์‚ฌ์šฉ์ž๋ณ„ ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๋„ ์ €์žฅํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ OAuth ์ž‘์—…์€ ํ•ด๋‹น ์†Œ์Šค Looker ์ธ์Šคํ„ด์Šค์— ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๋ฅผ ์ €์žฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Looker ์ž‘์—… ํ—ˆ๋ธŒ์—์„œ Looker ์ธ์Šคํ„ด์Šค๋กœ์˜ ์š”์ฒญ์—๋Š” ๋‹ค์Œ ์–‘์‹์ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

GET <host_looker_url>/downloads/<random_40_char_token>
POST <host_looker_url>/action_hub_state/<random_40_char_token>

์ด๋Ÿฌํ•œ URL์€ Looker ์ž‘์—… ํ—ˆ๋ธŒ๋กœ ์ „์†ก๋˜๊ธฐ ์ „์— Looker ์ธ์Šคํ„ด์Šค์—์„œ ์ฆ‰์‹œ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ด์œ ๋กœ Looker ์ž‘์—… ํ—ˆ๋ธŒ๋Š” <host_looker_url>์„ IP ์ฃผ์†Œ๋กœ ํ™•์ธํ•˜๊ณ  Looker ์ธ์Šคํ„ด์Šค๊ฐ€ ์žˆ๋Š” ๋„คํŠธ์›Œํฌ๋กœ ์š”์ฒญ์„ ์ „์†กํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Looker ์ž‘์—… ํ—ˆ๋ธŒ์—๋Š” ํ•ญ์ƒ ์š”์ฒญ์ด ๋ฐœ์‹ ๋˜๋Š” ๊ณ ์ • ์ด๊ทธ๋ ˆ์Šค IP ์ฃผ์†Œ(35.153.89.114, 104.196.138.163, 35.169.42.87)๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. IP ํ—ˆ์šฉ ๋ชฉ๋ก์„ ์‚ฌ์šฉ ์„ค์ •ํ•œ Looker ํ˜ธ์ŠคํŒ… ์ธ์Šคํ„ด์Šค์˜ ๊ด€๋ฆฌ์ž๋Š” ์ŠคํŠธ๋ฆฌ๋ฐ ๊ฒฐ๊ณผ๋ฅผ ์ง€์›ํ•˜๊ฑฐ๋‚˜ OAuth๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ž‘์—…์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์ด IP ์ฃผ์†Œ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ณ ๊ฐ ํ˜ธ์ŠคํŒ… ์ธ์Šคํ„ด์Šค ๊ณ ๋ ค์‚ฌํ•ญ

Looker ํ†ตํ•ฉ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด Looker ์ž‘์—… ํ—ˆ๋ธŒ๊ฐ€ Looker ์ธ์Šคํ„ด์Šค์™€ ํ†ต์‹ ํ•˜๊ณ  Looker ์ž‘์—… ํ—ˆ๋ธŒ ์š”๊ตฌ์‚ฌํ•ญ์„ ์ถฉ์กฑํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์ด์œ ๋กœ ๊ณ ๊ฐ์ด ํ˜ธ์ŠคํŒ…ํ•˜๋Š” Looker ์ธ์Šคํ„ด์Šค์—์„œ ์ด๊ฒƒ์ด ํ•ญ์ƒ ๊ฐ€๋Šฅํ•œ ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. Looker ์ž‘์—… ํ—ˆ๋ธŒ์™€ Looker ์ธ์Šคํ„ด์Šค ๊ฐ„์˜ ์–‘๋ฐฉํ–ฅ ํ†ต์‹ ์ด ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ Looker ์ž‘์—… ํ—ˆ๋ธŒ์—์„œ ์ฟผ๋ฆฌ ์ค‘๋‹จ์ด๋‚˜ ์ž‘์—… ์‚ฌ์šฉ ์ค‘์ง€์™€ ๊ฐ™์€ ์˜ˆ๊ธฐ์น˜ ์•Š๊ฑฐ๋‚˜ ์›์น˜ ์•Š๋Š” ๋™์ž‘์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Looker ์ž‘์—… ํ—ˆ๋ธŒ๊ฐ€ Looker ์ธ์Šคํ„ด์Šค์™€ ํ†ต์‹ ํ•  ์ˆ˜ ์—†๋Š” ์ž ์žฌ์  ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด Looker ๊ด€๋ฆฌ์ž๋Š” ์ด ํŽ˜์ด์ง€ ํ›„๋ฐ˜๋ถ€์— ํ‘œ์‹œ๋œ ์†”๋ฃจ์…˜ ์ค‘ ํ•˜๋‚˜๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ ์ ˆํ•œ ์†”๋ฃจ์…˜ ๋˜๋Š” ์†”๋ฃจ์…˜์˜ ์กฐํ•ฉ์€ Looker ์ธ์Šคํ„ด์Šค์˜ ์•„ํ‚คํ…์ฒ˜์— ๋”ฐ๋ผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

  • ๊ณ ๊ฐ ํ˜ธ์ŠคํŒ… ์ธ์Šคํ„ด์Šค๋ฅผ Looker ์ž‘์—… ํ—ˆ๋ธŒ๋กœ ํ™•์ธํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ ์ฆ‰, Looker ์ž‘์—… ํ—ˆ๋ธŒ๊ฐ€ Looker ์ธ์Šคํ„ด์Šค์—์„œ ์š”์ฒญ์„ ์ˆ˜์‹ ํ•  ์ˆ˜ ์—†๋‹ค๋ฉด Looker ๊ด€๋ฆฌ์ž๊ฐ€ public_host_url ๋ผ์ด์„ ์Šค ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด Google Cloud ์˜์—…ํŒ€์— ๋ฌธ์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ผ์ด์„ ์Šค ๊ธฐ๋Šฅ์€ ๊ด€๋ฆฌ์ž๊ฐ€ ์ธ์Šคํ„ด์Šค <host_looker_url>๊ณผ ๋‹ค๋ฅธ ํ™•์ธ ๊ฐ€๋Šฅํ•œ <public_host_url> ํ˜ธ์ŠคํŠธ ์ด๋ฆ„์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š” --public-host-url ์‹œ์ž‘ ์˜ต์…˜์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. public_host_url์€ ํŠน์ • Looker ์ž‘์—… ํ—ˆ๋ธŒ ์ฝœ๋ฐฑ URL์˜ ํ˜ธ์ŠคํŠธ ์ด๋ฆ„์„ ์žฌ์ •์˜ํ•˜๊ณ  ๊ณต๊ฐœ์ ์œผ๋กœ ํ™•์ธ ๊ฐ€๋Šฅํ•œ ์ด๋ฆ„์˜ public_host_url์ด ์žˆ๋Š” ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ๋ฅผ ํ†ตํ•ด ์ด๋Ÿฌํ•œ ์ฝœ๋ฐฑ URL์„ ๋ผ์šฐํŒ…ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ๋Š” Looker ์ž‘์—… ํ—ˆ๋ธŒ์— ๋Œ€ํ•œ ๊ณ ์ • ์ด๊ทธ๋ ˆ์Šค IP ์ฃผ์†Œ์˜ ์š”์ฒญ๋งŒ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” Looker ๊ด€๋ฆฌ์ž๋Š” Looker ์ž‘์—… ํ—ˆ๋ธŒ๊ฐ€ Looker ์ธ์Šคํ„ด์Šค์— ์š”์ฒญ์„ ์ „์†กํ•˜๋Š” ์ด๊ทธ๋ ˆ์Šค IP ์ฃผ์†Œ(35.153.89.114, 104.196.138.163, 35.169.42.87)๋ฅผ ํ—ˆ์šฉ ๋ชฉ๋ก์— ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • ๊ณ ๊ฐ ํ˜ธ์ŠคํŒ… ์ธ์Šคํ„ด์Šค URL์„ Looker ์ธ์Šคํ„ด์Šค๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ์ง€๋งŒ Looker ์ž‘์—… ํ—ˆ๋ธŒ๊ฐ€ Looker ์ธ์Šคํ„ด์Šค์— ์š”์ฒญ์„ ๋ณด๋‚ผ ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ, ์‚ฌ์šฉ์ž๊ฐ€ ์ŠคํŠธ๋ฆฌ๋ฐ ๊ฒฐ๊ณผ๋ฅผ ์ง€์›ํ•˜๊ฑฐ๋‚˜ OAuth๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ž‘์—…์„ ๊ตฌ์„ฑํ•˜๊ฑฐ๋‚˜ ์‚ฌ์šฉํ•˜์ง€ ๋ชปํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด Looker ๊ด€๋ฆฌ์ž๋Š” Looker ์ž‘์—… ํ—ˆ๋ธŒ๊ฐ€ Looker ์ธ์Šคํ„ด์Šค์— ์š”์ฒญ์„ ์ „์†กํ•˜๋Š” ์ด๊ทธ๋ ˆ์Šค IP ์ฃผ์†Œ(35.153.89.114, 104.196.138.163, 35.169.42.87)๋ฅผ ํ—ˆ์šฉ ๋ชฉ๋ก์— ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • ์•ž์„œ ์–ธ๊ธ‰ํ•œ ์†”๋ฃจ์…˜ ์ค‘ ์–ด๋А ๊ฒƒ๋„ Looker ์ธ์Šคํ„ด์Šค ์•„ํ‚คํ…์ฒ˜์— ์ ํ•ฉํ•˜์ง€ ์•Š์œผ๋ฉด Looker ๊ด€๋ฆฌ์ž๊ฐ€ ๋ชจ๋“  ์ž‘์—… ๋˜๋Š” ์ŠคํŠธ๋ฆฌ๋ฐ ๊ฒฐ๊ณผ๋ฅผ ์ง€์›ํ•˜๊ฑฐ๋‚˜ OAuth๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ž‘์—…์—๋งŒ ๊ณ ๊ฐ ํ˜ธ์ŠคํŒ… ์ž‘์—… ํ—ˆ๋ธŒ๋ฅผ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๊ณ ๊ฐ ํ˜ธ์ŠคํŒ… ์ž‘์—… ํ—ˆ๋ธŒ๋ฅผ ๋ฐฐํฌํ•˜๋ ค๋ฉด Looker ์ž‘์—… ํ—ˆ๋ธŒ๊ฐ€ ํ†ต์‹ ํ•  ์ˆ˜ ์žˆ๋„๋ก JAR ํŒŒ์ผ์ด ๊ณต๊ฐœ ์„œ๋ฒ„์—์„œ ํ˜ธ์ŠคํŒ…๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด ์†”๋ฃจ์…˜์€ ๊ถŒ์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ด ๋ฃจํŠธ ์ธ์ฆ์„œ ๋ชฉ๋ก์— ์—†๋Š” ์ธ์ฆ ๊ธฐ๊ด€(CA)์—์„œ ๋ฐœ๊ธ‰ํ•œ SSL ์ธ์ฆ์„œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ๊ณ ๊ฐ ํ˜ธ์ŠคํŒ… Looker ์ธ์Šคํ„ด์Šค์—์„œ OAuth ๋ฐ ์ŠคํŠธ๋ฆฌ๋ฐ ์ž‘์—…์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ปค์Šคํ…€ ์ž‘์—… ๋นŒ๋“œ

์ด ์„น์…˜์—์„œ๋Š” Looker ์ž‘์—… ํ—ˆ๋ธŒ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ปค์Šคํ…€ ์ž‘์—…์„ ์ž‘์„ฑ ๋ฐ ํ…Œ์ŠคํŠธํ•˜๋Š” ๋‹จ๊ณ„๋ฅผ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ์‹ค์ œ ์ฝ”๋“œ ์˜ˆ์‹œ๋ฅผ ๋ณด๋ ค๋ฉด GitHub์˜ looker-open-source/actions ์ €์žฅ์†Œ์—์„œ ๊ธฐ์กด ์ž‘์—…์„ ํ™•์ธํ•˜์„ธ์š”.

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ปค์Šคํ…€ ์ž‘์—…์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ๊ฐœ๋ฐœ ์ €์žฅ์†Œ ์„ค์ •
  2. ์ž‘์—… ์ž‘์„ฑ
  3. ์ž‘์—… ํ…Œ์ŠคํŠธ
  4. Looker ์ž‘์—… ํ—ˆ๋ธŒ ๋˜๋Š” ์ž์ฒด ๋น„๊ณต๊ฐœ ์ž‘์—… ํ—ˆ๋ธŒ ์„œ๋ฒ„์—์„œ ์ž‘์—… ๊ฒŒ์‹œ ๋ฐ ์‚ฌ์šฉ ์„ค์ •

๋‹ค๋ฅธ ์ž‘์—…๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ž‘์—…์„ ์‚ฌ์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋จผ์ € ํŠน์ • ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ LookML ๋ชจ๋ธ์„ ๊ตฌ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ ์ €์žฅ์†Œ ์„ค์ •

Looker ์ž‘์—… ํ—ˆ๋ธŒ๋Š” TypeScript๋กœ ์ž‘์„ฑ๋œ Node.js ์„œ๋ฒ„์ž…๋‹ˆ๋‹ค. ์ตœ์‹  JavaScript ๊ธฐ๋ฐ˜์˜ ์ž‘์€ ๋ ˆ์ด์–ด๋กœ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์˜ค๋ฅ˜๋ฅผ ํฌ์ฐฉํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š” ์œ ํ˜• ์ •๋ณด๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. JavaScript์— ์ต์ˆ™ํ•˜๋‹ค๋ฉด ๋Œ€๋ถ€๋ถ„์˜ TypeScript ์–ธ์–ด์— ์ต์ˆ™ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Looker ์ž‘์—… ํ—ˆ๋ธŒ๋ฅผ ์‹คํ–‰ํ•˜๋ ค๋ฉด ๋‹ค์Œ ์†Œํ”„ํŠธ์›จ์–ด๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

  • Node.js
  • ๋…ธ๋“œ ๋ฒ„์ „ ๊ด€๋ฆฌ์ž(NVM - ์ ์ ˆํ•œ Node.js ๋ฒ„์ „ ์„ ํƒ)
  • Yarn(์ข…์† ํ•ญ๋ชฉ ๊ด€๋ฆฌ)

ํ•„์š”ํ•œ ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ์„ค์น˜ํ–ˆ์œผ๋ฉด ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์„ ์„ค์ •ํ•  ์ค€๋น„๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ์˜ˆ์‹œ์—์„œ๋Š” Git๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  1. looker-open-source/actions ์ €์žฅ์†Œ๋ฅผ ๋กœ์ปฌ๋กœ ํด๋ก ํ•ฉ๋‹ˆ๋‹ค.

    git clone git@github.com:looker-open-source/actions.git
    
  2. actions/src/actions ๋””๋ ‰ํ„ฐ๋ฆฌ์— ํ•ด๋‹น ์ž‘์—… ์ด๋ฆ„์œผ๋กœ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    mkdir actions/src/actions/my_action
    
  3. ์ž‘์—…์„ ์‹คํ–‰ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ํŒŒ์ผ์„ ๋””๋ ‰ํ„ฐ๋ฆฌ์— ์ฑ„์›๋‹ˆ๋‹ค. ํŒŒ์ผ ๊ตฌ์กฐ ์˜ˆ์‹œ๋Š” ์ž‘์—… GitHub ์ €์žฅ์†Œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

Looker์—์„œ๋Š” ๋‹ค์Œ ํ•ญ๋ชฉ๋„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

  • ์ž‘์—…์˜ ์ธ์ฆ ๋ชฉ์ ๊ณผ ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•˜๋Š” ๋ฆฌ๋“œ๋ฏธ
  • Looker ์ž‘์—… ํ—ˆ๋ธŒ(๋˜๋Š” Looker ์ธ์Šคํ„ด์Šค์˜ ๋น„๊ณต๊ฐœ ์ž‘์—… ํ—ˆ๋ธŒ)์™€ Looker ๋ฐ์ดํ„ฐ ์ „์†ก ์ฐฝ์— ํ‘œ์‹œํ•  PNG ์•„์ด์ฝ˜
  • ์ž‘์—… ์ฝ”๋“œ์—์„œ ์‹คํ–‰ํ•˜๋ ค๋Š” ํ…Œ์ŠคํŠธ์— ๋Œ€ํ•œ ํŒŒ์ผ(์ž‘์—… ํ…Œ์ŠคํŠธ์™€ ๋‹ค๋ฆ„)

์ž‘์—… ์ž‘์„ฑ

Looker ์ž‘์—… ํ—ˆ๋ธŒ ์„œ๋ฒ„์˜ ์„ค๊ณ„ ์š”๊ตฌ์‚ฌํ•ญ์€ ์™„์ „ํžˆ ์Šคํ…Œ์ดํŠธ๋ฆฌ์Šค(Stateless)๋กœ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ด๋ฏ€๋กœ ์ž‘์—… ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋˜๋Š” ์„œ๋น„์Šค์— ์ •๋ณด๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ž‘์—… ์ˆ˜ํ–‰์— ํ•„์š”ํ•œ ๋ชจ๋“  ์ •๋ณด๋ฅผ ์ž‘์—… ํŒŒ์ผ์˜ ์š”์ฒญ ํ˜ธ์ถœ ๋‚ด์— ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ž‘์—… ํŒŒ์ผ์˜ ์‹ค์ œ ์ฝ˜ํ…์ธ ๋Š” ์„œ๋น„์Šค, ์ž‘์—…์ด ์ˆ˜ํ–‰๋˜๋Š” ์œ ํ˜• ๋˜๋Š” ์ˆ˜์ค€, ์ง€์ •ํ•ด์•ผ ํ•˜๋Š” ๋ฐ์ดํ„ฐ ๋˜๋Š” ์‹œ๊ฐํ™” ํ˜•์‹์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค. ๋˜ํ•œ ์ž‘์—…์„ OAuth 2.0 ์Šน์ธ ํ๋ฆ„์œผ๋กœ ๊ตฌ์„ฑํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์ž‘์—… ํŒŒ์ผ์€ /execute API ๋ฉ”์„œ๋“œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ Looker ๋‚ด์—์„œ ์ž‘์—…์„ ์‹คํ–‰ํ•  ๋•Œ๋งˆ๋‹ค Looker API ์š”์ฒญ์— DataActionRequest๊ฐ€ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. DataActionRequest์—๋Š” ์ž‘์—… ์‹คํ–‰์— ํ•„์š”ํ•œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ ๋ฐ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ž‘์—… ์‹คํ–‰ ์ „ ์‚ฌ์šฉ์ž์—๊ฒŒ์„œ ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ์ˆ˜์ง‘ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” /form ๋ฉ”์„œ๋“œ๋„ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. /form์—์„œ ์ง€์ •ํ•œ ํ•„๋“œ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ž‘์—…์„ ๋ฐ์ดํ„ฐ ์ „์†ก ๋Œ€์ƒ์œผ๋กœ ์„ ํƒํ•  ๋•Œ ์ „์†ก ๋˜๋Š” ์ผ์ • ํŒ์—…์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

์ž‘์—… ํŒŒ์ผ์„ ์ž‘์„ฑํ•  ๋•Œ๋Š” ์ตœ์†Œํ•œ ์ž‘์—… ์ •์˜์— ํ•„์ˆ˜๋กœ ํ‘œ์‹œ๋œ ๋‹ค์Œ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋งค๊ฐœ๋ณ€์ˆ˜ ํ•„์ˆ˜ ์„ค๋ช… ๋ฐ์ดํ„ฐ ์œ ํ˜•
name ์˜ˆ ์ž‘์—…์˜ ๊ณ ์œ  ์ด๋ฆ„์ž…๋‹ˆ๋‹ค. Looker ์ž‘์—… ํ—ˆ๋ธŒ์— ์žˆ๋Š” ๋ชจ๋“  ์ž‘์—… ๊ฐ„์— ๊ณ ์œ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด
url ์˜ˆ ์ด ์ž‘์—…์— ๋Œ€ํ•œ /execute ์—”๋“œํฌ์ธํŠธ์˜ ์ ˆ๋Œ€ URL์ž…๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด
label ์˜ˆ ์ธ๊ฐ„์ด ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ์ž‘์—… ๋ผ๋ฒจ์ž…๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด
supportedActionTypes ์˜ˆ ์ž‘์—…์„ ์ง€์›ํ•˜๋Š” ์ž‘์—… ์œ ํ˜• ๋ชฉ๋ก์ž…๋‹ˆ๋‹ค. ์œ ํšจํ•œ ๊ฐ’์€ "cell", "query", "dashboard"์ž…๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด
formURL ์•„๋‹ˆ์š” ์ด ์ž‘์—…์— ๋Œ€ํ•œ /form ์—”๋“œํฌ์ธํŠธ์˜ ์ ˆ๋Œ€ URL์ž…๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด
description ์•„๋‹ˆ์š” ์ž‘์—… ์„ค๋ช…์ž…๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด
params ์•„๋‹ˆ์š” ์ž‘์—…์˜ parameters ๋ฐฐ์—ด์ž…๋‹ˆ๋‹ค. ๊ฐ ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ๋ฌธ์ž์—ด ํ˜•์‹์œผ๋กœ ๋œ ์ด๋ฆ„, ๋ผ๋ฒจ, ์„ค๋ช…์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ์ด ํ•„๋“œ๋Š” ๊ด€๋ฆฌ ํŒจ๋„์˜ ์ž‘์—… ์‚ฌ์šฉ ์„ค์ • ํŽ˜์ด์ง€์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ์ž‘์—… ๋Œ€์ƒ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ํŠน์ • ๊ฐ’์„ ์ •์˜ํ•ด์•ผ ํ•˜๋Š” ์‚ฌ์šฉ์ž ์†์„ฑ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. parameters
supportedFormats ์•„๋‹ˆ์š” ์ž‘์—…์—์„œ ์ง€์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ ํ˜•์‹์˜ ๋ชฉ๋ก์ž…๋‹ˆ๋‹ค. ์œ ํšจํ•œ ๊ฐ’์€ "txt", "csv", "inline_json", "json", "json_detail", "json_detail_lite_stream", "xlsx", "html", "wysiwyg_pdf", "assembled_pdf", and "wysiwyg_png".์ž…๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด
supportedFormattings ์•„๋‹ˆ์š” ์ž‘์—…์—์„œ ์ง€์›ํ•˜๋Š” ํ˜•์‹ ์ง€์ • ์˜ต์…˜์˜ ๋ชฉ๋ก์ž…๋‹ˆ๋‹ค. ์œ ํšจํ•œ ๊ฐ’์€ "formatted" ๋ฐ "unformatted"์ž…๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด
supportedVisualizationFormattings ์•„๋‹ˆ์š” ์ž‘์—…์—์„œ ์ง€์›ํ•˜๋Š” ์‹œ๊ฐํ™” ํ˜•์‹ ์ง€์ • ์˜ต์…˜์˜ ๋ชฉ๋ก์ž…๋‹ˆ๋‹ค. ์œ ํšจํ•œ ๊ฐ’์€ "apply" ๋ฐ "noapply"์ž…๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด
iconName ์•„๋‹ˆ์š” ์ž‘์—…์˜ ์•„์ด์ฝ˜ ์ด๋ฏธ์ง€๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฐ์ดํ„ฐ URI์ž…๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด
requiredFields ์•„๋‹ˆ์š” ์ด ์ž‘์—…๊ณผ ํ˜ธํ™˜๋˜๋Š” ํ•„์ˆ˜ ํ•„๋“œ์˜ ์„ค๋ช… ๋ชฉ๋ก์ž…๋‹ˆ๋‹ค. ์ด ๋ชฉ๋ก์— ํ•ญ๋ชฉ์ด ์—ฌ๋Ÿฌ ๊ฐœ ์žˆ์œผ๋ฉด ์ž‘์—…์— ๋‘˜ ์ด์ƒ์˜ ํ•„๋“œ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. RequiredField
supportedDownloadSettings ์•„๋‹ˆ์š” ๋ฌด์ œํ•œ ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆฌ๋ฐ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์ผํšŒ์šฉ ๋‹ค์šด๋กœ๋“œ URL์„ ์ „์†กํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๋ถˆ๋ฆฌ์–ธ์ž…๋‹ˆ๋‹ค. ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” true/false ๋ถˆ๋ฆฌ์–ธ์ธ usesStreaming ๋งค๊ฐœ๋ณ€์ˆ˜์— ์˜ํ•ด ์„ค์ •๋ฉ๋‹ˆ๋‹ค. usesStreaming = true ์‹œ supportedDownloadSettings = url. usesStreaming = false ์‹œ supportedDownloadSettings = push. ๋ถˆ๋ฆฌ์–ธ
usesOAuth ์•„๋‹ˆ์š” ์ž‘์—…์ด OAuth ์ž‘์—…์ธ์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๋ถˆ๋ฆฌ์–ธ์ž…๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ด ์ž‘์—…์—์„œ ํŠน์ • ์‚ฌ์šฉ์ž์— ๋Œ€ํ•ด state๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ผํšŒ์šฉ ๋งํฌ๊ฐ€ ์ „์†ก๋˜๋Š”์ง€ ์—ฌ๋ถ€๊ฐ€ ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค. ๋ถˆ๋ฆฌ์–ธ
usesStreaming ์•„๋‹ˆ์š” ์ž‘์—…์ด ์ŠคํŠธ๋ฆฌ๋ฐ ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ์ง€์›ํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๋ถˆ๋ฆฌ์–ธ์ž…๋‹ˆ๋‹ค. ํ†ตํ•ฉ ์„œ๋น„์Šค ๋ชฉ๋ก์—์„œ ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆฌ๋ฐ ์‚ฌ์šฉ(์˜ˆ/์•„๋‹ˆ์š”) ์—ด์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ๋ฅผ ์ŠคํŠธ๋ฆฌ๋ฐํ•˜๋Š” ์ž‘์—…์—๋Š” ๋กœ์ปฌ ์ž‘์—… ํ—ˆ๋ธŒ ์„œ๋ฒ„ ๊ตฌ์„ฑ์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ OAuth ๋˜๋Š” ์ŠคํŠธ๋ฆฌ๋ฐ์„ ์‚ฌ์šฉํ•˜๋Š” ์ž‘์—…์˜ ๋กœ์ปฌ ์ž‘์—… ํ—ˆ๋ธŒ ์„ค์ • ๊ถŒ์žฅ์‚ฌํ•ญ ํŽ˜์ด์ง€๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”. ๋ถˆ๋ฆฌ์–ธ
minimumSupportedVersion ์•„๋‹ˆ์š” ๊ด€๋ฆฌ์ž ํŒจ๋„ ์ž‘์—… ํ—ˆ๋ธŒ ๋ชฉ๋ก์—์„œ ์ž‘์—…์ด ํ‘œ์‹œ๋˜๋Š” ์ตœ์†Œ Looker ๋ฒ„์ „์ž…๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด

Looker ์ž‘์—… ํ—ˆ๋ธŒ ์ž‘์—…์˜ ์˜ˆ์‹œ๋Š” GitHub์—์„œ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ง€์›๋˜๋Š” ์ž‘์—… ์œ ํ˜•

Looker๋Š” ์ž‘์—…์˜ supportedActionTypes ๋งค๊ฐœ๋ณ€์ˆ˜์— ์ง€์ •๋œ ๋Œ€๋กœ ์ฟผ๋ฆฌ, ์…€, ๋Œ€์‹œ๋ณด๋“œ์˜ ์„ธ ๊ฐ€์ง€ ์œ ํ˜•์˜ ์ž‘์—…์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

  • ์ฟผ๋ฆฌ ์ˆ˜์ค€ ์ž‘์—…: ์ „์ฒด ์ฟผ๋ฆฌ๋ฅผ ์ „์†กํ•˜๋Š” ์ž‘์—…์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์„ธ๊ทธ๋จผํŠธ ์ž‘์—…์€ ์ฟผ๋ฆฌ ์ˆ˜์ค€ ์ž‘์—…์ž…๋‹ˆ๋‹ค.
  • ์…€ ์ˆ˜์ค€ ์ž‘์—…: ์…€ ์ˆ˜์ค€ ์ž‘์—…์€ ๋ฐ์ดํ„ฐ ํ…Œ์ด๋ธ”์—์„œ ํŠน์ • ๋‹จ์ผ ์…€์˜ ๊ฐ’์„ ์ „์†กํ•ฉ๋‹ˆ๋‹ค. ์ด ์ž‘์—… ์œ ํ˜•์€ action ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ธก์ •๊ธฐ์ค€ ๋˜๋Š” ์ธก์ •๊ฐ’์— ๋Œ€ํ•ด ์ •์˜ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ ์ž‘์—…๊ณผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ํ…Œ์ด๋ธ” ๋‚ด์— ์žˆ๋Š” ํŠน์ • ์…€์˜ ์ •๋ณด๋ฅผ ์ „์†กํ•˜๊ธฐ ์œ„ํ•ด Looker๋Š” ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ž‘์—…์„ ํ•ด๋‹น ์…€์— ๋งคํ•‘ํ•ฉ๋‹ˆ๋‹ค. ์ž‘์—…์€ ์ง€์›ํ•˜๋Š” ํƒœ๊ทธ๋ฅผ requiredFields์— ์ง€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ž‘์—… ๋ฐ ํ•„๋“œ๋ฅผ ๋งคํ•‘ํ•˜๋ ค๋ฉด LookML์˜ ํ•„๋“œ๊ฐ€ LookML tags ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋งคํ•‘๋˜๋Š” ํƒœ๊ทธ๋ฅผ ์ง€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด Twilio ๋ฉ”์‹œ์ง€ ์ž‘์—…์€ phone ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ LookML ๊ฐœ๋ฐœ์ž๊ฐ€ Twilio ์ž‘์—…์ด ํ‘œ์‹œ๋  ์ „ํ™”๋ฒˆํ˜ธ ํ•„๋“œ๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋Œ€์‹œ๋ณด๋“œ ์ˆ˜์ค€ ์ž‘์—…: ๋Œ€์‹œ๋ณด๋“œ ์ˆ˜์ค€ ์ž‘์—…์€ ๋Œ€์‹œ๋ณด๋“œ์˜ ์ด๋ฏธ์ง€ ์ „์†ก์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด SendGrid ์ž‘์—…์€ ์ด๋ฉ”์ผ์„ ํ†ตํ•ด ๋Œ€์‹œ๋ณด๋“œ ์ด๋ฏธ์ง€๋ฅผ ์ „์†กํ•ฉ๋‹ˆ๋‹ค.

์ปค์Šคํ…€ ์ž‘์—…์— ์‚ฌ์šฉ์ž ์†์„ฑ ์ถ”๊ฐ€

์ปค์Šคํ…€ ์ž‘์—…์˜ ๊ฒฝ์šฐ ์ž‘์—… ํŒŒ์ผ์˜ params ๋งค๊ฐœ๋ณ€์ˆ˜์— ์‚ฌ์šฉ์ž ์†์„ฑ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ํ•„์ˆ˜์ธ ๊ฒฝ์šฐ ๊ฐ ์‚ฌ์šฉ์ž๋Š” send_to_integration ๊ถŒํ•œ ์™ธ์—๋„ ์‚ฌ์šฉ์ž ๊ณ„์ • ๋˜๋Š” ์†ํ•œ ์‚ฌ์šฉ์ž ๊ทธ๋ฃน์— ์ •์˜๋œ ์ด ์†์„ฑ์˜ ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ์ฝ˜ํ…์ธ ๋ฅผ ๋ณด๋‚ด๊ฑฐ๋‚˜ ์˜ˆ์•ฝํ•  ๋•Œ ์ž‘์—…์„ ๋Œ€์ƒ ์˜ต์…˜์œผ๋กœ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ž‘์—…์— ์‚ฌ์šฉ์ž ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜๋ ค๋ฉด ๋‹ค์Œ ์•ˆ๋‚ด๋ฅผ ๋”ฐ๋ฅด์„ธ์š”.

  1. Looker ๊ด€๋ฆฌ์ž๋Š” user_attribute_param์— ํ•ด๋‹นํ•˜๋Š” ์‚ฌ์šฉ์ž ์†์„ฑ์„ ๋งŒ๋“ค์–ด์•ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์•„์ง ์—†๋Š” ๊ฒฝ์šฐ).
  2. ์ž‘์—… ๋Œ€์ƒ์— ์ฝ˜ํ…์ธ ๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•˜๋Š” ์‚ฌ์šฉ์ž ๋˜๋Š” ์‚ฌ์šฉ์ž ๊ทธ๋ฃน์— ๋Œ€ํ•ด ์‚ฌ์šฉ์ž ์†์„ฑ์— ์œ ํšจํ•œ ๊ฐ’์„ ์ •์˜ํ•˜์„ธ์š”. (์ด๋Ÿฌํ•œ ์‚ฌ์šฉ์ž๋Š” send_to_integration ๊ถŒํ•œ๋„ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.)
  3. params ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” Looker ๊ด€๋ฆฌ์ž๊ฐ€ ๊ด€๋ฆฌ ํŒจ๋„์˜ ์ž‘์—… ๋ชฉ๋ก์—์„œ ์ž‘์—…์˜ ์‚ฌ์šฉ ์„ค์ • ํŽ˜์ด์ง€์—์„œ ๊ตฌ์„ฑํ•ด์•ผ ํ•˜๋Š” ์–‘์‹ ํ•„๋“œ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์ž‘์—… ํŒŒ์ผ์˜ params ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋‹ค์Œ์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
  params = [{
    description: "A description of the param.",
    label: "A label for the param.",
    name: "action_param_name",
    user_attribute_name: "user_attribute_name",
    required: true,
    sensitive: true,
  }]

์—ฌ๊ธฐ์—์„œ user_attribute_name์€ ๊ด€๋ฆฌ ํŒจ๋„์˜ ์‚ฌ์šฉ์ž ์„น์…˜์˜ ์‚ฌ์šฉ์ž ์†์„ฑ ํŽ˜์ด์ง€์— ์žˆ๋Š” ์ด๋ฆ„ ํ•„๋“œ์— ์ •์˜๋œ ์‚ฌ์šฉ์ž ์†์„ฑ์ž…๋‹ˆ๋‹ค. required: true๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•  ๋•Œ ์ž‘์—…์„ ํ™•์ธํ•˜๋ ค๋ฉด ์‚ฌ์šฉ์ž ์†์„ฑ์— null์ด ์•„๋‹Œ ์œ ํšจํ•œ ๊ฐ’์ด ์ •์˜๋˜์–ด ์žˆ์–ด์•ผ ํ•จ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. sensitive: true๋Š” ์‚ฌ์šฉ์ž ์†์„ฑ ๊ฐ’์ด ์•”ํ˜ธํ™”๋˜์–ด ์ž…๋ ฅํ•œ ํ›„์—๋Š” Looker UI์— ํ‘œ์‹œ๋˜์ง€ ์•Š์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์†์„ฑ ํ•˜์œ„ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ์ž‘์—… ํ—ˆ๋ธŒ ์„œ๋ฒ„์— ์—…๋ฐ์ดํŠธ๋ฅผ ๋ฐฐํฌํ•ฉ๋‹ˆ๋‹ค.
    • ์ƒˆ ์ž‘์—…์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒฝ์šฐ Looker ๊ด€๋ฆฌ์ž๊ฐ€ ๊ด€๋ฆฌ ํŒจ๋„์˜ ์ž‘์—… ํŽ˜์ด์ง€์— ์žˆ๋Š” ์ž‘์—… ์˜†์— ์žˆ๋Š” ์‚ฌ์šฉ ์„ค์ • ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜์—ฌ ์ž‘์—…์„ ์‚ฌ์šฉ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • ๊ธฐ์กด ์ž‘์—…์„ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๊ฒฝ์šฐ ์ƒˆ๋กœ๊ณ ์นจ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜์—ฌ ์ž‘์—… ๋ชฉ๋ก์„ ์ƒˆ๋กœ๊ณ ์นจํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ํ›„ ์„ค์ • ๋ฒ„ํŠผ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.
  2. Looker ๊ด€๋ฆฌ์ž๋Š” ์ž‘์—… ์„ค์ •/์ง€์› ํŽ˜์ด์ง€์—์„œ ์ ํ•ฉํ•œ ํ•„๋“œ ์˜ค๋ฅธ์ชฝ์— ์žˆ๋Š” ์‚ฌ์šฉ์ž ์†์„ฑ ์•„์ด์ฝ˜ ์„ ํด๋ฆญํ•˜๊ณ  ์›ํ•˜๋Š” ์‚ฌ์šฉ์ž ์†์„ฑ์„ ์„ ํƒํ•˜์—ฌ ์‚ฌ์šฉ์ž ์†์„ฑ์—์„œ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๋„๋ก ์ž‘์—…์˜ ์–‘์‹ ํ•„๋“œ๋ฅผ ๊ตฌ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์…€ ์ˆ˜์ค€ ์ž‘์—…์˜ requiredField ๋งค๊ฐœ๋ณ€์ˆ˜

์…€ ์ˆ˜์ค€ ์ž‘์—…์˜ ๊ฒฝ์šฐ ์ž‘์—… ํŒŒ์ผ์˜ requiredFields ๋งค๊ฐœ๋ณ€์ˆ˜์—์„œ ์ž‘์—…์ด ์ง€์›ํ•˜๋Š” ํƒœ๊ทธ๋ฅผ ์ง€์ •ํ•˜์—ฌ ํ•ด๋‹น ์ž‘์—… ๋Œ€์ƒ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๋„๋ก ๋ชจ๋ธ์˜ LookML ํ•„๋“œ๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋งค๊ฐœ๋ณ€์ˆ˜ ํ•„์ˆ˜ ์„ค๋ช… ๋ฐ์ดํ„ฐ ์œ ํ˜•
tag ์•„๋‹ˆ์š” ์žˆ์œผ๋ฉด, ์ด ํƒœ๊ทธ๋ฅผ ํฌํ•จํ•˜๋Š” ํ•„๋“œ๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด
any_tag ์•„๋‹ˆ์š” ์žˆ์œผ๋ฉด, tag๋ฅผ ๋Œ€์ฒดํ•˜๊ณ  ์ œ๊ณต๋œ ํƒœ๊ทธ๊ฐ€ ํฌํ•จ๋œ ํ•„๋“œ๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด
all_tags ์•„๋‹ˆ์š” ์žˆ์œผ๋ฉด, tag๋ฅผ ๋Œ€์ฒดํ•˜๊ณ  ์ œ๊ณต๋œ ํƒœ๊ทธ๊ฐ€ ๋ชจ๋‘ ํฌํ•จ๋œ ํ•„๋“œ๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด

์ง€์›๋˜๋Š” ๋ฐ์ดํ„ฐ ํ˜•์‹

DataActionRequest ํด๋ž˜์Šค๋Š” ์ž‘์—… ์ˆ˜ํ–‰์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ ์ „์†ก ํ˜•์‹์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ์ฟผ๋ฆฌ ์ˆ˜์ค€ ์ž‘์—…์—์„œ๋Š” ์—ฌ๋Ÿฌ ํ˜•์‹์œผ๋กœ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ๋Š” ์ฒจ๋ถ€ํŒŒ์ผ์ด ์š”์ฒญ์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ์ž‘์—…์€ ํ•˜๋‚˜ ์ด์ƒ์˜ supportedFormats๋ฅผ ์ง€์ •ํ•˜๊ฑฐ๋‚˜ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ํ˜•์‹์„ ์ง€์ •ํ•˜์—ฌ ์‚ฌ์šฉ์ž๊ฐ€ ํ˜•์‹์„ ์„ ํƒํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์…€ ์ˆ˜์ค€ ์ž‘์—…์—์„œ๋Š” ์…€์˜ ๊ฐ’์ด DataActionRequest์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

OAuth์˜ ์ž‘์—… ๊ตฌ์„ฑ

์‚ฌ์šฉ์ž๊ฐ€ OAuth๋กœ ์ž‘์—…์— ์ธ์ฆํ•  ์ˆ˜ ์žˆ๋„๋ก ์ž‘์—…์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Looker ์ž‘์—… ํ—ˆ๋ธŒ๋Š” ์Šคํ…Œ์ดํŠธ๋ฆฌ์Šค(Stateless)๋กœ ์œ ์ง€๋˜์–ด์•ผ ํ•˜์ง€๋งŒ Looker Action API์˜ ์–‘์‹ ์š”์ฒญ์„ ํ†ตํ•ด ์ƒํƒœ๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Looker ์ž‘์—… OAuth ํ๋ฆ„

Looker ์ž‘์—… ํ—ˆ๋ธŒ์˜ ์ž‘์—…์€ Hub.Action ๋Œ€์‹  OAuthAction์„ ํ™•์žฅํ•˜์—ฌ ์‚ฌ์šฉ์ž๋ฅผ ์ž‘์—…์— ์ธ์ฆํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ OAuth ๋ฉ”์„œ๋“œ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ถˆ๋ฆฌ์–ธ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  OAuth ์‚ฌ์šฉ ์„ค์ • ๋˜๋Š” ์ƒํƒœ ์‚ฌ์šฉ ์„ค์ • ์ž‘์—…์— ๋Œ€ํ•ด Looker๋Š” ์‚ฌ์šฉ์ž๋ณ„, ์ž‘์—…๋ณ„ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๋ฏ€๋กœ ๊ฐ ์ž‘์—…๊ณผ ์‚ฌ์šฉ์ž ์กฐํ•ฉ์— ๋…๋ฆฝ์ ์ธ OAuth ์ด๋ฒคํŠธ๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

์ž‘์—…์„ ๋งŒ๋“œ๋Š” ํ๋ฆ„์—๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ /form ์š”์ฒญ์ด ํฌํ•จ๋˜๋ฉฐ /execute ์š”์ฒญ์œผ๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค. OAuth์˜ ๊ฒฝ์šฐ /form ์š”์ฒญ์— ์‚ฌ์šฉ์ž๊ฐ€ ๋Œ€์ƒ ์„œ๋น„์Šค ๋‚ด์— ์ธ์ฆ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ํฌํ•จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ์ด๋ฏธ ์ธ์ฆ๋œ ๊ฒฝ์šฐ ์ž‘์—…์€ /execute ์š”์ฒญ์— ํ•„์š”ํ•œ ์‚ฌํ•ญ์— ๋”ฐ๋ผ ์ผ๋ฐ˜ /form์„ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ์ธ์ฆ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์ž‘์—…์€ OAuth ํ๋ฆ„์„ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๋งํฌ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

OAuth URL๋กœ ์ƒํƒœ ์ €์žฅ

Looker๋Š” ๋ณธ๋ฌธ์ด ๋น„์–ด ์žˆ๋Š” HTTP POST ์š”์ฒญ์„ ActionList ์—”๋“œํฌ์ธํŠธ๋กœ ์ „์†กํ•ฉ๋‹ˆ๋‹ค. ์ž‘์—…์ด ์ •์˜์— uses_oauth: true๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ ์ž‘์—…์— Looker์˜ ๋ชจ๋“  /form ์š”์ฒญ์˜ ์ผํšŒ์šฉ state_url์ด ์ „์†ก๋ฉ๋‹ˆ๋‹ค. state_url์€ ์ง€์ •๋œ ์ž‘์—…์˜ ์‚ฌ์šฉ์ž ์ƒํƒœ๋ฅผ ์„ค์ •ํ•˜๋Š” ํŠน์ˆ˜ํ•œ ์ผํšŒ์šฉ URL์ž…๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž๊ฐ€ ์—”๋“œํฌ์ธํŠธ๋กœ ์ธ์ฆ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ๋ฐ˜ํ™˜๋œ /form์€ ์ž‘์—…์˜ /oauth ์—”๋“œํฌ์ธํŠธ๋กœ ์ด๋™ํ•˜๋Š” oauth_link ์œ ํ˜•์˜ form_field๋ฅผ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. state_url์€ ์•”ํ˜ธํ™”๋˜๋ฉฐ ๋ฐ˜ํ™˜๋˜๋Š” oauth_url์— state ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ €์žฅ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

{
        "name": "login",
        "type": "oauth_link",
        "label": "Log in",
        "description": "OAuth Link",
        "oauth_url": "ACTIONHUB_URL/actions/my_action/oauth?state=encrypted_state_url"
}

์ด ์˜ˆ์‹œ์—์„œ /oauth ์—”๋“œํฌ์ธํŠธ๋Š” ์‚ฌ์šฉ์ž๋ฅผ ์ธ์ฆ ์„œ๋ฒ„๋กœ ๋ฆฌ๋””๋ ‰์…˜ํ•ฉ๋‹ˆ๋‹ค. /oauth ์—”๋“œํฌ์ธํŠธ๋Š” Dropbox OauthUrl์— ํ‘œ์‹œ๋œ ๊ฒƒ์ฒ˜๋Ÿผ OAuth ์ž‘์—…์˜ oauthUrl(...) ๋ฉ”์„œ๋“œ์—์„œ ๋ฆฌ๋””๋ ‰์…˜์„ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์•”ํ˜ธํ™”๋œ state_url์ด ํฌํ•จ๋œ state ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ Looker ์ž‘์—… ํ—ˆ๋ธŒ์— ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ž‘์—… ํ—ˆ๋ธŒ ๋ฆฌ๋””๋ ‰์…˜ URI๋กœ ์ƒํƒœ ์ €์žฅ

/oauth ์—”๋“œํฌ์ธํŠธ์—์„œ ์ž‘์—… ํ—ˆ๋ธŒ์˜ redirect_uri๋„ ์ƒ์„ฑ๋˜๊ณ  ์ž‘์—…์˜ oauthUrl(...) ๋ฉ”์„œ๋“œ๋กœ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. redirect_uri๋Š” /actions/src/actions/my_maction/oauth_redirect ํ˜•์‹์ด๋ฉฐ ์ธ์ฆ์ด ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ์— ์‚ฌ์šฉ๋˜๋Š” ์—”๋“œํฌ์ธํŠธ์ž…๋‹ˆ๋‹ค.

์ด ์—”๋“œํฌ์ธํŠธ๋Š” oauthFetchInfo(...) ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ์ถ”์ถœํ•˜๊ณ  ๋ชจ๋“  ์ƒํƒœ ๋˜๋Š” ์ธ์ฆ ์„œ๋ฒ„์—์„œ ์ˆ˜์‹ ๋œ auth๋ฅผ ์ˆ˜์‹ ํ•˜๊ฑฐ๋‚˜ ์ €์žฅํ•˜๋„๋ก ์‹œ๋„ํ•˜๊ธฐ ์œ„ํ•ด OauthAction ๋ฉ”์„œ๋“œ๋กœ ๊ตฌํ˜„๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

state๋Š” ์•”ํ˜ธํ™”๋œ state_url์„ ๋ณตํ˜ธํ™”ํ•˜๊ณ  ์ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Looker์— ๋‹ค์‹œ POST state๋ฅผ ์ „์†กํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ์— ์‚ฌ์šฉ์ž๊ฐ€ ์ด ์ž‘์—…์„ ์š”์ฒญํ•˜๋ฉด ์ƒˆ๋กœ ์ €์žฅ๋œ ์ƒํƒœ๊ฐ€ Looker ์ž‘์—… ํ—ˆ๋ธŒ๋กœ ์ „์†ก๋ฉ๋‹ˆ๋‹ค.

Looker ์ž‘์—… ํ—ˆ๋ธŒ ์ €์žฅ์†Œ์— ์ž‘์—… ํŒŒ์ผ ์ถ”๊ฐ€

์ž‘์—… ํŒŒ์ผ์ด ์ž‘์„ฑ๋˜๋ฉด Looker ์ž‘์—… ํ—ˆ๋ธŒ ์ €์žฅ์†Œ์—์„œ ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  1. ์ž‘์—… ํŒŒ์ผ(์˜ˆ: my_action.ts)์„ actions/src/actions/index.ts์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

    import "./my_action/my_action.ts"
    
  2. ์ž‘์—…์„ ์ž‘์„ฑํ•  ๋•Œ ํ™œ์šฉํ•œ ๋ชจ๋“  Node.js ํŒจํ‚ค์ง€ ์š”๊ตฌ์‚ฌํ•ญ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    yarn add aws-sdk
    yarn add express
    
  3. Looker ์ž‘์—… ํ—ˆ๋ธŒ ์„œ๋ฒ„์˜ Node.js ์ข…์† ํ•ญ๋ชฉ์„ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.

    yarn install
    
  4. ์ž‘์„ฑํ•œ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

yarn test

์ž‘์—… ํ…Œ์ŠคํŠธ

์ „์ฒด ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด์„œ๋Š” ๋น„๊ณต๊ฐœ ์ž‘์—… ํ—ˆ๋ธŒ ์„œ๋ฒ„๋ฅผ ํ˜ธ์ŠคํŒ…ํ•˜์—ฌ Looker ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•ด ์ž‘์—…์„ ์‹œ๋„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์„œ๋ฒ„๋Š” ์œ ํšจํ•œ SSL ์ธ์ฆ์„œ๊ฐ€ ์žˆ๋Š” ๊ณต๊ฐœ ์ธํ„ฐ๋„ท์— ์žˆ์–ด์•ผ ํ•˜๋ฉฐ Looker์™€์˜ ์—ฐ๊ฒฐ ๋˜๋Š” HTTPS ์š”์ฒญ์„ ์‹œ์ž‘ํ•˜๊ณ  ์ˆ˜์‹ ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด ๋‹ค์Œ ์˜ˆ์— ํ‘œ์‹œ๋œ ๊ฒƒ์ฒ˜๋Ÿผ Heroku์™€ ๊ฐ™์€ ํด๋ผ์šฐ๋“œ ๊ธฐ๋ฐ˜ ํ”Œ๋žซํผ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜๋Š” ์•ž์—์„œ ์–ธ๊ธ‰ํ•œ ์š”๊ตฌ์‚ฌํ•ญ์„ ์ถฉ์กฑํ•˜๋Š” ํ”Œ๋žซํผ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋กœ์ปฌ ์ž‘์—… ํ—ˆ๋ธŒ ์„œ๋ฒ„ ์„ค์ •

์ด ์˜ˆ์‹œ์—์„œ๋Š” looker-open-source/actions/src/actions GitHub ์ €์žฅ์†Œ์—์„œ ๊ฐœ๋ฐœํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ์ฝ”๋“œ๋ฅผ ์ƒˆ Git ๋ธŒ๋žœ์น˜์— ์ปค๋ฐ‹ํ•ฉ๋‹ˆ๋‹ค. ์ฝ”๋“œ๋ฅผ ์‰ฝ๊ฒŒ ์ถ”์ ํ•˜๊ณ  ์›ํ•˜๋Š” ๊ฒฝ์šฐ Looker๋กœ PR์„ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋„๋ก ๋ธŒ๋žœ์น˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋Šฅ์—์„œ ์ž‘์—…ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

  1. ์‹œ์ž‘ํ•˜๋ ค๋ฉด ๋ธŒ๋žœ์น˜๋ฅผ ๋งŒ๋“  ํ›„ ์ž‘์—…์„ ์Šคํ…Œ์ด์ง•ํ•˜๊ณ  ์ปค๋ฐ‹ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    git checkout -b my-branch-name
    git add file-names
    git commit -m commit-message
    
  2. ์ด ์˜ˆ์‹œ์—์„œ๋Š” ๋ธŒ๋žœ์น˜๋ฅผ Heroku๋กœ ํ‘ธ์‹œํ•˜๋ ค๋ฉด ๋ช…๋ น์ค„์—์„œ Heroku๋ฅผ ์›๊ฒฉ ์˜ต์…˜์œผ๋กœ Git ์ €์žฅ์†Œ๋ฅผ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.

    heroku login
    heroku create
    git push heroku
    
  3. Heroku๋Š” ์ด์ œ ์‚ฌ์šฉํ•  ์ž‘์—… ํ—ˆ๋ธŒ๋ฅผ ํ˜ธ์ŠคํŒ…ํ•˜๋Š” ๊ณต๊ฐœ URL์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. URL์„ ๋ฐฉ๋ฌธํ•˜๊ฑฐ๋‚˜ heroku logs๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ์ž‘์—… ํ—ˆ๋ธŒ๊ฐ€ ์‹คํ–‰๋˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๊ณต๊ฐœ URL์„ ์žŠ์€ ๊ฒฝ์šฐ ๋ช…๋ น์ค„์—์„œ ๋‹ค์Œ์„ ์‹คํ–‰ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

    heroku info -s | grep web_url
    

    Heroku๊ฐ€ ๊ณต๊ฐœ URL์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ: https://my-heroku-action-server-1234.herokuapp.com

  4. ๋ช…๋ น์ค„์—์„œ ์ž‘์—… ํ—ˆ๋ธŒ ๊ธฐ์ค€ URL์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

    heroku config:set ACTION_HUB_BASE_URL="https://my-heroku-action-server-1234.herokuapp.com"
    
  5. ์ž‘์—… ํ—ˆ๋ธŒ ๋ผ๋ฒจ์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

    heroku config:set ACTION_HUB_LABEL="Your Action Hub"
    
  6. Looker๊ฐ€ ์Šน์ธ ํ† ํฐ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์—… ํ—ˆ๋ธŒ์— ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ๋ช…๋ น์ค„์—์„œ ํ† ํฐ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

    heroku run yarn generate-api-key
    

    ์ด ์˜ˆ์‹œ์—์„œ์™€ ๊ฐ™์ด Heroku๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ๋Œ€์‹  ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์„ธ์š”.

    yarn generate-api-key
    

    Heroku๊ฐ€ ์Šน์ธ ํ† ํฐ์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ: Authorization: Token token="abcdefg123456789"

  7. ๋ณด์•ˆ ๋น„๋ฐ€ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ž‘์—… ํ—ˆ๋ธŒ ๋ณด์•ˆ ๋น„๋ฐ€์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

    heroku config:set ACTION_HUB_SECRET="abcdefg123456789"
    

    ๊ณ ๊ฐ ํ˜ธ์ŠคํŒ… ๋ฐฐํฌ์—๋Š” ์—ฌ๊ธฐ์—์„œ ์„ค๋ช…ํ•˜์ง€ ์•Š์€ ์ถ”๊ฐ€์ ์ธ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ๊ตฌ์„ฑ์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  8. ๊ด€๋ฆฌ์ž > ์ž‘์—…์œผ๋กœ ์ด๋™ํ•˜์—ฌ ๋กœ์ปฌ Looker ์ธ์Šคํ„ด์Šค์—์„œ ์ž‘์—…์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

    • ์ž‘์—… ๋ชฉ๋ก ํ•˜๋‹จ์—์„œ ์ž‘์—… ํ—ˆ๋ธŒ ์ถ”๊ฐ€๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.
    • ์ž‘์—… ํ—ˆ๋ธŒ URL์„ ์ž…๋ ฅํ•˜๊ณ , ์„ ํƒ์ ์œผ๋กœ ๋ณด์•ˆ ๋น„๋ฐ€ ํ‚ค๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.
    • Looker์˜ ๊ด€๋ฆฌ์ž ๋ฉ”๋‰ด ์•ˆ์—์„œ ์ž‘์—… ๋ชฉ๋ก์— ์žˆ๋Š” ์ž‘์—…์„ ์ฐพ์Šต๋‹ˆ๋‹ค.
    • ์‚ฌ์šฉ ์„ค์ •์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

ํŠน์ • ์œ ํ˜•์˜ ๋ฐ์ดํ„ฐ๋ฅผ Looker์—์„œ ์ „๋‹ฌํ•ด์•ผ ํ•˜๋Š” ์ž‘์—…์˜ ๊ฒฝ์šฐ ์ ์ ˆํ•œ tags ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ํฌํ•จํ•˜๋„๋ก ๋ชจ๋ธ์„ ๊ตฌ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ ์ž‘์—…์„ ํ…Œ์ŠคํŠธํ•  ์ค€๋น„๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋Œ€์‹œ๋ณด๋“œ ์ˆ˜์ค€ ๋ฐ ์ฟผ๋ฆฌ ์ˆ˜์ค€ ์ž‘์—… ํ…Œ์ŠคํŠธ

ํ•„์š”ํ•œ ๊ฒฝ์šฐ Looker ์ธ์Šคํ„ด์Šค์—์„œ ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ LookML ๋ชจ๋ธ์„ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. Look์„ ๋งŒ๋“ค๊ณ  ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์ €์žฅ๋œ Look์—์„œ ์˜ค๋ฅธ์ชฝ ์ƒ๋‹จ ๋ฉ”๋‰ด๋ฅผ ํด๋ฆญํ•˜๊ณ  ์ž‘์—…์„ ๋Œ€์ƒ์œผ๋กœ ์ง€์ •ํ•˜๊ณ  ์ „์†ก์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค. ์ „์†กํ•  ์–‘์‹์ด ์žˆ์œผ๋ฉด Looker๊ฐ€ ์ „์†ก ์ฐฝ์— ์ด๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

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

์…€ ์ˆ˜์ค€ ์ž‘์—… ํ…Œ์ŠคํŠธ

์ž‘์—…์— ์ ํ•ฉํ•œ ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•ด์„œ LookML ํ•„๋“œ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. Looker ์ธ์Šคํ„ด์Šค์—์„œ ์ด ํ•„๋“œ๊ฐ€ ํฌํ•จ๋œ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ํ…Œ์ด๋ธ”์—์„œ ํ•„๋“œ๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค. ์…€์—์„œ โ€ฆ์„ ํด๋ฆญํ•˜๊ณ  ๋“œ๋กญ๋‹ค์šด ๋ฉ”๋‰ด์—์„œ ์ „์†ก์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค. ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์˜ค๋ฅ˜๋ฅผ ํ•ด๊ฒฐํ•œ ํ›„ ๋ฐ์ดํ„ฐ ํ…Œ์ด๋ธ”์„ ์ „์ฒด ์ƒˆ๋กœ๊ณ ์นจํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ปค์Šคํ…€ ์ž‘์—… ๊ฒŒ์‹œ ๋ฐ ์‚ฌ์šฉ ์„ค์ •

์ปค์Šคํ…€ ์ž‘์—…์—๋Š” ๋‘ ๊ฐ€์ง€ ๊ฒŒ์‹œ ์˜ต์…˜์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ž‘์—…์ด ๊ฒŒ์‹œ๋˜์—ˆ์œผ๋ฉด ๊ด€๋ฆฌ์ž ํŒจ๋„์˜ ์ž‘์—… ํŽ˜์ด์ง€์—์„œ ์ž‘์—…์„ ์‚ฌ์šฉ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Looker ์ž‘์—… ํ—ˆ๋ธŒ์— ๊ฒŒ์‹œ

์ด ์ ‘๊ทผ ๋ฐฉ๋ฒ•์€ ๊ฐ€์žฅ ์‰ฌ์šด ๋ฐฉ๋ฒ•์ด๊ณ , Looker๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ์ œ๊ณตํ•˜๋ ค๋Š” ์ž‘์—…์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ž‘์—…์ด ํ…Œ์ŠคํŠธ๋˜์—ˆ์œผ๋ฉด GitHub์—์„œ looker-open-source/actions ์ €์žฅ์†Œ์— PR์„ ์ œ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.

    git push <your fork> <your development branch>
    
  2. looker-open-source/actions ์ €์žฅ์†Œ๋ฅผ ๋Œ€์ƒ์œผ๋กœ ์‚ฌ์šฉํ•ด์„œ pull ์š”์ฒญ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

  3. Looker Marketplace ๋ฐ ์ž‘์—… ํ—ˆ๋ธŒ ์ œ์ถœ ์–‘์‹์„ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. ์–‘์‹ ์š”๊ตฌ์‚ฌํ•ญ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ Looker Marketplace์— ์ฝ˜ํ…์ธ  ์ œ์ถœ์„ ์ฐธ์กฐํ•˜์„ธ์š”.

    Looker๊ฐ€ ์ž‘์—… ์ฝ”๋“œ๋ฅผ ๊ฒ€ํ† ํ•ฉ๋‹ˆ๋‹ค. Google์€ PR์„ ๊ฑฐ๋ถ€ํ•  ๊ถŒ๋ฆฌ๋ฅผ ๋ณด์œ ํ•˜์ง€๋งŒ ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์ด๋ฅผ ์ง€์›ํ•˜๊ณ  ๊ฐœ์„ ํ•˜๋Š” ์ œ์•ˆ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ํ›„ ์ฝ”๋“œ๋ฅผ looker-open-source/actions ์ €์žฅ์†Œ์— ๋ณ‘ํ•ฉํ•˜๊ณ  actions.looker.com์— ๋ฐฐํฌํ•ฉ๋‹ˆ๋‹ค. ์ฝ”๋“œ๊ฐ€ ๋ฐฐํฌ๋˜์—ˆ์œผ๋ฉด ๋ชจ๋“  Looker ๊ณ ๊ฐ๋“ค์—๊ฒŒ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

  4. Looker ์ธ์Šคํ„ด์Šค์—์„œ ์ž‘์—…์„ ์‚ฌ์šฉ ์„ค์ •ํ•˜๋ฉด ๋ฐ์ดํ„ฐ ์ „์†ก ์˜ต์…˜์œผ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

๋น„๊ณต๊ฐœ ์ž‘์—… ํ—ˆ๋ธŒ ์„œ๋ฒ„์— ๊ฒŒ์‹œ

ํšŒ์‚ฌ ๋˜๋Š” ์‚ฌ์šฉ ์‚ฌ๋ก€์— ๋”ฐ๋ผ ๋น„๊ณต๊ฐœ์ธ ์ปค์Šคํ…€ ์ž‘์—…์ด ์žˆ์„ ๋•Œ๋Š” ์ด๋Ÿฌํ•œ ์ž‘์—…์„ looker-open-source/actions ์ €์žฅ์†Œ์— ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋Œ€์‹  ์ž‘์—… ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด ์‚ฌ์šฉํ•œ ๊ฒƒ๊ณผ ๋™์ผํ•œ Node.js ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋น„๊ณต๊ฐœ ์ž‘์—… ํ—ˆ๋ธŒ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

์ž์ฒด ์ธํ”„๋ผ์—์„œ ๋˜๋Š” ํด๋ผ์šฐ๋“œ ๊ธฐ๋ฐ˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”Œ๋žซํผ(์˜ˆ์‹œ์—์„œ ์‚ฌ์šฉํ•œ Heroku)์„ ์‚ฌ์šฉํ•˜์—ฌ ๋‚ด๋ถ€ ์ž‘์—… ํ—ˆ๋ธŒ ์„œ๋ฒ„๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐฐํฌ ์ „ ๋น„๊ณต๊ฐœ ์ž‘์—… ํ—ˆ๋ธŒ ์„œ๋ฒ„์— Looker ์ž‘์—… ํ—ˆ๋ธŒ๋ฅผ ํฌํฌํ•˜๋Š” ๊ฒƒ์„ ์žŠ์ง€ ๋งˆ์„ธ์š”.

์ž‘์—…์— ์‚ฌ์šฉํ•  LookML ๋ชจ๋ธ ๊ตฌ์„ฑ

Looker ์ž‘์—… ํ—ˆ๋ธŒ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ปค์Šคํ…€ ์ž‘์—…๊ณผ ์ž‘์—… ๋ชจ๋‘ LookML ๋ชจ๋ธ์˜ tags ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ด€๋ จ ๋ฐ์ดํ„ฐ ํ•„๋“œ๋ฅผ ์‹๋ณ„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ด€๋ฆฌ ํŒจ๋„์˜ ์ž‘์—… ํŽ˜์ด์ง€์—์„œ ์„œ๋น„์Šค์— ํ•„์š”ํ•œ ํƒœ๊ทธ(์žˆ๋Š” ๊ฒฝ์šฐ)์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด Twilio ๋ฉ”์‹œ์ง€ ์ „์†ก ํ†ตํ•ฉ์€ ์ „ํ™” ๋ฒˆํ˜ธ ๋ชฉ๋ก์— ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•ฉ๋‹ˆ๋‹ค. ๊ด€๋ฆฌ์ž ํŒจ๋„์˜ ์ž‘์—… ํŒจ๋„์—์„œ ์ด ํ†ตํ•ฉ์—๋Š” "phone ํƒœ๊ทธ ์ง€์ • ํ•„๋“œ๊ฐ€ ์žˆ๋Š” ์ฟผ๋ฆฌ์— ์ž‘์—… ์‚ฌ์šฉ ๊ฐ€๋Šฅ" ๋ฌธ๊ตฌ๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

์ฆ‰, Twilio ๋ฉ”์‹œ์ง€ ์ „์†ก ์„œ๋น„์Šค์—๋Š” ์ „ํ™” ๋ฒˆํ˜ธ ํ•„๋“œ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๊ณ  tags ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ „ํ™” ๋ฒˆํ˜ธ๊ฐ€ ํฌํ•จ๋œ ์ฟผ๋ฆฌ์˜ ํ•„๋“œ ์‹๋ณ„ํ•˜๋Š” ์ฟผ๋ฆฌ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ํ•ด๋‹น ํ•„๋“œ์— tags: ["phone"]์„ ์ง€์ •ํ•˜์—ฌ LookML์—์„œ ์ „ํ™”๋ฒˆํ˜ธ ํ•„๋“œ๋ฅผ ์‹๋ณ„ํ•ฉ๋‹ˆ๋‹ค. ์ „ํ™” ๋ฒˆํ˜ธ ํ•„๋“œ์— ๋Œ€ํ•œ LookML์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ‘œ์‹œ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

dimension: phone {
  tags: ["phone"]
  type: string
  sql: ${TABLE}.phone ;;
}

ํƒœ๊ทธ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์€ ํ†ตํ•ฉ์—๋Š” ๊ด€๋ฆฌ ํŒจ๋„์˜ ์ž‘์—… ํŽ˜์ด์ง€์— '๋ชจ๋“  ์ฟผ๋ฆฌ์— ์ž‘์—…์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค'๋ผ๋Š” ํ•˜์œ„ ํ…์ŠคํŠธ๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž๊ฐ€ ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•  ์ˆ˜ ์žˆ๋„๋ก tags ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ LookML ๋ชจ๋ธ์˜ ํ•„์ˆ˜ ํ•„๋“œ๋ฅผ ์‹๋ณ„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ๋‹จ๊ณ„

Look ๋˜๋Š” Explore ๋˜๋Š” ๋Œ€์‹œ๋ณด๋“œ์˜ ์ฝ˜ํ…์ธ ๋ฅผ ํ†ตํ•ฉ ์„œ๋น„์Šค์— ์ „์†กํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ด…๋‹ˆ๋‹ค.