들어가며
이 글은 아래 게시물과 연계되는 내용을 다루고 있습니다.
꼭 아래 게시물의 내용을 모두 완료 후 읽어주세요.
소스 코드
https://github.com/LDK1009/Supabase-FCM-Push-Notification
GitHub - LDK1009/Supabase-FCM-Push-Notification: Next.js + Supabase + FCM 을 활용한 푸쉬 알림 기능 소스코드 저장
Next.js + Supabase + FCM 을 활용한 푸쉬 알림 기능 소스코드 저장소입니다. - LDK1009/Supabase-FCM-Push-Notification
github.com
git clone https://github.com/LDK1009/Supabase-FCM-Push-Notification.git
관련 게시물
https://sooncoding.tistory.com/285
[Firebase] FCM을 활용한 웹 푸쉬 알림 구현방법 A to Z
소스코드https://github.com/LDK1009/Supabase-FCM-Push-Notification GitHub - LDK1009/Supabase-FCM-Push-Notification: Next.js + Supabase + FCM 을 활용한 푸쉬 알림 기능 소스코드 저장Next.js + Supabase + FCM 을 활용한 푸쉬 알림 기
sooncoding.tistory.com
사전 준비
* FCM을 활용한 웹 푸쉬 알림 구현(필수!)
https://sooncoding.tistory.com/285
[Firebase] FCM을 활용한 웹 푸쉬 알림 구현방법 A to Z
소스코드https://github.com/LDK1009/Supabase-FCM-Push-Notification GitHub - LDK1009/Supabase-FCM-Push-Notification: Next.js + Supabase + FCM 을 활용한 푸쉬 알림 기능 소스코드 저장Next.js + Supabase + FCM 을 활용한 푸쉬 알림 기
sooncoding.tistory.com
supabase 회원가입 및 프로젝트 생성
Supabase | The Open Source Firebase Alternative
Build production-grade applications with a Postgres database, Authentication, instant APIs, Realtime, Functions, Storage and Vector embeddings. Start for free.
supabase.com
[Supabase] 프로젝트 생성 방법
들어가며이 글은 Supabase 회원가입이 완료되어있음을 가정하에 진행합니다.회원가입 미완료 상태라면 꼭 회원가입을 완료 후 진행 부탁드립니다. 대시보드 이동https://supabase.com/ Supabase | The Open
sooncoding.tistory.com
Docker Desktop 설치
https://docs.docker.com/desktop/setup/install/windows-install/
Windows
Get started with Docker for Windows. This guide covers system requirements, where to download, and instructions on how to install and update.
docs.docker.com
docker desktop 실행


이후 supabase 프로젝트 세팅을 위해 필수적으로 Docker Desktop을 실행해야합니다 .
시작하기(A to Z)
환경 변수 세팅
.env 수정

Supabase Dashboard > Project Setting > Data API
위 경로에서 Project URL과 anon key를 복사한 후 아래와 같이 환경 변수에 붙여넣습니다.

# 파이어베이스 초기화
NEXT_PUBLIC_FIREBASE_API_KEY=
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=
NEXT_PUBLIC_FIREBASE_PROJECT_ID=
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=
NEXT_PUBLIC_FIREBASE_APP_ID=
# 파이어베이스 웹 푸시 인증서
NEXT_PUBLIC_FIREBASE_VAPID_KEY=
# Supabase 환경변수
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
* 이 과정이 되어있지 않다면 아래 글을 모두 실행한 후 따라와주세요.
[Firebase] FCM을 활용한 웹 푸쉬 알림 구현방법 A to Z
소스코드https://github.com/LDK1009/Supabase-FCM-Push-Notification GitHub - LDK1009/Supabase-FCM-Push-Notification: Next.js + Supabase + FCM 을 활용한 푸쉬 알림 기능 소스코드 저장Next.js + Supabase + FCM 을 활용한 푸쉬 알림 기
sooncoding.tistory.com
Supabase 세팅
supabase 설치
npm install @supabase/supabase-js
개발 프로젝트 터미널에서 위 명령어를 입력합니다.
위 명령어를 통해 supabase를 설치합니다.

supabase 로그인
npx supabase login
개발 프로젝트 터미널에서 위 명령어를 입력합니다.
이후 아래 과정을 따릅니다.
1) 명령어 입력 후 엔터 입력
2) 링크 접속 후 액세스 토큰 복사
3) 터미널에 액세스 토큰 붙여넣기

