Supabase๋Š” PostgreSQL ๊ธฐ๋ฐ˜์˜ ์˜คํ”ˆ์†Œ์Šค Backend-as-a-Service(BaaS) ํ”Œ๋žซํผ์œผ๋กœ, AWS ๋˜๋Š” ๊ตฌ๊ธ€ Firebase์™€ ํ•จ๊ป˜ ํ˜„๋Œ€์ ์ธ ๋ฐฑ์—”๋“œ ์†”๋ฃจ์…˜์œผ๋กœ ์ฃผ๋ชฉ๋ฐ›๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ ๋ฌด๋ฃŒ ํ”Œ๋žœ์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ด€๋Œ€ํ•œ ๋ฆฌ์†Œ์Šค ๋•๋ถ„์— ๊ฐœ์ธ ํ”„๋กœ์ ํŠธ, ์Šคํƒ€ํŠธ์—…, ํ”„๋กœํ† ํƒ€์ž… ๊ฐœ๋ฐœ์— ๋„๋ฆฌ ํ™œ์šฉ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋ฌด๋ฃŒ ํ”Œ๋žœ ์‚ฌ์šฉ์ž๋“ค์€ ํ•˜๋‚˜์˜ ์ œ์•ฝ์‚ฌํ•ญ์„ ๋งˆ์ฃผํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. 7์ผ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ™œ๋™์ด ์—†์œผ๋ฉด ํ”„๋กœ์ ํŠธ๊ฐ€ ์ž๋™์œผ๋กœ ์ผ์‹œ์ •์ง€๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” Supabase๊ฐ€ ์„œ๋ฒ„ ๋ฆฌ์†Œ์Šค๋ฅผ ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์ •๋‹นํ•œ ์ •์ฑ…์ด์ง€๋งŒ, ์ •๊ธฐ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์‚ฌ์ด๋“œ ํ”„๋กœ์ ํŠธ๋‚˜ ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์„ ์šด์˜ํ•˜๋Š” ๊ฐœ๋ฐœ์ž์—๊ฒŒ๋Š” ๋ถˆํŽธํ•จ์„ ์•ผ๊ธฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ๋•Œ๋ฌธ์— ์ž๋™ ํ™œ์„ฑํ™”๋Š” 7์ผ ๋น„ํ™œ์„ฑํ™” ์ •์ฑ…์œผ๋กœ ์ธํ•œ ํ”„๋กœ์ ํŠธ ์ค‘๋‹จ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ํ•„์ˆ˜์ ์ž…๋‹ˆ๋‹ค.. ์„ฑ์žฅํ•ด์„œ ์‚ฌ์šฉ์ž๊ฐ€ ์ƒ์ฃผํ•˜๊ธฐ ์ „๊นŒ์ง€๋Š”์š” ใ…œใ…œ.

Supabase ๋ฌด๋ฃŒ ํ”Œ๋žœ์˜ ์ดํ•ด

์ •ํ™•ํžˆ ์–ด๋–ค ์ œ์•ฝ์ด ์žˆ๋Š”์ง€

Supabase ๋ฌด๋ฃŒ ํ”Œ๋žœ์€ ๊ฐœ๋ฐœ์ž๋“ค์—๊ฒŒ ์ƒ๋‹นํžˆ ๊ด€๋Œ€ํ•œ ๋ฆฌ์†Œ์Šค๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ํ”„๋กœ์ ํŠธ ๊ณ„ํš ์‹œ ๊ณ ๋ คํ•ด์•ผ ํ•  ์ œ์•ฝ์‚ฌํ•ญ๋“ค์ด ์žˆ์Šต๋‹ˆ๋‹ค:

์Šคํ† ๋ฆฌ์ง€ & ๋ฆฌ์†Œ์Šค

  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค: 500MB
  • ํŒŒ์ผ ์Šคํ† ๋ฆฌ์ง€: 1GB
  • ๋Œ€์—ญํญ: 5GB/์›”
  • Edge Functions: 500,000 ํ˜ธ์ถœ/์›”

๊ทธ๋ฆฌ๊ณ  ์ฃผ๋ชฉํ•ด์•ผ ํ•  ์ •์ฑ…:

  • 7์ผ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ™œ๋™์ด ์—†์œผ๋ฉด ํ”„๋กœ์ ํŠธ ์ž๋™ ์ผ์‹œ์ •์ง€
  • ์ผ์‹œ์ •์ง€๋œ ํ”„๋กœ์ ํŠธ๋Š” ๋Œ€์‹œ๋ณด๋“œ์—์„œ ์ˆ˜๋™์œผ๋กœ ์žฌํ™œ์„ฑํ™” ํ•„์š”
  • 14์ผ ๋™์•ˆ ์ผ์‹œ์ •์ง€ ์ƒํƒœ๊ฐ€ ์ง€์†๋˜๋ฉด ํ”„๋กœ์ ํŠธ ์‚ญ์ œ ๊ฐ€๋Šฅ์„ฑ

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

์™œ ์ด๋Ÿฐ ์ •์ฑ…์ด ์กด์žฌํ•˜๋Š”๊ฐ€?

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

๋‹ค๋ฅธ ๋Œ€์•ˆ๊ณผ ๋น„๊ต

๊ธฐ๋ŠฅSupabase ๋ฌด๋ฃŒFirebase SparkAWS Free Tier
๋ฐ์ดํ„ฐ๋ฒ ์ด์ŠคPostgreSQL 500MBFirestore 1GBDynamoDB 25GB
๋น„ํ™œ์„ฑํ™” ์ •์ฑ…7์ผ ๋ฏธ์‚ฌ์šฉ์‹œ ์ •์ง€์—†์Œ12๊ฐœ์›” ํ›„ ์ข…๋ฃŒ
Auth๋ฌด์ œํ•œ ์‚ฌ์šฉ์ž๋ฌด์ œํ•œCognito 50,000 MAU
Storage1GB5GBS3 5GB (12๊ฐœ์›”)
์‹ค์‹œ๊ฐ„ ๊ธฐ๋Šฅโœ…โœ…โŒ (์ถ”๊ฐ€ ๋น„์šฉ)
SQL ์ง€์›โœ… (PostgreSQL)โŒ (NoSQL)๋ถ€๋ถ„์ 
์ž์ฒด ํ˜ธ์ŠคํŒ…โœ…โŒโŒ

