최근에는 주로 앱 개발을 하다보니 Next.js에 대해 많이 까먹고 있다는 생각이 들기도 했고, 예전에 관심이 있어 알아봤다가 자료가 부족해 제대로 적용해보지 못해 아쉬움이 남았던 Supabase를 함께 사용할 수 있는 강의를 듣게 되었다. 강의를 듣고, 학습하면서 기억해두고 싶은 내용들을 남겨두려 이렇게 포스팅하게 되었다.
🌱 이 포스트는 해당 강의를 수강한 후 수업 내용을 기반으로 작성되었으며, 이미지 클릭 시 강의 소개 페이지로 이동합니다.
Supabase에 대한 간단한 설명과 장점은 🦕 Supabase란 무엇인가! 포스트에서 정리해보았으니, 이번 포스트에서는 강의를 통해 Supabase를 실제 웹 프로젝트에 간단하게 적용해보면서 느낀 점에 대해 작성해보고자 한다.
Supabase Database를 사용하면 아래 사진처럼 간단하게 PostgreSQL 기반의 DB 테이블을 구현할 수 있다.
표에 필요한 데이터를 채워주면 아래처럼 원하는 데이터를 담은 테이블이 생성된다.
Supabase CLI는 프로젝트를 로컬 환경에서 개발하고, Supabase 플랫폼에 배포하고, 데이터베이스 마이그레이션을 처리하고, 데이터베이스 스키마에서 직접 유형을 생성할 수 있는 도구를 제공한다.
아래의 명령어(window 기준)를 통해 Supabase CLI를 설치하면 로컬 환경에서도 supabase init
과 supabase start
만 사용하면 간편하게 Supabase를 실행시킬 수 있게 된다.
npx supabase login
Supabase API는 데이터베이스로부터 파생되므로 타입 안정적인 API 정의를 생성하기 위해 데이터베이스 인트로스펙션을 사용할 수 있다.
아래의 스크립트를 추가해주면 위에서 Supabase를 통해 생성한 테이블의 데이터를 TypeScript 타입으로 정의하고 types_db.ts
라는 파일명을 가지는 파일로 다운로드 받을 수 있게 된다.
"scripts": {
// ...
"generate-types": "npx supabase gen types typescript --project-id [project_id] --schema public > types_db.ts"
}
project_id
값은 환경변수로 설정한 NEXT_PUBLIC_SUPABASE_URL 값에서 https://
와 .supabase.co
사이의 값을 넣어주면 된다.
🤔 데이터베이스 인트로스펙션(Database Introspection)이란?
- 데이터베이스의 구조를 자동으로 분석하고 탐색하는 과정을 말한다.
- 이를 통해 데이터베이스의 다양한 메타데이터(스키마, 테이블, 컬럼, 인덱스, 뷰, 트리거 등)를 파악할 수 있다.
Supabase SSR은 Server-Side 환경에서 Supabase의 다양한 기능을 쉽게 통합하고 사용할 수 있도록 돕는 도구이다.
Supabase에서는 이 단일 라이브러리로 기존 Supabase Database/Auth/Storage가 지원하던 기능들을 모두 사용할 수 있게 하였다.
npm install @supabase/supabase-js @supabase/ssr
# Home > Project API > Project URL
NEXT_PUBLIC_SUPABASE_URL= ''
# Home > Project API > API Key
NEXT_PUBLIC_SUPABASE_ANON_KEY= ''
# Project Settings > API Settings > Project API keys > service_role
# 어드민에서 사용되므로 외부에 절대 공개하면 안 된다.
NEXT_SUPABASE_SERVICE_ROLE= ''
# Supabase DB Password
NEXT_SUPABASE_DB_PASSWORD= ''
Root Directory에 .env
또는 .env.local
파일을 생성하고 위와 같이 환경 변수를 설정해준다.
Next.js 환경에서 Supabase를 생성하기 위해서는 아래의 두 클라이언트 함수가 구현되어 있어야 한다.
utils
폴더 하위에 supabase
폴더를 생성하고, 아래의 두 유틸 함수를 생성해주면 된다. (함수의 경우 Supabase 공식 문서에서 발췌하였다.)
createBrowserClient
createBrowserClient
는 싱글톤 패턴을 사용하여 createClient
함수 호출 횟수에 관계 없이 하나의 인스턴스만을 생성한다.import { createBrowserClient } from '@supabase/ssr'
export function createClient() {
return createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)
}
createServerClient
import { createServerClient, type CookieOptions } from '@supabase/ssr'
import { cookies } from 'next/headers'
export function createClient() {
const cookieStore = cookies()
return createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
// 쿠키 관련 로직이 담긴다.
},
}
)
}
Root Directory에 middleware
함수를 정의해주어야 한다. 이를 통해 서버 컴포넌트 대신 쿠키를 사용해 만료된 인증 토큰을 새로 고치고 저장할 수 있다.
middleware
설정을 위한 상세한 코드는 여기(공식문서)에서 확인할 수 있다.
middleware
의 역할
supabase.auth.getUser
를 사용하여 인증 토큰을 새로고침한다.request.cookies.set
을 통해 새로고침된 인증 토큰을 서버 컴포넌트에 넘겨서 동일한 토큰에 대한 리프레시를 시도하지 않도록 막는다.response.cookies.set
을 통해 새로고침된 인증 토큰을 브라우저에 넘겨서 이전 토큰을 대체한다.⚠️ 주의할 점
supabase.auth.getUser()
를 사용해야 한다. 이는 매번 Supabase Auth 서버에 요청을 보내 인증 토큰을 재검증하기 때문에 사용하기에 안전하다.supabase.auth.getSession()
을 사용하면 안 된다.Supabase와는 관계 없지만 코드를 치면서 해결했던 오류를 추가로 기록해둔다.
Next.js 14 버전에서 material-tailwind/react 컴포넌트를 사용하자 아래와 같은 메세지와 함께 해당 라이브러리에서 import해온 모든 컴포넌트에 오류가 발생했다.
Property 'crossOrigin' is missing in type ~
찾아보니 라이브러리와 최신 TypeScript 버전 사이에 오류가 있는 것 같았다.
package.json 파일에서 typescript의 버전을 5.2.2로, @types/react의 버전을 18.2.19로 수정하고 npm install
을 다시 해줌으로써 해결할 수 있었다.
혼자 작성하는 코드여서 망설임 없이 해당 방법을 사용했지만 팀 프로젝트였다면 다른 해결 방법을 모색하거나 다른 UI Inventory를 사용했을 것 같다.