Supabase 사용하기 With Vite + React + TypeScript

이어진·2025년 2월 12일
0

타입스크립트

목록 보기
5/5
post-thumbnail

오늘은 Supabse 사용기에 대해 포스팅하겠습니다.

Expense-Tracker 프로젝트에서 사용자가 수입 및 지출을 입력하면 데이터베이스에 저장되도록 하기 위해 Supabase를 채택했습니다.

채택한 이유는 다음과 같습니다.

  1. API Request의 횟수 무제한

Firebase는 read, write, delete에 요청에 대해 제한이 있습니다. 또한 가장 큰 문제는 개발 상황에서 api request가 제대로 기능하는지 계속해서 확인할 텐데, Firebase Database 탭에 접근하는 것만으로도 document read 카운트로 집계됩니다. 2만회? 5만회? 금방입니다...

  1. PostgreSQL을 기반으로한 오픈소스 데이터베이스
    Supabase 는 PostgreSQL을 기반으로 한 오픈소스 데이터베이스를 사용합니다. 관계형 데이터베이스이므로, 스키마를 정의하고 테이블 간의 관계를 설정할 수 있습니다. 이는 복잡한 데이터 모델링과 SQL 기반의 고급 쿼리에 강점을 갖습니다.
    제 프로젝트에서는 그렇게 복잡한 모델링이 필요하진 않지만, 사용해 본다면 경험이 될 것이라 생각했습니다.

Supabase

회원 가입

Supabase 로 들어가서, 회원 가입 및 로그인을 진행합니다.

React Supabase CRUD Tutorial 해당 링크의 유튜버를 따라 진행해줍니다~

테이블 생성

Table Editor 탭에서, New Table을 생성해줍니다.

칼럼 생성

저는 이렇게 작성해줬습니다.

  • input_type : 수입 및 지출
  • amount : 수입 및 지출액
  • place : 거래처
  • memo : 메모
  • date : 거래 날짜
  • category : 카테고리

VSCode

이제 vscode로 넘어와서 supabase 설정을 해줍시다.

터미널에 아래 명령어를 입력해줍니다. (저는 pnpm을 사용합니다.)

pnpm install supabase
supabase gen types typescript --project-id 여러분의프로젝트ID > database.types.ts

프로젝트 ID는 Project Setting 탭에서 확인할 수 있습니다.
저렇게 하면 데이터베이스의 타입들을 자동으로 생성해줄 수 있습니다. 만약 supabase에서 타입을 변경해도, 같은 명령어를 입력하면 갱신해서 가져올 수 있습니다.

Supabase 초기 타입 정의

typescript를 사용하므로 type 정의는 중요합니다.
supabase 폴더를 하나 만들어, supabase.ts 파일을 생성해줍니다.

import { Database } from '../database.types';
import { createClient } from '@supabase/supabase-js'

const supabaseUrl = import.meta.env.VITE_APP_SUPABASE_URL
const supabaseKey = import.meta.env.VITE_APP_SUPABASE_API_KEY

if (!supabaseUrl || !supabaseKey) {
	throw new Error('Missing Supabase environment variables')
}

const supabase = createClient<Database>(supabaseUrl, supabaseKey)

export default supabase

Database 타입은 위에서 supabase gen types ~~ 명령어로 생성해준 파일에서 가져옵니다. 조금 더 안정적이게 되겠죠.

.env

VITE_APP_SUPABASE_URL, VITE_APP_SUPABASE_API_KEY가 뭐지? 하시는 분들이 계실 수도 있습니다. API Key를 노출하는 것은 보안상 좋지 않습니다. 때문에 루트 경로에 .env 파일을 생성하고, .gitignore에 추가해준 뒤, 본인의 URL과 API Key를 작성해줍니다.

VITE_APP_SUPABASE_URL = https://본인URL.supabase.co
VITE_APP_SUPABASE_API_KEY = abcdsedfafeaf~~~

URL과 API Key는 Home 탭에서 아래로 살짝 내리면 찾을 수 있습니다.

Supabase with react-query

저는 react-query를 사용해서 Supabase를 사용해 볼 겁니다.

1. api 파일 만들기

api 폴더를 하나 만들어서, api.ts 파일을 하나 생성합니다. 이제 우리는 이 파일에서 api 로직을 관리하게 됩니다.

interface RequestValue {
  input_type: string
  category: Json
  amount: number
  place: string
  memo: string
  date: string
}

const categoryToJson = (category : ICategory): Json => ({
  id: category.id,
  name: category.name,
  value: category.value,
})

export const addData = async (input: IInputFormData) => {
  const requestData : RequestValue = {
    input_type: input.inputType,
    category: categoryToJson(input.category),
    amount: input.amount,
    place: input.place,
    memo: input.memo,
    date: input.date,
  }

  const { data, error } = await supabase
    .from('expenseList')
    .insert(requestData)

  if (error) {
    throw error
  } else {
    console.log('Data inserted Success')
  }
  return true
}

IInputFormData 라는 형식에 맞춰 input을 받고, RequestValue 타입에 맞춰 supabase의 expenseList 테이블에 데이터를 전송합니다.

2. api 호출

이제 api를 호출할 컴포넌트로 이동합니다. 저는 InputForm 이라는 컴포넌트에서 onSubmit 으로 넘겨줄 겁니다.

const InputForm = ({ children }: { children: React.ReactNode }) => {
	const { handleSubmit } = useFormContext<IInputFormData>()

	const mutation = useMutation({
		mutationFn: addData,
		onSuccess: () => {
			alert('저장이 완료되었습니다.')
		},
		onError: () => {
			alert('저장에 실패하였습니다. 다시 시도해주세요.')
		},
	})

	const onSubmit: SubmitHandler<IInputFormData> = (data) => {
		mutation.mutate(data)
	}

	return (
		<div className='pt-[40px] pb-[60px] px-10'>
			<form onSubmit={handleSubmit(onSubmit)} className='h-full'>
				{children}
				<button type='submit'>
					확인
				</button>
			</form>
		</div>
	)
}

데이터를 저장할 때는 useMutation 을 사용합니다. mutation할 함수를 정해주고, 성공 및 실패 각각에 대한 로직을 간단하게 작성해줍니다.

결과

테이블에 제대로 데이터가 들어오는 것을 확인할 수 있습니다!



참고
https://www.youtube.com/watch?v=tW1HO7i9EIM&t=1517s
https://hanbin-sla.tistory.com/entry/Supabase-vs-Firebase
https://supabase.com/docs/reference/javascript/typescript-support

profile
코딩하는 말하는 감자

0개의 댓글