supabase 프로젝트 기본 폴더 구조 및 파일 생성
npx supabase init
개발 프로젝트 터미널에서 위 명령어를 입력합니다.
위 명령어는 Supabase 프로젝트에 필요한 기본 폴더 구조와 파일들을 생성합니다.


Supabase 테이블 생성
테이블 생성
create table public.profiles (
id uuid references auth.users(id) not null primary key,
fcm_token text
);
create table public.notifications (
id uuid not null default gen_random_uuid(),
user_id uuid references auth.users(id) not null,
created_at timestamp with time zone not null default now(),
body text not null
);
Supabase Dashboard > SQL Editor 에서 위 SQL을 입력합니다.
위 명령어는 유저 정보를 저장할 profiles 테이블과 푸쉬 알림 정보를 저장할 notifications 테이블을 생성합니다.
참고) 이후 과정에서 notification 테이블에 데이터가 추가될 때 자동으로 푸쉬 알림이 발송되도록 할 것 입니다.


Supabase 엣지 함수 생성 / 작성 / 배포
엣지 함수 생성
프로젝트 폴더에서 터미널을 열어 아래 명령어를 실행합니다.
npx supabase functions new push
개발 프로젝트 터미널에서 위 명령어를 입력합니다.
위 명령어는 Supabase 프로젝트에서 "push"라는 이름의 새로운 서버리스 함수(serverless function) 함수를 생성합니다.

