데이터 구조 관리

스키마 변경이 통제되지 않으면 생기는 일

스키마 자동 수집 아키텍처, DBMS별 수집 전략, 갭 분석(개발-운영, ERD-DBMS, 표준-실제), 변경 요청 워크플로, 작업 규칙 자동 검증, 변경 이력 관리, 환경별 스키마 관리를 다룬다.

Data Governance
저자

Kwangmin Kim

공개

2026년 03월 27일

1 통제되지 않은 스키마 변경이 만드는 장애

운영 중인 서비스에서 개발자가 DBA를 통하지 않고 직접 운영 DB에 ALTER TABLE을 실행했다. 칼럼 타입을 VARCHAR(100)에서 VARCHAR(200)으로 바꾼 것이다. 기능 자체는 문제없이 동작한다. 그러나 2주 후 그 테이블을 DW로 적재하는 ETL이 실패하기 시작한다. ETL의 소스 칼럼 매핑이 100자 기준으로 설계되어 있었기 때문이다. 운영 DB와 DW의 스키마가 불일치하게 된 것이다.

이 사례에서 문제의 핵심은 변경 자체가 아니라 변경이 추적되지 않았다는 것이다. 변경 이력이 없으니 “언제 누가 뭘 바꿨는지”를 모른다. 영향받는 시스템 목록이 없으니 연쇄 영향을 사전에 파악하지 못했다. 개발, 스테이징, 운영 환경 간 스키마를 비교하는 수단이 없으니 불일치를 발견하지 못했다.

데이터 구조 관리는 이 세 가지 문제를 시스템적으로 해결한다. 변경 이력을 자동으로 남기고, 영향도를 분석하고, 환경 간 갭을 자동으로 탐지한다. 앞선 글에서 라이프사이클 2단계(모델 설계)의 핵심으로 “ERD는 살아있는 설계 기준이어야 한다”고 설명했다. 이 글에서는 그 원칙이 실제 시스템에서 어떻게 구현되는지를 구체적으로 다룬다.


2 스키마 자동 수집: 저장소와 대상 DB의 분리

2.1 수집 아키텍처의 핵심 원칙

구조 관리의 출발점은 실제 DBMS의 스키마를 메타데이터 저장소로 가져오는 것이다. DMBOK은 “메타데이터 저장소는 설명적 정보를 저장하는 소프트웨어 도구”이며 “저장하는 것보다 공유하는 것이 더 중요하다”고 강조한다 (DAMA International, 2017, Ch.5). 이 수집 과정에서 지켜야 할 원칙이 세 가지 있다.

저장소 DB와 대상 DB는 물리적으로 분리한다. 메타데이터를 저장하는 DB와 스키마를 수집하는 대상 DB가 같으면 메타데이터 시스템 자체가 대상 DB에 의존하게 된다. 대상 DB 장애 시 메타데이터 시스템도 영향을 받고, 대상 DB의 스키마 정보를 저장소가 정확히 반영하는지 검증하기 어렵다.

수집 쿼리는 시스템 카탈로그만 읽는다. 실제 데이터를 읽지 않는다. information_schema, sys, dba_ 접두사 뷰처럼 DBMS가 제공하는 메타데이터 뷰만 조회한다. 운영 서버 부하를 최소화하는 동시에 수집 커넥션에 필요한 권한을 최소화한다(SELECT on system views만 필요).

변경 감지 방식으로 수집한다. 매번 전체 스키마를 수집해서 저장소를 덮어쓰면 이전 상태가 사라진다. 올바른 방식은 이전 수집 결과와 현재 수집 결과를 비교해서 추가, 변경, 삭제된 객체만 저장소에 반영하고 변경 이력을 남기는 것이다.

2.2 DBMS별 스키마 수집 전략

멀티 DBMS를 지원하려면 각 DBMS의 시스템 카탈로그 쿼리를 별도로 관리해야 한다. 동일한 정보를 조회하더라도 DBMS마다 뷰 이름과 칼럼명이 다르다.

DBMS 테이블 목록 칼럼 목록 코멘트 특이사항
Oracle ALL_TABLES ALL_TAB_COLS ALL_COL_COMMENTS (조인 필요) NUM_ROWS는 통계 수집 시점 근사값
PostgreSQL information_schema.tables information_schema.columns pg_catalog.pg_description (조인 필요) pg_total_relation_size() 함수로 크기 조회
MySQL/MariaDB information_schema.TABLES information_schema.COLUMNS COLUMN_COMMENT 필드 (조인 불필요) InnoDB의 TABLE_ROWS는 근사값
MS SQL Server sys.tables sys.columns sys.extended_properties (조인 필요) 확장 속성 기반 코멘트 관리