Firebase์˜ ์žฅ์ :

  • ๋น„ํ™œ์„ฑํ™” ์ •์ฑ…์ด ์—†์Œ (์ด๊ฒŒ ์ œ์ผ ํฌ๋‹ค!)
  • Google ์ƒํƒœ๊ณ„์™€์˜ ์™„๋ฒฝํ•œ ํ†ตํ•ฉ
  • ๋” ์„ฑ์ˆ™ํ•œ ๋ฌธ์„œ์™€ ์ปค๋ฎค๋‹ˆํ‹ฐ

Firebase์˜ ๋‹จ์ :

  • NoSQL๋งŒ ์ง€์› (๋ณต์žกํ•œ ์ฟผ๋ฆฌ๊ฐ€ ์–ด๋ ค์›€)
  • ๋ฐฑ์—”๋“œ ๋กœ์ง์ด ๋ณต์žกํ•ด์ง€๋ฉด Cloud Functions ๋น„์šฉ ํญํƒ„
  • vendor lock-in์ด ์‹ฌํ•จ

AWS์˜ ์žฅ์ :

  • ๊ฐ€์žฅ ๊ฐ•๋ ฅํ•˜๊ณ  ์œ ์—ฐํ•จ
  • ํ”„๋กœ๋•์…˜ ๋ ˆ๋ฒจ ์ธํ”„๋ผ
  • ์„ธ๋ฐ€ํ•œ ๋น„์šฉ ์ œ์–ด

AWS์˜ ๋‹จ์ :

  • ๋Ÿฌ๋‹ ์ปค๋ธŒ๊ฐ€ ๊ฐ€ํŒŒ๋ฆ„ (์„ค์ •๋งŒ ํ•˜๋ฃจ ๊ฑธ๋ฆผโ€ฆ)
  • ๋ฌด๋ฃŒ ํ‹ฐ์–ด๊ฐ€ 12๊ฐœ์›” ์ œํ•œ
  • ์‹ค์ˆ˜๋กœ ๊ณผ๊ธˆ๋  ์œ„ํ—˜์„ฑ

์™œ Supabase๋ฅผ ์„ ํƒํ–ˆ๋Š”์ง€

1. ๋น ๋ฅธ ํ”„๋กœํ† ํƒ€์ดํ•‘

  • API ์ž๋™ ์ƒ์„ฑ (ํ…Œ์ด๋ธ” ๋งŒ๋“ค๋ฉด REST API ์ฆ‰์‹œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ)
  • ์‹ค์‹œ๊ฐ„ ๊ธฐ๋Šฅ ๋‚ด์žฅ (์ฑ„ํŒ…, ์•Œ๋ฆผ ๊ตฌํ˜„์ด ์‰ฌ์›€)
  • Row Level Security๋กœ ๊ฐ„๋‹จํ•œ ๊ถŒํ•œ ๊ด€๋ฆฌ

2. ์˜คํ”ˆ์†Œ์Šค

  • ์–ธ์  ๊ฐ€ ํŠธ๋ž˜ํ”ฝ์ด ํ„ฐ์ง€๋ฉด ์ง์ ‘ ํ˜ธ์ŠคํŒ… ๊ฐ€๋Šฅ
  • vendor lock-in ํšŒํ”ผ
  • ์ปค๋ฎค๋‹ˆํ‹ฐ๊ฐ€ ํ™œ๋ฐœํ•˜๊ณ  ํˆฌ๋ช…ํ•จ

3. ๊ฐœ๋ฐœ์ž ๊ฒฝํ—˜

// ์ด๊ฒŒ ์ „๋ถ€๋‹ค. ์ง„์งœ๋กœ.
const { data } = await supabase.from("posts").select("*").eq("user_id", userId);

๋ณต์žกํ•œ ์„ค์ • ์—†์ด ๋ฐ”๋กœ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒŒ ๊ฐ€์žฅ ํฐ ๋งค๋ ฅ์ž…๋‹ˆ๋‹ค.

๊ฒฐ๋ก ์ ์œผ๋กœ:

  • ๋น ๋ฅด๊ฒŒ ํ”„๋กœํ† ํƒ€์ž… ๋งŒ๋“ค๊ณ  ์‹ถ๋‹ค โ†’ Supabase
  • ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ๊ด€๊ณ„๊ฐ€ ์žˆ๋‹ค โ†’ Supabase
  • ๋น„ํ™œ์„ฑํ™” ์ •์ฑ…์ด ์‹ซ๋‹ค โ†’ Firebase (ํ•˜์ง€๋งŒ ์ด์ œ SupabaseZombi๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค!)
  • ํ”„๋กœ๋•์…˜ ๋ ˆ๋ฒจ ํ™•์žฅ์„ฑ์ด ํ•„์š”ํ•˜๋‹ค โ†’ AWS (๋˜๋Š” Supabase Pro)

7์ผ ๋น„ํ™œ์„ฑํ™” ์ •์ฑ…์„ ํšจ๊ณผ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์ž๋™ํ™” ์†”๋ฃจ์…˜์ด ํ•„์š”ํ–ˆ๊ณ , ์ด๊ฒƒ์ด SupabaseZombi ํ”„๋กœ์ ํŠธ์˜ ์‹œ์ž‘์ ์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ “keep-alive”๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ์กด์žฌํ•˜๋Š” ์—ฌ๋Ÿฌ ํ”„๋กœ์ ํŠธ๋“ค์„ ์ฐธ๊ณ ํ•˜์—ฌ, ๋”์šฑ ๊ฐœ์„ ๋œ ์†”๋ฃจ์…˜์„ ๋งŒ๋“ค๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ์ˆ ์  ํ•ด๊ฒฐ ๋ฐฉ์•ˆ ๋ชจ์ƒ‰

