본문 바로가기
C.W.K.
Stream
Lesson 02 of 10 · published

JSONB가 도움일 때와 게으름일 때

~12 min · extensions, jsonb

Level 0스키마 새싹
0 XP0/86 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

쓰기에 알맞은 세 경우

  1. 여러 출처의 이벤트나 감사 기록처럼 모양이 실제로 달라져.
  2. 가능한 속성이 50개여도 각 행은 5-10개만 쓰는 희소 데이터야.
  3. 사용자 설정처럼 키 집합이 시간에 따라 진화해.

피해야 할 세 핑계

마이그레이션을 피하려고, 막연히 유연하다는 이유로, ORM이 쉽게 지원한다는 이유로 모든 값을 JSONB에 넣지 마. 검증 부담을 모든 소비자에게 떠넘기게 돼.

안정된 열과 가변 영역을 함께 써

식별자·종류·시각처럼 안정된 값은 NOT NULL·CHECK·외래 키가 있는 열에 두고, 정말 달라지는 payload만 JSONB에 둬. 관계형 정합성과 JSON 유연성을 동시에 얻는 가장 흔한 답이야.

Code

안티패턴: 모든 값을 JSONB에 넣기·sql
-- 이거 하지 마
CREATE TABLE everything (
    id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    data JSONB NOT NULL  -- 어깨 으쓱
);
-- 필수 필드 NOT NULL 없음, FK 없음, 타입 안전 없음, 제약 없음.
안정된 열과 유연한 JSONB를 함께 쓰기·sql
CREATE TABLE events (
    id          INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    user_id     INTEGER NOT NULL REFERENCES users(id),
    event_type  TEXT NOT NULL CHECK (event_type IN ('click','view','signup','purchase')),
    occurred_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    payload     JSONB NOT NULL DEFAULT '{}'::jsonb  -- 타입별 추가
);

CREATE INDEX events_user_id_idx ON events (user_id);
CREATE INDEX events_payload_gin ON events USING gin (payload);

Exercise

제어할 수 있는 JSONB 열을 골라 행의 90%에 존재하는 키를 나열해. 자주 있는 키는 실제 열로 올리고 정말 드문 키만 JSONB에 남기는 마이그레이션을 설계해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.