엣지 함수 작성
// 이 파일에서 ts및 eslint오류 무시
/* eslint-disable */
// @ts-nocheck
// Supabase 클라이언트 라이브러리와 Google 인증 라이브러리 가져오기
import { createClient } from 'npm:@supabase/supabase-js@2'
import { JWT } from 'npm:google-auth-library@9'
// Firebase 서비스 계정 정보 가져오기
import serviceAccount from '../service-account.json' with { type: 'json' }
// 알림 데이터 구조 정의
interface Notification {
id: string // 알림 고유 ID
user_id: string // 알림을 받을 사용자 ID
body: string // 알림 내용
}
// Supabase 웹훅에서 전송되는 페이로드 구조 정의
interface WebhookPayload {
type: 'INSERT' // 데이터베이스 작업 유형 (여기서는 새 레코드 삽입)
table: string // 변경된 테이블 이름
record: Notification // 삽입된 알림 레코드
schema: 'public' // 데이터베이스 스키마
}
// Supabase 클라이언트 초기화 (환경 변수에서 URL과 서비스 롤 키 가져옴)
const supabase = createClient(
Deno.env.get('SUPABASE_URL')!,
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
)
// Deno 서버 함수 정의 - 웹훅 요청 처리
Deno.serve(async (req) => {
// 요청 본문에서 웹훅 페이로드 파싱
const payload: WebhookPayload = await req.json()
// Supabase에서 사용자의 FCM 토큰 조회
const { data } = await supabase
.from('profiles')
.select('fcm_token')
.eq('id', payload.record.user_id) // 알림 대상 사용자 ID로 필터링
.single() // 단일 결과 반환
// FCM 토큰 추출
const fcmToken = data!.fcm_token as string
// Firebase 메시징 API 접근을 위한 액세스 토큰 획득
const accessToken = await getAccessToken({
clientEmail: serviceAccount.client_email,
privateKey: serviceAccount.private_key,
})
// Firebase Cloud Messaging API 호출하여 푸시 알림 전송
const res = await fetch(
`https://fcm.googleapis.com/v1/projects/${serviceAccount.project_id}/messages:send`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${accessToken}`, // 인증 토큰 설정
},
body: JSON.stringify({
message: {
token: fcmToken, // 사용자 기기의 FCM 토큰
notification: {
title: `Notification from Supabase`, // 알림 제목
body: payload.record.body, // 알림 내용
},
},
}),
}
)
// API 응답 처리
const resData = await res.json()
// 오류 응답 처리 (HTTP 상태 코드가 200-299 범위 외인 경우)
if (res.status < 200 || 299 < res.status) {
throw resData
}
// 성공 응답 반환
return new Response(JSON.stringify(resData), {
headers: { 'Content-Type': 'application/json' },
})
})
// Firebase 메시징 API 접근을 위한 액세스 토큰 생성 함수
const getAccessToken = ({
clientEmail,
privateKey,
}: {
clientEmail: string // 서비스 계정 이메일
privateKey: string // 서비스 계정 비공개 키
}): Promise<string> => {
return new Promise((resolve, reject) => {
// Google JWT 클라이언트 생성
const jwtClient = new JWT({
email: clientEmail,
key: privateKey,
scopes: ['https://www.googleapis.com/auth/firebase.messaging'], // Firebase 메시징 API 접근 범위
})
// 인증 토큰 요청
jwtClient.authorize((err, tokens) => {
if (err) {
reject(err)
return
}
resolve(tokens!.access_token!) // 액세스 토큰 반환
})
})
}
supabase/functions/push/index.ts
위 경로에 있는 엣지함수 파일에 위 코드를 복사 및 붙여넣기 합니다.
위 코드는 Supabase 데이터베이스에서 새로운 알림 레코드가 추가되면(INSERT) 웹훅을 통해 이 함수가 트리거됩니다.
함수는 아래 단계로 동작합니다.
1) 웹훅 페이로드에서 알림 정보와 사용자 ID를 추출합니다.
2) Supabase 데이터베이스의 'profiles' 테이블에서 해당 사용자의 FCM 토큰을 조회합니다.
3) Google 서비스 계정 정보를 사용하여 Firebase 메시징 API에 접근하기 위한 액세스 토큰을 생성합니다.
4) FCM API를 호출하여 사용자의 기기로 푸시 알림을 전송합니다.
5) 응답을 처리하고 결과를 반환합니다.
참고) 이후 과정에서 웹훅을 활용하여 notification 테이블에 데이터가 추가될 때(INSERT) 위 엣지 함수를 실행시켜 사용자에게 푸쉬알림을 발송하는 기능을 구현할 것입니다.
FCM 비공개키 생성

Firebase > 프로젝트 설정 > 서비스 계정
위 경로에서 비공개키를 생성합니다.
FCM 비공개키 적용

'새 비공개 키 생성' 버튼 클릭 시 위와 같이 json 파일이 다운로드 됩니다.
다운로드된 json파일을 열어 모든 코드를 복사한 후 프로젝트 폴더의 아래 경로에 코드를 붙여넣습니다.

supabase / functions / service-account.json
개발 프로젝트에서 위 경로에 service-account.json 파일을 생성합니다.
이전 비공개키 json 파일에서 복사한 코드를 붙여넣기합니다.
혹은, 해당 json 파일을 위 경로로 옮긴 후 파일명을 수정하여도 무방합니다.
비공개키 이그노어
# Supabase
.branches
.temp
# dotenvx
.env.keys
.env.local
.env.*.local
# Firebase
firebase-adminsdk.json
service-account.json
# Environment variables
.env
.env.*
!.env.example
supabase / .gitignore
위 경로의 파일 내용을 위 코드처럼 변경합니다.
이를 통해 프로젝트를 push할 때 service-account.json 등 보안과 관련된 파일을 무시함으로써 원격 저장소(레포지토리)에 저장되지 않도록합니다.
Supabsae 프로젝트 연결
npx supabase link
개발 프로젝트 터미널에서 위 명령어를 입력합니다.
이 명령어는 로컬 Supabase 프로젝트를 원격 Supabase 프로젝트와 연결(링크)합니다.

1) 프로젝트 선택 후 엔터

2) 데이터베이스 비밀번호 입력 후 엔터
(* 데이터베이스 비밀번호란? : Supabase 프로젝트 생성 시 입력한 데이터베이스 비밀번호입니다. 관련 게시물 > supabase 프로젝트 생성 방법을 참고하세요.)
엣지 함수 배포
npx supabase functions deploy push --no-verify-jwt
개발 프로젝트 터미널에서 위 명령어를 입력합니다.
이 명령어는 'push'라는 이름의 서버리스 함수를 Supabase 클라우드에 배포합니다.
이 명령어를 실행하기 전 Docker Desktop을 필수적으로 실행해야합니다.
명령어 실행 시 Docker Desktop이 필요한 이유
1. 초기화 단계: 명령어가 실행되면 Supabase CLI가 Docker를 사용하여 빌드 환경을 준비합니다.
2. 코드 분석 단계: Docker 컨테이너 내에서 함수 코드와 의존성을 분석합니다.
3. 빌드 단계: Docker를 사용하여 함수 코드와 필요한 모든 의존성을 포함한 컨테이너 이미지를 생성합니다.
4. 패키징 단계: 빌드된 함수를 배포 가능한 형태로 패키징합니다.
5. 배포 단계: 패키징된 함수를 Supabase 클라우드로 업로드합니다.
Docker Desktop은 이 모든 과정에서 일관된 환경을 제공하고, 함수가 로컬 환경의 특성에 영향받지 않도록 격리된 환경에서 빌드와 패키징을 수행하는 데 필수적입니다.


Supabase 웹훅 활성화 / 생성
Supabase 데이터베이스 웹훅 활성화

supabase 프로젝트 > database > Webhooks

웹훅 활성화
Supabase 데이터베이스 웹훅 생성

웹훅 생성

웹훅 이름 : notification-web-hooks
notifications 테이블 선택합니다.

Event를 Insert로 설정합니다.
이로써 notifications 테이블에 데이터가 삽입(INSERT) 시 설정한 엣지함수가 실행됩니다.
참고) 아래 과정에서 실행할 엣지함수를 선택합니다.

웹훅 구성을 Supabase Edge Functions로 설정합니다.

notification 테이블에 데이터가 INSERT될 때 실행시킬 엣지함수를 지정합니다.
이전에 생성 및 배포한 push 엣지 함수를 선택합니다.
이를 통해 notification 테이블에 데이터가 INSERT될 때마다 웹훅을 통해 push 엣지 함수가 실행됩니다.

웹훅 생성
웹 푸쉬 알림 테스트
유저 생성
npx next dev --experimental-https
개발 서버를 HTTPS 로 실행시킵니다.
회원가입

회원가입할 이메일과 패스워드를 입력하고 회원가입 버튼을 클릭합니다.

회원가입한 이메일에서 이메일을 인증합니다.
로그인

이메일과 비밀번호를 입력 후 로그인 버튼을 클릭합니다.
FCM 토큰 발급

FCM 토큰 발급 버튼을 클릭합니다.
uid + FCM 토큰 저장

FCM 토큰 저장 버튼을 클릭합니다.
위 버튼 클릭 시 profiles 테이블에 유저의 uid와 기기의 FCM 토큰이 저장됩니다.
푸시 알림 테스트

전송하고싶은 푸시 알림 메시지 내용을 작성합니다.
푸쉬 알림 테스트 버튼을 클릭합니다.
버튼 클릭 시 유저의 uid와 푸쉬 알림 메시지 내용이 notifications 테이블에 삽입(INSERT)됩니다.
notifications 테이블에 데이터가 INSERT 되었으므로 이전에 설정한 웹훅이 실행되어 push 엣지함수가 실행됩니다.push 엣지함수에서 notifications에 삽입된 데이터를 확인하고 삽입된 데이터의 uid와 일치하는 FCM 토큰 값은 profiles 테이블에서 찾습니다. 이후 해당 FCM 토큰으로 푸쉬 알림을 보냅니다.이 과정을 통해 사용자는 푸쉬 알림을 받습니다.

정상적으로 푸시 알림이 오는 것을 확인할 수 있습니다.
끝.
문제해결
1. Docker Desktop 오류
만약 supabase 프로젝트 실행이나 엣지함수 배포 시 오류가 발생한다면 아래 과정을 따라간 후 다시 명령어를 입력해보세요.
========== 개발 프로젝트 터미널에서 입력
기존 supabase 인스턴스 중지
npx supabase stop
========== CMD에서 입력
사용중인 포트 확인
netstat -ano | findstr 54322
docker 컨테이너 확인
docker ps -a
docker 컨테이너 중지
for /f %i in ('docker ps -a -q') do docker rm %i
docker 컨테이너 삭제
for /f "tokens=*" %i in ('docker ps -a -q') do docker rm %i
docker 컨테이너 확인
docker ps -a
========== 만약 위 과정을 모두 실행해도 여전히 오류가 발생한다면 아래 과정을 따라가세요.
도커 이미지 모두 삭제

docker rmi $(docker images -q) --force
볼륨 모두 삭제

docker volume rm $(docker volume ls -q)
혹은 사용하지 않는 모든 리소스 삭제
docker system prune -a --volumes
'백엔드 > Supabase' 카테고리의 다른 글
[Supabase] 참조키가 2개 이상일 때 테이블 조인 방법 (0) | 2025.04.10 |
---|---|
[Supabase] 수파베이스 구글 로그인 연동 방법 (0) | 2025.04.09 |
[Supabase] 프로젝트 생성 방법 (0) | 2025.04.03 |
[Supabase + Next.js] DB에 저장된 문자열 데이터를 불러올 때 \n 줄바꿈 문제와 해결 방법 (0) | 2025.03.29 |
Supabase 조인 테이블 응답 데이터와 Array.flat() 활용하기 | 배열 평탄화 (0) | 2025.03.17 |
들어가며
이 글은 아래 게시물과 연계되는 내용을 다루고 있습니다.
꼭 아래 게시물의 내용을 모두 완료 후 읽어주세요.
소스 코드
https://github.com/LDK1009/Supabase-FCM-Push-Notification
GitHub - LDK1009/Supabase-FCM-Push-Notification: Next.js + Supabase + FCM 을 활용한 푸쉬 알림 기능 소스코드 저장
Next.js + Supabase + FCM 을 활용한 푸쉬 알림 기능 소스코드 저장소입니다. - LDK1009/Supabase-FCM-Push-Notification
github.com
git clone https://github.com/LDK1009/Supabase-FCM-Push-Notification.git
관련 게시물
https://sooncoding.tistory.com/285
[Firebase] FCM을 활용한 웹 푸쉬 알림 구현방법 A to Z
소스코드https://github.com/LDK1009/Supabase-FCM-Push-Notification GitHub - LDK1009/Supabase-FCM-Push-Notification: Next.js + Supabase + FCM 을 활용한 푸쉬 알림 기능 소스코드 저장Next.js + Supabase + FCM 을 활용한 푸쉬 알림 기
sooncoding.tistory.com
사전 준비
* FCM을 활용한 웹 푸쉬 알림 구현(필수!)
https://sooncoding.tistory.com/285
[Firebase] FCM을 활용한 웹 푸쉬 알림 구현방법 A to Z
소스코드https://github.com/LDK1009/Supabase-FCM-Push-Notification GitHub - LDK1009/Supabase-FCM-Push-Notification: Next.js + Supabase + FCM 을 활용한 푸쉬 알림 기능 소스코드 저장Next.js + Supabase + FCM 을 활용한 푸쉬 알림 기
sooncoding.tistory.com
supabase 회원가입 및 프로젝트 생성
Supabase | The Open Source Firebase Alternative
Build production-grade applications with a Postgres database, Authentication, instant APIs, Realtime, Functions, Storage and Vector embeddings. Start for free.
supabase.com
[Supabase] 프로젝트 생성 방법
들어가며이 글은 Supabase 회원가입이 완료되어있음을 가정하에 진행합니다.회원가입 미완료 상태라면 꼭 회원가입을 완료 후 진행 부탁드립니다. 대시보드 이동https://supabase.com/ Supabase | The Open
sooncoding.tistory.com
Docker Desktop 설치
https://docs.docker.com/desktop/setup/install/windows-install/
Windows
Get started with Docker for Windows. This guide covers system requirements, where to download, and instructions on how to install and update.
docs.docker.com
docker desktop 실행


이후 supabase 프로젝트 세팅을 위해 필수적으로 Docker Desktop을 실행해야합니다 .
시작하기(A to Z)
환경 변수 세팅
.env 수정

Supabase Dashboard > Project Setting > Data API
위 경로에서 Project URL과 anon key를 복사한 후 아래와 같이 환경 변수에 붙여넣습니다.

# 파이어베이스 초기화
NEXT_PUBLIC_FIREBASE_API_KEY=
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=
NEXT_PUBLIC_FIREBASE_PROJECT_ID=
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=
NEXT_PUBLIC_FIREBASE_APP_ID=
# 파이어베이스 웹 푸시 인증서
NEXT_PUBLIC_FIREBASE_VAPID_KEY=
# Supabase 환경변수
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
* 이 과정이 되어있지 않다면 아래 글을 모두 실행한 후 따라와주세요.
[Firebase] FCM을 활용한 웹 푸쉬 알림 구현방법 A to Z
소스코드https://github.com/LDK1009/Supabase-FCM-Push-Notification GitHub - LDK1009/Supabase-FCM-Push-Notification: Next.js + Supabase + FCM 을 활용한 푸쉬 알림 기능 소스코드 저장Next.js + Supabase + FCM 을 활용한 푸쉬 알림 기
sooncoding.tistory.com
Supabase 세팅
supabase 설치
npm install @supabase/supabase-js
개발 프로젝트 터미널에서 위 명령어를 입력합니다.
위 명령어를 통해 supabase를 설치합니다.

supabase 로그인
npx supabase login
개발 프로젝트 터미널에서 위 명령어를 입력합니다.
이후 아래 과정을 따릅니다.
1) 명령어 입력 후 엔터 입력
2) 링크 접속 후 액세스 토큰 복사
3) 터미널에 액세스 토큰 붙여넣기

supabase 프로젝트 기본 폴더 구조 및 파일 생성
npx supabase init
개발 프로젝트 터미널에서 위 명령어를 입력합니다.
위 명령어는 Supabase 프로젝트에 필요한 기본 폴더 구조와 파일들을 생성합니다.


Supabase 테이블 생성
테이블 생성
create table public.profiles (
id uuid references auth.users(id) not null primary key,
fcm_token text
);
create table public.notifications (
id uuid not null default gen_random_uuid(),
user_id uuid references auth.users(id) not null,
created_at timestamp with time zone not null default now(),
body text not null
);
Supabase Dashboard > SQL Editor 에서 위 SQL을 입력합니다.
위 명령어는 유저 정보를 저장할 profiles 테이블과 푸쉬 알림 정보를 저장할 notifications 테이블을 생성합니다.
참고) 이후 과정에서 notification 테이블에 데이터가 추가될 때 자동으로 푸쉬 알림이 발송되도록 할 것 입니다.


Supabase 엣지 함수 생성 / 작성 / 배포
엣지 함수 생성
프로젝트 폴더에서 터미널을 열어 아래 명령어를 실행합니다.
npx supabase functions new push
개발 프로젝트 터미널에서 위 명령어를 입력합니다.
위 명령어는 Supabase 프로젝트에서 "push"라는 이름의 새로운 서버리스 함수(serverless function) 함수를 생성합니다.

엣지 함수 작성
// 이 파일에서 ts및 eslint오류 무시
/* eslint-disable */
// @ts-nocheck
// Supabase 클라이언트 라이브러리와 Google 인증 라이브러리 가져오기
import { createClient } from 'npm:@supabase/supabase-js@2'
import { JWT } from 'npm:google-auth-library@9'
// Firebase 서비스 계정 정보 가져오기
import serviceAccount from '../service-account.json' with { type: 'json' }
// 알림 데이터 구조 정의
interface Notification {
id: string // 알림 고유 ID
user_id: string // 알림을 받을 사용자 ID
body: string // 알림 내용
}
// Supabase 웹훅에서 전송되는 페이로드 구조 정의
interface WebhookPayload {
type: 'INSERT' // 데이터베이스 작업 유형 (여기서는 새 레코드 삽입)
table: string // 변경된 테이블 이름
record: Notification // 삽입된 알림 레코드
schema: 'public' // 데이터베이스 스키마
}
// Supabase 클라이언트 초기화 (환경 변수에서 URL과 서비스 롤 키 가져옴)
const supabase = createClient(
Deno.env.get('SUPABASE_URL')!,
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
)
// Deno 서버 함수 정의 - 웹훅 요청 처리
Deno.serve(async (req) => {
// 요청 본문에서 웹훅 페이로드 파싱
const payload: WebhookPayload = await req.json()
// Supabase에서 사용자의 FCM 토큰 조회
const { data } = await supabase
.from('profiles')
.select('fcm_token')
.eq('id', payload.record.user_id) // 알림 대상 사용자 ID로 필터링
.single() // 단일 결과 반환
// FCM 토큰 추출
const fcmToken = data!.fcm_token as string
// Firebase 메시징 API 접근을 위한 액세스 토큰 획득
const accessToken = await getAccessToken({
clientEmail: serviceAccount.client_email,
privateKey: serviceAccount.private_key,
})
// Firebase Cloud Messaging API 호출하여 푸시 알림 전송
const res = await fetch(
`https://fcm.googleapis.com/v1/projects/${serviceAccount.project_id}/messages:send`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${accessToken}`, // 인증 토큰 설정
},
body: JSON.stringify({
message: {
token: fcmToken, // 사용자 기기의 FCM 토큰
notification: {
title: `Notification from Supabase`, // 알림 제목
body: payload.record.body, // 알림 내용
},
},
}),
}
)
// API 응답 처리
const resData = await res.json()
// 오류 응답 처리 (HTTP 상태 코드가 200-299 범위 외인 경우)
if (res.status < 200 || 299 < res.status) {
throw resData
}
// 성공 응답 반환
return new Response(JSON.stringify(resData), {
headers: { 'Content-Type': 'application/json' },
})
})
// Firebase 메시징 API 접근을 위한 액세스 토큰 생성 함수
const getAccessToken = ({
clientEmail,
privateKey,
}: {
clientEmail: string // 서비스 계정 이메일
privateKey: string // 서비스 계정 비공개 키
}): Promise<string> => {
return new Promise((resolve, reject) => {
// Google JWT 클라이언트 생성
const jwtClient = new JWT({
email: clientEmail,
key: privateKey,
scopes: ['https://www.googleapis.com/auth/firebase.messaging'], // Firebase 메시징 API 접근 범위
})
// 인증 토큰 요청
jwtClient.authorize((err, tokens) => {
if (err) {
reject(err)
return
}
resolve(tokens!.access_token!) // 액세스 토큰 반환
})
})
}
supabase/functions/push/index.ts
위 경로에 있는 엣지함수 파일에 위 코드를 복사 및 붙여넣기 합니다.
위 코드는 Supabase 데이터베이스에서 새로운 알림 레코드가 추가되면(INSERT) 웹훅을 통해 이 함수가 트리거됩니다.
함수는 아래 단계로 동작합니다.
1) 웹훅 페이로드에서 알림 정보와 사용자 ID를 추출합니다.
2) Supabase 데이터베이스의 'profiles' 테이블에서 해당 사용자의 FCM 토큰을 조회합니다.
3) Google 서비스 계정 정보를 사용하여 Firebase 메시징 API에 접근하기 위한 액세스 토큰을 생성합니다.
4) FCM API를 호출하여 사용자의 기기로 푸시 알림을 전송합니다.
5) 응답을 처리하고 결과를 반환합니다.
참고) 이후 과정에서 웹훅을 활용하여 notification 테이블에 데이터가 추가될 때(INSERT) 위 엣지 함수를 실행시켜 사용자에게 푸쉬알림을 발송하는 기능을 구현할 것입니다.
FCM 비공개키 생성