๊ธฐ์กด ์˜คํ”ˆ์†Œ์Šค ์†”๋ฃจ์…˜ ๋ถ„์„

๊ฐœ๋ฐœ์ž ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ๋Š” ์ด๋ฏธ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ์—ฌ๋Ÿฌ ์˜คํ”ˆ์†Œ์Šค ํ”„๋กœ์ ํŠธ๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. GitHub์—์„œ ์ฐพ์€ supabase-inactive-fix๋Š” ์ •๊ธฐ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ํ™œ๋™์„ ๋ฐœ์ƒ์‹œ์ผœ ํ”„๋กœ์ ํŠธ๋ฅผ ํ™œ์„ฑ ์ƒํƒœ๋กœ ์œ ์ง€ํ•˜๋Š” ํ›Œ๋ฅญํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์ด์—ˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์‹ค์ œ ์‚ฌ์šฉํ•˜๋ฉด์„œ ๋ช‡ ๊ฐ€์ง€ ๊ฐœ์„  ํฌ์ธํŠธ๋ฅผ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค:

  • ํŒจํ„ด์˜ ๋‹ค์–‘์„ฑ: ๋งค๋ฒˆ ๋™์ผํ•œ ๊ฐœ์ˆ˜์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฝ์ž…ํ•˜๋Š” ๊ณ ์ • ํŒจํ„ด
  • ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ: ์ง€์†์ ์œผ๋กœ ๋ˆ„์ ๋˜๋Š” ๋”๋ฏธ ๋ฐ์ดํ„ฐ์˜ ๊ด€๋ฆฌ ๋ฐฉ์•ˆ ๋ถ€์žฌ
  • ๋ฐฐํฌ ๋ณต์žก๋„: Docker ์ด๋ฏธ์ง€ ๋นŒ๋“œ ๊ณผ์ •์˜ ๋ณต์žก์„ฑ
  • ๋ชจ๋‹ˆํ„ฐ๋ง: ์‹คํ–‰ ๊ฒฐ๊ณผ์™€ ์ƒํƒœ์— ๋Œ€ํ•œ ์‹ค์‹œ๊ฐ„ ํ”ผ๋“œ๋ฐฑ ๋ถ€์กฑ

SupabaseZombi ํ”„๋กœ์ ํŠธ ์†Œ๊ฐœ

์ด๋Ÿฌํ•œ ๊ฐœ์„ ์ ์„ ๋ฐ˜์˜ํ•˜์—ฌ SupabaseZombi๋ผ๋Š” ์˜คํ”ˆ์†Œ์Šค ํ”„๋กœ์ ํŠธ๋ฅผ ๊ฐœ๋ฐœํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ํ”„๋กœ์ ํŠธ๋Š” Supabase์˜ ์ •์ฑ…์„ ์กด์ค‘ํ•˜๋ฉด์„œ๋„, ๊ฐœ๋ฐœ์ž๊ฐ€ ํ”„๋กœ์ ํŠธ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์ž๋™ํ™” ์†”๋ฃจ์…˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

ํ”„๋กœ์ ํŠธ๋ช…์˜ ์˜๋ฏธ: “Zombie(์ข€๋น„)”๋Š” ๊ณ„์†ํ•ด์„œ ํ™œ๋™ํ•˜๋Š” ํŠน์„ฑ์„ ์€์œ ์ ์œผ๋กœ ํ‘œํ˜„ํ•œ ๊ฒƒ์œผ๋กœ, ํ”„๋กœ์ ํŠธ๊ฐ€ ์ง€์†์ ์œผ๋กœ ํ™œ์„ฑ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•œ๋‹ค๋Š” ์˜๋ฏธ๋ฅผ ๋‹ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•ต์‹ฌ ๊ธฐ์ˆ  ๊ตฌํ˜„

1. ๋™์  ๋ฐ์ดํ„ฐ ์ƒ์„ฑ ์ „๋žต

# 1. ๊ฐ€๋ณ€์  ๋ฐ์ดํ„ฐ ์‚ฝ์ž… (1~10๊ฐœ)
insert_count = random.randint(1, 10)

# 2. ์ž„๊ณ„๊ฐ’ ์ดˆ๊ณผ ์‹œ ์ž๋™ ์ •๋ฆฌ (50๊ฐœ ์ดˆ๊ณผ โ†’ 30๊ฐœ ์œ ์ง€)
if current_count > 50:
    delete_count = current_count - 30
    # ์˜ค๋ž˜๋œ ๋ฐ์ดํ„ฐ๋ถ€ํ„ฐ ์‚ญ์ œ

๋žœ๋ค ์‚ฝ์ž… ๊ฐœ์ˆ˜์˜ ์ด์ :

  • ๊ณ ์ • ํŒจํ„ด ๋Œ€๋น„ ๋”์šฑ ์ž์—ฐ์Šค๋Ÿฌ์šด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ™œ๋™ ์‹œ๋ฎฌ๋ ˆ์ด์…˜
  • ํŠธ๋ž˜ํ”ฝ ํŒจํ„ด์ด ๋‹ค์–‘ํ•˜์—ฌ ์‹œ์Šคํ…œ ํ…Œ์ŠคํŠธ์—๋„ ์œ ์šฉ

์ž๋™ ๋ฐ์ดํ„ฐ ์ •๋ฆฌ์˜ ํ•„์š”์„ฑ:

  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ณต๊ฐ„ ํšจ์œจ์„ฑ ์œ ์ง€ (๋ฌด๋ฃŒ ํ”Œ๋žœ์€ 500MB ์ œํ•œ)
  • Keep-Alive ๋ชฉ์ ์˜ ์ž„์‹œ ๋ฐ์ดํ„ฐ์ด๋ฏ€๋กœ ์žฅ๊ธฐ ๋ณด๊ด€ ๋ถˆํ•„์š”
  • ์ผ์ • ์ˆ˜๋Ÿ‰ ์œ ์ง€๋กœ ์ฟผ๋ฆฌ ์„ฑ๋Šฅ ์ตœ์ ํ™”

