[친구하자] PostgreSQL 호스팅과 ORM, 함께 써야 하는 이유

Supabase(관리형 PostgreSQL)와 SQLAlchemy(ORM)는 경쟁 관계가 아니라 인프라 레이어와 접근 레이어를 각각 담당한다. supabase-py 클라이언트만 쓸 때의 한계, 레이어 분리의 이점, 교체 가능한 구조까지 정리합니다.

데이터베이스를 선택할 때 “어떤 DB를 쓸까”에만 집중하기 쉽지만, 실제로는 어디에 둘 것인가(인프라)코드에서 어떻게 접근할 것인가(접근 방식) 를 따로 결정해야 한다. Supabase와 SQLAlchemy는 각각 다른 레이어를 담당하며, 둘을 함께 쓰면 한쪽을 교체할 때 다른 쪽에 영향을 주지 않는 구조를 만들 수 있다.


들어가며

데이터베이스를 선택할 때 흔히 “어떤 DB를 쓸까”에만 집중합니다. 하지만 실제 개발에서는 두 가지를 따로 결정해야 합니다.

  • 어디에 데이터베이스를 둘 것인가 (인프라)
  • 어떻게 코드에서 접근할 것인가 (접근 방식)

이 두 레이어를 구분하지 않으면, 나중에 둘 중 하나를 바꾸고 싶을 때 전체를 다 뜯어내야 하는 상황이 생깁니다.


1. Supabase는 “어디에”를 해결한다

Supabase는 PostgreSQL을 호스팅해 주는 플랫폼입니다. 서버 설정, SSL 인증서, 백업, 모니터링 같은 인프라 관리를 대신 해 줍니다. 부가적으로 Auth, Storage, Realtime 같은 기능도 제공하지만, 핵심은 관리형 Postgres 서버입니다.

즉, Supabase를 쓴다는 것은 “PostgreSQL을 직접 운영하지 않겠다”는 결정입니다.


2. SQLAlchemy는 “어떻게”를 해결한다

SQLAlchemy는 Python 코드에서 데이터베이스에 접근하는 방법을 제공하는 ORM(Object-Relational Mapper)입니다.

-- SQL을 직접 쓰는 대신
SELECT * FROM users WHERE github_id = 'abc123';
# Python 문법으로
result = await db.execute(select(User).where(User.github_id == github_id))

ORM이 해주는 일은 단순히 “SQL을 Python처럼 쓰게 해주는 것” 이상입니다.

  • 타입 안전성 — 컬럼 타입이 Python 타입으로 매핑되어 IDE 자동완성과 정적 분석이 가능
  • 트랜잭션 관리commit, rollback을 명시적으로 제어
  • 커넥션 풀링 — DB 연결을 재사용해서 성능 최적화
  • 마이그레이션 연동 — Alembic 같은 도구가 모델 정의를 읽어 스키마 변경 이력을 관리

3. Supabase 클라이언트만 쓰면 안 될까

Supabase는 자체 Python 클라이언트(supabase-py)를 제공합니다. 이걸로도 데이터를 읽고 쓸 수 있습니다.

# supabase-py 방식
result = supabase.table("users").select("*").eq("github_id", "abc123").execute()

하지만 이 방식은 내부적으로 REST API(PostgREST)를 통해 데이터베이스에 접근합니다. 이는 몇 가지 제약을 만듭니다.

  • 복잡한 JOIN이나 서브쿼리 표현에 한계가 있음
  • HTTP 오버헤드 존재
  • 세밀한 트랜잭션 제어가 어려움
  • 스키마 마이그레이션 도구와 연동이 자연스럽지 않음

간단한 CRUD에는 충분하지만, 서비스가 커질수록 한계가 드러납니다.


4. 레이어를 분리하면 생기는 이점

인프라 레이어와 접근 레이어를 분리해서 설계하면 한 가지 중요한 유연성이 생깁니다.

인프라를 바꿔도 애플리케이션 코드가 바뀌지 않는다.

Supabase에서 AWS RDS로, 혹은 로컬 Docker Postgres로 옮기더라도 SQLAlchemy 코드는 그대로입니다. DATABASE_URL 환경변수 하나만 바꾸면 됩니다. 반대로, SQLAlchemy를 다른 ORM으로 교체해도 Supabase 연결 설정은 영향을 받지 않습니다.

애플리케이션 코드
        ↓
SQLAlchemy  ← 이 레이어만 알면 DB 벤더에 종속되지 않음
        ↓
PostgreSQL (Supabase / RDS / 로컬 / 무엇이든)

마무리

 SupabaseSQLAlchemy
역할인프라 (어디에)접근 방식 (어떻게)
담당DB 호스팅, 운영, 부가 기능ORM, 트랜잭션, 커넥션 풀, 마이그레이션
교체 가능성RDS, 로컬 Postgres 등으로다른 ORM, 순수 SQL 등으로

둘은 경쟁 관계가 아니라 다른 문제를 각각 해결합니다. “Supabase를 쓰면 ORM이 필요 없다”는 생각은, “AWS를 쓰면 코드를 짤 필요가 없다”는 말과 같습니다.

인프라와 접근 레이어를 분리해 두면, 나중에 한쪽을 교체할 때 다른 쪽에 영향을 주지 않는 유연한 구조를 가져갈 수 있습니다.