들어가며
PostgreSQL은 매년 새로운 메이저 버전을 출시합니다. 그리고 각 메이저 버전은 5년이라는 명확한 수명을 가지고 있습니다. 출시 후 5년이 지나면 보안 패치를 포함한 모든 지원이 종료됩니다. 즉, 데이터베이스를 운영하는 한 메이저 버전 업그레이드는 피할 수 없는 일상적인 운영 과제입니다.
그런데 현실에서 메이저 버전 업그레이드는 미루고 미루다가 결국 지원 종료(EOL) 직전에야 부랴부랴 진행되는 경우가 많습니다. 이유는 단순합니다. 업그레이드가 무섭기 때문입니다. 수 테라바이트짜리 운영 데이터베이스를 건드린다는 것, 그리고 그 과정에서 발생할 수 있는 다운타임이 두렵기 때문입니다.
이 글에서는 PostgreSQL 메이저 버전 업그레이드의 세 가지 대표 전략을 비교합니다. 가장 단순한 dump/restore, 파일 레벨에서 빠르게 동작하는 pg_upgrade, 그리고 거의 무중단에 가까운 논리 복제(logical replication) 방식입니다. 각 방식의 동작 원리, 다운타임 트레이드오프, 실제 명령어 절차, 그리고 흔히 빠지는 함정까지 다룹니다. RDS와 Aurora 같은 관리형 환경에서의 고려사항도 함께 살펴봅니다.
이 글이 다루는 것은 "메이저" 버전 업그레이드입니다. 15.3에서 15.8로 가는 마이너 업그레이드는 바이너리만 교체하고 재시작하면 끝나는 단순한 작업입니다. 데이터 디렉터리 포맷이 바뀌지 않기 때문입니다. 하지만 15에서 16으로 가는 메이저 업그레이드는 내부 카탈로그 구조와 데이터 디렉터리 레이아웃이 바뀌기 때문에 별도의 전략이 필요합니다.
메이저 업그레이드가 어려운 이유
먼저 왜 메이저 업그레이드가 단순 재시작으로 끝나지 않는지 이해해야 합니다. PostgreSQL은 메이저 버전마다 데이터 파일의 내부 포맷, 시스템 카탈로그 구조, WAL 포맷 등이 변경될 수 있습니다.
핵심은 `PG_VERSION` 파일과 카탈로그 버전입니다. 데이터 디렉터리에는 어떤 메이저 버전이 만들었는지를 나타내는 정보가 들어있고, 새 버전의 서버는 자기보다 낮은 버전이 만든 데이터 디렉터리를 그대로 열 수 없습니다. 마이너 버전은 이 포맷을 유지하기로 보장하지만, 메이저 버전은 그렇지 않습니다.
따라서 메이저 업그레이드는 본질적으로 "구버전 데이터를 신버전 포맷으로 옮기는" 작업입니다. 이 옮기는 방식이 무엇이냐에 따라 dump/restore, pg_upgrade, 논리 복제로 갈립니다.
[마이너 업그레이드] 15.3 -> 15.8
바이너리 교체 + 재시작 -> 끝 (데이터 포맷 동일)
[메이저 업그레이드] 15 -> 16
데이터를 신버전 포맷으로 변환/이전 필요
├─ dump/restore : 논리적으로 전부 내보내고 다시 적재
├─ pg_upgrade : 카탈로그만 변환, 데이터 파일 재사용
└─ logical replication : 신버전을 구축하고 변경분을 실시간 동기화
세 가지 전략 개요
1. dump/restore
가장 고전적이고 단순한 방식입니다. 구버전에서 `pg_dump` 또는 `pg_dumpall`로 전체 데이터를 논리적으로 추출하고, 신버전에 `pg_restore` 또는 `psql`로 적재합니다.
장점은 명확합니다. 가장 안전하고, 이식성이 높으며, 데이터가 완전히 재작성되므로 테이블 비대화(bloat)가 자연스럽게 정리됩니다. 신구 버전 간 아키텍처가 달라도(예: 32비트에서 64비트) 동작합니다.
단점도 명확합니다. 느립니다. 전체 데이터를 한 줄 한 줄 INSERT하고 인덱스를 다시 빌드해야 하므로, 데이터 크기에 비례해 시간이 폭발적으로 늘어납니다. 수백 GB만 되어도 다운타임이 몇 시간 단위가 됩니다.
2. pg_upgrade
PostgreSQL이 공식 제공하는 인플레이스(in-place) 업그레이드 도구입니다. 핵심 아이디어는 "데이터 파일은 대부분 그대로 두고 시스템 카탈로그만 변환한다"는 것입니다.
특히 `--link` 모드를 사용하면 구버전 데이터 파일에 하드 링크를 걸어 신버전이 재사용합니다. 즉 수 테라바이트의 데이터를 복사하지 않습니다. 그래서 데이터 크기와 거의 무관하게, 보통 수 분 내에 업그레이드가 끝납니다.
단점은 같은 서버(같은 파일 시스템)에서 동작해야 한다는 점, 그리고 `--link` 사용 시 구버전으로의 즉각적인 롤백이 어려워진다는 점입니다.
3. 논리 복제 (logical replication)
PostgreSQL 10부터 도입된 publication/subscription 기반 논리 복제를 활용합니다. 신버전 인스턴스를 미리 구축해 두고, 구버전을 publisher로, 신버전을 subscriber로 설정해 데이터를 실시간 동기화합니다. 초기 데이터가 모두 복제되고 변경분까지 따라잡으면, 짧은 순간에 애플리케이션 연결만 신버전으로 전환합니다.
장점은 다운타임이 수 초에서 수십 초 수준으로 줄어든다는 것입니다. 전환 전까지 구버전이 계속 서비스하고 있으므로 충분히 검증할 시간도 확보됩니다. 단점은 절차가 복잡하고, 논리 복제가 지원하지 않는 항목(시퀀스 자동 동기화 등)을 수동으로 처리해야 한다는 점입니다.
다운타임 트레이드오프 비교
세 방식의 가장 큰 차이는 결국 다운타임과 운영 복잡도의 트레이드오프입니다.
| 항목 | dump/restore | pg_upgrade (--link) | 논리 복제 |
| --- | --- | --- | --- |
| 다운타임 | 매우 김 (데이터 크기 비례) | 짧음 (보통 수 분) | 거의 없음 (수 초~수십 초) |
| 데이터 크기 영향 | 매우 큼 | 거의 없음 | 초기 동기화에만 영향 |
| 디스크 추가 사용 | 신버전만큼 추가 | 거의 없음 (하드 링크) | 신버전만큼 추가 |
| 롤백 난이도 | 쉬움 (구버전 그대로) | 어려움 (link 시) | 쉬움 (전환 전까지) |
| 절차 복잡도 | 낮음 | 중간 | 높음 |
| 버전 간 점프 | 자유로움 | 인접/다단계 가능 | publisher 10 이상 필요 |
| bloat 정리 효과 | 있음 | 없음 | 있음 |
선택 기준을 단순화하면 다음과 같습니다.
데이터가 작고(수 GB) 다운타임 여유 있음
-> dump/restore (가장 단순, 가장 안전)
데이터가 크고 짧은 점검창(수 분)을 잡을 수 있음
-> pg_upgrade --link
다운타임을 거의 허용할 수 없음 / 24x7 서비스
-> 논리 복제
pg_upgrade 상세 절차
이제 가장 널리 쓰이는 pg_upgrade를 실제 명령어 수준에서 살펴봅니다. 전제는 구버전(예: 15)과 신버전(예: 16)의 바이너리가 같은 서버에 모두 설치되어 있다는 것입니다.
사전 준비
먼저 신버전 바이너리를 설치하고, 새 데이터 디렉터리를 초기화합니다. 이때 구버전과 동일한 로케일/인코딩으로 초기화해야 합니다.
구버전과 신버전 데이터 디렉터리 경로
OLD_BIN=/usr/lib/postgresql/15/bin
NEW_BIN=/usr/lib/postgresql/16/bin
OLD_DATA=/var/lib/postgresql/15/main
NEW_DATA=/var/lib/postgresql/16/main
신버전 데이터 디렉터리 초기화 (구버전과 동일한 로케일/인코딩)
"$NEW_BIN/initdb" -D "$NEW_DATA" \
--encoding=UTF8 --locale=en_US.UTF-8
호환성 사전 점검 (--check)
실제 업그레이드 전에 반드시 `--check` 모드로 호환성을 먼저 검증합니다. 이 단계는 데이터를 전혀 건드리지 않고, 업그레이드를 막을 수 있는 문제를 미리 보고해줍니다.
두 서버 모두 정지된 상태에서 실행
"$NEW_BIN/pg_upgrade" \
--old-bindir="$OLD_BIN" \
--new-bindir="$NEW_BIN" \
--old-datadir="$OLD_DATA" \
--new-datadir="$NEW_DATA" \
--check
`--check`가 보고하는 대표적인 문제는 제거된 데이터 타입(예: 과거의 `abstime`), 호환되지 않는 확장 모듈, 신버전에 미설치된 확장 등입니다. 여기서 나온 모든 경고를 해소하기 전에는 실제 업그레이드를 진행하지 않습니다.
실제 업그레이드 (--link)
점검이 통과하면 실제 업그레이드를 진행합니다. `--link`를 붙이면 데이터 파일을 복사하는 대신 하드 링크를 만들어 시간을 크게 단축합니다.
반드시 구버전/신버전 서버를 모두 정지한 상태에서!
"$NEW_BIN/pg_upgrade" \
--old-bindir="$OLD_BIN" \
--new-bindir="$NEW_BIN" \
--old-datadir="$OLD_DATA" \
--new-datadir="$NEW_DATA" \
--link
업그레이드가 끝나면 두 가지 스크립트가 생성됩니다. 하나는 통계 정보를 재수집하는 스크립트이고(신버전은 플래너 통계를 가져오지 못하므로 ANALYZE가 필요), 다른 하나는 구버전 데이터 디렉터리를 삭제하는 스크립트입니다.
신버전 서버 기동 후, 반드시 통계 재수집
"$NEW_BIN/vacuumdb" --all --analyze-in-stages
검증이 끝난 뒤에야 구버전 데이터 삭제
./delete_old_cluster.sh
--link 모드의 핵심 주의사항
`--link`는 강력하지만 그만큼 위험합니다. 가장 중요한 규칙은 **신버전 클러스터를 기동한 순간 구버전은 더 이상 안전하지 않다**는 것입니다.
하드 링크로 같은 데이터 파일을 공유하기 때문에, 신버전이 쓰기를 시작하면 구버전 데이터도 함께 변경됩니다. 즉 신버전을 한 번이라도 정상 기동해 쓰기가 발생하면 구버전으로의 롤백은 사실상 불가능합니다.
[--link 모드의 위험 구간]
pg_upgrade --link 완료
│
▼
신버전 기동 (쓰기 발생) ─── 이 시점부터 구버전 롤백 불가
│
▼
검증 OK -> 운영
검증 NG -> 백업에서 복구해야 함 (구버전 그냥 켤 수 없음)
그래서 `--link` 업그레이드 전에는 반드시 신뢰할 수 있는 백업(또는 스냅샷)을 확보해야 합니다. 만약 디스크 여유가 있다면 `--link` 대신 기본 복사 모드를 쓰는 것도 안전한 선택입니다. 복사 모드는 느리지만 구버전이 그대로 남아 있어 롤백이 자유롭습니다.
또 하나, `--link`는 구버전과 신버전 데이터 디렉터리가 **같은 파일 시스템**에 있어야 합니다. 하드 링크는 파일 시스템 경계를 넘을 수 없기 때문입니다.
논리 복제 기반 무중단 업그레이드
다운타임을 거의 허용할 수 없는 환경이라면 논리 복제가 답입니다. 큰 그림은 다음과 같습니다.
[논리 복제 업그레이드 흐름]
구버전(15) Publisher 신버전(16) Subscriber
│ │
│ 1. publication 생성 │
│ ───────────────────────────► │ 2. 스키마 미리 생성
│ │ 3. subscription 생성
│ 4. 초기 데이터 복사 ───────► │
│ 5. 변경분 스트리밍 ────────► │ (실시간 따라잡기)
│ │
│ 6. lag ~= 0 확인 │
│ 7. 쓰기 차단 + 시퀀스 동기화 │
│ 8. 애플리케이션 전환 ───────► │ (신버전이 운영)
1단계: 구버전 준비
publisher 쪽에서 논리 복제를 켜야 합니다. `wal_level`을 `logical`로 올리고 재시작이 필요합니다.
postgresql.conf (구버전)
wal_level = logical
max_replication_slots = 10
max_wal_senders = 10
2단계: 스키마 사전 이전
논리 복제는 데이터(행)만 복제합니다. 테이블 정의, 인덱스, 제약, 함수 같은 스키마는 자동으로 만들어 주지 않습니다. 따라서 신버전에 스키마를 미리 만들어야 합니다.
구버전에서 스키마만 추출 (데이터 제외)
pg_dump -h OLD_HOST -U postgres -d appdb \
--schema-only --no-owner -f schema.sql
신버전에 스키마 적재
psql -h NEW_HOST -U postgres -d appdb -f schema.sql
3단계: publication과 subscription
이제 구버전에 publication을, 신버전에 subscription을 만듭니다.
-- 구버전(Publisher)에서 실행
CREATE PUBLICATION pub_all FOR ALL TABLES;
-- 신버전(Subscriber)에서 실행
CREATE SUBSCRIPTION sub_all
CONNECTION 'host=OLD_HOST dbname=appdb user=repl password=secret'
PUBLICATION pub_all
WITH (copy_data = true);
`copy_data = true`로 만들면 subscription 생성 즉시 초기 데이터 복사가 시작되고, 복사가 끝나면 자동으로 변경분 스트리밍으로 전환됩니다.
4단계: 동기화 진행 상황 확인
복제가 따라잡고 있는지 모니터링합니다. publisher 쪽에서 복제 지연(lag)을 확인할 수 있습니다.
-- 구버전(Publisher)에서: 복제 지연 확인
SELECT
slot_name,
pg_size_pretty(
pg_wal_lsn_diff(pg_current_wal_lsn(), confirmed_flush_lsn)
) AS lag
FROM pg_replication_slots;
-- 신버전(Subscriber)에서: 각 테이블 동기화 상태
SELECT srrelid::regclass AS table_name, srsubstate
FROM pg_subscription_rel;
`srsubstate`가 `r`(ready)이면 해당 테이블은 초기 복사를 마치고 스트리밍 단계에 들어간 것입니다.
5단계: 시퀀스 동기화
여기가 논리 복제의 가장 큰 함정입니다. **논리 복제는 시퀀스 값을 복제하지 않습니다.** 테이블 데이터는 따라왔지만 시퀀스의 현재 값(`last_value`)은 신버전에서 초기 상태로 남아 있습니다. 이 상태로 전환하면 PK 충돌이 발생합니다.
전환 직전, 쓰기를 차단한 상태에서 모든 시퀀스를 수동으로 맞춰야 합니다.
-- 구버전에서 각 시퀀스의 현재 값을 추출하는 SQL 생성
SELECT
'SELECT setval(' || quote_literal(schemaname || '.' || sequencename)
|| ', ' || COALESCE(last_value, 1) || ');'
FROM pg_sequences;
이 결과로 나온 setval 문들을 신버전에서 실행하면 시퀀스가 맞춰집니다. 안전을 위해 약간의 여유분(예: 현재 값에 1000을 더해)을 두는 것도 좋은 방법입니다.
6단계: 컷오버
이제 전환입니다. 절차는 짧고 단호하게 진행합니다.
[컷오버 순서]
1. 애플리케이션 쓰기 차단 (read-only 전환 또는 트래픽 중단)
2. 복제 lag = 0 최종 확인 (남은 변경분 모두 반영 대기)
3. 시퀀스 값 동기화 (5단계)
4. 신버전에서 subscription 비활성화/제거
5. 애플리케이션 연결 문자열을 신버전으로 변경
6. 트래픽 재개, 신버전 정상 동작 모니터링
이 컷오버 구간에서만 쓰기가 멈추므로, 실질적인 다운타임은 수 초에서 수십 초에 그칩니다.
확장, 시퀀스, 대용량 데이터 처리
업그레이드 방식과 무관하게 신경 써야 할 공통 항목들이 있습니다.
확장 모듈 (extensions)
`pg_upgrade`는 확장의 SQL 객체는 옮겨주지만, 확장의 공유 라이브러리(.so)는 신버전에 미리 설치되어 있어야 합니다. 예를 들어 PostGIS를 쓴다면 신버전에 맞는 PostGIS 패키지가 먼저 깔려 있어야 합니다.
업그레이드 후에는 확장 버전을 신버전에 맞게 올리는 작업이 추가로 필요할 수 있습니다.
-- 업그레이드 후 확장 버전 갱신
ALTER EXTENSION postgis UPDATE;
-- 설치된 확장과 사용 가능한 최신 버전 비교
SELECT name, default_version, installed_version
FROM pg_available_extensions
WHERE installed_version IS NOT NULL;
대용량 데이터와 인덱스
dump/restore나 논리 복제는 대상 쪽에서 인덱스를 다시 빌드합니다. 수억 행 테이블의 인덱스 재생성은 시간과 자원을 많이 먹습니다. 초기 적재 시에는 인덱스를 나중에 만들고, `maintenance_work_mem`을 크게 잡아 빌드 속도를 높이는 것이 좋습니다.
초기 적재/인덱스 빌드 중 일시적으로 크게 (신버전)
maintenance_work_mem = 2GB
max_wal_size = 8GB
논리 복제에서 초기 복사가 너무 느리다면, 큰 테이블은 publication에서 제외하고 별도로 옮긴 뒤 나중에 추가하는 분할 전략도 고려할 수 있습니다.
검증과 롤백
업그레이드는 "끝났다"가 아니라 "검증까지 끝났다"가 진짜 완료입니다.
검증 체크리스트
[업그레이드 후 검증 항목]
□ 모든 데이터베이스/스키마/테이블 개수 일치
□ 핵심 테이블 row count 신구 일치
□ 통계 재수집(ANALYZE) 완료
□ 확장 정상 동작 및 버전 확인
□ 시퀀스 값 정상 (논리 복제 시 필수)
□ 주요 쿼리 실행 계획 회귀 점검
□ 애플리케이션 스모크 테스트 통과
특히 실행 계획 회귀는 자주 간과됩니다. 메이저 버전이 바뀌면 플래너의 동작이 미묘하게 달라질 수 있어, 잘 돌던 쿼리가 갑자기 느려질 수 있습니다. 업그레이드 직후 통계를 다시 모으고, 핵심 쿼리의 실행 계획을 비교하는 것이 좋습니다.
롤백 전략
방식별로 롤백 난이도가 크게 다릅니다.
| 방식 | 롤백 방법 |
| --- | --- |
| dump/restore | 구버전이 그대로 살아 있으므로 연결만 되돌리면 됨 |
| pg_upgrade (복사) | 구버전 데이터 디렉터리 보존 -> 구버전 재기동 |
| pg_upgrade (--link) | 신버전 기동 후엔 사실상 백업 복구만 가능 |
| 논리 복제 | 컷오버 전엔 자유, 컷오버 후엔 역방향 복제 설계 필요 |
논리 복제에서 컷오버 이후의 롤백까지 대비하려면, 전환 후에도 신버전 -> 구버전 방향의 역복제를 미리 구성해 두는 고급 전략이 필요합니다. 이렇게 하면 문제가 생겼을 때 구버전으로 다시 트래픽을 돌릴 수 있지만, 구성 복잡도가 크게 올라갑니다.
관리형 환경: RDS와 Aurora
클라우드 관리형 PostgreSQL에서는 업그레이드 메커니즘이 추상화되어 있습니다.
RDS for PostgreSQL
RDS는 콘솔이나 API로 메이저 버전 업그레이드를 트리거할 수 있고, 내부적으로 `pg_upgrade`를 사용합니다. 업그레이드 전 자동으로 스냅샷을 떠두므로 롤백 안전성이 어느 정도 확보됩니다. 다만 그동안 인스턴스가 사용 불가 상태가 되므로 다운타임이 발생합니다.
블루/그린 배포(Blue/Green Deployment)를 쓰면 다운타임을 크게 줄일 수 있습니다. 그린 환경에 신버전을 미리 만들고 논리 복제로 동기화한 뒤, 짧은 전환만으로 승격합니다.
Aurora PostgreSQL
Aurora도 인플레이스 메이저 업그레이드를 지원하며, 마찬가지로 블루/그린 배포를 제공합니다. Aurora는 스토리지가 컴퓨트와 분리되어 있어, 업그레이드 모델이 일반 RDS와 다소 다르게 동작합니다. 관리형 환경에서는 직접 pg_upgrade를 돌리는 대신, 제공되는 업그레이드 경로와 블루/그린 기능을 우선 활용하는 것이 운영 부담이 적습니다.
공통적으로, 관리형이든 셀프 호스팅이든 **업그레이드 전 백업/스냅샷 확보**와 **사전 호환성 점검**은 동일하게 중요합니다.
흔히 빠지는 함정
마지막으로 실무에서 자주 만나는 함정들을 정리합니다.
첫째, **로케일과 인코딩 불일치**입니다. 신버전 데이터 디렉터리를 구버전과 다른 로케일로 초기화하면 pg_upgrade가 거부하거나, 통과하더라도 정렬 순서가 미묘하게 달라져 인덱스가 깨질 수 있습니다. glibc collation 버전 변경도 인덱스 손상을 유발할 수 있으니, 업그레이드 후 텍스트 인덱스 재빌드를 검토하는 것이 안전합니다.
둘째, **확장 미설치**입니다. 신버전에 확장 라이브러리를 깔지 않은 채 pg_upgrade를 돌리면 `--check` 단계에서 실패합니다. 모든 확장을 사전에 신버전용으로 설치해야 합니다.
셋째, **논리 복제의 시퀀스 누락**입니다. 앞서 강조했듯 시퀀스는 자동으로 동기화되지 않습니다. 컷오버 직전 setval을 빠뜨리면 신버전에서 첫 INSERT부터 PK 충돌이 터집니다.
넷째, **PK 없는 테이블의 논리 복제 제약**입니다. 논리 복제로 UPDATE/DELETE를 복제하려면 대상 테이블에 기본키 또는 REPLICA IDENTITY가 필요합니다. 이게 없으면 INSERT만 복제되거나 에러가 납니다.
다섯째, **통계 재수집 누락**입니다. pg_upgrade는 플래너 통계를 가져오지 않습니다. 업그레이드 직후 ANALYZE를 돌리지 않으면 모든 쿼리가 잘못된 실행 계획으로 동작해 데이터베이스 전체가 느려집니다.
여섯째, **--link 후 구버전 기동**입니다. 검증한답시고 신버전과 구버전을 둘 다 켜는 순간 데이터가 손상될 수 있습니다. --link 모드에서는 둘 중 하나만 살아 있어야 합니다.
마치며
PostgreSQL 메이저 버전 업그레이드는 결국 "다운타임을 얼마나 줄일 수 있는가"와 "운영 복잡도를 얼마나 감당할 수 있는가" 사이의 선택입니다. 데이터가 작다면 dump/restore의 단순함이 최선이고, 데이터가 크지만 짧은 점검창을 잡을 수 있다면 pg_upgrade --link가 강력합니다. 다운타임을 거의 허용할 수 없다면 논리 복제가 답이지만 그만큼 더 많은 손이 갑니다.
어떤 방식을 택하든 변하지 않는 원칙이 있습니다. 사전에 `--check`로 호환성을 검증하고, 신뢰할 수 있는 백업을 확보하고, 업그레이드 후 통계를 다시 모으고, 그리고 운영에 올리기 전에 충분히 검증하는 것입니다. 업그레이드는 미룰수록 위험이 커지는 일입니다. EOL에 쫓기기 전에, 평온한 시기에 한 번이라도 리허설을 돌려보는 것이 가장 좋은 전략입니다.
참고 자료
- [pg_upgrade 공식 문서](https://www.postgresql.org/docs/current/pgupgrade.html)
- [Logical Replication 공식 문서](https://www.postgresql.org/docs/current/logical-replication.html)
- [pg_dump 공식 문서](https://www.postgresql.org/docs/current/app-pgdump.html)
- [CREATE PUBLICATION 레퍼런스](https://www.postgresql.org/docs/current/sql-createpublication.html)
- [CREATE SUBSCRIPTION 레퍼런스](https://www.postgresql.org/docs/current/sql-createsubscription.html)
- [PostgreSQL Versioning Policy](https://www.postgresql.org/support/versioning/)
- [Upgrading the PostgreSQL DB engine for Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_UpgradeDBInstance.PostgreSQL.html)
- [Amazon RDS Blue/Green Deployments](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/blue-green-deployments.html)
- [Upgrading Amazon Aurora PostgreSQL DB clusters](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/USER_UpgradeDBInstance.PostgreSQL.html)
- [PostgreSQL Wiki: Upgrading](https://wiki.postgresql.org/wiki/Upgrading)
현재 단락 (1/192)
PostgreSQL은 매년 새로운 메이저 버전을 출시합니다. 그리고 각 메이저 버전은 5년이라는 명확한 수명을 가지고 있습니다. 출시 후 5년이 지나면 보안 패치를 포함한 모든 지...