Skip to content

feat: Supabase 연결부 및 환경별 스키마 분리 추가 - #22

Merged
KKardy merged 5 commits into
mainfrom
feat/supabase-db-connection
Jun 18, 2026
Merged

KKardy merged 5 commits into
mainfrom
feat/supabase-db-connection

Conversation

@KKardy

@KKardy KKardy commented Jun 6, 2026 •

Copy link
Copy Markdown
Member

📌 Related Issue

GM-2
브랜치명은 다음 테스크부터 신경쓸게요!

🚀 Description

서버가 Supabase(PostgreSQL)에 붙는 연결부를 추가하고, 하나의 Supabase 안에서 Postgres 스키마로 환경(develop/production)을 분리합니다.
기존 main(PR #2)에 이미 들어와 있던 DB 연결부와 충돌하지 않도록, 새로 만들지 않고 기존 DatabaseService에 합치는 방향으로 정리했습니다.

🔧 Supabase 연결 옵션

Supabase는 DB 앞에 연결을 모아 나눠 쓰게 해주는 커넥션 풀러를 둡니다. 포트에 따라 동작이 다릅니다.

포트 방식 용도 env
트랜잭션 풀러 6543 요청마다 연결 교체 평상시 앱 쿼리 DATABASE_URL
세션 풀러 5432 연결을 끝까지 유지 마이그레이션 DATABASE_URL_DIRECT
  • prepare: false — 6543은 연결이 계속 바뀌어 prepared statement를 못 쓰므로 끔.
  • TLS — 코드에 박지 않고 연결 문자열의 ?sslmode=require로 제어. (로컬 postgres는 미지정 → 로컬/테스트 안 깨짐)
  • connection.search_path — 접속 시 바라볼 스키마를 고정해 환경 격리.
  • 마이그레이션은 5432 필수 — 6543(트랜잭션 모드)은 락/멀티스테이트먼트 DDL에서 깨질 수 있어, DATABASE_URL_DIRECT 미설정 시 에러로 막습니다(폴백 안 함).

🗂 환경 분리 (스키마 기반)

  • 선택 기준은 DATABASE_SCHEMA 하나(NODE_ENV에 의존하지 않음). 미설정 시 안전한 기본값 develop, 운영에서만 production 주입.
  • 테이블 DDL은 스키마명 없이 생성 → 마이그레이션 기록을 하나로 유지. 적용 시 search_path로 대상 스키마 결정.
  • 적용 기록 테이블(__drizzle_migrations)은 환경 스키마별로 분리 → dev/prod가 기록을 공유해 한쪽만 반영되는 문제 방지.

✅ 기존 main 대비 변경점

  • DB 모듈 위치 src/database/ → src/infrastructures/db/ 로 이전 (레이어 컨벤션)
  • env는 process.env 직접 읽기 대신 ConfigService(valibot 검증) 경유로 통일
  • env 변수 통일: DB_POOL_SIZE(기본 10→5) 유지, DATABASE_SCHEMA·DATABASE_URL_DIRECT 추가
  • DatabaseService에 Supabase 풀러 연결 옵션 적용
  • 테이블 스키마 컨벤션: per-module src/modules/**/*.schema.ts
  • db:push 제거(versioned generate/migrate와 섞이면 마이그레이션 기록이 꼬임), db:schema-init·db:studio 추가

🧪 마이그레이션 워크플로

bun run db:schema-init   # 환경 스키마 생성 (최초 1회, 5432)
bun run db:generate      # 스키마 변경 → SQL 생성
bun run db:migrate       # 적용 (5432)

🔭 후속 작업 (별도 PR)

  • env 관리: GCP Secret Manager + Pulumi — local/dev/prod secret을 GCP Secret Manager에 보관하고, 서버 기동 시(onModuleInit 등) 환경에 맞는 secret을 받아오는 방식으로 구현 예정. feat: Add pulumi gcp and cloud run deploy workflow #21(Pulumi/Cloud Run) 의존이라 이 PR과 분리합니다. 이 PR은 DATABASE_URL(_DIRECT)이 외부에서 주입된다고 가정합니다.

🧷 테스트

로컬 Postgres로 검증 완료:

  • bun run db:schema-init → 5432 연결 + develop 스키마 생성 확인
  • 실제 DI 스택(ConfigModule→DatabaseService→health) → database: up + graceful shutdown 확인
  • 우리 연결 옵션으로 search_path/current_schema = develop 라우팅 확인
  • bun run test / health indicator 단위 테스트 통과

참고: Supabase 풀러 고유 동작(6543 트랜잭션 모드 + sslmode=require)은 별도 환경에서 수동 확인.

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 개발/운영 환경별 데이터베이스 스키마 분리 지원
    • 마이그레이션/초기 배포용 스키마 생성 스크립트 추가
  • 변경사항

    • DATABASE_SCHEMA 환경 변수 추가(미설정 시 develop, 허용값 develop|production)
    • 데이터베이스 연결 풀 기본값 조정(10 → 5)
    • 마이그레이션 대상 스키마 범위가 환경에 따라 반영되도록 개선
    • 데이터베이스 관련 스크립트 재구성(db:push 제거, db:schema-init/db:studio 추가)
  • 테스트

    • 헬스 체크 테스트 업데이트

@coderabbitai

coderabbitai Bot commented Jun 6, 2026 •

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

다환경(develop/production) 지원을 위해 데이터베이스 스키마 분리 로직을 도입합니다. DbSchema 타입과 resolveDbSchema 함수로 환경별 스키마를 결정하고, Drizzle 마이그레이션에 search_path 옵션을 추가하며, 배포 시 스키마를 초기화하는 스크립트를 추가합니다. 런타임 DatabaseService를 새 위치로 이동하고 스키마 격리를 지원하도록 재구현합니다.

Changes

데이터베이스 다환경 스키마 분리

Layer / File(s) Summary
스키마 결정 로직 및 환경 설정
src/infrastructures/db/db.env.ts, src/config/env.schema.ts
DbSchema 타입과 resolveDbSchema() 함수로 DATABASE_SCHEMA 값을 develop/production으로 정규화하고, 환경 변수 스키마에 DATABASE_SCHEMA 필드를 추가하며 DB_POOL_SIZE 기본값을 10에서 5로 조정합니다.
Drizzle 마이그레이션 설정
drizzle.config.ts
DATABASE_SCHEMA에서 계산된 스키마를 search_path 쿼리 파라미터로 DATABASE_URL에 추가하고, 대상 스키마 글로브 패턴을 ./src/modules/**/*.schema.ts로 변경하며 casing: "snake_case" 설정을 적용합니다.
스키마 초기화 스크립트
scripts/db-schema-init.ts, package.json
배포 시 환경별 스키마를 미리 생성하는 db-schema-init 스크립트를 추가하고, db:push 대신 db:schema-init과 db:studio를 스크립트 목록에 등록합니다.
런타임 데이터베이스 서비스
src/infrastructures/db/database.service.ts
새 위치에서 DatabaseService를 재구현하여 DATABASE_SCHEMA를 읽고 런타임 연결의 search_path를 설정하며, 모듈 종료 시 postgres 클라이언트를 정리합니다.
환경 설정 및 참조 갱신
.env.example, src/app.module.ts, src/health/drizzle.health-indicator.ts, src/health/drizzle.health-indicator.spec.ts
환경 변수 예시에 스키마 분리 관련 가이드를 추가하고, DatabaseService 및 DatabaseModule의 임포트 경로를 ./infrastructures/db/로 갱신합니다.

Sequence Diagram

sequenceDiagram
  participant Deployment as 배포 프로세스
  participant InitScript as db-schema-init
  participant Database as PostgreSQL
  participant Drizzle as Drizzle-Kit
  participant Runtime as 런타임<br/>DatabaseService
  
  Deployment->>InitScript: DATABASE_URL, DATABASE_SCHEMA
  InitScript->>Database: CREATE SCHEMA IF NOT EXISTS {schema}
  Database-->>InitScript: 스키마 생성 완료
  
  Deployment->>Drizzle: db:migrate<br/>(search_path={schema})
  Drizzle->>Database: 마이그레이션 적용
  Database-->>Drizzle: 마이그레이션 완료
  
  Deployment->>Runtime: ConfigService
  Runtime->>Database: search_path={schema}로<br/>연결 설정
  Database-->>Runtime: 연결 완료
  Runtime->>Runtime: 스키마 격리 상태 유지
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • mash-up-kr/Team-MINO-Node#2: 두 PR 모두 DatabaseService와 drizzle.config.ts, 환경변수 스키마(DB_POOL_SIZE, DB 연결 설정)를 중심으로 postgres 연결 구성을 변경하며, 본 PR은 DATABASE_SCHEMA와 search_path로 스키마 분리까지 확장합니다.

Suggested reviewers

  • sudosubin
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 변경사항의 주요 내용(Supabase 연결부 및 환경별 스키마 분리)을 명확하게 요약하고 있으며, 개발자 관점에서 가장 중요한 변화를 잘 나타내고 있습니다.
Description check ✅ Passed PR 설명이 저장소의 필수 템플릿 구조(Related Issue, Description, Done, Notes)를 따르고 있으며, 변경사항의 목적, 기술적 상세사항, 테스트 결과, 후속 작업까지 충실하게 기술되어 있습니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/supabase-db-connection

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

KKardy and others added 3 commits June 8, 2026 23:20
DB 연결부를 레이어 컨벤션에 맞춰 src/database → src/infrastructures/db로
옮기고, import 경로(app.module, health indicator + spec)를 갱신합니다.
중앙 schema 플레이스홀더는 제거하고 drizzle 스키마 소스를 모듈별
*.schema.ts로 전환합니다. 동작 변경은 없습니다.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
하나의 Supabase 인스턴스 안에서 Postgres 스키마로 환경을 가릅니다.

- db.env.ts: resolveDbSchema() — DATABASE_SCHEMA만으로 스키마 결정
  (NODE_ENV 비의존, 미설정 시 안전한 기본값 develop)
- drizzle.config: 테이블 DDL은 스키마명 없이 생성하고 search_path로
  대상 스키마 지정, __drizzle_migrations 기록을 환경 스키마별로 분리.
  마이그레이션은 세션 풀러(DATABASE_URL_DIRECT, 5432) 필수 — 미설정 시 에러.
- scripts/db-schema-init.ts: 환경 스키마 사전 생성(CREATE SCHEMA)
- env.schema: DATABASE_SCHEMA / DATABASE_URL_DIRECT 추가, DB_POOL_SIZE 기본 5
- package.json: db:schema-init / db:studio 추가, db:push 제거
  (versioned generate/migrate와 섞이면 마이그레이션 기록이 꼬임)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- prepare: false (6543 트랜잭션 풀러는 prepared statement 미지원)
- connection.search_path: 환경 스키마 고정 (DATABASE_SCHEMA 기반)
- casing: snake_case (drizzle 인스턴스)
- DB_POOL_SIZE 기본값 5

TLS는 연결 문자열의 sslmode로 제어하므로 로컬 postgres는 영향 없음.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@KKardy
KKardy marked this pull request as ready for review June 8, 2026 14:42
@KKardy
KKardy force-pushed the feat/supabase-db-connection branch from 8f40206 to 8261254 Compare June 8, 2026 14:42
@KKardy KKardy changed the title [WIP] feat: Supabase 연결부 및 환경별 스키마 분리 추가 feat: Supabase 연결부 및 환경별 스키마 분리 추가 Jun 8, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/db-schema-init.ts`:
- Line 37: The top-level call to main() should explicitly handle promise
rejections: wrap the call to main() with a rejection handler (e.g.,
main().catch(err => { console.error("Failed to initialize DB schema:", err);
process.exit(1); })) or replace it with an immediately-invoked async wrapper
that catches errors and exits with a non-zero code; update the invocation of
main() so any thrown/rejected error is logged via console/process logger and the
process exits with code 1.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 58f112cc-c2de-4f82-af76-f35994018e26

📥 Commits

Reviewing files that changed from the base of the PR and between c6b4c8b and 8261254.

📒 Files selected for processing (13)
  • .env.example
  • drizzle.config.ts
  • package.json
  • scripts/db-schema-init.ts
  • src/app.module.ts
  • src/config/env.schema.ts
  • src/database/database.service.ts
  • src/database/schema/index.ts
  • src/health/drizzle.health-indicator.spec.ts
  • src/health/drizzle.health-indicator.ts
  • src/infrastructures/db/database.module.ts
  • src/infrastructures/db/database.service.ts
  • src/infrastructures/db/db.env.ts
💤 Files with no reviewable changes (2)
  • src/database/database.service.ts
  • src/database/schema/index.ts

Comment thread scripts/db-schema-init.ts Outdated
@KKardy KKardy self-assigned this Jun 10, 2026

@sudosubin sudosubin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저희는 Cloud Run 환경이긴 하지만 서버리스/Edge 환경인 것은 아니어서 Pooler transaction mode 보다는 Pooler session mode이 더 좋다는 생각이 들었어요. 그리고 Pooler를 사용하면 약간의 레이턴시가 더 증가하기도 해서 Direct connection을 그냥 사용해보면 더 좋을 것 같아요.

(ipv6 이슈로 연결이 불가하면 그 때 Pooler session mode를 테스트해봐도 될 것 같아요)

@minsour minsour left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

수빈님 리뷰만 보면 될 것 같습니다 👍

sudosubin 리뷰 반영: Cloud Run은 상주 서버라 트랜잭션 풀러 대신
Direct connection(또는 session pooler)이 적합. 이에 맞춰:
- DatabaseService: prepare:false 제거(트랜잭션 풀러 전용 → prepared statement 복구)
- DATABASE_URL_DIRECT 제거, 런타임·마이그레이션 모두 단일 DATABASE_URL 사용
- drizzle.config / db-schema-init: DATABASE_URL 기준으로 정리
- .env.example: Direct connection 우선, IPv6 불가 시 session pooler 폴백 안내

CodeRabbit 반영: db-schema-init main()에 rejection 핸들러 추가.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@sudosubin sudosubin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@KKardy
KKardy merged commit f2e0be3 into main Jun 18, 2026
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants