콘텐츠로 이동

ADR-0005: DB Layer: sqlc

Umbra 의 Go 코드에서 PostgreSQL 에 접근할 때 sqlc 로 타입 안전한 코드를 생성한다.

Status

Accepted

  • Decided at — 2026-04-13
  • Decided by — Pablo

Context

PostgreSQL 을 선택한 후(ADR-0004) Go 에서의 DB 접근 레이어를 결정해야 한다. 선택 기준:

  • 결제 도메인의 트랜잭션 제어가 명시적
  • SQL 가시성 (옵티마이저 힌트, 인덱스 활용 가능)
  • 타입 안전성 (컴파일 타임에 type mismatch 감지)
  • Atlas 와 책임 중복 없음

후보: sqlc, sqlx, GORM, ent.

Decision

sqlc 를 DB 레이어로 채택한다. 도메인별로 별도 sqlc 패키지를 생성한다.

선택 근거:

  • SQL-first — 모든 쿼리가 .sql 파일에 명시적. N+1 같은 의도치 않은 쿼리가 발생하지 않음
  • 타입 안전 — SQL 에서 Go struct + 함수가 자동 생성되어 컴파일 타임에 mismatch 감지
  • Atlas 와 책임 분리 — Atlas 는 schema 관리, sqlc 는 쿼리. AutoMigrate 중복 없음
  • 결제 도메인 안전성 — 트랜잭션 제어가 명시적이라 ORM 의 자동 트랜잭션 함정 회피
  • 도메인별 패키지 분리db/queries/billing/engine/billing/adapter/persistence/sqlc/ 로 자연 결합

Consequences

Positive

  • 모든 쿼리가 코드 리뷰 대상 (SQL 그대로)
  • 쿼리 성능 튜닝 가능 (인덱스, JOIN 전략 직접 작성)
  • 생성된 코드가 얇아 디버깅 쉬움
  • 도메인별 패키지 분리로 schema 경계 강제

Negative

  • CRUD 쿼리를 직접 작성해야 함 (GORM 대비 보일러플레이트)
  • sqlc generate 가 CI 단계로 추가됨
  • 복잡한 동적 쿼리 (IN list with variable size 등) 는 별도 처리 필요

Neutral

  • sqlc 는 .sql 파일에서 코드 생성만 하므로 런타임 의존성 없음
  • 생성 코드는 git commit 함 (CI 검증, 코드 리뷰 가능)

Alternatives considered

Alternative 1: GORM

Pros

  • CRUD 자동 생성으로 빠른 프로토타이핑
  • 연관관계 Preload 편의

Cons

  • 결제 도메인 트랜잭션 위험 — 자동 생성 트랜잭션이 의도와 다르게 동작 가능
  • 리플렉션 마법, 디버깅 시 실제 SQL 추적 필요
  • AutoMigrate 가 Atlas 와 책임 중복
  • Go 답지 않다는 비판의 대표

Why rejected — 결제 트랜잭션의 안전성이 최우선. GORM 의 자동 생성 SQL 이 의도와 불일치할 위험 허용 불가.

Alternative 2: sqlx

Pros

  • SQL 직접 작성 (가시성 100%)
  • 학습 곡선 매우 낮음
  • database/sql 얇은 래퍼

Cons

  • 타입 안전성 없음 (scan 실패는 런타임 에러)
  • struct 와 SQL 의 동기화 수동
  • sqlc 대비 보일러플레이트 많음

Why rejected — sqlc 가 sqlx 의 장점(SQL 명시성) + 타입 안전성 둘 다 제공. sqlc 가 상위 호환.

Alternative 3: ent

Pros

  • 그래프 기반 스키마
  • 코드 생성으로 타입 안전

Cons

  • 고유 DSL 학습 부담
  • PostgreSQL 고급 기능 (JSONB 조작, CTE) 지원이 ORM 계층으로 추상화
  • 복잡한 쿼리는 raw SQL fallback 필요

Why rejected — 학습 부담과 SQL 추상화가 결제 SaaS 에 부적합.

Compliance

  • db/queries/{domain}/*.sql 에 쿼리 정의
  • sqlc.yaml 에서 도메인별 패키지 분리 설정
  • 생성 코드는 engine/{domain}/adapter/persistence/sqlc/ 에 위치
  • 다른 도메인의 sqlc 패키지를 import 금지 (import 검사)
  • 동적 쿼리는 sqlc 외 squirrel 등 query builder 사용 허용

Revisit triggers

  • sqlc 의 PostgreSQL 신기능 지원이 6개월 이상 지연되면 재평가
  • 쿼리 수가 폭증하여 .sql 파일 관리가 부담되면 대안 검토

References