일단 이 기술스택을 잘 이해하기 위해서는 Supabase, Next.js에 대한 오해를 바로잡는 게 제일 우선이라고 생각한다. 이 오해들을 바로 잡지 못하면, 혼란스러울 수 있다.
오해 1: Next.js는 프론트엔드 프레임워크다?
Next.js는 프론트엔드 프레임워크가 아니다. Next.js는 풀스택 웹 애플리케이션을 구축하기 위한 프레임워크다. 이 사실로부터 기본적인 마인드셋이 장착되어야한다.
모든 자바스크립트(타입스크립트) 코드(모듈)는 서버 런타임에서 실행되는 것이 기본값이다.
이건 *.tsx, *.jsx 와 같은 확장자로 작성되는 React Component에도 마찬가지다. 여기서 의아한 부분이 생길 수 있다. "React는 브라우저에서 자바스크립트로 HTML을 만드는 클라이언트 사이드 렌더링인데?"라는 의문이다.
안타깝게도 이건 낡은 지식이다. React 컴포넌트는 더 이상 클라이언트 사이드에서만 실행되지 않는다. React 18부터 RSC(React Server Component)라는 기술이 도입되었고, 말 그대로 컴포넌트를 클라이언트가 아닌 서버에서 미리 렌더링하는 기술이다. 따라서, RSC는 Next.js에서만 쓸 수 있는 것도 아니다. 다만 Next.js가 가장 RSC를 잘 구현해냈을 뿐..
→ use client; 라는 해괴망측한 키워드가 왜 생겼는지 이해가 될 수도 있다.
오해 2: Supabase는 프론트엔드에서 데이터베이스를 직접 제어하는 도구다?
Supabase는 Postgres에 붙어서 REST API를 제공하는 PostgREST를 애플리케이션 개발자가 쉽게 사용할 수 있도록 얇은 레이어를 제공하는 SaaS(또는 Baas)다. 여기서 말하는 얇은 레이어를 코드 수준에서는 Supabase SDK라고 보면 된다.
기본적으로 나는 Supabase SDK를 프론트엔드에서 호출하는 것을 절대절대절대하지 않는다.
이유1: RLS(Row Level Security)
백엔드 서버를 별도로 하나 띄우지 않고도 백엔드 로직(CRUD)이 포함된 어플리케이션을 만들 수 있기 때문에, 일반적인 백엔드와 다르게 supabase는 RLS를 많이 쓰도록 권장되어있고 이게 큰 장점 중 하나일 "수도" 있다.
하지만, 진짜 큰 문제는 디버깅이다. RLS로 인한 문제 발생 시, 내 애플리케이션의 코드 수준이 아닌 Supabase를 통해 문제를 진단하고, 해결해야한다. 이는 LLM에게도 복잡한 문제로 다가올 수 있다. 로그를 확인해보고, RLS 규칙을 찾아보고, 특정 사용자의 정보를 확인해야하기 때문이다.
게다가 제어권이 개발자에게 있어야 할 비즈니스 로직이 RLS로 넘어가서 단위 테스트 작성에도 어려움이 있다.
그래서 나의 경우, 차라리 RBAC 개념을 나타낸 테이블 하나를 두고, 애플리케이션 코드 수준에서 권한을 제어하는 것을 선호한다.
이유 2: DB와 강결합
DB 변경에 프론트엔드 코드가 죽는다. 백엔드 애플리케이션이면 그럴 수도 있지라며 이해하겠지만, 프론트엔드 애플리케이션이 DB에 강결합되도록 설계를 하는 건… 굳이 추가 설명이 필요하지 않을 것 같습니다.
여담
나는 사실 Next.js 풀스택으로 인한 인지 혼란에 큰 고통을 받았던 사람이다. 그런 이유로 최근에는 새로운 조합의 기술을 선택하고 있다.
- DB: Drizzle ORM과 Supabase에 붙은 PostgreSQL, 이유는 AWS보다 저렴하고, DB를 Web UI로 보기 편하면서 Auth가 매우 맘에든다. 단, Supabase SDK를 통한 Data API는 비활성화한다. 이렇게 하면, Supabase SDK를 통한 HTTP 요청이 불가능하다.
- Backend: Hono.js
- Frontend: Vite + React SPA
