
PostgreSQL 17 업데이트: VACUUM 메모리 최적화와 JSON_TABLE 활용법
데이터베이스를 운영하다 보면 누구나 한 번쯤 겪는 골칫거리가 있습니다. 데이터가 쌓이고 변경될수록 백그라운드 청소 작업인 VACUUM이 서버 자원을 지나치게 소모하는 현상, 그리고 비정형 데이터를 조회할 때 길어지는 JSON 전용 문법입니다. PostgreSQL 17은 이 두 가지 고질적인 병목을 정면으로 해결하는 핵심 개선을 담았습니다.
VACUUM 메모리 소모를 최대 20배 줄인 비결
PostgreSQL은 다중 버전 동시성 제어 방식을 사용하므로 데이터가 수정되거나 삭제되면 기존 행을 바로 지우지 않고 비활성 상태로 둡니다. 이 쓸모없어진 행을 정리해 저장 공간을 재사용할 수 있게 만드는 작업이 바로 VACUUM입니다.
기존 버전의 VACUUM은 정리가 필요한 행의 위치 정보를 평면 배열 형태로 메모리에 저장했습니다. 이 방식은 대용량 테이블에서 작업 메모리를 빠르게 잠식했습니다. 메모리가 한도에 도달하면 테이블 청소를 잠시 멈추고 인덱스 청소를 강제로 수행한 뒤 다시 테이블로 돌아오는 다중 패스 방식이 발생했습니다. 이 과정에서 과도한 디스크 입출력이 일어나 전체 데이터베이스 응답 속도가 떨어지는 문제가 잦았습니다.
PostgreSQL 17은 정리 대상 행의 식별자를 추적하는 내부 메모리 자료구조를 기수 트리 구조 기반의 TID 저장소로 전면 교체했습니다. 동일한 블록의 행 주소를 압축해 저장하기 때문에 메모리 소모량이 기존 대비 최대 20배까지 줄어듭니다. 기존에 존재하던 작업 메모리 상한선 제한도 해제되어, 동일한 메모리 크기로도 수많은 인덱스를 한 번에 청소할 수 있게 되었습니다. 덕분에 쓰기 작업이 많은 대형 시스템에서도 정체 없는 안정적인 청소 주기를 유지할 수 있습니다.
복잡한 JSON 조회를 단순화하는 JSON_TABLE
그동안 PostgreSQL에서 JSONB 컬럼 안의 배열이나 중첩 필드를 표 형태로 풀어서 보려면 번거로운 함수들을 엮어서 사용해야 했습니다. jsonb_array_elements로 배열을 펼치고 라테럴 조인을 건 뒤 연산자로 필드를 일일이 추출하는 방식은 쿼리를 작성하기도 어렵고 읽기도 까다로웠습니다.
PostgreSQL 17에 표준 SQL 규격인 JSON_TABLE 함수가 도입되면서 이 흐름이 깔끔하게 정리되었습니다. JSON 문서와 경로 표현식을 넘겨주면 이를 가상의 관계형 테이블 행과 열로 바로 투영해 줍니다.
PostgreSQL 17에서 검증한 JSON_TABLE 기본 사용 예시입니다.
복잡한 중첩 함수 체이닝 없이 각 경로의 데이터를 일반 데이터베이스 컬럼 타입으로 지정해 곧바로 필터링하거나 기존 관계형 테이블과 직접 조인할 수 있습니다.
어떤 프로젝트에 도입해야 할까
로그 수집 테이블이나 주문 이력처럼 잦은 데이터 변경과 삭제가 일어나는 서비스를 운영 중이라면 PostgreSQL 17 업그레이드만으로도 유지보수 비용을 크게 낮출 수 있습니다. 별도의 설정 튜닝 없이도 메모리 누수 위험과 VACUUM 지연 현상이 눈에 띄게 완화되기 때문입니다.
외부 API 응답을 JSONB 컬럼에 그대로 보관한 뒤 내부 배치 작업에서 정형 데이터로 변환해 집계하는 애플리케이션에서도 유용합니다. 복잡한 서브쿼리와 라테럴 조인이 단순한 테이블 함수 호출로 바뀌어 쿼리 유지보수가 쉬워집니다.
단순한 단일 테이블 조회 위주의 소규모 정적 웹사이트라면 서둘러 마이그레이션할 필요는 없습니다. 대규모 트랜잭션이 발생하는 실서비스 환경이나 비정형 데이터 분석 비중이 높은 팀부터 순차적으로 업그레이드를 검토해 보길 권합니다.
