lifecarelog
프론트엔드

프로젝트마다 DB가 따로면 프론트는 뭐가 달라지나

서비스별로 DB를 분리하면 프론트엔드 화면에서는 클라이언트 인스턴스와 로딩 상태 설계가 달라집니다. 실제로 겪은 구현 패턴을 정리했어요.

7분 읽기

서비스를 하나씩 늘리다 보면 "DB 하나에 다 넣을까, 서비스마다 따로 팔까"를 언젠가 정하게 됩니다. 저는 플랜씨·플랜비·플랜엘처럼 성격이 다른 서비스를 만들면서 서비스당 하나씩 분리하는 쪽을 골랐는데, 백엔드 이야기로만 끝나지 않더라고요. 프론트엔드 화면 코드가 먼저 달라집니다.

클라이언트가 여러 개가 되는 순간

DB가 하나일 때는 createClient()를 한 번 만들어 앱 전체에서 쓰면 끝이었어요. 분리하고 나니 프로젝트 URL도 키도 서비스마다 다릅니다. 여기서 흔한 실수가 컴포넌트 안에서 그때그때 클라이언트를 만드는 겁니다. 직접 해 보니 리렌더마다 새 인스턴스가 생기고, 인증 세션을 붙여 쓰는 화면에서는 세션 복구가 어긋났어요.

그래서 모듈 최상단에서 한 번만 만들고 export 하는 형태로 바꿨습니다.

// lib/db/calculator.ts
import { createClient } from '@supabase/supabase-js'
 
export const calcDb = createClient(
  process.env.NEXT_PUBLIC_CALC_URL!,
  process.env.NEXT_PUBLIC_CALC_ANON_KEY!
)

파일 하나에 서비스 하나. 서비스가 4개면 파일도 4개예요. 늘어난 것 같지만, 어떤 화면이 어떤 DB를 건드리는지가 import 한 줄로 드러나서 오히려 읽기 쉬워졌습니다.

환경변수 분리서비스별 클라이언트 모듈화면에서 import

로딩 상태를 합치면 안 되는 이유

두 서비스 데이터를 한 화면에 같이 보여줄 일이 생깁니다. 여기서 isLoading 하나로 묶으면, 한쪽이 느릴 때 이미 도착한 데이터까지 스켈레톤에 갇혀요. 테스트해 보면 체감 차이가 꽤 큽니다.

React Query를 쓴다면 쿼리 키 앞에 서비스 이름을 붙이고 상태도 따로 두는 편이 낫습니다.

const calc = useQuery({ queryKey: ['calc', 'history'], queryFn: fetchCalcHistory })
const law = useQuery({ queryKey: ['law', 'recent'], queryFn: fetchLawRecent })

calc.isLoading과 law.isLoading을 각 섹션에서 따로 쓰면, 먼저 온 쪽이 먼저 그려집니다. 키 앞머리를 나눠 두면 캐시 무효화도 서비스 단위로 끊을 수 있고요.

실제로 치른 비용

좋은 점만 있진 않았습니다. 정리해 보면 이렇습니다.

  • 환경변수 2배
  • 조인 불가
  • 키 관리 분산
  • 경계 명확

가장 번거로운 건 환경변수입니다. 서비스 하나에 URL과 anon key 2개니까, 4개 서비스면 8개를 로컬·배포 양쪽에 맞춰야 해요. 처음 세팅할 때 10분 정도 걸렸고, 오타 하나로 엉뚱한 프로젝트를 바라본 적도 있습니다. 지금은 클라이언트 모듈 안에서 값이 비었으면 바로 던지게 해 뒀어요.

if (!process.env.NEXT_PUBLIC_CALC_URL) {
  throw new Error('CALC_URL 환경변수가 없습니다')
}

빌드 시점이나 첫 호출에서 바로 터지는 편이, 조용히 404를 받는 것보다 낫습니다.

두 번째는 조인이 안 된다는 점. DB가 다르면 SQL로 묶을 수 없으니 프론트에서 합쳐야 해요. 이건 각오하고 고른 부분이라, 애초에 서로 조인할 일이 없는 단위로 나눴습니다. 플랜씨의 계산 기록과 플랜엘의 검색 이력은 같은 화면에 놓일 수는 있어도 한 쿼리로 묶일 일은 없거든요.

언제 나누고 언제 합칠까

돌려 보니 기준은 단순했습니다. 두 데이터가 한 트랜잭션으로 묶여야 하면 같은 DB, 화면에서만 나란히 보이면 되면 따로. 회원과 결제는 같이, 계산기 기록과 법령 검색 이력은 따로. 이 기준만 지키면 나중에 합치거나 쪼개는 일이 잘 안 생깁니다.

무료 플랜 기준으로는 프로젝트를 여러 개 두는 게 부담이 적어서 시작 단계에서 특히 쓸 만해요. 다만 프로젝트마다 비활동 기간이 지나면 쉬는 상태로 들어가니, 자주 안 쓰는 서비스는 주기적으로 깨워 주는 장치를 함께 붙여 두는 편이 안전합니다.

정리하면 DB 분리는 백엔드 결정처럼 보이지만, 실제로 손이 가장 많이 가는 건 프론트의 클라이언트 모듈 구성과 로딩 상태 설계입니다. 나눌 거라면 화면 코드부터 나눌 준비를 해 두세요.

#supabase#프론트엔드#상태관리

라이프케어로그 서비스가 궁금하신가요?

AI 기반 건강·일정·재활 관리 앱을 직접 써보세요.

서비스 살펴보기

관련 글

댓글

아직 댓글이 없어요. 첫 댓글을 남겨주세요.