postgresqljsonbdatabase
PostgreSQL JSONB, 스키마리스의 유혹과 계약
✨ AI 요약
긴 글, 핵심만 먼저 — 이 글을 3줄로 정리해드려요.
조회 42
"이 필드는 구조가 자주 바뀌니까 JSONB로 하자"는 결정은 달콤하다. 마이그레이션 없이 필드를 늘릴 수 있으니까. 하지만 공짜가 아니다.
JSONB가 맞는 자리
- 외부 API의 원본 응답 보관 (웹훅 페이로드, 수집 데이터)
- 사용자 정의 속성처럼 구조를 서비스가 통제하지 않는 데이터
- 읽기 전용에 가깝고, 조건 검색이 드문 메타데이터
공통점은 "구조의 주인이 내가 아니다"라는 것. 반대로 우리 도메인의 핵심 데이터를 JSONB에 넣는 건 대부분 후회로 끝난다.
컬럼이 맞는 자리
JSONB 안의 특정 키로 자주 WHERE/ORDER BY/JOIN 한다면 그건 컬럼이어야 한다. 통계도, 제약(NOT NULL, FK, CHECK)도, 타입 보장도 컬럼에만 있다. "tags를 JSONB로 넣을까 조인 테이블로 뺄까" 고민이라면 — 태그로 검색할 거면 테이블이다.
그래도 쓸 때의 계약
-- 존재/포함 검색은 GIN 인덱스
CREATE INDEX idx_events_payload ON events USING GIN (payload);
-- 특정 키만 자주 찾으면 표현식 인덱스가 더 가볍다
CREATE INDEX idx_events_type ON events ((payload->>'type'));
- 연산자를 구분하자:
->는 JSONB 반환,->>는 텍스트 반환. 비교 시 타입이 달라 인덱스를 놓치는 흔한 원인 - GIN 인덱스는 쓰기 비용이 크다. 쓰기 많은 테이블엔 표현식 인덱스로 좁혀서
- 애플리케이션에서 Zod 등으로 스키마 검증을 걸어라. DB가 안 지켜주는 구조는 코드가 지켜야 한다
한 줄 요약
JSONB는 "구조를 모르는 데이터의 보관함"이지 "마이그레이션 회피 수단"이 아니다. 검색하는 순간 컬럼으로 승격 — 이 규칙 하나면 대부분의 후회를 피한다.