2. ์Šค์ผ€์ค„๋ง ์‹œ์Šคํ…œ

import schedule
import time

def keep_alive_job():
    """์ •๊ธฐ์ ์ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ™œ๋™ ์ƒ์„ฑ"""
    # Supabase์— ๋ฐ์ดํ„ฐ ์‚ฝ์ž…
    insert_random_data()
    # ์ž„๊ณ„๊ฐ’ ์ดˆ๊ณผ ์‹œ ์˜ค๋ž˜๋œ ๋ฐ์ดํ„ฐ ์ •๋ฆฌ
    cleanup_old_data()

# 24์‹œ๊ฐ„ ์ฃผ๊ธฐ ์‹คํ–‰ (7์ผ ์ •์ฑ… ๋Œ€๋น„ ์ถฉ๋ถ„ํ•œ ์—ฌ์œ )
schedule.every(24).hours.do(keep_alive_job)

while True:
    schedule.run_pending()
    time.sleep(60)  # 1๋ถ„๋งˆ๋‹ค ์Šค์ผ€์ค„ ํ™•์ธ

24์‹œ๊ฐ„ ์ฃผ๊ธฐ๋Š” 7์ผ ์ •์ฑ…์„ ์ค€์ˆ˜ํ•˜๋ฉด์„œ๋„ ์ถฉ๋ถ„ํ•œ ์•ˆ์ „ ๋งˆ์ง„์„ ํ™•๋ณดํ•˜๋Š” ์ตœ์ ์˜ ๊ฐ„๊ฒฉ์ž…๋‹ˆ๋‹ค. ๋” ์งง์€ ๊ฐ„๊ฒฉ์€ ๋ถˆํ•„์š”ํ•œ ๋ฆฌ์†Œ์Šค ์‚ฌ์šฉ์„ ์ดˆ๋ž˜ํ•˜๋ฉฐ, Supabase์˜ ์ •์ฑ… ์˜๋„์—๋„ ๋ถ€ํ•ฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ ๊ณผ์ •์—์„œ์˜ ๊ธฐ์ˆ ์  ์˜์‚ฌ๊ฒฐ์ •

1. ๊ตฌ์„ฑ ๊ด€๋ฆฌ ๋ฐฉ์‹: ํ™˜๊ฒฝ๋ณ€์ˆ˜ vs ์„ค์ •ํŒŒ์ผ

์ดˆ๊ธฐ์—๋Š” ๋ชจ๋“  ๊ตฌ์„ฑ์„ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ ๊ด€๋ฆฌํ•˜๋Š” ์ „ํ†ต์ ์ธ ๋ฐฉ์‹์„ ์ฑ„ํƒํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์—ฌ๋Ÿฌ Supabase ํ”„๋กœ์ ํŠธ๋ฅผ ๋™์‹œ์— ๊ด€๋ฆฌํ•ด์•ผ ํ•˜๋Š” ์š”๊ตฌ์‚ฌํ•ญ์ด ๋ฐœ์ƒํ•˜๋ฉด์„œ ๊ตฌ์กฐ์  ํ•œ๊ณ„์— ์ง๋ฉดํ–ˆ์Šต๋‹ˆ๋‹ค.

Before:

SUPABASE_URL_1=...
SUPABASE_KEY_1=...
SUPABASE_URL_2=...
SUPABASE_KEY_2=...

๊ฐœ์„ ๋œ JSON ๊ธฐ๋ฐ˜ ๊ตฌ์„ฑ:

[
  {
    "name": "ํ”„๋กœ์ ํŠธ1",
    "supabase_url": "https://xxx.supabase.co",
    "supabase_key": "your-key",
    "table_name": "keep-alive"
  },
  {
    "name": "ํ”„๋กœ์ ํŠธ2",
    "supabase_url": "https://yyy.supabase.co",
    "supabase_key_env": "SUPABASE_KEY_2", // ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์ฐธ์กฐ๋„ ์ง€์›
    "table_name": "keep-alive"
  }
]

JSON ๊ธฐ๋ฐ˜ ๊ตฌ์„ฑ์˜ ์žฅ์ :

  • ํ™•์žฅ์„ฑ: ๋ฌด์ œํ•œ ํ”„๋กœ์ ํŠธ ์ถ”๊ฐ€ ๊ฐ€๋Šฅ
  • ๊ฐ€๋…์„ฑ: ๊ตฌ์กฐํ™”๋œ ํ˜•์‹์œผ๋กœ ๊ด€๋ฆฌ ์šฉ์ด
  • ์œ ์—ฐ์„ฑ: ์ง์ ‘ ๊ฐ’ ์ž…๋ ฅ๊ณผ ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์ฐธ์กฐ ๋ชจ๋‘ ์ง€์›
  • ๋ฒ„์ „ ๊ด€๋ฆฌ: Git์œผ๋กœ ๊ตฌ์„ฑ ์ด๋ ฅ ์ถ”์  ๊ฐ€๋Šฅ (๋ฏผ๊ฐ ์ •๋ณด๋Š” .gitignore ์ฒ˜๋ฆฌ)

2. Docker ์ปจํ…Œ์ด๋„ˆํ™” ์ „๋žต ์ตœ์ ํ™”

๊ธฐ์กด ๋ฐฉ์‹์˜ ๋ฌธ์ œ์ :

  • Dockerfile ์ž‘์„ฑ โ†’ ์ด๋ฏธ์ง€ ๋นŒ๋“œ โ†’ ์ปจํ…Œ์ด๋„ˆ ์‹คํ–‰์˜ ๋‹ค๋‹จ๊ณ„ ํ”„๋กœ์„ธ์Šค
  • ์ฝ”๋“œ ์ˆ˜์ • ์‹œ๋งˆ๋‹ค ์ด๋ฏธ์ง€ ์žฌ๋นŒ๋“œ ํ•„์š”
  • ๋นŒ๋“œ ์‹œ๊ฐ„๊ณผ ๋””์Šคํฌ ๊ณต๊ฐ„ ์†Œ๋ชจ

