Postgres의 JSONB를 사용한 비정형 데이터 저장 및 인덱싱
Ethan Miller
Product Engineer · Leapcell

소개
오늘날의 데이터 중심 세계에서 애플리케이션은 빈번하게 다양하고 진화하는 데이터 구조에 직면합니다. 구조화된 데이터에 탁월하지만, 사용자 프로필, 센서 판독값 또는 구성 설정과 같은 정보의 반구조적이거나 완전히 비정형적인 특성을 수용하는 데 어려움을 겪는 경우가 많습니다. 스키마 마이그레이션에 대한 끊임없는 필요성과 미리 정의된 열의 경직성은 민첩한 개발 및 동적 데이터 모델에 상당한 병목 현상이 될 수 있습니다. 이러한 어려움은 많은 개발자를 NoSQL 데이터베이스로 이끌었지만, 이미 PostgreSQL의 강력함과 신뢰성을 활용하고 있는 사람들에게는 강력한 네이티브 솔루션이 있습니다. 바로 JSONB 데이터 유형입니다. 이 글에서는 PostgreSQL에서 JSONB를 사용하여 비정형 데이터를 저장하고 효율적으로 인덱싱하는 것의 강력한 이점을 살펴보고, 유연성과 트랜잭션 무결성이라는 두 가지 장점을 모두 제공하는 방법을 보여줍니다.
JSONB 및 핵심 개념 이해
이점들을 살펴보기 전에 관련 핵심 용어를 명확히 이해해 봅시다.
- 비정형 데이터: 미리 정의된 데이터 모델이 없거나 미리 정의된 방식으로 구성되지 않은 데이터입니다. 예시에는 텍스트 문서, 이미지, 오디오, 비디오 또는 이 맥락에서는 필드가 레코드마다 다를 수 있는 유연한 JSON 문서가 포함됩니다.
- JSON(JavaScript Object Notation): 사람이 읽고 쓰기 쉬우며 기계가 파싱하고 생성하기 쉬운 경량 데이터 교환 형식입니다. 이름/값 쌍의 컬렉션(객체)과 값의 순서 있는 목록(배열)으로 구성됩니다.
- JSONB(JSON Binary): PostgreSQL에서 JSON 데이터를 위한 이진 저장 형식입니다. 일반
JSON
유형은 입력 텍스트의 정확한 복사본을 저장하는 반면,JSONB
는 JSON 데이터의 분해된 이진 표현을 저장합니다. 이는JSONB
가 처리가 더 효율적이고(검색 시 재파싱 불필요), 인덱싱을 지원하며, 공백 및 키 순서를 더 간결하게 저장한다는 것을 의미합니다.
JSON
과 JSONB
의 근본적인 차이는 매우 중요합니다. JSON
은 본질적으로 JSON을 포함하는 텍스트 필드인 반면, JSONB
는 JSON의 구조와 내용을 이해하는 독단적이고 최적화된 데이터 유형입니다. 이러한 이해는 쿼리 및 인덱싱에 대한 강력함을 가능하게 합니다.
JSONB 사용의 이점
PostgreSQL에 JSONB
를 통합하면 비정형 및 반구조화된 데이터를 관리하는 데 여러 가지 중요한 이점이 있습니다.
유연성 및 스키마 진화
JSONB
열을 사용하면 동일한 테이블 내의 행마다 구조가 다를 수 있는 문서를 저장할 수 있습니다. 이렇게 하면 모든 가능한 속성에 대한 엄격한 스키마 정의가 필요 없게 되어, 비용이 많이 드는 스키마 마이그레이션 없이 진화하는 애플리케이션 요구 사항에 데이터베이스를 매우 적응시킬 수 있습니다.
예시: 서로 다른 사용자마다 다른 세트의 개인화된 설정을 가질 수 있는 사용자 기본 설정을 저장합니다.
CREATE TABLE users ( id SERIAL PRIMARY KEY, username VARCHAR(50) UNIQUE NOT NULL, preferences JSONB ); -- 사용자 1: 알림 설정이 있음 INSERT INTO users (username, preferences) VALUES ('alice', '{"theme": "dark", "notifications": {"email": true, "sms": false}}'); -- 사용자 2: 언어 및 시간대 설정이 있음 INSERT INTO users (username, preferences) VALUES ('bob', '{"language": "en-US", "timezone": "America/New_York"}'); -- 사용자 3: 나중에 다른 구조를 가질 수 있음 INSERT INTO users (username, preferences) VALUES ('charlie', '{"privacy_settings": {"data_sharing": false, "tracking": true}}');
여기서 preferences
열은 각 사용자마다 완전히 다른 JSON 구조를 가질 수 있어 엄청난 유연성을 제공합니다.
풍부한 쿼리 기능
PostgreSQL은 JSONB
데이터를 쿼리하기 위해 특별히 설계된 강력한 연산자와 함수 세트를 제공합니다. SQL 쿼리 내에서 직접 JSON 문서의 내부 요소를 필터링, 추출 및 조작할 수 있습니다.
->
및->>
: JSON 객체 필드를 (각각 JSONB 또는 텍스트로) 추출합니다.#>
및#>>
: 경로에서 JSON 객체 필드를 (각각 JSONB 또는 텍스트로) 추출합니다.@>
: 왼쪽 JSONB 값이 오른쪽 JSONB 값을 포함하는지 확인합니다.?
: 문자열이 JSONB 값의 최상위 키로 존재하는지 확인합니다.?|
: 문자열 목록 중 하나라도 최상위 키로 존재하는지 확인합니다.?&
: 문자열 목록이 모두 최상위 키로 존재하는지 확인합니다.JSONB_ARRAY_ELEMENTS()
: JSON 배열을 JSONB 값 집합으로 확장합니다.
예시: 'dark' 테마를 선호하거나 이메일 알림이 활성화된 사용자를 찾습니다.
-- 'dark' 테마가 있는 사용자 찾기 SELECT username, preferences FROM users WHERE preferences->>'theme' = 'dark'; -- 이메일 알림이 활성화된 사용자 찾기 SELECT username, preferences FROM users WHERE preferences->'notifications'->>'email' = 'true'; -- 기본 설정에 'language' 또는 'timezone' 키가 포함된 사용자 찾기 SELECT username, preferences FROM users WHERE preferences ?| ARRAY['language', 'timezone'];
효율적인 인덱싱으로 성능 향상
JSONB
의 가장 강력한 기능 중 하나는 인덱싱이 가능하다는 점이며, 이는 대규모 데이터 세트에서 쿼리 성능을 크게 향상시킵니다. PostgreSQL은 JSONB
를 위한 다양한 유형의 인덱스를 제공합니다.
- GIN(Generalized Inverted Index) 인덱스: JSONB 문서 내의 키 또는 키-값 쌍을 쿼리하는 데 이상적입니다.
jsonb_ops
(기본 GIN): JSONB 문서의 모든 키와 값을 인덱싱합니다.@>
(포함) 또는?
(키 존재) 연산자에 유용합니다.jsonb_path_ops
: 더 큰 JSON 조각이나 경로를 비교할 때, 특히@>
(포함) 연산자 확인에 더 효율적입니다.?
또는?|
연산자는 지원하지 않습니다.
예시: 더 빠른 조회를 위해 GIN 인덱스를 만듭니다.
-- preferences JSONB의 모든 키와 값 인덱싱 CREATE INDEX idx_users_preferences_gin ON users USING GIN (preferences jsonb_ops); -- 쿼리 패턴을 알고 있다면 특정 경로 또는 키 인덱싱 -- 테마별로 자주 쿼리하는 경우: -- 이 접근 방식은 특정 쿼리에 대해 전체 jsonb_ops 인덱스보다 빠른 식을 인덱싱합니다. CREATE INDEX idx_users_preferences_theme ON users ((preferences->>'theme')) WHERE preferences->>'theme' IS NOT NULL;
idx_users_preferences_gin
을 사용하면 SELECT username FROM users WHERE preferences @> '{"theme": "dark"}'
쿼리가 인덱스를 사용하여 검색을 크게 가속화합니다.
원자성 및 트랜잭션
많은 NoSQL 솔루션과 달리 PostgreSQL의 JSONB
는 관계형 데이터베이스의 전체 트랜잭션 컨텍스트 내에서 작동합니다. 이는 매우 유연한 데이터 구조를 다룰 때에도 데이터 무결성을 보장하는 완전한 ACID(원자성, 일관성, 격리성, 내구성) 속성을 제공한다는 것을 의미합니다. JSONB 필드를 수정하는 작업이 실패하면 전체 트랜잭션을 롤백할 수 있습니다.
하이브리드 데이터 모델
JSONB
는 동일한 테이블 내에서 전통적인 열(id
, username
등)에 구조화된 데이터를 저장하고 JSONB
열에 비정형 데이터를 저장할 수 있는 강력한 하이브리드 데이터 모델을 가능하게 합니다. 이를 통해 단일하고 일관된 시스템에서 관계형 및 문서 지향 접근 방식의 강점을 모두 활용할 수 있습니다. 예를 들어, 필수적이고 자주 쿼리되는 속성은 인덱싱된 고정 열에 저장하고, 덜 구조적이거나 진화하는 세부 정보는 JSONB
에 저장할 수 있습니다.
애플리케이션 시나리오
- 사용자 프로필 및 기본 설정: 지속적인 스키마 변경 없이 다양한 사용자 설정, 연락처 세부 정보 및 사용자 지정 속성을 저장합니다.
- 전자 상거래 제품 카탈로그: 다양한 사양을 가진 제품(예: 전화기는 저장 공간과 RAM, 티셔츠는 크기와 색상)을 처리합니다.
- 로깅 및 이벤트 데이터: 구조가 자주 변경될 수 있는 유연한 이벤트 페이로드 또는 로그 항목을 저장합니다.
- 센서 데이터: 잠재적으로 다른 데이터 포인트를 제공하는 다양한 센서에서 텔레메트리 데이터를 기록합니다.
- 구성 관리: 동적 응용 프로그램 또는 마이크로서비스 구성을 저장합니다.
결론
PostgreSQL의 JSONB
데이터 유형은 관계형 데이터베이스의 강력함과 신뢰성을 포기하지 않고도 비정형 및 반구조화된 데이터를 관리하기 위한 강력하고 우아한 솔루션을 제공합니다. 스키마 진화에 대한 탁월한 유연성, 강력한 쿼리 기능, 성능을 위한 효율적인 인덱싱을 모두 완벽하게 트랜잭션 가능한 환경 내에서 제공합니다. JSONB
를 채택함으로써 개발자는 데이터 무결성과 쿼리 속도를 유지하면서 변화하는 데이터 요구 사항에 적응하는 민첩한 애플리케이션을 구축할 수 있습니다. 실제로 관계형 세계와 문서 세계 사이의 간극을 메우는 다목적 도구입니다.