Supabase를 내려놓고 AWS로 옮긴 이유

런칭한지 3개월만에 그리고 크리스마스에 인프라를 갈아엎는다는 건 좀 이상한 선택처럼 보일 수 있다. 보통은 조용히 지나가야 하는 날이고, 서비스 입장에서도 '괜히 리스크를 만들지 말자'가 자연스러운 본능이니까. 그런데도 그날을 기준으로 Supabase를 내려놓고 AWS 자체 인프라로 옮겼다.
그 시점에는 더 빠르게 만들기보다 예측 가능한 상태로 운영하기가 더 중요해졌고, Supabase는 그 단계에서 주는 이점보다 제약이 더 커졌다.
Supabase를 싫어해서 떠난 게 아니다. 초기에 Supabase는 최고의 선택이었다. 프로토타이핑을 하면서 살아남아야 했고, 필요한 건 완성된 인프라보다 속도였다. 기능을 만들고, 붙이고, 테스트하고, 반응을 보고, 또 바꾸는 게 우선인 시기에는 BaaS의 속도가 생존 확률을 높여준다. Supabase를 쓰던 시절은 지금 생각해도 합리적이었다.
서비스가 커지면서 제어권이 필요해졌다
문제는 서비스가 커지고 운영의 깊이가 생기면서부터다.
그때부터는 어떤 의사결정이든 이번 주에 빨리 붙일 수 있냐보다 다음주에도 똑같이 안정적으로 굴러가냐가 더 중요한 질문이 된다. 그 질문을 놓고 보면, 관리형 플랫폼의 편리함은 어느 순간부터 제어권을 포기하는 비용으로 바뀌더라.
Supabase 자체가 나쁘다는 얘기가 아니다. 관리형 서비스는 구조적으로 플랫폼 이슈가 생길 때 할 수 있는 대응이 제한적이다. 트래픽이 작을 때는 버티면 된다. 근데 유저가 늘어나면 그 '버티기'가 도박이 되더라.
장애가 한 번만 나도 신뢰가 크게 흔들리는 구간이 오는데, 그때 할 수 있는 게 별로 없다는 감각은 생각보다 피로하게 누적된다. AWS로 옮긴 건 단순히 서버를 직접 띄우는 행위가 아니라, 가용성과 성능을 직접 설계하고 운영하면서 예측 가능한 상태로 만드는 작업이었다.
DB를 직접 만지고 싶었다
Supabase가 PostgreSQL 기반이라서 당연히 강력하다. 하지만 시스템이 커질수록 Postgres를 쓴다는 사실보다 Postgres를 어느 정도까지 내가 통제할 수 있느냐가 더 중요해진다.
세밀한 파라미터 튜닝, 특정 확장(Extension) 도입, 백업/덤프 전략을 비즈니스 요구사항에 맞게 마음대로 구성하는 것. 이런 것들이 필요해지는 순간이 오는데, 그 단계에서 Supabase는 원하는 만큼의 자유도를 주지 못했다. 특히 데이터의 중요도가 커지면서 원하는 방식으로 백업하고, 복구 시나리오를 설계하고, DR(재난 복구)을 돌릴 수 있느냐가 운영의 핵심이 되었다.
지금은 RDS로 옮겨서 워크로드에 맞춘 DB 설정과 백업/복구 시나리오를 직접 운영하고 있고, 그게 정신적으로도 훨씬 덜 불안하다.
Auth, 직접 짜기로 했다
Supabase Auth는 분명 편하다. 문제는 서비스에 맞게 인증 흐름을 확장하려고 할수록, 특히 커스텀 도메인(Custom URL)이나 OAuth 확장 같은 걸 만질수록, 비용과 제약이 체감되기 시작한다는 점이었다.
인증은 제품이 커질수록 부가 기능에서 핵심 인프라로 바뀐다. 핵심 인프라가 외부 서비스의 플랜 구조에 의해 제한되기 시작하면, 그건 개발자의 귀찮음 수준을 넘어서 사업 운영의 구조 문제가 된다.
Supabase Auth 테이블 구조와 최대한 호환되도록 인증 로직을 자체 구현했고, 불필요한 고정 지출을 줄이면서도 서비스 특유의 복잡한 인증 흐름을 더 자유롭게 태울 수 있게 됐다. 편했던 걸 버리고 귀찮은 걸 택한 게 아니라, 장기적으로 귀찮음을 줄이는 방향으로 귀찮음을 선납한 느낌이다.
프론트에서 DB 직접 접근은 차단했다
Supabase는 프론트엔드에서 DB에 직접 접근하는 패턴을 자연스럽게 권장한다. 하지만 보안과 비즈니스 로직의 응집도를 위해 모든 처리를 Backend API를 거치도록 설계해왔다.
프론트에서 DB를 직접 만지게 되면 빠른 건 맞다. 근데 서비스가 커질수록 보안 경계가 흐려지고, 로직이 분산되고, 권한 모델이 복잡해지면서 결국 유지보수 비용이 폭발하기 쉽다. 애초에 DB는 서버 뒤에 숨긴다는 원칙을 가져갔고, 이 구조에서는 Supabase가 제공하는 클라이언트 지향 기능들이 오히려 오버헤드가 되기 시작했다.
AWS로 옮기면서 프론트의 DB 접근을 완전히 차단하고, API 기반 통신 구조를 더 깔끔하게 확립했다. 이건 속도를 늦춘 게 아니라, 이후 속도를 유지하기 위한 구조를 만든 쪽이다.
비용과 운영 가시성
트래픽이 늘기 시작하면 이번 달 Supabase 청구서가 얼마 나올까는 생각보다 큰 스트레스가 된다. 관리형 서비스 특성상 비용이 블랙박스처럼 느껴질 때가 있고, 부가 기능을 추가할 때마다 비용이 붙는 구조는 운영의 예측 가능성을 떨어뜨린다.
반면 AWS는 좋든 싫든 계산이 가능하다. 예약 인스턴스(RI) 같은 선택지도 있고, 비용 모니터링을 세밀하게 붙이면 예산 수립이 명확해진다. CloudWatch로 로그/메트릭을 깊게 끌어올 수 있으니 장애 대응 속도가 달라진다.
장애가 안 나게 해주세요는 바람이고, 장애가 나도 빨리 탐지하고 빨리 복구할 수 있게 하자는 시스템이다. 후자로 가야 하는 단계에 들어와 있었던 거다.
마이그레이션은 빡셌다
마이그레이션은 예쁘게 끝나는 일이 아니다. 특히 세 가지가 가장 빡셨다.
- 데이터 호환성. Supabase Auth 테이블 구조를 유지하면서 자체 로직으로 옮기기 위해 스키마를 정교하게 설계해야 했다.
- min-downtime. 사용자 경험을 망치지 않기 위해 데이터 이전 전략을 촘촘히 짜야 했다.
- 의존성 제거. 클라이언트 코드 곳곳에 스며든 Supabase SDK를 걷어내고 순수 API 기반으로 교체하는 작업이었다.
이런 건 하면 되지 수준이 아니다. 한 번 잘못하면 제품 전체가 불안정해지는 타입의 작업이라서 집중력이 필요했다.
더 멀리 달리기 위한 선택
돌이켜보면 이건 안 하면 안 되는 일이었다. Supabase는 여전히 좋은 도구고, 아이디어를 빠르게 검증할 때는 지금도 최고의 옵션 중 하나다.
다만 서비스가 본 궤도에 오르고, 운영을 장기적으로 책임져야 하는 시점에서는 자체 인프라를 구축하는 일이 결국 예측 가능성과 제어권을 사는 행위가 된다.
12월 25일은 그런 날이었다. 더 빠르게 달리는 날이 아니라, 앞으로 더 멀리 달릴 수 있게 바닥을 다시 까는 날.
이 선택 덕분에, 지금은 성능과 비용이 예측 가능한 변수로 바뀌었다. 그게 얻은 가장 큰 성과다.