์ตœ์ ํ™”๋œ ์ ‘๊ทผ ๋ฐฉ์‹:

# ๊ณต์‹ Python ์ด๋ฏธ์ง€ + ๋ณผ๋ฅจ ๋งˆ์šดํŠธ ํ™œ์šฉ
docker run -d \
  -v $(pwd)/main_standalone.py:/app/main.py:ro \
  -v $(pwd)/config.json:/app/config.json:ro \
  python:3.11-slim \
  sh -c "pip install supabase requests && python /app/main.py"

๊ฐœ์„  ํšจ๊ณผ:

  • ๋นŒ๋“œ ์ œ๊ฑฐ: ์ฆ‰์‹œ ์‹คํ–‰ ๊ฐ€๋Šฅ, ๊ฐœ๋ฐœ ์ฃผ๊ธฐ ๋‹จ์ถ•
  • ์œ ์—ฐ์„ฑ: ์†Œ์Šค ์ฝ”๋“œ ์ˆ˜์ • ํ›„ ์ปจํ…Œ์ด๋„ˆ๋งŒ ์žฌ์‹œ์ž‘
  • ๋‹จ์ˆœ์„ฑ: Dockerfile ๊ด€๋ฆฌ ์˜ค๋ฒ„ํ—ค๋“œ ์ œ๊ฑฐ
  • ํ‘œ์ค€ํ™”: ๊ณต์‹ Python ์ด๋ฏธ์ง€๋กœ ์ผ๊ด€์„ฑ ๋ณด์žฅ

3. ๊ตฌ์กฐํ™”๋œ ๋กœ๊น… ์‹œ์Šคํ…œ

์šด์˜ ๊ฐ€์‹œ์„ฑ ํ–ฅ์ƒ์„ ์œ„ํ•œ ์ƒ์„ธ ๋กœ๊น…:

2025-10-30 09:00:00 - INFO - == '2025-10-30 09:00:00' Run start (2 servers)
2025-10-30 09:00:00 - INFO - = Server #1: My Database
2025-10-30 09:00:01 - INFO - โœ“ SUCCESS | #15 data | Inserted: 7 | Deleted: 0
2025-10-30 09:00:01 - INFO - = Server #2: Another Database
2025-10-30 09:00:02 - INFO - โœ“ SUCCESS | #53 data | Inserted: 5 | Deleted: 23
2025-10-30 09:00:02 - INFO - == Next run: '2025-10-31 09:00:02'

๋กœ๊น… ์‹œ์Šคํ…œ์˜ ํ•ต์‹ฌ ์š”์†Œ:

  • ํƒ€์ž„์Šคํƒฌํ”„: ๊ฐ ์ž‘์—…์˜ ์ •ํ™•ํ•œ ์‹คํ–‰ ์‹œ๊ฐ„ ๊ธฐ๋ก
  • ์ž‘์—… ๊ฒฐ๊ณผ: ์„ฑ๊ณต/์‹คํŒจ ์ƒํƒœ ๋ช…ํ™•ํžˆ ํ‘œ์‹œ
  • ํ†ต๊ณ„ ์ •๋ณด: ์‚ฝ์ž…/์‚ญ์ œ๋œ ๋ฐ์ดํ„ฐ ๊ฐœ์ˆ˜ ์ถ”์ 
  • ๋‹ค์Œ ์‹คํ–‰ ์˜ˆ๊ณ : ์Šค์ผ€์ค„ ํˆฌ๋ช…์„ฑ ์ œ๊ณต

๊ตฌ์กฐํ™”๋œ ๋กœ๊ทธ๋Š” ๋ฌธ์ œ ๋ฐœ์ƒ ์‹œ ์‹ ์†ํ•œ ์ง„๋‹จ๊ณผ ๋””๋ฒ„๊น…์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋ฉฐ, ์‹œ์Šคํ…œ์˜ ์ •์ƒ ๋™์ž‘ ์—ฌ๋ถ€๋ฅผ ์‰ฝ๊ฒŒ ๋ชจ๋‹ˆํ„ฐ๋งํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

4. ์‹ค์‹œ๊ฐ„ ์•Œ๋ฆผ ์‹œ์Šคํ…œ ํ†ตํ•ฉ

ํ…”๋ ˆ๊ทธ๋žจ ๋ด‡ API๋ฅผ ํ™œ์šฉํ•œ ์•Œ๋ฆผ:

์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ํ…”๋ ˆ๊ทธ๋žจ์œผ๋กœ ์‹ค์‹œ๊ฐ„ ์ˆ˜์‹ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ํ†ตํ•ฉํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„์— ์ง์ ‘ ์ ‘์†ํ•˜์ง€ ์•Š๊ณ ๋„ ์‹œ์Šคํ…œ ์ƒํƒœ๋ฅผ ๋ชจ๋‹ˆํ„ฐ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•Œ๋ฆผ ๋‚ด์šฉ:

  • โœ… ์„ฑ๊ณต ์‹œ: ๊ฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ณ„ ์ฒ˜๋ฆฌ ํ†ต๊ณ„
  • โŒ ์‹คํŒจ ์‹œ: ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ ์„œ๋ฒ„ ์‹๋ณ„ ๋ฐ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€
  • ๐Ÿ“Š ์š”์•ฝ ์ •๋ณด: ์ „์ฒด ํ”„๋กœ์ ํŠธ ์ƒํƒœ ๊ฐœ์š”

์ด๋Ÿฌํ•œ ์•Œ๋ฆผ ์‹œ์Šคํ…œ์€ ๋ฌธ์ œ ๋ฐœ์ƒ ์‹œ ์ฆ‰๊ฐ์ ์ธ ๋Œ€์‘์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋ฉฐ, ํŠนํžˆ ์—ฌ๋Ÿฌ ํ”„๋กœ์ ํŠธ๋ฅผ ๊ด€๋ฆฌํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

์‚ฌ์šฉ๋ฒ•

