본문으로 건너뛰기
2.4 initdb와 첫 클러스터

2.4 initdb와 첫 클러스터

initdb는 빈 디렉토리에 PostgreSQL 클러스터 골격을 만들어 주는 명령입니다. 1.2에서 PGDATA의 결과 구조를 봤다면, 본 절에서는 그 결과를 만드는 initdb 자체의 옵션과 의사결정을 봅니다. 이 시점에서 결정한 일부 옵션(체크섬·인코딩·로케일·WAL 세그먼트 크기)은 이후 변경 불가라 운영 시작 전에 신중히 골라야 합니다.

한 줄 요약

initdb \
  -D /var/lib/pgsql/17/data \
  --encoding=UTF8 \
  --locale-provider=icu --icu-locale=ko-KR \
  --data-checksums \
  --wal-segsize=16 \
  -U postgres -W

이 한 줄에 들어간 결정들을 풀어 봅니다.

옵션 별 상세

-D PGDATA 위치

빈(또는 존재하지 않는) 디렉토리. 이미 파일이 있으면 거부한다 — 실수로 기존 클러스터를 덮어쓰지 않게 막는 안전장치.

initdb -D /var/lib/pgsql/17/data
# initdb: error: directory "/var/lib/pgsql/17/data" exists but is not empty

PGDATA 환경변수로도 지정 가능합니다.

--data-checksums — 페이지 체크섬

상태동작
비활성(기본)페이지 손상이 발생해도 PostgreSQL은 모름. 통계만 망가질 수도, 무한 루프에 빠질 수도
활성페이지 읽을 때마다 CRC32C 체크. 손상 시 즉시 ERROR 발생

운영 권장은 무조건 켜기. 약간의 CPU 비용(12%)을 감수하더라도 디스크 비트 부패를 조기 발견하는 가치가 큽니다.

initdb --data-checksums ...

PG 18부터는 pg_checksums --enable이미 만들어진 클러스터에도 체크섬을 추가 가능해졌습니다. 그 전 버전에서는 클러스터를 다시 만들어야 했습니다.

--encoding — 클러스터 기본 인코딩

template1·postgres·template0의 인코딩을 결정합니다. 기본값은 OS 로케일에 맞춰 추론됩니다. 운영용은 항상 UTF8.

initdb --encoding=UTF8 ...

데이터베이스마다 CREATE DATABASE ... ENCODING = ...로 다르게 줄 수 있지만, template1이 UTF8이 아니면 매번 TEMPLATE template0를 명시해야 해서 운영 부담이 커집니다.

로케일 — --locale / --locale-provider