Firebase > 프로젝트 설정 > 서비스 계정
위 경로에서 비공개키를 생성합니다.
FCM 비공개키 적용

'새 비공개 키 생성' 버튼 클릭 시 위와 같이 json 파일이 다운로드 됩니다.
다운로드된 json파일을 열어 모든 코드를 복사한 후 프로젝트 폴더의 아래 경로에 코드를 붙여넣습니다.

supabase / functions / service-account.json
개발 프로젝트에서 위 경로에 service-account.json 파일을 생성합니다.
이전 비공개키 json 파일에서 복사한 코드를 붙여넣기합니다.
혹은, 해당 json 파일을 위 경로로 옮긴 후 파일명을 수정하여도 무방합니다.
비공개키 이그노어
# Supabase
.branches
.temp
# dotenvx
.env.keys
.env.local
.env.*.local
# Firebase
firebase-adminsdk.json
service-account.json
# Environment variables
.env
.env.*
!.env.example
supabase / .gitignore
위 경로의 파일 내용을 위 코드처럼 변경합니다.
이를 통해 프로젝트를 push할 때 service-account.json 등 보안과 관련된 파일을 무시함으로써 원격 저장소(레포지토리)에 저장되지 않도록합니다.
Supabsae 프로젝트 연결
npx supabase link
개발 프로젝트 터미널에서 위 명령어를 입력합니다.
이 명령어는 로컬 Supabase 프로젝트를 원격 Supabase 프로젝트와 연결(링크)합니다.