# 1. ์ €์žฅ์†Œ ํด๋ก 
git clone https://github.com/shsm0520/supabasezombi.git
cd supabasezombi

# 2. ์„ค์ • ํŒŒ์ผ ์ž‘์„ฑ
cp config.json.example config.json
# config.json ํŽธ์ง‘

# 3. Docker Compose๋กœ ์‹คํ–‰
docker-compose up -d

# 4. ๋กœ๊ทธ ํ™•์ธ
docker-compose logs -f

์ด์ œ ์ž๋™ํ™” ์‹œ์Šคํ…œ์ด ํ”„๋กœ์ ํŠธ๋ฅผ ํ™œ์„ฑ ์ƒํƒœ๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.

ํ”„๋กœ์ ํŠธ ์„ฑ๊ณผ ๋ฐ ํšจ๊ณผ

๋‹ฌ์„ฑํ•œ ๋ชฉํ‘œ

1. ์ž๋™ํ™”๋œ ํ”„๋กœ์ ํŠธ ๊ด€๋ฆฌ

  • 7์ผ๋งˆ๋‹ค ๋Œ€์‹œ๋ณด๋“œ์— ์ ‘์†ํ•˜์—ฌ ์ˆ˜๋™์œผ๋กœ ์žฌํ™œ์„ฑํ™”ํ•  ํ•„์š” ์ œ๊ฑฐ
  • ๊ฐœ๋ฐœ์ž๊ฐ€ ์‹ค์ œ ๊ฐœ๋ฐœ์— ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ด€๋ฆฌ ๋ถ€๋‹ด ์ตœ์†Œํ™”

2. ๋ฉ€ํ‹ฐ ํ”„๋กœ์ ํŠธ ์ง€์›

  • ๋‹จ์ผ ์ปจํ…Œ์ด๋„ˆ๋กœ ์—ฌ๋Ÿฌ Supabase ํ”„๋กœ์ ํŠธ ๋™์‹œ ๊ด€๋ฆฌ
  • ํ”„๋กœ์ ํŠธ๋ณ„ ๋…๋ฆฝ์ ์ธ ์„ค์ • ๋ฐ ๋ชจ๋‹ˆํ„ฐ๋ง

3. ํšจ์œจ์ ์ธ ๋ฆฌ์†Œ์Šค ์‚ฌ์šฉ

  • ์ž๋™ ๋ฐ์ดํ„ฐ ์ •๋ฆฌ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ณต๊ฐ„ ์ตœ์ ํ™”
  • ๋ฌด๋ฃŒ ํ”Œ๋žœ์˜ 500MB ์ œํ•œ ๋‚ด์—์„œ ์•ˆ์ •์  ์šด์˜

4. ์‹ค์‹œ๊ฐ„ ๋ชจ๋‹ˆํ„ฐ๋ง

  • ํ…”๋ ˆ๊ทธ๋žจ ์•Œ๋ฆผ์œผ๋กœ ์‹คํ–‰ ๊ฒฐ๊ณผ ์ฆ‰์‹œ ํ™•์ธ
  • ๋ฌธ์ œ ๋ฐœ์ƒ ์‹œ ์‹ ์†ํ•œ ๋Œ€์‘ ๊ฐ€๋Šฅ

5. ๋ฐฐํฌ ์šฉ์ด์„ฑ

  • Docker ๊ธฐ๋ฐ˜์œผ๋กœ ํ”Œ๋žซํผ ๋…๋ฆฝ์  ์‹คํ–‰
  • ๋ณต์žกํ•œ ์„ค์ • ์—†์ด ๋น ๋ฅธ ๊ตฌ์ถ• ๊ฐ€๋Šฅ

ํ–ฅํ›„ ๊ฐœ๋ฐœ ๋กœ๋“œ๋งต

์ปค๋ฎค๋‹ˆํ‹ฐ ํ”ผ๋“œ๋ฐฑ ๊ธฐ๋ฐ˜ ๊ฐœ์„  ๊ณ„ํš

ํ”„๋กœ์ ํŠธ๋ฅผ ์˜คํ”ˆ์†Œ์Šค๋กœ ๊ณต๊ฐœํ•œ ํ›„ ๋‹ค์–‘ํ•œ ์‚ฌ์šฉ์ž ํ”ผ๋“œ๋ฐฑ๊ณผ ์ œ์•ˆ์„ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ํ–ฅํ›„ ๊ฐœ๋ฐœ ๋ฐฉํ–ฅ์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ณ„ํšํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹จ๊ธฐ ๋กœ๋“œ๋งต (๊ตฌํ˜„ ์˜ˆ์ •) โœ…

1. ์œ ์—ฐํ•œ ์Šค์ผ€์ค„๋ง ์˜ต์…˜

{
  "schedule": {
    "interval_hours": 12, // 12์‹œ๊ฐ„ ๊ฐ„๊ฒฉ ์‹คํ–‰
    "run_at": "09:00" // ํŠน์ • ์‹œ๊ฐ ์‹คํ–‰
  }
}

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

2. ๋‹ค์–‘ํ•œ ์•Œ๋ฆผ ์ฑ„๋„ ์ง€์›

ํ˜„์žฌ๋Š” ํ…”๋ ˆ๊ทธ๋žจ๋งŒ ์ง€์›ํ•˜์ง€๋งŒ, ๊ธฐ์—… ํ™˜๊ฒฝ์—์„œ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” Slack๊ณผ ๊ฐœ๋ฐœ์ž ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ์ธ๊ธฐ ์žˆ๋Š” Discord ํ†ตํ•ฉ์„ ์ถ”๊ฐ€ํ•  ๊ณ„ํš์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ํŒ€ ๋‹จ์œ„ ํ˜‘์—… ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ๋„ ํšจ๊ณผ์ ์œผ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ค‘์žฅ๊ธฐ ๋กœ๋“œ๋งต (๊ฒ€ํ†  ์ค‘) ๐Ÿค”

3. Web ๊ธฐ๋ฐ˜ ๊ด€๋ฆฌ ๋Œ€์‹œ๋ณด๋“œ