PostgreSQL의 정렬 순서(ORDER BYLIKE·ILIKE·정규식은 모두 로케일에 영향받습니다.

옵션의미
--locale=C.UTF-8C 로케일 (ASCII 바이트 순서, 가장 빠름)
--locale=ko_KR.UTF-8한국어 로케일
--locale-provider=icu (PG 15+)OS libc 대신 ICU 사용 — 정렬 결과가 OS 버전에 좌우되지 않음
--icu-locale=ko-KRICU 로케일 (provider=icu일 때)

ICU 권장 이유: OS의 glibc 업그레이드 시 정렬 순서가 바뀌어 인덱스가 깨지는 사고가 종종 발생한다(2018년 glibc 2.28에서 collation 대규모 변경 사례). ICU는 libc와 독립적으로 collation 버전을 관리합니다.

initdb --locale-provider=icu --icu-locale=ko-KR --encoding=UTF8 ...

대용량 데이터에서 정렬 순서가 중요하지 않다면 C.UTF-8을 쓰면 가장 빠릅니다.

--wal-segsize — WAL 세그먼트 크기

기본은 16MB.

크기권장 시나리오
16MB (기본)일반 OLTP. 백업·복제 도구들 거의 모두 16MB 가정
64MB·128MB트랜잭션 양이 매우 많은 시스템에서 WAL 파일 갯수 폭증 회피

initdb 시에만 결정 가능합니다. 이후 변경하려면 클러스터 재생성 필요합니다.

-U / -W — 슈퍼유저

옵션의미
-U postgres슈퍼유저 이름 (기본 postgres)
-W비밀번호 입력 프롬프트
--pwfile=<path>비밀번호를 파일에서 읽음 (자동화에 유리)

기본은 비밀번호 없이 만들어집니다. pg_hba.conf가 trust/peer로 두면 동작은 하지만, 운영 시작 전 비밀번호 또는 인증 방식을 반드시 설정해야 합니다.

--auth — 기본 인증 방식

pg_hba.conf에 들어갈 초기 메서드.

옵션의미
--auth=scram-sha-256비밀번호 인증. 권장
--auth=trust인증 없음. 개발·테스트에서만
--auth=peer로컬 OS 사용자명과 DB 사용자명이 같으면 통과 (Unix 소켓 전용)
initdb --auth-local=peer --auth-host=scram-sha-256 ...

클러스터 초기화 후 자동 만들어지는 것

initdb가 끝나면 다음이 들어 있습니다.

$PGDATA/
├── PG_VERSION                      # 메이저 버전 문자열 (예: "17")
├── postgresql.conf                 # 기본 설정 (대부분 주석 처리됨)
├── pg_hba.conf                     # 인증 정책
├── pg_ident.conf                   # OS 사용자 ↔ DB 사용자 매핑
├── postgresql.auto.conf            # 비어 있음. ALTER SYSTEM이 여기 씀
├── base/
│   ├── 1/                          # template1
│   ├── 4/                          # template0
│   └── 5/                          # postgres
├── global/                         # pg_database, pg_authid 등 cluster-wide 카탈로그
├── pg_wal/                         # 초기 WAL 세그먼트 (000000010000000000000001 등)
├── pg_xact/                        # 트랜잭션 커밋 상태
└── ... (다수 디렉토리)

표준 데이터베이스 3개:

DB용도
postgres관리·기본 접속용
template1새 DB 만들 때 복제되는 템플릿. 여기 객체를 만들면 이후 새 DB에도 자동으로 들어감
template0변경 금지 백업 템플릿. encoding·locale을 다르게 한 DB를 만들 때 베이스로 씀

첫 SQL 확인

# 클러스터 기동
pg_ctl -D /var/lib/pgsql/17/data -l logfile start

# 확인
psql -U postgres -d postgres -c "
SELECT version(),
       current_setting('data_checksums'),
       current_setting('server_encoding'),
       current_setting('lc_collate'),
       current_setting('wal_segment_size');"

여기서 본 값들은 사실상 영구라 운영 시작 전에 다시 점검할 가치가 있습니다.

흔한 함정

함정결과회피
--data-checksums 깜빡디스크 손상을 못 잡음항상 명시
lc_collate를 OS 로케일에 의존OS glibc 업그레이드 시 인덱스 무효화ICU provider 사용
--encoding=SQL_ASCII (기본 OS가 ASCII일 때)UTF-8 데이터 깨짐--encoding=UTF8 명시
슈퍼유저 비밀번호 미설정pg_hba.conf가 trust인 경우 공개망에서 사고initdb 직후 ALTER USER postgres WITH PASSWORD '...';
PGDATA 디렉토리 권한이 0700 아님postmaster가 시작 거부chmod 0700
initdb로 만든 클러스터의 일부 옵션(인코딩·로케일·세그먼트 크기·블록 크기)은 이후에 변경할 수 없다. 변경하려면 pg_dump → 다른 옵션으로 재초기화 → 복원이 필요합니다. 운영 시작 전 한 번 더 확인합니다.

자동화 친화적 호출

CI·Ansible에서는 패스워드 파일·비대화 모드를 씁니다.

echo 'super_strong_password' > /tmp/pgpwd
chmod 600 /tmp/pgpwd

initdb \
  -D /var/lib/pgsql/17/data \
  --encoding=UTF8 \
  --locale-provider=icu --icu-locale=ko-KR \
  --data-checksums \
  --auth-local=peer --auth-host=scram-sha-256 \
  -U postgres --pwfile=/tmp/pgpwd

shred -u /tmp/pgpwd

정리

  • initdb는 빈 디렉토리에 클러스터 골격 + postgres/template1/template0 생성
  • 운영 권장 옵션 묶음: --data-checksums, --encoding=UTF8, ICU 로케일, SCRAM-SHA-256 인증
  • 한번 정하면 못 바꾸는 옵션이 많음 — 시작 전 한 번 더 점검
  • ICU 로케일은 OS glibc 변경으로부터 인덱스를 보호
  • 슈퍼유저 비밀번호는 --pwfile 또는 초기 ALTER USER로 즉시 설정

다음 절(2.5)에서는 클러스터에 접속할 때 쓰는 클라이언트 도구 — psql, pgcli, DBeaver 등 — 을 봅니다.