76f43cea9b
Build & Deploy to K8s / build-and-deploy (push) Successful in 4m30s
- application.yml, k8s configmap, docker-compose 4종: SPRING_DATASOURCE_URL path
- provisioning 코드: {prefix}_vexplor → {prefix}_invyone 테넌트 DB 네이밍 규칙
- 프론트 마법사: Step1Basic, Step4Run 미리보기 라벨
- CompanyAccordionRow: 기본 DB 이름 포맷
- 마이그레이션/멀티테넌시 문서 동기화
- Traefik 와일드카드 설정 산출물 보관 (notes/)
비밀번호(vexplor0909!!) 및 역사 기록 문서(INVYONE_CONCEPT,
DDD1542, test-output, dashboard-runtime-fixes) 는 의도적으로 미변경.
105 lines
3.6 KiB
Markdown
105 lines
3.6 KiB
Markdown
# 079 마이그레이션 실행 가이드 — 멀티테넌시 Phase 1
|
|
|
|
작성일: 2026-04-24
|
|
작성자: gbpark
|
|
관련 문서: `notes/gbpark/2026-04-24-company-db-provisioning-execution-plan.md`
|
|
|
|
## 목적
|
|
|
|
회사별 DB 자동 프로비저닝 & 서브도메인 라우팅을 위한 메타 컬럼을 `COMPANY_MNG` 테이블에 추가.
|
|
|
|
Phase 1 은 **라우팅 no-op** 단계 — 컬럼만 추가, 실제 라우팅은 Phase 2에서.
|
|
|
|
## 추가되는 컬럼
|
|
|
|
| 컬럼 | 타입 | 설명 |
|
|
|---|---|---|
|
|
| `DB_NAME` | VARCHAR(64) | 실제 DB 이름 (예: `qnc_invyone`). Phase 3 이전엔 NULL 허용 |
|
|
| `SUBDOMAIN` | VARCHAR(64) | 접속 서브도메인 (예: `qnc`). UNIQUE |
|
|
| `DB_HOST` | VARCHAR(128) | DB 서버 호스트 (향후 분산 대비). 기본 NULL |
|
|
| `DB_STATUS` | VARCHAR(20) | `provisioning` / `schema_copied` / `admin_created` / `active` / `failed` / `suspended`. 기본 `active` |
|
|
|
|
> 기존 `STATUS` 컬럼('active'/'inactive')과 혼동 주의. `DB_STATUS` 는 **DB 프로비저닝 상태**로 별개 역할.
|
|
|
|
## SQL
|
|
|
|
```sql
|
|
-- 079: COMPANY_MNG 멀티테넌시 메타 컬럼 추가
|
|
ALTER TABLE COMPANY_MNG
|
|
ADD COLUMN IF NOT EXISTS DB_NAME VARCHAR(64),
|
|
ADD COLUMN IF NOT EXISTS SUBDOMAIN VARCHAR(64),
|
|
ADD COLUMN IF NOT EXISTS DB_HOST VARCHAR(128),
|
|
ADD COLUMN IF NOT EXISTS DB_STATUS VARCHAR(20) DEFAULT 'active';
|
|
|
|
-- 서브도메인 UNIQUE 인덱스 (NULL 다수 허용)
|
|
CREATE UNIQUE INDEX IF NOT EXISTS UX_COMPANY_MNG_SUBDOMAIN
|
|
ON COMPANY_MNG (SUBDOMAIN)
|
|
WHERE SUBDOMAIN IS NOT NULL;
|
|
|
|
-- 기존 회사들은 DB_STATUS 기본값 'active' 로 채워짐 (DEFAULT 덕분).
|
|
-- 확인용 조회:
|
|
-- SELECT COMPANY_CODE, COMPANY_NAME, DB_NAME, SUBDOMAIN, DB_HOST, DB_STATUS FROM COMPANY_MNG;
|
|
```
|
|
|
|
## 실행 방법
|
|
|
|
### 방법 1: DBeaver / pgAdmin
|
|
1. `invyone` DB 연결
|
|
2. 위 SQL 블록 복사 & 실행
|
|
3. 확인 쿼리 돌려서 컬럼 생성 여부 확인
|
|
|
|
### 방법 2: psql
|
|
```bash
|
|
psql -h 183.99.177.40 -U postgres -d invyone <<'SQL'
|
|
ALTER TABLE COMPANY_MNG
|
|
ADD COLUMN IF NOT EXISTS DB_NAME VARCHAR(64),
|
|
ADD COLUMN IF NOT EXISTS SUBDOMAIN VARCHAR(64),
|
|
ADD COLUMN IF NOT EXISTS DB_HOST VARCHAR(128),
|
|
ADD COLUMN IF NOT EXISTS DB_STATUS VARCHAR(20) DEFAULT 'active';
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS UX_COMPANY_MNG_SUBDOMAIN
|
|
ON COMPANY_MNG (SUBDOMAIN)
|
|
WHERE SUBDOMAIN IS NOT NULL;
|
|
SQL
|
|
```
|
|
|
|
## 확인 쿼리
|
|
|
|
```sql
|
|
-- 1. 컬럼 생성 확인
|
|
SELECT column_name, data_type, column_default, is_nullable
|
|
FROM information_schema.columns
|
|
WHERE table_name = 'company_mng'
|
|
AND column_name IN ('db_name', 'subdomain', 'db_host', 'db_status')
|
|
ORDER BY column_name;
|
|
|
|
-- 2. 기존 회사 DB_STATUS 자동 채워짐 확인
|
|
SELECT COMPANY_CODE, COMPANY_NAME, STATUS, DB_STATUS FROM COMPANY_MNG;
|
|
|
|
-- 3. UNIQUE 인덱스 확인
|
|
SELECT indexname, indexdef FROM pg_indexes
|
|
WHERE tablename = 'company_mng' AND indexname = 'ux_company_mng_subdomain';
|
|
```
|
|
|
|
## 롤백
|
|
|
|
```sql
|
|
DROP INDEX IF EXISTS UX_COMPANY_MNG_SUBDOMAIN;
|
|
ALTER TABLE COMPANY_MNG
|
|
DROP COLUMN IF EXISTS DB_NAME,
|
|
DROP COLUMN IF EXISTS SUBDOMAIN,
|
|
DROP COLUMN IF EXISTS DB_HOST,
|
|
DROP COLUMN IF EXISTS DB_STATUS;
|
|
```
|
|
|
|
## 기존 API/화면 영향
|
|
|
|
- `admin.xml` 의 `insertCompany` / `updateCompany` 는 이 컬럼들을 참조 안 함. 신규 컬럼은 기본값/NULL 로 채워짐 → **회귀 없음**.
|
|
- 기존 회사관리 UI (`frontend/app/(main)/admin/userMng/companyList`) 변경 불필요. Phase 3 에서 마법사 UI 신설 시 함께 수정.
|
|
|
|
## 체크리스트
|
|
|
|
- [ ] `invyone` DB 에 위 SQL 실행
|
|
- [ ] 확인 쿼리 1, 2, 3 모두 통과
|
|
- [ ] `SELECT * FROM COMPANY_MNG LIMIT 1;` 로 기존 데이터 정상 조회 확인
|