diff --git a/Rocky9 postgresql-17 설치 명령어.txt b/Rocky9 postgresql-17 설치 명령어.txt new file mode 100644 index 0000000..d5f9954 --- /dev/null +++ b/Rocky9 postgresql-17 설치 명령어.txt @@ -0,0 +1,23 @@ +dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm +dnf update -y +dnf -qy module disable postgresql + +dnf install -y postgresql17-server + +su - postgres +/usr/pgsql-17/bin/initdb -D /var/lib/pgsql/17/data/ +exit + +systemctl enable --now postgresql-17 +cd /tmp +git clone --branch v0.8.1 https://github.com/pgvector/pgvector.git +cd pgvector + +dnf config-manager --set-enabled crb +dnf install -y perl-IPC-Run +dnf install -y git gcc make postgresql17-devel redhat-rpm-config + +PATH=/usr/pgsql-17/bin:$PATH make +PATH=/usr/pgsql-17/bin:$PATH make install + +systemctl restart postgresql-17 \ No newline at end of file diff --git a/database_setup.sql b/database_setup.sql new file mode 100644 index 0000000..d31441f --- /dev/null +++ b/database_setup.sql @@ -0,0 +1,83 @@ +-- ============================================ +-- Dewey 애플리케이션 데이터베이스 설정 스크립트 +-- ============================================ +-- 이 스크립트는 postgres superuser로 실행해야 합니다. +-- 실행 방법: psql -U postgres -f database_setup.sql + +-- 1. 데이터베이스 생성 (필요한 경우) +-- CREATE DATABASE dewey_memory; + +-- 2. dewey_memory 데이터베이스에 연결 +\c dewey_memory + +-- 3. pgvector 확장 설치 (superuser 권한 필요) +CREATE EXTENSION IF NOT EXISTS vector; + +-- 4. dewey 사용자에게 필요한 최소 권한만 부여 +-- (보안을 위해 최소한의 권한만 부여) +GRANT CONNECT ON DATABASE dewey_memory TO dewey; +GRANT USAGE ON SCHEMA public TO dewey; +GRANT CREATE ON SCHEMA public TO dewey; + +-- 5. 기존 테이블/시퀀스에 대한 권한 부여 +GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO dewey; +GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO dewey; + +-- 6. 향후 생성될 테이블/시퀀스에 대한 기본 권한 설정 +ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO dewey; +ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO dewey; + +-- 7. dewey 사용자가 확장을 생성할 수 없도록 명시적으로 제한 +-- (확장 생성은 superuser만 가능하므로 이미 제한되어 있음) +-- 하지만 혹시 모를 권한을 명시적으로 제거 +REVOKE CREATE ON DATABASE dewey_memory FROM dewey; + +-- 8. dewey 사용자가 다른 사용자를 생성하거나 권한을 부여할 수 없도록 제한 +-- (이미 dewey는 일반 사용자이므로 불필요하지만 명시적으로 확인) +DO $$ +BEGIN + -- dewey가 superuser인지 확인하고 제거 (혹시 모를 경우 대비) + IF EXISTS ( + SELECT 1 FROM pg_user WHERE usename = 'dewey' AND usesuper = true + ) THEN + ALTER USER dewey WITH NOSUPERUSER; + RAISE NOTICE 'dewey 사용자의 superuser 권한이 제거되었습니다.'; + ELSE + RAISE NOTICE 'dewey 사용자는 이미 일반 사용자입니다.'; + END IF; + + -- dewey가 데이터베이스를 생성할 수 없도록 제한 + IF EXISTS ( + SELECT 1 FROM pg_user WHERE usename = 'dewey' AND usecreatedb = true + ) THEN + ALTER USER dewey WITH NOCREATEDB; + RAISE NOTICE 'dewey 사용자의 CREATEDB 권한이 제거되었습니다.'; + ELSE + RAISE NOTICE 'dewey 사용자는 이미 CREATEDB 권한이 없습니다.'; + END IF; + + -- dewey가 다른 사용자를 생성할 수 없도록 제한 + IF EXISTS ( + SELECT 1 FROM pg_user WHERE usename = 'dewey' AND usecreaterole = true + ) THEN + ALTER USER dewey WITH NOCREATEROLE; + RAISE NOTICE 'dewey 사용자의 CREATEROLE 권한이 제거되었습니다.'; + ELSE + RAISE NOTICE 'dewey 사용자는 이미 CREATEROLE 권한이 없습니다.'; + END IF; +END $$; + +-- 9. 권한 확인 +\echo '=== dewey 사용자 권한 확인 ===' +\du dewey + +\echo '=== public 스키마 권한 확인 ===' +\dn+ public + +\echo '=== pgvector 확장 확인 ===' +SELECT extname, extversion FROM pg_extension WHERE extname = 'vector'; + +\echo '=== 스크립트 실행 완료 ===' +\echo 'dewey 사용자는 이제 최소한의 권한만 가지고 있습니다.' +\echo '애플리케이션은 테이블/인덱스 생성 및 데이터 조작만 가능합니다.' + diff --git a/src/main/java/com/pandol365/dewey/config/DatabaseInitializer.java b/src/main/java/com/pandol365/dewey/config/DatabaseInitializer.java index c85728b..e18624d 100644 --- a/src/main/java/com/pandol365/dewey/config/DatabaseInitializer.java +++ b/src/main/java/com/pandol365/dewey/config/DatabaseInitializer.java @@ -24,8 +24,17 @@ public class DatabaseInitializer implements CommandLineRunner { try { log.info("=== 데이터베이스 초기화 시작 ==="); - // 1. pgvector 확장 확인 및 생성 - initializePgVectorExtension(); + // 1. pgvector 확장 확인 (확장 생성은 시도만 하고, 실패해도 계속 진행) + boolean pgvectorAvailable = checkPgVectorExtension(); + + if (!pgvectorAvailable) { + log.warn("pgvector 확장이 설치되지 않았습니다. 벡터 검색 기능을 사용하려면 pgvector 확장을 설치해주세요."); + log.warn("설치 방법: PostgreSQL 서버에서 다음 명령어 실행:"); + log.warn(" psql -U postgres -d dewey_memory -c 'CREATE EXTENSION vector;'"); + log.warn("또는 dewey 사용자에게 확장 생성 권한 부여 후 애플리케이션 재시작"); + log.info("=== 데이터베이스 초기화 완료 (pgvector 없음) ==="); + return; + } // 2. memory_embeddings 테이블 생성 createMemoryEmbeddingsTable(); @@ -42,15 +51,64 @@ public class DatabaseInitializer implements CommandLineRunner { } /** - * pgvector 확장 생성 + * pgvector 확장 확인 + * @return 확장이 사용 가능하면 true */ - private void initializePgVectorExtension() { + private boolean checkPgVectorExtension() { try { log.info("pgvector 확장 확인 중..."); - jdbcTemplate.execute("CREATE EXTENSION IF NOT EXISTS vector"); - log.info("pgvector 확장 확인 완료"); + + // 현재 데이터베이스에서 확장이 이미 존재하는지 확인 + Integer count = jdbcTemplate.queryForObject( + "SELECT COUNT(*) FROM pg_extension WHERE extname = 'vector'", + Integer.class + ); + + if (count != null && count > 0) { + log.info("pgvector 확장이 이미 설치되어 있습니다."); + return true; + } + + // 확장이 없으면 생성 시도 + log.info("pgvector 확장 생성 시도 중..."); + try { + jdbcTemplate.execute("CREATE EXTENSION IF NOT EXISTS vector"); + + // 생성 후 다시 확인 + count = jdbcTemplate.queryForObject( + "SELECT COUNT(*) FROM pg_extension WHERE extname = 'vector'", + Integer.class + ); + + if (count != null && count > 0) { + log.info("pgvector 확장 생성 완료"); + return true; + } else { + log.warn("pgvector 확장 생성 후에도 확인되지 않습니다."); + return false; + } + } catch (Exception e) { + // 확장이 이미 존재하는 경우도 있으므로 다시 확인 + log.debug("CREATE EXTENSION 실패, 재확인 중: {}", e.getMessage()); + count = jdbcTemplate.queryForObject( + "SELECT COUNT(*) FROM pg_extension WHERE extname = 'vector'", + Integer.class + ); + + if (count != null && count > 0) { + log.info("pgvector 확장이 존재합니다 (생성 시도 중 오류 발생했지만 확장은 존재함)"); + return true; + } + + log.warn("pgvector 확장 생성 실패: {}", e.getMessage()); + log.warn("현재 데이터베이스에 pgvector 확장이 없습니다. 다음 명령어를 실행해주세요:"); + log.warn(" psql -d dewey_memory -c 'CREATE EXTENSION vector;'"); + return false; + } + } catch (Exception e) { - log.warn("pgvector 확장 생성 실패 (이미 존재할 수 있음): {}", e.getMessage()); + log.error("pgvector 확장 확인 중 오류 발생: {}", e.getMessage(), e); + return false; } }