Contents
see List개요
Supabase Edge Functions는 Deno 런타임 기반의 서버리스 함수로, 전 세계 엣지 로케이션에서 실행됩니다. Supabase Realtime은 PostgreSQL의 변경사항을 WebSocket으로 실시간 전달하는 시스템입니다. 이 두 기능을 결합하면 별도의 서버 인프라 없이도 실시간 협업 도구, 알림 시스템, 라이브 대시보드를 구축할 수 있습니다.
핵심 개념
Edge Functions: Deno Deploy 위에서 동작하며, TypeScript를 네이티브로 지원합니다. Cold start가 매우 빠르고(약 200ms), 전 세계 엣지 네트워크에서 실행되어 사용자에게 가까운 위치에서 응답합니다. 외부 API 연동, Webhook 처리, 이메일 발송, 결제 처리 등에 활용됩니다.
Realtime 채널: Supabase Realtime은 세 가지 모드를 지원합니다. Postgres Changes(DB 변경 감지), Broadcast(클라이언트 간 메시지), Presence(온라인 상태 공유)입니다. 이 세 가지를 조합하면 대부분의 실시간 기능을 구현할 수 있습니다.
Database Webhooks: 테이블의 INSERT, UPDATE, DELETE 이벤트가 발생하면 자동으로 Edge Function을 호출하는 트리거입니다. 이벤트 기반 아키텍처를 간단하게 구현할 수 있습니다.
RLS와 Realtime: Realtime 구독도 RLS 정책을 따릅니다. 사용자는 자신이 접근 권한이 있는 데이터의 변경사항만 수신할 수 있어 보안이 유지됩니다.
실전 예제
Edge Functions와 Realtime을 결합한 실시간 알림 시스템 구현 예제입니다.
// supabase/functions/send-notification/index.ts
import { serve } from 'https://deno.land/std@0.177.0/http/server.ts'
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
serve(async (req) => {
const payload = await req.json()
const { record } = payload
const supabase = createClient(
Deno.env.get('SUPABASE_URL')!,
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
)
// 게시물 작성자 조회
const { data: post } = await supabase
.from('posts')
.select('user_id, title')
.eq('id', record.post_id)
.single()
// 알림 저장
await supabase.from('notifications').insert({
user_id: post.user_id,
type: 'new_comment',
message: `"${post.title}"에 새 댓글이 달렸습니다.`,
data: { comment_id: record.id, post_id: record.post_id },
is_read: false,
})
return new Response(JSON.stringify({ success: true }), {
headers: { 'Content-Type': 'application/json' },
})
})
클라이언트에서 실시간 구독을 설정하는 예제입니다.
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY)
// 1. Postgres Changes - 알림 테이블 변경 감지
const notificationChannel = supabase
.channel('my-notifications')
.on('postgres_changes',
{
event: 'INSERT',
schema: 'public',
table: 'notifications',
filter: `user_id=eq.${currentUser.id}`,
},
(payload) => {
showToast(payload.new.message)
updateNotificationBadge()
}
)
.subscribe()
// 2. Presence - 온라인 사용자 표시
const presenceChannel = supabase.channel('online-users')
presenceChannel
.on('presence', { event: 'sync' }, () => {
const state = presenceChannel.presenceState()
updateOnlineUsers(Object.values(state).flat())
})
.subscribe(async (status) => {
if (status === 'SUBSCRIBED') {
await presenceChannel.track({
user_id: currentUser.id,
name: currentUser.name,
online_at: new Date().toISOString(),
})
}
})
// 3. Broadcast - 실시간 커서 위치 공유
const cursorChannel = supabase.channel('cursors')
cursorChannel
.on('broadcast', { event: 'cursor' }, ({ payload }) => {
renderCursor(payload.userId, payload.x, payload.y)
})
.subscribe()
활용 팁
- Edge Function 최적화: 자주 사용하는 Supabase 클라이언트는 함수 외부에서 생성하면 재사용되어 성능이 향상됩니다. 그러나 요청별로 다른 인증이 필요하면 함수 내부에서 생성하세요.
- Realtime 필터링: filter 옵션으로 관심 있는 데이터만 구독하면 불필요한 네트워크 트래픽을 줄일 수 있습니다.
- Broadcast vs Postgres Changes: 클라이언트 간 직접 메시지(커서, 타이핑 상태)는 Broadcast를, DB 변경 감지는 Postgres Changes를 사용하세요. Broadcast가 레이턴시가 더 낮습니다.
- 에러 처리: Edge Function에서 에러가 발생해도 Database Webhook은 재시도합니다. 멱등성(Idempotency)을 보장하는 설계가 중요합니다.
- 로컬 개발: supabase functions serve로 로컬에서 Edge Function을 테스트할 수 있습니다. --env-file로 환경변수를 전달하세요.
마무리
Supabase Edge Functions와 Realtime의 조합은 실시간 애플리케이션 개발의 진입 장벽을 크게 낮춰줍니다. WebSocket 서버 관리, 스케일링, 인프라 운영 없이도 프로덕션 수준의 실시간 기능을 구축할 수 있습니다. Next.js와 함께 사용하면 풀스택 실시간 애플리케이션을 빠르게 개발할 수 있습니다.