PostgreSQL 18 DBA 가이드: 비동기 I/O·uuidv7·OAuth로 달라진 운영 기준
이 챕터를 쓰는 이유
PostgreSQL 18.0은 2025년 9월 25일 GA가 됐고, 18.4 보안 패치는 2026년 5월 14일에 배포됐다(CVE 11개 포함). 이 챕터는 18.4 패치 배포를 계기로 PostgreSQL 18 시리즈가 현재 프로덕션에서 운영되고 있다는 사실을 바탕으로, DBA가 반드시 이해해야 할 운영 변화를 정리한다.
18.x의 변화는 기능 추가 수준이 아니다. 비동기 I/O 서브시스템 도입은 PostgreSQL 25년 역사에서 가장 큰 I/O 아키텍처 변화 중 하나다. 이를 이해하지 못하면 클라우드 스토리지에서 2~3배의 성능 향상을 놓치거나, 반대로 잘못된 설정으로 문제를 일으킬 수 있다.
기준 버전: PostgreSQL 18.4 (2026-05-14 기준). 릴리스 날짜: PostgreSQL 18.0 GA 2025-09-25, 18.4 보안 패치 2026-05-14.
PostgreSQL 18 이전의 I/O 한계
PostgreSQL 17까지 모든 I/O는 동기 방식으로 처리됐다. 백엔드 프로세스가 디스크에서 페이지를 읽을 때 운영체제가 응답할 때까지 해당 프로세스는 완전히 블로킹된다. 단일 프로세스가 단일 I/O 요청만 처리하는 구조였다.
이 방식은 로컬 NVMe처럼 레이턴시가 낮은 스토리지에서는 문제가 없다. 하지만 클라우드 환경(AWS EBS, GCP Persistent Disk, Azure Managed Disk)에서는 I/O 레이턴시가 수백 마이크로초~수 밀리초 수준이다. 시퀀셜 스캔은 수백만 개의 블록을 순서대로 읽는데, 각 요청을 기다리는 동안 CPU가 놀고 있었다.
해결책은 비동기 I/O: 여러 I/O 요청을 동시에 발행하고, 각 응답이 올 때마다 처리하는 방식이다.
비동기 I/O 서브시스템: io_method
PostgreSQL 18은 io_method GUC(Grand Unified Configuration)를 도입해 세 가지 I/O 방식 중 하나를 선택할 수 있게 했다.
io_method 설정 방법
postgresql.conf에서 설정하며 재시작이 필요하다. 런타임 변경은 불가능하다.
# io_method는 postgresql.conf에서만 설정
io_method = worker # 기본값, 모든 플랫폼
io_method = io_uring # Linux 5.1+, --with-liburing 빌드 필요
io_method = sync # 레거시/디버그용io_uring을 사용하려면 PostgreSQL이 --with-liburing 옵션으로 빌드됐는지 먼저 확인한다.
-- liburing 지원 빌드 확인
SELECT pg_config_setting('with_liburing');
-- 또는
SHOW io_method;어떤 워크로드에서 효과가 있는가
AIO는 현재 읽기 연산에만 적용된다: 시퀀셜 스캔(Seq Scan), 비트맵 힙 스캔(Bitmap Heap Scan), VACUUM 읽기 단계. 쓰기와 WAL은 여전히 동기 방식이다.
효과가 큰 환경:
- 클라우드 네트워크 연결 스토리지(EBS, GCP PD, Azure Disk)
- 디스크에서 읽어야 하는 cold data 비율이 높은 분석 쿼리
- VACUUM이 자주 필요한 대형 테이블
효과가 제한적인 환경:
- 데이터 대부분이 shared_buffers에 캐시된 경우
- 로컬 NVMe SSD (레이턴시가 낮아 비동기 효과가 작음, 단 small gain은 있음)
- CPU 바운드 쿼리 (조인, 집계 등)
새로운 모니터링 포인트: effective_io_concurrency 파라미터가 이제 실질적인 의미를 가진다. worker/io_uring 모드에서 동시 발행 I/O 요청 수를 제어한다.
uuidv7: B-트리 인덱스 단편화 해결
PostgreSQL 18은 uuidv7() 함수를 내장했다.
UUIDv4 vs UUIDv7의 차이
| 특성 | UUIDv4 | UUIDv7 |
|---|---|---|
| 생성 방식 | 완전 무작위 | 타임스탬프 + 무작위 |
| 정렬 | 무작위 순서 | 시간 순서 정렬 |
| B-트리 인덱스 | 심각한 단편화 | 순차 삽입 패턴 |
| INSERT 성능 | 페이지 분리 빈번 | 훨씬 낮은 분리 빈도 |
| 전역 고유성 | 보장 | 보장 (ts+random) |
UUIDv4로 기본 키 인덱스를 만들면 각 INSERT가 B-트리의 무작위 위치에 들어가 페이지 분리(page split)가 자주 발생한다. 페이지 분리는 쓰기 증폭과 인덱스 블로트의 주원인이다.
UUIDv7은 48비트 밀리초 타임스탬프로 시작해 새 레코드가 인덱스의 오른쪽(최신) 부분에 삽입되도록 보장한다. 순차 삽입 패턴이어서 SERIAL이나 BIGSERIAL과 유사한 인덱스 효율을 내면서 전역 고유성도 유지한다.
-- uuidv7 사용 예시 (PostgreSQL 18+)
CREATE TABLE events (
id UUID DEFAULT uuidv7() PRIMARY KEY,
created_at TIMESTAMPTZ DEFAULT now(),
payload JSONB
);
-- 타임스탬프 추출 (uuidv7에서 생성 시각 복원 가능)
SELECT uuidv7_to_timestamptz('0191f5c7-1234-7abc-bdef-000000000001');가상 생성 열(Virtual Generated Columns)
PostgreSQL 18에서 GENERATED ALWAYS AS ... STORED 대신 기본값이 가상 생성 열로 바뀌었다.
STORED vs VIRTUAL 비교
| 구분 | STORED | VIRTUAL |
|---|---|---|
| 저장 위치 | 디스크에 실제 저장 | 저장 없음 |
| 계산 시점 | INSERT/UPDATE 시 | SELECT 시 |
| 쓰기 오버헤드 | 있음 (계산 + 저장) | 없음 |
| 읽기 오버헤드 | 없음 | 있음 (매번 계산) |
| 인덱스 생성 | 가능 | Open question (제한적) |
-- VIRTUAL generated column (PostgreSQL 18 기본)
CREATE TABLE products (
price NUMERIC,
tax_rate NUMERIC,
-- VIRTUAL: 디스크에 저장 안 됨, 쿼리 시 계산
total_price NUMERIC GENERATED ALWAYS AS (price * (1 + tax_rate)) VIRTUAL,
-- STORED: 이전 방식, 명시적으로 선언 필요
total_price_stored NUMERIC GENERATED ALWAYS AS (price * (1 + tax_rate)) STORED
);쓰기 집약적인 테이블에서 자주 계산하는 컬럼을 가상 생성 열로 전환하면 INSERT/UPDATE 성능이 개선된다.
기타 DBA 주요 변경사항
NOT NULL 추가: 전체 테이블 스캔 없음
이전에는 기존 테이블에 NOT NULL 제약을 추가하면 테이블 전체를 스캔해 기존 값을 검증했다. 대형 테이블에서는 수십 분이 걸렸다.
PostgreSQL 18은 이 검증을 지연(deferred) 방식으로 처리한다. 제약 추가는 즉시 완료되고, 기존 데이터 검증은 백그라운드에서 진행된다.
-- 18+: 즉시 완료, 백그라운드 검증
ALTER TABLE large_table ADD CONSTRAINT chk_col_not_null CHECK (col IS NOT NULL) NOT VALID;
-- 이후 검증 완료 선언
ALTER TABLE large_table VALIDATE CONSTRAINT chk_col_not_null;OAuth 인증
PostgreSQL 18은 OAuth 2.0 인증을 pg_hba.conf에서 설정할 수 있다. 구현은 익스텐션 방식으로 특정 OAuth 제공자(Okta, Azure AD, Google 등)에 맞는 플러그인을 설치한다.
# pg_hba.conf 예시 (OAuth)
hostssl all all 0.0.0.0/0 oauth issuer="https://auth.example.com" scope="postgres"기업 환경에서 중앙 IdP를 통한 데이터베이스 접근 제어가 가능해진다.
더 빠른 pg_upgrade
PostgreSQL 18은 pg_upgrade --copy-file-range를 도입해 파일 복사 속도를 개선했다. 대형 데이터베이스에서 업그레이드 다운타임이 줄어든다.
18.4 보안 패치 요약
2026년 5월 14일 배포된 18.4에는 11개 CVE가 포함됐다.
| CVE | 심각도 | 내용 |
|---|---|---|
| CVE-2026-6479 | High | startup 패킷 처리 시 무제한 재귀 → 백엔드 크래시 |
| CVE-2026-6473 | Medium | pg_createsubscriber 구독 이름 SQL 인젝션 |
| CVE-2026-6638 | Medium | 논리 복제 오리진 검사에서 SQL 실행 가능 |
CVE-2026-6479는 미인증 원격 공격자가 악의적인 SSL/GSS 협상 패킷으로 백엔드를 크래시시킬 수 있어 즉시 업그레이드가 권장된다.
PostgreSQL 18 업그레이드 체크리스트
--with-liburing으로 빌드됐는지 확인. 배포판마다 다를 수 있다.uname -r. Amazon Linux 2023, Ubuntu 22.04+, RHEL 9+는 기본 충족.effective_io_concurrency를 클라우드 스토리지는 200~256, 로컬 SSD는 1~4로 조정한다. 기본값(1)은 AIO 효과를 충분히 내지 못한다.SELECT state, count(*) FROM pg_aios GROUP BY state;maintenance_io_concurrency도 함께 조정해 VACUUM 성능을 높인다. 클라우드: 10~32 권장.uuidv7()를 기본값으로 사용한다. 기존 UUIDv4 기본 키 컬럼 마이그레이션은 인덱스 재구축이 필요하므로 영향도를 먼저 평가한다.uuidv7_to_timestamptz() 함수를 활용한다. created_at 컬럼을 별도 유지할지 UUID에서 추출할지 설계에 반영한다.정리
PostgreSQL 18의 DBA 핵심 판단 기준은 세 가지다.
비동기 I/O: 클라우드 스토리지 환경이라면 io_method = worker(기본값)로 즉시 이득을 볼 수 있다. Linux 5.1+ 환경이고 io_uring 빌드가 되어 있다면 io_uring으로 추가 최적화를 검토한다. effective_io_concurrency를 반드시 조정해야 효과가 나타난다.
uuidv7: 신규 서비스에서 전역 고유 ID가 필요하다면 UUIDv4 대신 uuidv7이 B-트리 인덱스 효율 측면에서 명확히 유리하다. 기존 테이블 마이그레이션은 인덱스 재구축 비용을 감안해 결정한다.
보안 패치: 18.4 미만 버전은 CVE-2026-6479로 인해 미인증 원격 크래시가 가능하다. 바로 패치하는 것이 맞다.
References
- PostgreSQL 18 Released — PostgreSQL Project (2025-09-25)
- PostgreSQL 18.4, 17.10 Released — 11 Security Fixes (2026-05-14)
- Release 18 — PostgreSQL Documentation
- Waiting for Postgres 18: Accelerating Disk Reads with Asynchronous I/O — pganalyze
- PostgreSQL 18 Asynchronous I/O: A Complete Guide — Better Stack
- Postgres 18 Features: Async I/O, UUIDv7, OAuth and More — Xata
- What's New in PostgreSQL 18: A DBA's Perspective — Bytebase
- Benchmarking Postgres 17 vs 18 — PlanetScale
- Exploring why PostgreSQL 18 put asynchronous I/O in your database — Aiven
- High-Performance DBMSs with io_uring: When and How to use it — arXiv:2512.04859