이 차이들을 흡수하는 추상화 레이어를 설계해야 한다. DBMS 타입에 따라 다른 수집 쿼리를 실행하지만, 결과를 동일한 스키마의 내부 데이터 구조로 정규화해서 저장소에 저장한다. 표준 관리에서 다룬 DBMS별 DDL 생성기와 동일한 추상화 원칙이 수집기에도 적용된다.

2.3 행 수(Row Count) 수집의 주의사항

테이블의 행 수를 정확히 파악하는 것은 품질 진단, 데이터 마이그레이션 계획, 인덱스 설계 등에서 중요한 정보다. 그러나 COUNT(*) 쿼리는 테이블 전체를 스캔하므로 운영 서버에 부하를 준다.

접근법 정확도 부하 적합한 상황
시스템 통계 근사값 낮음 (마지막 통계 수집 시점) 거의 없음 일상적 모니터링
COUNT(*) 야간 배치 높음 높음 정확한 값이 필요한 마이그레이션, 감사

근사값으로 충분한 경우에는 시스템 통계를 사용하고, 정확한 값이 필요한 경우에만 야간 배치로 실행하는 방식이 현실적이다.


3 갭 분석: 불일치를 자동으로 탐지한다

3.1 갭 분석이 필요한 3가지 상황

상황 1: 개발 DB와 운영 DB 간 갭. 개발에서 스키마를 변경했는데 운영에 배포되지 않은 경우. 또는 운영에서 직접 스키마를 변경했는데 개발에 반영되지 않은 경우. 이 갭이 누적되면 개발 환경에서 정상 동작하는 기능이 운영에서 오류가 나는 상황이 발생한다.

상황 2: ERD 모델과 DBMS 간 갭. ERD를 수정했는데 실제 DBMS에 적용되지 않은 경우. 또는 DBMS를 직접 수정했는데 ERD가 업데이트되지 않은 경우. DMBOK은 “개발 이터레이션 종료 시 물리 모델을 역공학하여 논리 모델과 일치하는지 확인하는 것이 모범 사례”라고 권고한다 (DAMA International, 2017, Ch.5). 이 갭이 누적되면 ERD는 설계 문서로서의 의미를 잃어버린다.

상황 3: 표준과 실제 스키마 간 갭. 표준에 정의된 명명 규칙을 따르지 않는 칼럼이 배포된 경우. 이 갭은 표준 준수율이라는 품질 지표로 표현된다.

3.2 갭 탐지 로직

갭 분석은 두 소스에서 동일 객체를 가져와 비교하는 것이다. 비교 단위는 테이블-칼럼 수준이다.

갭 탐지 알고리즘:

입력: source_conn_id (개발 DB), target_conn_id (운영 DB)

1. source에서 테이블 목록 조회
2. target에서 테이블 목록 조회
3. source에만 있는 테이블 → "테이블 누락" 갭
4. target에만 있는 테이블 → "테이블 불필요" 갭
5. 양쪽에 모두 있는 테이블에 대해 칼럼 비교:
   a. source에만 있는 칼럼 → "칼럼 누락" 갭
   b. target에만 있는 칼럼 → "칼럼 불필요" 갭
   c. 양쪽에 모두 있는 칼럼:
      - 데이터 타입 다름 → "타입 불일치" 갭
      - 길이 다름 → "길이 불일치" 갭
      - NULL 허용 여부 다름 → "NULL 정책 불일치" 갭
      - 기본값 다름 → "기본값 불일치" 갭

이 알고리즘을 실행하면 갭 분석 결과 목록이 생성된다. 각 갭 항목은 결과 테이블에 저장되고, 해당 갭을 해소하는 DDL이 자동 생성된다.

3.3 갭 분석에서 변경 요청으로

갭 분석 결과에서 “개발에는 있고 운영에는 없는 칼럼” 목록을 선택하면 운영 배포 변경 요청이 자동으로 생성되어야 한다. 이것이 갭 분석을 단순한 비교 도구가 아니라 변경 관리 워크플로의 시작점으로 만드는 설계다.

갭 분석 결과 예시:
  개발 DB: TB_ORDER 테이블에 CANCEL_REASON VARCHAR(500) 칼럼 존재
  운영 DB: TB_ORDER 테이블에 CANCEL_REASON 칼럼 없음

-> 자동 생성된 변경 요청:
  제목: [갭분석] TB_ORDER.CANCEL_REASON 칼럼 운영 배포
  자동 생성 DDL:
    Oracle:     ALTER TABLE TB_ORDER ADD (CANCEL_REASON VARCHAR2(500));
    MySQL:      ALTER TABLE TB_ORDER ADD COLUMN CANCEL_REASON VARCHAR(500);
    PostgreSQL: ALTER TABLE TB_ORDER ADD COLUMN CANCEL_REASON VARCHAR(500);