1) 프로젝트 선택 후 엔터

2) 데이터베이스 비밀번호 입력 후 엔터
(* 데이터베이스 비밀번호란? : Supabase 프로젝트 생성 시 입력한 데이터베이스 비밀번호입니다. 관련 게시물 > supabase 프로젝트 생성 방법을 참고하세요.)
엣지 함수 배포
npx supabase functions deploy push --no-verify-jwt
개발 프로젝트 터미널에서 위 명령어를 입력합니다.
이 명령어는 'push'라는 이름의 서버리스 함수를 Supabase 클라우드에 배포합니다.
이 명령어를 실행하기 전 Docker Desktop을 필수적으로 실행해야합니다.
명령어 실행 시 Docker Desktop이 필요한 이유
1. 초기화 단계: 명령어가 실행되면 Supabase CLI가 Docker를 사용하여 빌드 환경을 준비합니다.
2. 코드 분석 단계: Docker 컨테이너 내에서 함수 코드와 의존성을 분석합니다.
3. 빌드 단계: Docker를 사용하여 함수 코드와 필요한 모든 의존성을 포함한 컨테이너 이미지를 생성합니다.
4. 패키징 단계: 빌드된 함수를 배포 가능한 형태로 패키징합니다.
5. 배포 단계: 패키징된 함수를 Supabase 클라우드로 업로드합니다.
Docker Desktop은 이 모든 과정에서 일관된 환경을 제공하고, 함수가 로컬 환경의 특성에 영향받지 않도록 격리된 환경에서 빌드와 패키징을 수행하는 데 필수적입니다.


