C.W.K.
Stream
Lesson 01 of 10 · published

JSONB: 반정형 데이터, first-class

~14 min · extensions, jsonb

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

Relational + document 하이브리드

JSONB 가 PostgreSQL 의 binary 인코딩 JSON 타입. JSON (텍스트 그대로 저장) 과 다르게, JSONB 가 insert 시 빠른 binary 형태로 파싱, 인덱싱 (GIN) 지원, 풍부한 연산자 셋 제공. "MongoDB 필요한가?" 대부분 질문의 답.

외울 가치 있는 연산자

  • -> 필드 접근 (JSONB 반환): data->'user'.
  • ->> TEXT 로 필드 접근: data->>'name'.
  • @> 포함: data @> '{"type":"click"}'.
  • ? 키 존재: data ? 'email'.
  • jsonb_path_exists(data, '$.orders[*] ? (@.total > 100)') SQL/JSON path 쿼리.

JSONB 쓸 때와 안 쓸 때

서브 오브젝트 모양 진짜 다양할 때 JSONB (이벤트 payload, 외부 API 응답, 설정 blob). 스키마 설계 회피 수단으로 JSONB 회피 — 모든 행에 같은 5 필드 있으면 그건 적절한 타입과 제약 있는 진짜 컬럼이어야.

Code

JSONB 생성 + 쿼리·sql
CREATE TABLE events (
    id   INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    occurred_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    data JSONB NOT NULL
);

CREATE INDEX events_data_gin ON events USING gin (data);

INSERT INTO events (data) VALUES
('{"type":"click","page":"/home","user_id":42}'),
('{"type":"signup","plan":"pro","user_id":43}'),
('{"type":"click","page":"/blog","user_id":42}');

-- Containment 쿼리 (GIN 사용)
SELECT data->>'page' AS page, COUNT(*)
FROM   events
WHERE  data @> '{"type":"click"}'
GROUP  BY 1;

-- SELECT 의 필드 접근
SELECT id, data->>'type' AS event_type, (data->>'user_id')::int AS user_id
FROM   events;
JSONB 필드 update·sql
-- 필드 설정 또는 교체
UPDATE events SET data = jsonb_set(data, '{plan}', '"enterprise"') WHERE id = 2;

-- 필드 제거
UPDATE events SET data = data - 'page' WHERE id = 1;

-- 두 JSONB document 병합 (충돌 시 오른쪽 이김)
UPDATE events SET data = data || '{"reviewed": true}'::jsonb WHERE id = 1;

External links

Exercise

테이블에 JSONB metadata 컬럼 추가. 다양한 키로 행 insert. @> 로 특정 키/값 포함 행 쿼리. GIN 인덱스 추가; EXPLAIN 전후 비교.

Progress

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

댓글 0

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

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