DDL을 DBMS 타입별로 다르게 생성해야 한다. 수집기와 마찬가지로 DBMS별 DDL 생성기를 추상화 레이어로 설계해야 하는 이유다.


4 변경 요청 워크플로: 통제된 배포의 설계

4.1 왜 변경 요청 프로세스가 필요한가

개발자가 운영 DB에 직접 DDL을 실행하는 것을 막는 것만으로는 부족하다. 변경 요청 시스템이 없으면 개발자는 DBA에게 이메일이나 메신저로 변경을 요청하고, DBA가 직접 실행하고, 결과를 다시 메신저로 알린다. 이 과정에서 요청 내용의 정확성 검증이 없고, 변경 이력이 메신저 로그에만 남고, 동시에 여러 변경이 들어오면 순서 관리가 안 된다.

변경 요청 시스템은 이 과정을 구조화한다. 변경 내용의 명확한 기술, 자동 검증, 승인 프로세스, 실행 추적, 이력 보존이 한 흐름 안에서 이루어진다.

4.2 변경 요청의 생명 주기

DRAFT (작성 중)
  -> 개발자가 변경 요청 작성, DDL 자동 생성 또는 직접 입력
  -> 작업 규칙 자동 검증 (blocking/non-blocking)

SUBMITTED (제출됨)
  -> 제출 시 작업 규칙 재검증, 검토자 지정

REVIEWING (검토 중)
  -> DA 검토: 표준 준수 여부, 명명 규칙
  -> DBA 검토: 성능, 용량, 인덱스 적절성
  -> 필요시 반려 또는 수정 요청

APPROVED (승인됨)
  -> 배포 스케줄 확정

DEPLOYED (배포 완료)
  -> DDL 실행, 실행 결과 저장
  -> 스키마 메타데이터 자동 갱신, 갭 분석 결과 갱신

REJECTED / CANCELLED
  -> 반려 사유 기록, 재작성 후 재제출 가능

4.3 작업 규칙 자동 검증: 배포 전 품질 게이트

작업 규칙(Work Rule)은 변경 요청 제출 시 자동으로 실행되는 검증 규칙이다. DA와 DBA가 검토하기 전에 명백한 위반을 먼저 걸러낸다.

규칙 유형 검증 로직
칼럼명은 표준 단어 조합이어야 한다 non-blocking 칼럼명 파싱 -> 표준 단어 목록에서 확인 -> 미등록 시 경고
PK 칼럼은 삭제할 수 없다 blocking 삭제 대상 칼럼이 PK인지 확인 -> PK이면 차단
NOT NULL 칼럼 추가 시 기본값 필요 blocking 테이블 행 수 > 0이면 기본값 필수 체크
칼럼 타입 축소는 데이터 손실 경고 non-blocking 현재 최대 길이와 변경 후 길이 비교 -> 손실 가능 시 경고
인덱스 선두 칼럼 변경은 검토 필요 non-blocking 인덱스 구성 변경 포함 시 DBA 검토 권고

blocking 규칙은 위반 시 제출 자체를 차단한다. non-blocking 규칙은 경고를 표시하되 제출은 허용하고 검토 단계에서 최종 판단한다. 이 구분이 있어야 과도한 차단으로 인한 개발 생산성 저하를 방지할 수 있다.

4.4 DDL 자동 생성의 정확도와 한계

DDL 자동 생성은 편의 기능이지 완전한 자동화가 아니다. 자동 생성된 DDL이 항상 최적이지는 않는다.

새 칼럼 추가 시 자동 생성 DDL은 기본적인 ADD COLUMN 구문만 생성한다. 인덱스 필요 여부, 파티션 키 사용 여부, 스토리지 파라미터는 DBA가 판단해서 수동으로 추가해야 한다. 특히 대용량 테이블(수억 건)의 칼럼 변경은 특별한 처리가 필요하다. Oracle에서 대용량 테이블에 칼럼을 추가하면 테이블 전체에 락이 걸릴 수 있으므로 온라인 DDL 방식이나 Shadow Table 전략이 필요하다. 자동 생성 DDL은 이런 특수 케이스를 처리하지 못하므로 DBA 검토가 필수적이다.


5 변경 이력 관리: 과거로 돌아가는 능력

5.1 이력 보존의 이중 구조

스키마 변경 이력은 두 가지 방식으로 보존된다.

이력 유형 보존 내용 답할 수 있는 질문
변경 요청 이력 변경의 의도, 승인자, 실행된 DDL “왜 이 변경을 했는가”, “누가 승인했는가”
스키마 스냅샷 이력 변경 시점마다 칼럼의 상태 “3개월 전 이 칼럼의 타입은 무엇이었는가”

이 두 이력이 모두 있어야 완전한 추적이 가능하다. 변경 요청 이력만 있으면 요청 이전의 상태를 모른다. 스냅샷 이력만 있으면 변경의 의도와 승인 과정을 모른다.