Supabase 웹훅 활성화 / 생성
Supabase 데이터베이스 웹훅 활성화

supabase 프로젝트 > database > Webhooks

웹훅 활성화
Supabase 데이터베이스 웹훅 생성

웹훅 생성

웹훅 이름 : notification-web-hooks
notifications 테이블 선택합니다.

Event를 Insert로 설정합니다.
이로써 notifications 테이블에 데이터가 삽입(INSERT) 시 설정한 엣지함수가 실행됩니다.
참고) 아래 과정에서 실행할 엣지함수를 선택합니다.

웹훅 구성을 Supabase Edge Functions로 설정합니다.

notification 테이블에 데이터가 INSERT될 때 실행시킬 엣지함수를 지정합니다.
이전에 생성 및 배포한 push 엣지 함수를 선택합니다.
이를 통해 notification 테이블에 데이터가 INSERT될 때마다 웹훅을 통해 push 엣지 함수가 실행됩니다.

웹훅 생성
웹 푸쉬 알림 테스트
유저 생성
npx next dev --experimental-https
개발 서버를 HTTPS 로 실행시킵니다.
회원가입

회원가입할 이메일과 패스워드를 입력하고 회원가입 버튼을 클릭합니다.

회원가입한 이메일에서 이메일을 인증합니다.
로그인

