|
| 1 | +# #97 PostgreSQL 17 및 pgvector 0.8.1 로컬 실행 환경 지원 추가 구현 |
| 2 | + |
| 3 | +## 1. 배경 |
| 4 | + |
| 5 | +현재 로컬 데이터베이스 실행 경로는 OpenSQL/PostgreSQL 14.6에 강하게 결합되어 있다. |
| 6 | + |
| 7 | +- `docker/opensql/Dockerfile`은 `tmaxopensql/postgres:14.6`을 기반으로 pgvector 0.8.0을 컴파일한다. |
| 8 | +- `docker/opensql/init-and-start.sh`은 `/usr/pgsql-14`와 `/var/lib/pgsql/14/data`를 사용한다. |
| 9 | +- `docker-compose.yml`은 `linux/amd64`를 강제하고 `opensql_data` 볼륨을 사용한다. |
| 10 | +- Local/Test Datasource의 기본 `sslmode=require`는 SSL을 활성화하지 않은 로컬 컨테이너와 맞지 않는다. |
| 11 | +- Claim 성능 Benchmark는 PostgreSQL 14.6을 실행 전제조건으로 고정한다. |
| 12 | +- README는 더 이상 사용하는 로컬 기준이 아닌 OpenSQL 14.6 실행 절차를 안내한다. |
| 13 | + |
| 14 | +공식 OpenSQL 17.8 설치 환경은 Rocky Linux 9.7 x86-64 단일 서버다. macOS arm64 개발 환경에서 |
| 15 | +공급사 설치 파일을 직접 실행하는 대신, 로컬 개발은 PostgreSQL 17 + pgvector 0.8.1로 표준화한다. |
| 16 | +공식 OpenSQL 호환성은 별도 원격 환경에서 같은 검증 SQL과 애플리케이션 회귀 시나리오로 확인한다. |
| 17 | + |
| 18 | +## 2. 목표 |
| 19 | + |
| 20 | +1. macOS arm64와 x86-64 개발 환경에서 동일한 로컬 DB 구성을 실행한다. |
| 21 | +2. PostgreSQL 17과 pgvector 0.8.1 버전을 재현 가능하게 고정한다. |
| 22 | +3. 기존 JDBC, Flyway, `vector(1024)`, HNSW 검색 계약을 유지한다. |
| 23 | +4. PostgreSQL 14 데이터 볼륨을 PostgreSQL 17에서 잘못 재사용하지 않는다. |
| 24 | +5. 공급사 설치 파일, 라이선스, 다운로드 정보와 비밀정보가 Git 및 Docker Build Context에 유입되지 않게 한다. |
| 25 | +6. 로컬 PostgreSQL과 공식 OpenSQL 원격 환경의 공통 검증 기준을 문서화한다. |
| 26 | + |
| 27 | +## 3. 환경 분리 결정 |
| 28 | + |
| 29 | +| 구분 | 로컬 개발 | 공식 최종 검증 | |
| 30 | +| --- | --- | --- | |
| 31 | +| DBMS | PostgreSQL 17 | OpenSQL 17.8 | |
| 32 | +| Vector Extension | pgvector 0.8.1 | pgvector 0.8.1 | |
| 33 | +| 실행 환경 | Docker Desktop, host architecture | Rocky Linux 9.7 x86-64 Single | |
| 34 | +| 설치 파일 | 공개 pgvector Docker Image | 공급사 제공 파일, Repository 외부 보관 | |
| 35 | +| 데이터 | 새 PostgreSQL 17 전용 Volume | 원격 검증용 격리 Database | |
| 36 | +| 목적 | 반복 개발 및 회귀 테스트 | 공식 호환성 확인 | |
| 37 | + |
| 38 | +로컬 기본 이미지는 공개 공식 이미지 `pgvector/pgvector:0.8.1-pg17`을 사용한다. 이미지가 제공하는 |
| 39 | +PostgreSQL 공식 Entry Point를 그대로 사용하므로 공급사 전용 시작 Script와 PostgreSQL 14 경로가 |
| 40 | +필요하지 않다. |
| 41 | + |
| 42 | +## 4. 로컬 컨테이너 설계 |
| 43 | + |
| 44 | +### 4.1 PostgreSQL Service |
| 45 | + |
| 46 | +- `docker-compose.yml`에서 Custom Build 대신 `pgvector/pgvector:0.8.1-pg17`을 직접 사용한다. |
| 47 | +- `platform: linux/amd64`를 제거해 Image Manifest가 Host Architecture를 선택하도록 한다. |
| 48 | +- 기존 기본 접속 계약을 유지한다. |
| 49 | + - Host: `localhost` |
| 50 | + - Port: `55432` |
| 51 | + - Database: `app` |
| 52 | + - User: `app` |
| 53 | + - Password: 환경변수 `DB_PASSWORD`, 로컬 기본값만 Compose에서 제공 |
| 54 | +- Health Check는 PostgreSQL 표준 `pg_isready`를 사용한다. |
| 55 | +- MinIO, Embedding Server, Ollama Service는 수정하지 않는다. |
| 56 | + |
| 57 | +### 4.2 Vector Extension 초기화 |
| 58 | + |
| 59 | +`docker/postgres/init/001-enable-vector.sql`을 `/docker-entrypoint-initdb.d/`에 Read-only로 |
| 60 | +Mount한다. |
| 61 | + |
| 62 | +~~~sql |
| 63 | +CREATE EXTENSION IF NOT EXISTS vector; |
| 64 | +~~~ |
| 65 | + |
| 66 | +PostgreSQL 공식 Entry Point는 새 Data Directory를 초기화할 때 이 SQL을 대상 Database에서 실행한다. |
| 67 | +따라서 Spring Boot가 기동해 Flyway V32를 적용하기 전에 `vector` Type과 HNSW Access Method가 |
| 68 | +준비된다. |
| 69 | + |
| 70 | +### 4.3 데이터 볼륨 |
| 71 | + |
| 72 | +- PostgreSQL 17은 새 Named Volume `docgrid_postgres17_data`를 사용한다. |
| 73 | +- Mount 경로는 `/var/lib/postgresql/data`다. |
| 74 | +- 기존 `opensql_data`는 자동 삭제, Mount 또는 In-place Upgrade하지 않는다. |
| 75 | +- 기존 데이터 이전이 필요하면 `pg_dump`/`pg_restore` 기반의 별도 작업으로 분리한다. |
| 76 | + |
| 77 | +새 Volume을 사용하는 이유는 PostgreSQL Major Version이 다른 Data Directory의 직접 재사용을 |
| 78 | +차단하고, Rollback 시 기존 PostgreSQL 14 데이터를 보존하기 위해서다. |
| 79 | + |
| 80 | +## 5. 애플리케이션 연결 설계 |
| 81 | + |
| 82 | +### 5.1 Local Profile |
| 83 | + |
| 84 | +`application-local.yml`의 기본 `DB_SSLMODE`를 `disable`로 변경한다. 로컬 Docker Network는 |
| 85 | +SSL을 활성화하지 않으므로 기본 실행이 실제 컨테이너 설정과 일치해야 한다. 환경변수 Override 계약은 |
| 86 | +유지한다. |
| 87 | + |
| 88 | +### 5.2 Test Profile |
| 89 | + |
| 90 | +`application-test.yml`도 기본 `DB_SSLMODE=disable`을 사용한다. 기존 격리 Schema와 |
| 91 | +`public` Search Path는 유지한다. |
| 92 | + |
| 93 | +~~~text |
| 94 | +currentSchema={TEST_DB_SCHEMA},public |
| 95 | +~~~ |
| 96 | + |
| 97 | +격리 Schema에는 Flyway Table과 애플리케이션 Table을 생성하고, `public`은 pgvector Extension이 |
| 98 | +제공하는 `vector` Type과 Operator를 찾는 용도로 사용한다. |
| 99 | + |
| 100 | +### 5.3 Production Profile |
| 101 | + |
| 102 | +`application-prod.yml`의 `PROD_DB_URL`, `PROD_DB_USERNAME`, `PROD_DB_PASSWORD` 계약은 |
| 103 | +변경하지 않는다. 운영 SSL Mode는 운영 URL에서 명시한다. |
| 104 | + |
| 105 | +## 6. Schema 및 검색 호환성 |
| 106 | + |
| 107 | +이번 작업은 Flyway Migration을 추가하거나 이미 적용된 Migration을 수정하지 않는다. |
| 108 | + |
| 109 | +- `embeddings.vector`: `vector(1024) NOT NULL` |
| 110 | +- `search_queries.query_vector`: `vector(1024)` |
| 111 | +- `embeddings.vector`: `vector_cosine_ops` 기반 HNSW Index |
| 112 | +- Java Mapping: 기존 `float[]`과 PostgreSQL `PGobject` 변환 유지 |
| 113 | +- 검색: 기존 `<=>` Cosine Distance Query 유지 |
| 114 | + |
| 115 | +PostgreSQL 17 및 pgvector 0.8.1에서 기존 계약이 그대로 동작하는지는 실제 Database를 사용해 검증한다. |
| 116 | + |
| 117 | +## 7. Benchmark 환경 가드 |
| 118 | + |
| 119 | +`EmbeddingJobClaimPerformanceBenchmark` 실행 전 다음을 검증한다. |
| 120 | + |
| 121 | +1. 전용 Test Schema 사용 |
| 122 | +2. Benchmark 전용 PostgreSQL Application Name 사용 |
| 123 | +3. `SHOW server_version` 결과가 17 계열 |
| 124 | +4. `vector` Extension Version이 정확히 0.8.1 |
| 125 | +5. Hikari Pool Size와 MXBean 준비 |
| 126 | + |
| 127 | +성능 합격 기준 자체는 변경하지 않는다. 환경 전환 후의 실제 결과는 새 Test Result 문서에 기록해 |
| 128 | +이전 PostgreSQL 14.6 결과와 환경 Fingerprint를 구분한다. |
| 129 | + |
| 130 | +## 8. API 및 상태 계약 |
| 131 | + |
| 132 | +이 작업에서 REST API, 요청/응답 DTO, 인증·권한, Domain Entity 상태 전이는 변경하지 않는다. |
| 133 | +DB Runtime과 개발 환경만 교체한다. |
| 134 | + |
| 135 | +## 9. 공급사 파일 및 보안 경계 |
| 136 | + |
| 137 | +- OpenSQL 설치 Archive, 압축 해제 비밀번호, 다운로드 URL과 라이선스 XML은 Repository 내부에 두지 않는다. |
| 138 | +- 공급사 파일은 Repository 외부 접근 제한 디렉터리 또는 원격 Rocky Linux 서버에서만 관리한다. |
| 139 | +- 공급사 파일을 Docker Build Context에 복사하거나 Mount하지 않는다. |
| 140 | +- 실제 운영 DB Password와 라이선스 정보는 문서, Commit, Log와 Test Result에 기록하지 않는다. |
| 141 | +- Repository 내부에서 공급사 파일 유입이 감지되면 작업을 중단하고 추적 여부부터 확인한다. |
| 142 | + |
| 143 | +## 10. 변경 대상 |
| 144 | + |
| 145 | +| 영역 | 변경 | |
| 146 | +| --- | --- | |
| 147 | +| 설계 | 이 문서 추가 | |
| 148 | +| Container | `docker-compose.yml`, `docker/postgres/init/001-enable-vector.sql` | |
| 149 | +| 기존 Container | `docker/opensql/`의 로컬 기본 구성 제거 | |
| 150 | +| Application | `application-local.yml`, `application-test.yml` | |
| 151 | +| Benchmark | `EmbeddingJobClaimPerformanceBenchmark` | |
| 152 | +| 운영 문서 | `README.md`, `docs/local-db.md` | |
| 153 | +| 검증 기록 | `docs/test-results/Gimini-3-#97-postgresql17-pgvector-local-environment.md` | |
| 154 | + |
| 155 | +과거 `docs/test-results/` 문서는 당시 실행 사실을 보존해야 하므로 소급 수정하지 않는다. |
| 156 | + |
| 157 | +## 11. 검증 계획 |
| 158 | + |
| 159 | +### 11.1 정적 검증 |
| 160 | + |
| 161 | +~~~bash |
| 162 | +docker compose config |
| 163 | +git status --short --ignored |
| 164 | +rg '14\.6|pgsql-14|opensql_data|linux/amd64' docker-compose.yml docker README.md src/main src/test |
| 165 | +~~~ |
| 166 | + |
| 167 | +### 11.2 Database 검증 |
| 168 | + |
| 169 | +~~~sql |
| 170 | +SHOW server_version; |
| 171 | +SELECT extversion FROM pg_extension WHERE extname = 'vector'; |
| 172 | + |
| 173 | +SELECT format_type(a.atttypid, a.atttypmod) |
| 174 | +FROM pg_attribute a |
| 175 | +JOIN pg_class c ON c.oid = a.attrelid |
| 176 | +WHERE c.relname = 'embeddings' |
| 177 | + AND a.attname = 'vector'; |
| 178 | + |
| 179 | +SELECT indexdef |
| 180 | +FROM pg_indexes |
| 181 | +WHERE tablename = 'embeddings' |
| 182 | + AND indexdef ILIKE '%USING hnsw%'; |
| 183 | +~~~ |
| 184 | + |
| 185 | +### 11.3 애플리케이션 회귀 검증 |
| 186 | + |
| 187 | +- `./gradlew test` |
| 188 | +- 실제 PostgreSQL 기반 Claim 동시성 통합 테스트 |
| 189 | +- 문서 인덱싱 완료·실패·Lease 복구·Worker Polling 통합 테스트 |
| 190 | +- Vector 저장 및 검색 통합 테스트 |
| 191 | +- Claim Benchmark 환경 사전검증과 Smoke 실행 |
| 192 | +- Local Profile Application 기동 및 Hibernate `ddl-auto=validate` |
| 193 | + |
| 194 | +## 12. Rollback |
| 195 | + |
| 196 | +1. Application과 PostgreSQL 17 Container를 중지한다. |
| 197 | +2. Compose와 Local/Test 설정 Commit을 Revert한다. |
| 198 | +3. 기존 PostgreSQL 14 `opensql_data`는 삭제하지 않고 이전 구성에서 다시 Mount한다. |
| 199 | +4. PostgreSQL 17 전용 Volume은 명시적인 사용자 확인 없이 삭제하지 않는다. |
| 200 | +5. 두 환경 간 데이터 자동 변환을 시도하지 않는다. |
| 201 | + |
| 202 | +## 13. 커밋 분리 |
| 203 | + |
| 204 | +1. 상세 설계 문서 |
| 205 | +2. PostgreSQL 17 + pgvector 0.8.1 Container Runtime |
| 206 | +3. Local/Test 연결 및 Benchmark 환경 가드 |
| 207 | +4. 로컬 실행 및 공식 OpenSQL 원격 검증 Runbook |
| 208 | +5. 실제 회귀 검증 결과 |
| 209 | + |
| 210 | +## 14. 완료 조건 |
| 211 | + |
| 212 | +- PostgreSQL 17 + pgvector 0.8.1 로컬 DB가 Host Architecture 강제 없이 기동된다. |
| 213 | +- PostgreSQL 14 볼륨을 재사용하거나 삭제하지 않는다. |
| 214 | +- Vector Extension이 Flyway보다 먼저 준비된다. |
| 215 | +- Flyway 전체 Migration과 Hibernate Schema Validation이 통과한다. |
| 216 | +- `vector(1024)` 저장과 HNSW Index가 유지된다. |
| 217 | +- Local/Test 연결 기본값이 로컬 컨테이너와 일치한다. |
| 218 | +- Production Datasource 계약은 바뀌지 않는다. |
| 219 | +- 공급사 파일과 비밀정보가 Git 및 Docker Build Context에 포함되지 않는다. |
| 220 | +- 전체 테스트와 실제 PostgreSQL 회귀 검증 결과가 기록된다. |
| 221 | + |
| 222 | +Closes #97 |
0 commit comments