온톨로지 이관 실행 런북 (P2~P5)
작성: 2026-10-16 · 상태: 확정 절차 — 계획·근거는 docs/ontology-ownership-move-plan.md, 경계는 UiPlatform docs/SERVICE_BOUNDARIES.md·docs/ONTOLOGY_SCOPE.md. 대상: 운영자(배포·DB 실행 담당). 서비스 = OntologyService(https://ontology.rlab.monster) · 저장소 github.com:hohyun94/OntologyService(비공개).
확정 사항 (2026-10-16): 이름 OntologyService · DB PostgreSQL A안(같은 서버 · 논리 DB ontology · 계정 ontology_service) · 감사 이력 복사 · 번역 팩 폴백 마지막 팩 캐시 · P2 로컬 1회 실행 · P3 순차 절체(ProcessCenter → DocumentLibrary → GuideCenter) · P4 1주 관찰 후 표면 전환 · 폐쇄망 번들 미포함(추후).
1. 사전 준비 (운영자)
1-1. PostgreSQL — 콘솔과 같은 서버
-- 관리자 계정으로 한 번
CREATE DATABASE ontology;
CREATE ROLE ontology_service LOGIN PASSWORD '<secret>';
GRANT ALL PRIVILEGES ON DATABASE ontology TO ontology_service;
ALTER DATABASE ontology OWNER TO ontology_service;
\c ontology
GRANT ALL ON SCHEMA public TO ontology_service; -- PG 15+ 는 public 스키마 권한이 따로다같은 논리 DB 를 공유하지 않는 이유: 이 서비스는 이관 호환을 위해 표 이름을 콘솔과 똑같이 쓴다 → 같은 이름 공간에서는
CREATE TABLE이 충돌한다(계획 §14).
1-2. Coolify 앱 + 환경변수
| 변수 | 값 | 비고 |
|---|---|---|
DATABASE_DIALECT | postgresql | |
DATABASE_URL | postgres://ontology_service:<secret>@<host>:5432/ontology | |
PUBLIC_BASE_URL | https://ontology.rlab.monster | 콘솔이 번역 팩을 읽을 주소 |
PORTAL_API_KEYS_JSON | 소비자 3곳 키 원문 | 각 소비자 앱 env 에서 확보 — 콘솔 DB 엔 해시만 있다 |
ONTOLOGY_SERVICE_JWT_SECRET | 32바이트+ 랜덤 | 관리자 세션(8시간) |
PORTAL_CONSOLE_ENVELOPE_MASTER_KEY | 콘솔과 같은 값 | 과거 감사 스냅샷 복호화의 전제 |
PORTAL_CONSOLE_ENVELOPE_LEGACY_MASTER_KEYS | 콘솔과 같은 값(있으면) | 키 회전 이력 |
ONTOLOGY_SERVICE_ADMIN_API_KEYS_JSON | 관리자 키(선택) | 미설정이면 관리자 키 경로는 503 |
PORT / RUN_MIGRATIONS_ON_START | 3400 / true | 배포가 스키마를 반영한다 |
- 빌드: 저장소 루트
Dockerfile(2단계 ·vendor/의 portal-foundation tarball 포함) · 온프렘은docker-compose.onprem.yml· 헬스GET /healthz. - ⚠️ 봉투 키를 공유하면 키가 두 곳에 존재한다 → 이관 완료 후 회전 계획을 세운다(계획 §11).
1-3. 배포 확인
curl -s https://ontology.rlab.monster/healthz
# {"service":"ontology-service","status":"ok","dialect":"postgresql","databaseConfigured":true}- 관리자 화면:
https://ontology.rlab.monster/(계정 로그인 — 최초 계정 생성 절차는 저장소 README) - 마이그레이션은 시작 명령이 적용한다(
node dist/migrate.js && node dist/index.js). 끄려면RUN_MIGRATIONS_ON_START=false.
2. P2 데이터 이관 (로컬 1회 — 확정 2026-10-16)
2-1. 기준값 수집 (콘솔 DB · 읽기 계정)
SELECT 'glossary', count(*), max(updated_at) FROM directory_glossary_terms
UNION ALL SELECT 'relations', count(*), max(updated_at) FROM directory_ontology_relations
UNION ALL SELECT 'links', count(*), max(updated_at) FROM directory_content_term_links
UNION ALL SELECT 'audit', count(*), max(created_at) FROM directory_audit_logs WHERE entity_type = 'ONTOLOGY';2-2. 실행
cd ~/projects/OntologyService
# ① 무엇을 옮길지만 본다(쓰기 없음)
CONSOLE_DATABASE_URL='postgres://<console-reader>@<console-host>:5432/<console-db>' \
DATABASE_URL='postgres://ontology_service:<secret>@<host>:5432/ontology' \
pnpm p2:migrate -- --dry-run
# ② 본 실행 — 표 3개 + 감사 이력 복사, 끝에 자동 대조(어긋나면 exit 1)
... pnpm p2:migrate
# ③ 절체 직전 증분(그 시각 이후 바뀐 행만)
... pnpm p2:migrate -- --since 2026-10-16T00:00:00Z
# ④ 대조만 다시
... pnpm p2:migrate -- --verify-only- 표 3개는
id기준ON CONFLICT DO UPDATE(멱등·증분), 감사 이력은entity_type='ONTOLOGY'만DO NOTHING(불변 기록). - 쓰기 동결 창은 두지 않는다 — 콘솔이 계속 쓰는 동안 복사하고 절체 직전에 ③을 한 번 더 돌린다.
2-3. P2 완료 조건 (체크 없이 P3 금지)
- [ ] 4개 표의 행 수·최신 시각 일치(감사는
entity_type='ONTOLOGY'조건 포함) - [ ] 번역 팩 지문(
translationPackVersion)과 온톨로지 팩 개념/관계 수 일치 - [ ] 감사 1건이 복호화된다(봉투 키 공유 검증 — 스냅샷이 깨지면 키가 다르다)
- [ ] 승인 필터(
status='approved'·is_active) 결과 동일
3. P3 소비자 절체 (순차 — 확정 2026-10-16)
| 순서 | repo | 할 일 | 확인 |
|---|---|---|---|
| 1 | ProcessCenter | Coolify env 에 ONTOLOGY_BASE_URL=https://ontology.rlab.monster 추가 → 재배포 | 용어 매칭 push → 원장 반영 / termLinkSync 오류 없음 |
| 2 | DocumentLibrary | 같음 | contentTermService 링크 조회 정상 |
| 3 | GuideCenter | 같음(번역 팩 출처가 바뀐다) | translationGlossary 팩 수신·번역 정상 |
| 4 | PortalConsole(번역 실행) | env ONTOLOGY_BASE_URL + 마지막 팩 캐시 적용(코드 변경) | 지식 서비스 중단 시 캐시로 번역 지속, 캐시도 없으면 용어 없이 번역 + 응답에 표시 |
- 키는 바꾸지 않는다 — 주소만 바꾼다(scope 이름
glossary:read·glossary:write유지). - 소비자에
DIRECTORY_BASE_URL폴백을 남긴다(롤백 = env 한 줄). - 실연결 1회: 각 repo 테스트(
termLinkSync.test.ts등) + 실제 push/pull 1건.
4. P4 표면 전환 (1주 관찰 후 — 확정 2026-10-16)
콘솔 표면 전환 완료(2026-10-17): 관리자 메뉴의 온톨로지 탭을 제거하고, 등록된
ontology포털(PLATFORM_SERVICE) 주소를 레일 하단OntologyService런처로 연다.OntologyDesk자산은 롤백(§5)을 위해 파일로만 남긴다. 아래 2~3은 별도 작업이다.
- 콘솔 관리자 메뉴 온톨로지 탭 제거 → 레일 하단 런처(FileStore 와 같은
.platform-launch패턴, 등록된ontology포털 주소 필요 — 「포털 연동 설정」에서applicationType=PLATFORM_SERVICE로 등록). - ProcessCenter 전문용어사전: 쓰기 제거 + OntologyService 링크(중복 편집 종료).
- 콘솔 tRPC/REST 는 1릴리스 폐기 예고 후 P5 에서 제거.
5. 롤백
| 단계 | 롤백 방법 |
|---|---|
| P2 | 콘솔 원장이 그대로 살아 있다(쓰기 차단 없음) — 새 서비스 데이터만 비운다 |
| P3 | 해당 소비자 env 에서 ONTOLOGY_BASE_URL 삭제 → DIRECTORY_BASE_URL 폴백 → 재배포 |
| P4 | 온톨로지 탭 복구(런처는 그대로 둔다) |
중단 조건: 팩 지문 불일치 · 소비자 실연결 실패 · 감사 스냅샷 복호화 실패 · 행 수 차이 1건 이상 · 툴팁 정의 미표시.
6. 폐쇄망 번들 (추후 — 확정 2026-10-16: 온라인 안정화 후)
deploy-offline/apps.conf 에 추가할 줄:
"ontology-service|$PROJECTS/OntologyService|Dockerfile|docker-compose.onprem.yml|ontology-service:onprem|-"