이메일과 비밀번호를 입력 후 로그인 버튼을 클릭합니다.
FCM 토큰 발급

FCM 토큰 발급 버튼을 클릭합니다.
uid + FCM 토큰 저장

FCM 토큰 저장 버튼을 클릭합니다.
위 버튼 클릭 시 profiles 테이블에 유저의 uid와 기기의 FCM 토큰이 저장됩니다.
푸시 알림 테스트

전송하고싶은 푸시 알림 메시지 내용을 작성합니다.
푸쉬 알림 테스트 버튼을 클릭합니다.
버튼 클릭 시 유저의 uid와 푸쉬 알림 메시지 내용이 notifications 테이블에 삽입(INSERT)됩니다.
notifications 테이블에 데이터가 INSERT 되었으므로 이전에 설정한 웹훅이 실행되어 push 엣지함수가 실행됩니다.push 엣지함수에서 notifications에 삽입된 데이터를 확인하고 삽입된 데이터의 uid와 일치하는 FCM 토큰 값은 profiles 테이블에서 찾습니다. 이후 해당 FCM 토큰으로 푸쉬 알림을 보냅니다.이 과정을 통해 사용자는 푸쉬 알림을 받습니다.

정상적으로 푸시 알림이 오는 것을 확인할 수 있습니다.
끝.
문제해결
1. Docker Desktop 오류
만약 supabase 프로젝트 실행이나 엣지함수 배포 시 오류가 발생한다면 아래 과정을 따라간 후 다시 명령어를 입력해보세요.
========== 개발 프로젝트 터미널에서 입력
기존 supabase 인스턴스 중지
npx supabase stop
========== CMD에서 입력
사용중인 포트 확인
netstat -ano | findstr 54322
docker 컨테이너 확인
docker ps -a
docker 컨테이너 중지
for /f %i in ('docker ps -a -q') do docker rm %i
docker 컨테이너 삭제
for /f "tokens=*" %i in ('docker ps -a -q') do docker rm %i
docker 컨테이너 확인
docker ps -a
========== 만약 위 과정을 모두 실행해도 여전히 오류가 발생한다면 아래 과정을 따라가세요.
도커 이미지 모두 삭제

docker rmi $(docker images -q) --force
볼륨 모두 삭제

docker volume rm $(docker volume ls -q)
혹은 사용하지 않는 모든 리소스 삭제
docker system prune -a --volumes
'백엔드 > Supabase' 카테고리의 다른 글
[Supabase] 참조키가 2개 이상일 때 테이블 조인 방법 (0) | 2025.04.10 |
---|---|
[Supabase] 수파베이스 구글 로그인 연동 방법 (0) | 2025.04.09 |
[Supabase] 프로젝트 생성 방법 (0) | 2025.04.03 |
[Supabase + Next.js] DB에 저장된 문자열 데이터를 불러올 때 \n 줄바꿈 문제와 해결 방법 (0) | 2025.03.29 |
Supabase 조인 테이블 응답 데이터와 Array.flat() 활용하기 | 배열 평탄화 (0) | 2025.03.17 |