5.2 이력 테이블 설계: FK를 제거하는 이유

이력 테이블에서 외래키(FK) 제약조건을 제거하는 것이 일반적으로 받아들여지는 설계 원칙이다. 원본 테이블의 레코드가 삭제될 때 이력 테이블의 참조 레코드는 영구 보존되어야 한다. FK가 있으면 원본 삭제 시 CASCADE DELETE로 이력도 함께 삭제되거나, FK 위반으로 삭제 자체가 막힌다. 어느 쪽도 원하는 결과가 아니다.

이력 테이블에는 원본 ID를 일반 칼럼으로 저장하고, 이것이 이력 조회의 키로 사용되지만 FK 제약은 없다. 이력 테이블의 무결성은 애플리케이션 레이어에서 보장한다.

5.3 롤백 시나리오

잘못된 변경이 배포된 경우 이력에서 이전 상태를 조회하고 역방향 DDL을 생성해서 롤백할 수 있어야 한다.

칼럼 타입이 VARCHAR(100) -> VARCHAR(200)으로 변경된 후 문제가 발생했다면, 이력에서 이전 상태(VARCHAR(100))를 확인하고 ALTER TABLE ... MODIFY COLUMN ... VARCHAR(100)을 생성해서 롤백 변경 요청을 만든다. 단, 타입을 축소하는 방향의 롤백은 데이터 손실 위험이 있으므로 먼저 현재 데이터의 최대 길이를 확인해야 한다. 작업 규칙의 “칼럼 타입 축소 경고”가 바로 이 상황에 적용된다.


6 환경별 스키마 관리: 개발-스테이징-운영의 3계층

6.1 환경 분리의 의미

환경 분리는 개발 중인 기능이 운영 서비스에 영향을 주지 않도록 하기 위한 기본 원칙이다. 스키마 관리 관점에서 각 환경은 다음과 같이 구분된다.

환경 변경 자유도 변경 통제 수준
개발(DEV) 자유로운 실험 변경 이력만 남김
스테이징(STAGING) 운영과 동일 구조 유지 운영 배포 전 검증 필수
운영(PROD) 승인된 변경만 허용 변경 요청 워크플로 필수

이 3개 환경의 스키마를 메타데이터 시스템이 각각 독립적으로 수집하고, 환경 간 갭을 지속적으로 모니터링해야 한다. DEV -> STAGING, STAGING -> PROD, DEV -> PROD 갭을 각각 분석할 수 있어야 한다.

6.2 DW 환경의 특수성

DW(Data Warehouse) 환경은 운영 DB와 다른 특성을 갖는다. 운영 DB가 OLTP 최적화 설계라면 DW는 OLAP 최적화 설계다. 정규화 대신 비정규화, 행 지향 스토리지 대신 열 지향 스토리지, 소수의 복잡한 쿼리에 최적화된 인덱스 설계가 특징이다.

DW 환경의 스키마도 메타데이터 시스템에서 관리해야 한다. 운영 DB의 테이블이 DW에서 어떤 테이블로 변환되는지의 매핑 관계(데이터 흐름)와 함께 관리하면, 운영 DB 스키마 변경 시 DW의 영향 범위를 자동으로 파악할 수 있다. 라이프사이클 설계에서 다룬 영향도 분석(Impact Analysis)이 구체적으로 적용되는 지점이다.


7 표준 준수 검증과 구조 관리의 연결

스키마 변경 요청이 제출될 때 표준 관리 모듈과 연동한 검증이 일어난다. 이 연동이 “표준이 규칙이 되는 순간”의 구체적인 구현이다.

칼럼 추가 요청이 들어오면 시스템은 칼럼명을 파싱한다. 칼럼명 CUST_REG_DT를 보면 구성 단어는 CUST(고객), REG(등록), DT(일자)다. 각 단어가 표준 단어 목록에 있는지 확인한다. 있으면 각 단어의 기본 도메인을 확인한다. DT의 기본 도메인이 “날짜 도메인”이라면 이 칼럼의 도메인을 자동으로 “날짜 도메인”으로 제안한다. 요청자가 도메인을 별도로 지정하지 않으면 자동 추론된 도메인이 적용된다.

이 자동화가 있으면 칼럼이 추가될 때마다 DA가 도메인을 수동으로 매핑하는 작업이 필요 없다. 표준 단어 체계가 잘 설계되어 있으면 대부분의 칼럼이 자동으로 도메인을 얻는다. 도메인이 매핑되면 품질 진단에서 해당 칼럼에 대한 규칙도 자동으로 활성화된다. 표준 -> 도메인 -> 품질 규칙으로 이어지는 자동화 체인이 완성되는 것이다.


8 관련 주제

카테고리 내 연결

Subscribe

Enjoy this blog? Get notified of new posts by email: