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 emptyPGDATA 환경변수로도 지정 가능합니다.
--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 BY)·LIKE·ILIKE·정규식은 모두 로케일에 영향받습니다.
| 옵션 | 의미 |
|---|---|
--locale=C.UTF-8 | C 로케일 (ASCII 바이트 순서, 가장 빠름) |
--locale=ko_KR.UTF-8 | 한국어 로케일 |
--locale-provider=icu (PG 15+) | OS libc 대신 ICU 사용 — 정렬 결과가 OS 버전에 좌우되지 않음 |
--icu-locale=ko-KR | ICU 로케일 (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 등 — 을 봅니다.