localhost:8080 โ†’
  - ๋“ฑ๋ก๋œ ํ”„๋กœ์ ํŠธ ๋ชฉ๋ก ๋ฐ ์ƒํƒœ
  - ์‹คํ–‰ ํžˆ์Šคํ† ๋ฆฌ ๊ทธ๋ž˜ํ”„
  - GUI ๊ธฐ๋ฐ˜ ์„ค์ • ๋ณ€๊ฒฝ
  - ์ˆ˜๋™ ์‹คํ–‰ ํŠธ๋ฆฌ๊ฑฐ

์›น UI๋Š” ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ํฌ๊ฒŒ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์ง€๋งŒ, ํ”„๋กœ์ ํŠธ์˜ ๋ณต์žก๋„๋„ ์ฆ๊ฐ€์‹œํ‚ต๋‹ˆ๋‹ค. ์ปค๋ฎค๋‹ˆํ‹ฐ ํ”ผ๋“œ๋ฐฑ์„ ํ†ตํ•ด ์‹ค์ œ ์ˆ˜์š”๋ฅผ ํŒŒ์•…ํ•œ ํ›„ ๊ฐœ๋ฐœ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

4. ํ—ฌ์Šค์ฒดํฌ API ์—”๋“œํฌ์ธํŠธ

# GET /health ์‘๋‹ต ์˜ˆ์‹œ
{
  "status": "healthy",
  "last_run": "2025-10-31 09:00:00",
  "next_run": "2025-11-01 09:00:00",
  "databases": {
    "total": 3,
    "healthy": 3,
    "failed": 0
  }
}

์™ธ๋ถ€ ๋ชจ๋‹ˆํ„ฐ๋ง ์‹œ์Šคํ…œ ํ†ตํ•ฉ์„ ์œ„ํ•œ ํ—ฌ์Šค์ฒดํฌ ์—”๋“œํฌ์ธํŠธ์ž…๋‹ˆ๋‹ค. ๋ณด์•ˆ ๊ณ ๋ ค์‚ฌํ•ญ(์ธ์ฆ, ๋ฐฉํ™”๋ฒฝ ์„ค์ • ๋“ฑ)์„ ์ถฉ๋ถ„ํžˆ ๊ฒ€ํ† ํ•œ ํ›„ ๊ตฌํ˜„ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

5. ์ง€๋Šฅํ˜• ์žฌ์‹œ๋„ ๋ฉ”์ปค๋‹ˆ์ฆ˜

๋„คํŠธ์›Œํฌ ์ผ์‹œ์  ์žฅ์• ๋‚˜ Supabase ์„œ๋น„์Šค ์ ๊ฒ€ ์‹œ ์ž๋™์œผ๋กœ ์žฌ์‹œ๋„ํ•˜๋Š” ๋กœ์ง์ž…๋‹ˆ๋‹ค. Exponential backoff ์ „๋žต์„ ์ ์šฉํ•˜์—ฌ ํšจ์œจ์ ์ธ ์žฌ์‹œ๋„๋ฅผ ๊ณ„ํšํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

6. ์ƒ์„ธ ๋ถ„์„ ๋ฐ ํ†ต๊ณ„

  • ์‹คํ–‰ ์ด๋ ฅ ๋ฐ ์„ฑ๊ณต๋ฅ  ์ถ”์ 
  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ณ„ ์„ฑ๋Šฅ ๋ฉ”ํŠธ๋ฆญ
  • ํ‰๊ท  ์‘๋‹ต ์‹œ๊ฐ„ ๋ถ„์„
  • ๋ฐ์ดํ„ฐ ์ฆ๊ฐ€ ์ถ”์ด ๋ชจ๋‹ˆํ„ฐ๋ง

์žฅ๊ธฐ์ ์œผ๋กœ๋Š” Grafana, Prometheus์™€ ๊ฐ™์€ ํ‘œ์ค€ ๋ชจ๋‹ˆํ„ฐ๋ง ๋„๊ตฌ์™€์˜ ํ†ตํ•ฉ๋„ ๊ณ ๋ คํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์žฅ๊ธฐ ๋น„์ „ (๋ณด๋ฅ˜ ์ค‘) โธ๏ธ

7. ํฌ๋กœ์Šค ํ”Œ๋žซํผ GUI ํด๋ผ์ด์–ธํŠธ

Electron ๊ธฐ๋ฐ˜ ๋ฐ์Šคํฌํ†ฑ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ๋”์šฑ ์ง๊ด€์ ์ธ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ํ˜„์žฌ์˜ Docker ๊ธฐ๋ฐ˜ ์†”๋ฃจ์…˜๋„ ์ถฉ๋ถ„ํžˆ ๊ฐ„ํŽธํ•˜๋ฏ€๋กœ, ์‹ค์ œ ์ˆ˜์š”๋ฅผ ํ™•์ธํ•œ ํ›„ ๊ฒฐ์ •ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

8. ๋‹ค์–‘ํ•œ Keep-Alive ์ „๋žต

  • ๊ฒฝ๋Ÿ‰ API ํ˜ธ์ถœ ๋ฐฉ์‹ (๋ฐ์ดํ„ฐ ์‚ฝ์ž… ์—†์ด)
  • Edge Functions ์ฃผ๊ธฐ์  ํŠธ๋ฆฌ๊ฑฐ
  • Storage ๋ ˆ๋ฒจ ํ™œ๋™ ์ƒ์„ฑ

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

9. SaaS ํ”Œ๋žซํผ์œผ๋กœ ํ™•์žฅ

