들어가며
QA 7차(P56)에서 14건의 버그를 마지막으로 수정했다. 이제 코드 품질 이외의 릴리즈 준비 작업을 정리한다.
전체 코드베이스를 체크한 결과, 코드 밖에서 할 일은 두 가지였다:
- CHANGELOG.md가 없다 — 릴리즈 태그 전에 있어야 하는 기본 산출물
- README.md가 최근 코드 변경을 반영하지 않는다 — 9곳의 불일치
릴리즈 체크리스트
| 항목 | 상태 |
|---|---|
| LICENSE (MIT) | OK |
| go.mod (replace 없음, 공개 의존성만) | OK |
| Dockerfile (multi-stage, amd64/arm64) | OK |
| CI/CD (lint, test -race, build, benchmark, Docker publish) | OK |
| .gitignore (바이너리, .env, IDE) | OK |
| Helm Chart (values, templates, NOTES) | OK |
| 하드코딩된 시크릿 | 없음 |
| CHANGELOG.md | MISSING |
| README.md 코드 동기화 | 9곳 불일치 |
보안, 의존성, CI 파이프라인은 모두 정상이다. 릴리즈 블로커는 없고, 문서 정리만 남았다.
1. CHANGELOG.md 작성
Keep a Changelog 형식으로 작성했다. v1.0.0은 첫 릴리즈이므로 Added 섹션에 모든 기능을 나열하고, Fixed 섹션에 pre-release QA 수정 내역을 정리했다.
구조
## [1.0.0] - 2026-03-17
### Added
- Transaction-Level Connection Pooling
- Automatic Read/Write Routing
- AST-Based Query Classification
- Side-effectful SELECT detection
- EXPLAIN ANALYZE with write sub-query
- CTE with write operations
- Locking clause detection
- Query Caching (LRU + Redis Pub/Sub)
- Prepared Statement Multiplexing
- ...33개 기능
### Fixed (Pre-release QA)
- CopyBoth goroutine race (#247)
- Rate limiter clock skew (#247)
- SQL error message leak (#247)
- Cache stale tableIndex (#247)
- ...16건 수정
총 33개 Added 항목, 16개 Fixed 항목이다. 각 Fixed 항목에는 PR 번호를 붙여서 추적 가능하게 했다.
2. README.md 코드 동기화
9곳의 불일치를 수정했다. 한국어(README.md)와 영어(README_en.md) 양쪽 모두.
2.1 쿼리 분류 설명 업데이트
QA 6차에서 MERGE, CALL, COMMENT를 write 분류에 추가했지만 README는 여전히 “INSERT, UPDATE, DELETE, DDL"만 언급하고 있었다.
- 쓰기 쿼리(INSERT, UPDATE, DELETE, DDL)는 Writer(Primary)로
+ 쓰기 쿼리(INSERT, UPDATE, DELETE, MERGE, CALL, COMMENT, DDL)는 Writer(Primary)로
+ EXPLAIN ANALYZE가 쓰기 쿼리를 포함하면 Writer로 라우팅합니다.
2.2 ABORT 트랜잭션 키워드
QA 7차에서 ABORT를 ROLLBACK 동의어로 추가했다.
- BEGIN ~ COMMIT/ROLLBACK 내부의 모든 쿼리는 Writer로 전송됩니다.
+ BEGIN ~ COMMIT/ROLLBACK/ABORT 내부의 모든 쿼리는 Writer로 전송됩니다.
2.3 SET CONSTRAINTS 특수 처리
Session Compatibility Guard 설명에 트랜잭션 범위 SET 변형을 명시:
- LISTEN/UNLISTEN, 세션 SET, DECLARE CURSOR, ...
+ ... SET LOCAL, SET TRANSACTION, SET CONSTRAINTS는 트랜잭션 범위이므로
+ 감지에서 제외됩니다.
2.4 Data API COPY 제한
기능 설명과 Data API 섹션 양쪽에 추가:
+ COPY 문은 HTTP 특성상 지원되지 않습니다.
2.5 TLS 설정 섹션
코드에 TLSConfig 구조체(enabled, cert_file, key_file)가 있지만 설정 예시에 빠져있었다:
tls:
enabled: false
cert_file: "/path/to/server.crt"
key_file: "/path/to/server.key"
2.6 config.watch 옵션
ConfigOptionsConfig.Watch 필드가 있지만 설정 예시에 없었다:
config:
watch: false # true: fsnotify로 설정 파일 변경 감시 (hot-reload)
출시 직전 최종 확인 포인트
문서 정리는 종종 “출시 직전에 시간 남으면 하는 일"로 밀리지만, 실제로는 운영 리스크를 줄이는 마지막 방어선이다. README와 CHANGELOG가 코드와 어긋나 있으면 사용자 온보딩이 틀어지고, 장애가 났을 때도 어떤 기능이 어느 시점에 들어갔는지 추적이 어려워진다. 그래서 저는 릴리즈 직전 확인을 코드, 문서, 배포 산출물 세 축으로 본다.
- 코드 축: QA Round 6와 QA Round 7에서 막은 이슈가 릴리즈 브랜치에 모두 반영됐는지 확인
- 문서 축: README, Helm values, Admin API 예제, TLS 설정 예시가 현재 바이너리 동작과 일치하는지 확인
- 산출물 축: 태그, Docker 이미지, GitHub Release note, 이후 포스트인 SQL Redaction처럼 즉시 이어질 후속 계획까지 연결
이 과정을 해두면 v1.0.0은 단순히 “태그를 찍었다"가 아니라, 외부 사용자가 실제로 설치하고 운영할 수 있는 첫 버전이 된다. 릴리즈 준비 글이 별도 편으로 존재하는 이유도 바로 이 전환점을 분명히 남기기 위해서다.
릴리즈 절차
이 PR이 머지되면 남은 절차는:
git tag -a v1.0.0 -m "Initial release"
git push origin v1.0.0
태그 푸시 시 .github/workflows/release.yml이 트리거되어:
- Docker 이미지 빌드 (linux/amd64, linux/arm64)
- GHCR에
ghcr.io/jyukki97/pgmux:1.0.0퍼블리시 - GitHub Release 생성
마무리
P1(“PG Wire Protocol 이해”)부터 P57(“v1.0.0 릴리즈 준비”)까지 57편의 시리즈를 쓰는 동안:
- 33개 기능을 구현하고
- 7차 QA를 거쳐 50건 이상의 버그를 수정했다
처음 TCP 리스너를 띄우고 PostgreSQL 핸드셰이크를 중계하던 P1에서, 트랜잭션 풀링, AST 쿼리 분류, Prepared Statement Multiplexing, Causal Consistency, Query Mirroring까지 — PgBouncer가 제공하지 못하는 기능들을 Go로 구현할 수 있었다.
이 시리즈는 여기서 마무리하고, 이후 운영 경험이나 새 기능이 추가되면 별도 포스트로 다룰 예정이다.
💬 댓글