개인의 기록
  • 소개
  • 프로젝트
  • 글
  • 링크

© 2026 newgirok

← 글 목록

Supabase Edge Functions — 서버리스 함수로 백엔드 로직 실행

2025년 4월 20일
SupabaseEdge FunctionsServerlessDenoWebhook

Supabase는 데이터베이스와 인증을 넘어 Edge Functions라는 서버리스 실행 환경을 제공한다. Node.js가 아닌 Deno 런타임 위에서 동작하기 때문에 TypeScript를 별도 컴파일 없이 바로 실행할 수 있다. Webhook 처리, 외부 API 호출, AI 연동까지 단일 플랫폼 안에서 해결할 수 있어 별도 백엔드 서버 없이도 복잡한 로직을 배포할 수 있다.

Deno 런타임과 실행 모델

Edge Functions는 Cloudflare Workers와 유사한 V8 Isolate 모델로 동작한다. 각 함수 호출은 독립된 격리 환경에서 실행되며, 콜드 스타트가 수십 밀리초 수준으로 매우 짧다.

클라이언트 요청
      │
      ▼
┌─────────────────┐
│  Supabase CDN   │  글로벌 엣지 노드
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  Deno Isolate   │  함수 코드 실행
│  (Edge Fn)      │
└────────┬────────┘
         │
    ┌────┴─────┐
    ▼          ▼
 Supabase   외부 API
  DB / Auth

V8 Isolate — Node.js 프로세스 대신 V8 엔진의 격리된 컨텍스트를 사용해 메모리를 공유하지 않는 경량 실행 단위.

배포 방법

Supabase CLI로 함수를 생성하고 배포한다.

# 함수 생성
supabase functions new hello-world

# 로컬 실행 (핫 리로드)
supabase functions serve hello-world

# 프로덕션 배포
supabase functions deploy hello-world

생성된 파일 구조는 supabase/functions/hello-world/index.ts이며, 진입점은 항상 Deno.serve 핸들러다.

Deno.serve(async (req: Request) => {
  const { name } = await req.json()
  return new Response(
    JSON.stringify({ message: `Hello, ${name}!` }),
    { headers: { "Content-Type": "application/json" } }
  )
})

Webhook 처리

외부 서비스(GitHub, Stripe 등)의 Webhook을 수신할 때 서명 검증이 필수다.

import { crypto } from "https://deno.land/std@0.177.0/crypto/mod.ts"

Deno.serve(async (req) => {
  const signature = req.headers.get("stripe-signature") ?? ""
  const body = await req.text()
  const secret = Deno.env.get("STRIPE_WEBHOOK_SECRET")!

  const isValid = await verifyStripeSignature(body, signature, secret)
  if (!isValid) return new Response("Unauthorized", { status: 401 })

  const event = JSON.parse(body)
  // 이벤트 처리 로직
  return new Response("ok")
})

Webhook 서명 검증 — 요청 본문과 타임스탬프를 HMAC-SHA256으로 해싱해 전송자의 신원을 확인하는 방식.

외부 API 호출 및 AI 연동

Edge Functions 내부에서 fetch를 직접 사용할 수 있다. OpenAI API 호출 예시는 다음과 같다.

Deno.serve(async (req) => {
  const { prompt } = await req.json()

  const response = await fetch("https://api.openai.com/v1/chat/completions", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${Deno.env.get("OPENAI_API_KEY")}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      model: "gpt-4o-mini",
      messages: [{ role: "user", content: prompt }],
    }),
  })

  const data = await response.json()
  return new Response(JSON.stringify(data.choices[0].message))
})

환경 변수는 supabase secrets set KEY=value 명령으로 안전하게 주입한다.

Cron 작업 활용

pg_cron 확장과 결합하면 Edge Functions를 주기적으로 트리거할 수 있다.

-- 매일 자정에 Edge Function 호출
select cron.schedule(
  'daily-cleanup',
  '0 0 * * *',
  $$
  select net.http_post(
    url := 'https://<project>.supabase.co/functions/v1/cleanup',
    headers := '{"Authorization": "Bearer <anon-key>"}'::jsonb
  )
  $$
);
트리거 방식사용 사례
HTTP 요청Webhook, API 엔드포인트
Database Webhook레코드 변경 시 알림 발송
pg_cron정기 배치 작업
Auth Hook회원가입 후처리

Edge Functions는 Supabase 프로젝트와 동일한 네트워크 내에서 실행되기 때문에 Service Role Key를 사용하면 RLS를 우회한 관리자 권한 DB 접근도 가능하다. 단, 이 키는 반드시 서버 사이드에서만 사용해야 한다.

← 이전 글Supabase RPC — PostgreSQL 함수를 API처럼 호출하는 방법
다음 글 →Supabase CLI — 로컬 개발 환경 구성 도구