“SupabaseZombi.io”์™€ ๊ฐ™์€ ํด๋ผ์šฐ๋“œ ์„œ๋น„์Šค๋กœ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์€ ๋งค๋ ฅ์ ์ธ ์•„์ด๋””์–ด์ž…๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๋Š” ํšŒ์›๊ฐ€์ž… ํ›„ Supabase ์ •๋ณด๋งŒ ์ž…๋ ฅํ•˜๋ฉด ๋˜๋Š” ํŽธ๋ฆฌํ•œ ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๋Š” ์ธํ”„๋ผ ๋น„์šฉ, ๊ฐœ์ธ์ •๋ณด ๋ณดํ˜ธ, ์ง€์† ๊ฐ€๋Šฅํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋ชจ๋ธ ๋“ฑ ๋ณต์žกํ•œ ๊ณ ๋ ค์‚ฌํ•ญ์„ ์ˆ˜๋ฐ˜ํ•˜๋ฏ€๋กœ ์‹ ์ค‘ํžˆ ๊ฒ€ํ† ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

์ปค๋ฎค๋‹ˆํ‹ฐ ์ฐธ์—ฌ ํ™˜์˜

์˜คํ”ˆ์†Œ์Šค ํ”„๋กœ์ ํŠธ์˜ ํ•ต์‹ฌ์€ ์ปค๋ฎค๋‹ˆํ‹ฐ์ž…๋‹ˆ๋‹ค. ์–ด๋–ค ๊ธฐ๋Šฅ์ด ๊ฐ€์žฅ ์œ ์šฉํ• ์ง€, ์–ด๋–ค ๊ฐœ์„ ์ด ํ•„์š”ํ•œ์ง€์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์˜๊ฒฌ์„ GitHub Issues๋ฅผ ํ†ตํ•ด ๊ณต์œ ํ•ด ์ฃผ์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค. Pull Request๋Š” ์–ธ์ œ๋‚˜ ํ™˜์˜ํ•˜๋ฉฐ, ํ•จ๊ป˜ ๋” ๋‚˜์€ ๋„๊ตฌ๋ฅผ ๋งŒ๋“ค์–ด๊ฐ€๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

๋งบ์Œ๋ง

ํ”„๋กœ์ ํŠธ์˜ ์˜์˜

SupabaseZombi๋Š” Supabase ๋ฌด๋ฃŒ ํ”Œ๋žœ์˜ 7์ผ ๋น„ํ™œ์„ฑํ™” ์ •์ฑ…์„ ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์˜คํ”ˆ์†Œ์Šค ์ž๋™ํ™” ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ์ด ํ”„๋กœ์ ํŠธ๋Š” Supabase์˜ ์ •์ฑ…์„ ์กด์ค‘ํ•˜๋ฉด์„œ๋„, ๊ฐœ๋ฐœ์ž๊ฐ€ ํ”„๋กœ์ ํŠธ ๊ด€๋ฆฌ์— ์†Œ์š”๋˜๋Š” ์‹œ๊ฐ„์„ ์ ˆ์•ฝํ•˜๊ณ  ์‹ค์ œ ๊ฐœ๋ฐœ์— ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋•์Šต๋‹ˆ๋‹ค.

๊ธฐ์ˆ ์  ๊ฐ€์น˜

  • ์ž๋™ํ™”: ๋ฐ˜๋ณต์ ์ธ ์ˆ˜๋™ ์ž‘์—… ์ œ๊ฑฐ
  • ํ™•์žฅ์„ฑ: ๋‹ค์ค‘ ํ”„๋กœ์ ํŠธ ๋™์‹œ ๊ด€๋ฆฌ
  • ํšจ์œจ์„ฑ: ๋ฆฌ์†Œ์Šค ์ตœ์ ํ™” ๋ฐ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ
  • ๊ฐ€์‹œ์„ฑ: ์‹ค์‹œ๊ฐ„ ๋ชจ๋‹ˆํ„ฐ๋ง ๋ฐ ์•Œ๋ฆผ
  • ์ด์‹์„ฑ: Docker ๊ธฐ๋ฐ˜ ํ”Œ๋žซํผ ๋…๋ฆฝ์  ๋ฐฐํฌ

์˜คํ”ˆ์†Œ์Šค ๊ธฐ์—ฌ

์ด ํ”„๋กœ์ ํŠธ๋Š” MIT ๋ผ์ด์„ ์Šค ํ•˜์— ๊ณต๊ฐœ๋˜์–ด ์žˆ์œผ๋ฉฐ, ๋ˆ„๊ตฌ๋‚˜ ์ž์œ ๋กญ๊ฒŒ ์‚ฌ์šฉ, ์ˆ˜์ •, ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ปค๋ฎค๋‹ˆํ‹ฐ์˜ ํ”ผ๋“œ๋ฐฑ๊ณผ ๊ธฐ์—ฌ๋ฅผ ํ†ตํ•ด ์ง€์†์ ์œผ๋กœ ๋ฐœ์ „ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋น„์Šทํ•œ ๊ณผ์ œ๋ฅผ ์ง๋ฉดํ•˜๊ณ  ์žˆ๋Š” ๊ฐœ๋ฐœ์ž๋ผ๋ฉด ์ด ์†”๋ฃจ์…˜์ด ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ถ๊ธˆํ•œ ์ ์ด๋‚˜ ๊ฐœ์„  ์ œ์•ˆ์ด ์žˆ๋‹ค๋ฉด GitHub Issues์—์„œ ๋…ผ์˜ํ•ด ์ฃผ์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

๐Ÿ‘‰ GitHub ์ €์žฅ์†Œ: https://github.com/shsm0520/supabasezombi

๋ฉด์ฑ…์‚ฌํ•ญ

๋ณธ ํ”„๋กœ์ ํŠธ๋Š” Supabase์˜ ์„œ๋น„์Šค ์•ฝ๊ด€์„ ์ค€์ˆ˜ํ•˜๋ฉฐ, ์ •์ƒ์ ์ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ™œ๋™์„ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ํ•˜๋Š” ๊ธฐ์ˆ ์  ์†”๋ฃจ์…˜์ž…๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๋Š” ์ž์‹ ์˜ Supabase ํ”„๋กœ์ ํŠธ์— ๋Œ€ํ•ด ์ „์ ์ธ ์ฑ…์ž„์„ ์ง€๋ฉฐ, ๋ณธ ๋„๊ตฌ๋Š” “์žˆ๋Š” ๊ทธ๋Œ€๋กœ” ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.