Search
๐Ÿ“š

EP26. Supabase Edge Functions Batch

์ƒ์„ฑ์ผ
2024/06/30 12:58
๋งˆ์ง€๋ง‰ ์—…๋ฐ์ดํŠธ

EP26. Supabase Edge Functions Batch

1. ๋ฐฐ์น˜ ์ž‘์—…์ด๋ž€

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

2. Supabase Edge Functions์—์„œ์˜ ๋ฐฐ์น˜

์•„์‰ฝ๊ฒŒ๋„(?) Supbase Edge Functions์—์„œ ์ž์ฒด์ ์œผ๋กœ ๋ฐฐ์น˜ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค๋งŒ. PostgreSQL ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ํ™œ์šฉํ•ด ๋ฐฐ์น˜ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
โ€ข
pg_cron: ์ฃผ๊ธฐ์ ์œผ๋กœ PostgreSQL ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค
โ€ข
pg_net: PostgreSQL์—์„œ ๋„คํŠธ์›Œํฌ ์š”์ฒญ์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.
โ€ข
Edge functions: ์ฃผ๊ธฐ์ ์œผ๋กœ ์‹คํ–‰ํ•  ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
์œ„ 3๊ฐ€์ง€ ๊ธฐ๋Šฅ์„ ์กฐํ•ฉํ•˜๋ฉด?
์ฃผ๊ธฐ์ ์œผ๋กœ ํ˜ธ์ถœํ•˜๋Š” PostgreSQL์—์„œ Edge Functions๋กœ ๋„คํŠธ์›Œํฌ ์š”์ฒญ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋‹ค โ‡’ Edge Functions ํ•จ์ˆ˜๋ฅผ ์ฃผ๊ธฐ์ ์œผ๋กœ ์‹คํ–‰์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค ๏ธ

3. ๋ฐฐ์น˜ function ์ถ”๊ฐ€

supabase functions new batch
Bash
๋ณต์‚ฌ
batch๋ผ๋Š” ์ด๋ฆ„์˜ functions๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
์•ž์œผ๋กœ ๋ฐฐ์น˜ ์ž‘์—…์ด ํ•„์š”ํ•œ ๋‚ด์šฉ๋“ค์€ batch function ๋‚ด์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
supabase/functions/batch ๋””๋ ‰ํ† ๋ฆฌ๊ฐ€ ์ƒ์„ฑ๋˜๋ฉฐ ๊ธฐ๋ณธ index.ts ํŒŒ์ผ๋„ ํ•จ๊ป˜ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.
index.ts ํŒŒ์ผ์„ ์ˆ˜์ •ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
import { Hono } from "https://deno.land/x/hono/mod.ts"; import { enqueuePushNotification } from "../push/enqueuePushNotification.ts"; // Hono ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. const app = new Hono(); // ์Šค์ผ€์ค„ ์ž‘์—…์„ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค. ์ž‘์—…์€ endpoint๋กœ ๊ตฌ๋ถ„๋ฉ๋‹ˆ๋‹ค. app.get("/job-a", async (c) => { // TODO: ๋ฐฐ์น˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ์‹œ) ํ‘ธ์‹œ ์•Œ๋ฆผ ๋ฐœ์†ก await enqueuePushNotification({ userId: "", title: "๋ฐฐ์น˜์ž‘์—…", body: "job-a", }); return c.json("ok"); }); app.get("/job-b", async (c) => { // TODO: ๋ฐฐ์น˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ์‹œ) ํ‘ธ์‹œ ์•Œ๋ฆผ ๋ฐœ์†ก await enqueuePushNotification({ userId: "", title: "๋ฐฐ์น˜์ž‘์—…", body: "job-b", }); return c.json("ok"); }); // ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹œ์ž‘ํ•˜์—ฌ ์š”์ฒญ์„ ์ˆ˜์‹ ํ•ฉ๋‹ˆ๋‹ค. Deno.serve(app.fetch);
TypeScript
๋ณต์‚ฌ
index.ts์—๋Š” ๋‹ค์–‘ํ•œ ๋ฐฐ์น˜์ž‘์—…์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ž‘์—…์€ endpoint๋กœ ๊ตฌ๋ถ„ํ•ฉ๋‹ˆ๋‹ค. ์ถ”ํ›„ postgreSQL์—์„œ ์ฃผ๊ธฐ์ ์œผ๋กœ ์œ„ endpoint๋กœ API๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ž‘์—…์ด ์ˆ˜ํ–‰๋˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
์˜ˆ์‹œ๋กœ ์ด์ „ ๊ฐ•์˜์—์„œ ๊ตฌํ˜„ํ–ˆ๋˜ ํ‘ธ์‹œ ์•Œ๋ฆผ ๊ธฐ๋Šฅ์„ ์ด์šฉํ•ด ์ฃผ๊ธฐ์ ์œผ๋กœ ํ‘ธ์‹œ์•Œ๋ฆผ์„ ๋ฐœ์†กํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
userId์—๋Š” ํ‘ธ์‹œ ์ˆ˜์‹ ํ•  ์œ ์ €์˜ userId๋กœ ๋ณ€๊ฒฝํ•ด์„œ ์‚ฌ์šฉํ•ด์ฃผ์„ธ์š”.

4. Batch ํ•จ์ˆ˜ ๋ฐฐํฌ

bash deploy.sh
TypeScript
๋ณต์‚ฌ
๋ฐฐํฌ ์Šคํฌ๋ฆฝํŠธ๋กœ batch function ์„ ๋ฐฐํฌํ•ฉ๋‹ˆ๋‹ค.
supabase ์ฝ˜์†”์—์„œ ๋ฐฐํฌ๋œ ํ•จ์ˆ˜ ์ •๋ณด๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

5. pg_net extension ์„ค์ •

4๋ฒˆ ๊ณผ์ •์—์„œ 2๊ฐœ์˜ ๋ฐฐ์น˜์ž‘์—…์„ ์ƒ์„ฑํ–ˆ์œผ๋ฉฐ ๊ฐ๊ฐ์˜ ์ž‘์—…์€ API ํ˜ธ์ถœ์„ ํ†ตํ•ด ์‹คํ–‰์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.