Skip to content

Commit 7b954f8

Browse files
authored
Merge pull request #98 from DocGrid/feature/97
로컬 PostgreSQL 17 및 pgvector 0.8.1 환경으로 전환
2 parents 08bd034 + 2b81a98 commit 7b954f8

14 files changed

Lines changed: 734 additions & 69 deletions

.env.example

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
# .env.example - 이 파일을 복사해서 .env로 만들고 값을 채우세요
22
# cp .env.example .env
33

4-
# OpenSQL-PG local DB (docker-compose 기본값)
4+
# PostgreSQL 17 + pgvector 0.8.1 local DB (docker-compose 기본값)
55
DB_HOST=localhost
66
DB_PORT=55432
77
DB_NAME=app
88
DB_USER=app
99
DB_PASSWORD=local_password
1010
DB_SCHEMA=public
11+
DB_SSLMODE=disable
1112
SPRING_PROFILES_ACTIVE=local
1213

1314
# MinIO (docker-compose 기본값)

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,6 @@ out/
4040
### Environment ###
4141
.env
4242
.env.properties
43+
44+
# 공급사 설치 파일과 라이선스는 Repository 외부에 보관한다.
45+
/.local-vendor/

README.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,22 @@
22

33
## Local DB
44

5-
로컬 개발 DB는 Docker Compose로 실행합니다. 기본 DB 이미지는 OpenSQL-PG 호환 이미지인 `tmaxopensql/postgres:14.6`입니다.
5+
로컬 개발 DB는 Docker Compose로 실행합니다. 기본 이미지는 PostgreSQL 17과 pgvector 0.8.1을
6+
함께 제공하는 `pgvector/pgvector:0.8.1-pg17`입니다.
67

78
```bash
89
cp .env.example .env
9-
docker pull tmaxopensql/postgres:14.6
10-
docker compose up -d
10+
docker compose pull postgres
11+
docker compose up -d postgres
1112
docker compose ps
1213
./gradlew bootRun --args='--spring.profiles.active=local'
1314
```
1415

15-
DB 기본 접속 정보는 `localhost:55432`, database `app`, user `app`, password `local_password`입니다.
16+
DB 기본 접속 정보는 `localhost:55432`, database `app`, user `app`입니다. 로컬 기본
17+
`DB_SSLMODE``disable`이며 실제 비밀번호와 운영 접속정보는 환경변수로 주입합니다.
18+
19+
PostgreSQL 17은 `docgrid_postgres17_data` 전용 볼륨을 사용합니다. 기존 PostgreSQL 14
20+
`opensql_data` 볼륨을 재사용하거나 자동 삭제하지 않습니다.
1621

1722
자세한 내용은 [docs/local-db.md](docs/local-db.md)를 참고하세요.
1823

docker-compose.yml

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,22 @@
11
services:
22
postgres:
3-
build:
4-
context: ./docker/opensql
5-
dockerfile: Dockerfile
6-
platform: linux/amd64
7-
container_name: local-opensql
3+
image: pgvector/pgvector:0.8.1-pg17
4+
container_name: docgrid-postgres17
85
environment:
96
POSTGRES_DB: ${DB_NAME:-app}
107
POSTGRES_USER: ${DB_USER:-app}
118
POSTGRES_PASSWORD: ${DB_PASSWORD:-local_password}
129
ports:
1310
- "${DB_PORT:-55432}:5432"
1411
volumes:
15-
- opensql_data:/var/lib/pgsql
16-
- ./docker/opensql/vars.yml:/tmp/settings/vars/vars.yml:ro
12+
- postgres17-data:/var/lib/postgresql/data
13+
- ./docker/postgres/init/001-enable-vector.sql:/docker-entrypoint-initdb.d/001-enable-vector.sql:ro
1714
healthcheck:
18-
test: ["CMD-SHELL", "/usr/pgsql-14/bin/pg_isready -U app -d app"]
15+
test: ["CMD-SHELL", "pg_isready -U \"$${POSTGRES_USER}\" -d \"$${POSTGRES_DB}\""]
1916
interval: 10s
2017
timeout: 5s
2118
retries: 10
22-
start_period: 90s
19+
start_period: 30s
2320
networks:
2421
- docgrid-local
2522

@@ -81,8 +78,8 @@ networks:
8178
docgrid-local:
8279

8380
volumes:
84-
opensql_data:
85-
name: opensql_data
81+
postgres17-data:
82+
name: docgrid_postgres17_data
8683
minio-data:
8784
huggingface-cache:
8885
ollama-data:

docker/opensql/Dockerfile

Lines changed: 0 additions & 16 deletions
This file was deleted.

docker/opensql/init-and-start.sh

Lines changed: 0 additions & 24 deletions
This file was deleted.

docker/opensql/vars.yml

Lines changed: 0 additions & 6 deletions
This file was deleted.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-- Flyway V32가 vector(1024) 타입과 HNSW 인덱스를 만들기 전에 Extension을 준비한다.
2+
CREATE EXTENSION IF NOT EXISTS vector;
Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
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

Comments
 (0)