테이블 정의서·컬럼 정의서 쓰는 법
· 갱신
테이블 정의서와 컬럼 정의서는 대부분의 SI·공공 프로젝트에서 제출 대상입니다. 그래서 이 문서를 만드는 방식도 대체로 비슷합니다. 오픈이 가까워지면 운영 DB에서 테이블 목록을 뽑고, 사내 어딘가에서 받은 엑셀 양식에 붙여 넣고, 설명 칸을 손으로 채웁니다. 검수를 통과하면 그 파일은 산출물 폴더에 들어가고, 그다음부터는 아무도 열지 않습니다.
문제는 이 방식이 틀렸다는 것이 아닙니다. 제출까지는 실제로 잘 작동합니다. 문제는 이렇게 만든 정의서의 수명이 제출일까지라는 데 있습니다. 그날 이후 DB는 계속 바뀌고 파일은 그대로이기 때문에, 두 달 뒤 그 문서는 맞는 곳과 틀린 곳이 섞인 상태가 됩니다. 그리고 한 군데가 틀렸다는 것이 확인되는 순간, 나머지가 맞는지도 확인해 보기 전에는 쓸 수 없는 문서가 됩니다.
그래서 이 글은 양식을 나열하는 대신 두 가지를 구분합니다. 정의서에 반드시 적어야 하는 것과, 적으면 안 되는 것입니다. 후자가 이 글의 핵심입니다. 정의서가 낡는 이유는 대부분 적지 않아도 될 것을 적었기 때문입니다.
정의서를 누가 언제 읽는가
항목을 정하기 전에 독자를 정해야 합니다. 실무에서 정의서를 실제로 펼치는 순간은 대략 네 가지입니다.
| 읽는 사람 | 읽는 시점 | 찾는 것 |
|---|---|---|
| 검수·감리 담당 | 산출물 검수 | 표준 준수 여부, 문서와 실제의 일치 |
| 인수인계 받는 개발자 | 프로젝트 종료 후 | 이 컬럼이 왜 있는지 |
| 운영·장애 대응자 | 사고 발생 시 | 어느 테이블이 무슨 업무를 담는지 |
| 데이터 활용·분석 담당 | 신규 요건 | 값의 의미와 유효 범위 |
네 독자의 공통점이 하나 있습니다. 아무도 컬럼 타입을 알아내려고 정의서를 펴지 않습니다. 타입은 DB에 접속하면 1초 만에 나오고, 그쪽이 언제나 더 정확합니다. 정의서를 펴는 이유는 예외 없이 DB에서 뽑을 수 없는 정보 때문입니다.
이 관찰이 아래 모든 판단의 기준입니다. 정의서의 가치는 스키마를 옮겨 적은 부분이 아니라, 스키마에 없는 부분에 있습니다.
테이블 정의서에 무엇을 적는가
테이블 정의서는 한 줄에 테이블 하나입니다. 권고 항목은 다음과 같습니다.
| 항목 | 예 | 필요한 이유 |
|---|---|---|
| 논리명 | 주문 | 업무 담당자가 검색하는 이름입니다 |
| 물리명 | ORDER | DB와 대조하는 유일한 키입니다 |
| 설명 | 고객이 확정한 구매 요청 1건 | 한 행이 무엇을 뜻하는지를 적습니다 |
| 컬럼 수 | 14 | 문서와 실제의 불일치를 가장 빨리 드러냅니다 |
| 주제 영역 | 판매 | 테이블이 수백 개가 되면 이것 없이는 못 찾습니다 |
설명 칸이 이 표의 전부라고 봐도 됩니다. 그리고 여기서 가장 흔한 실패는 테이블명을 풀어 쓴 문장을 설명이라고 적는 것입니다. ORDER_DTL의 설명이 “주문 상세 테이블”이면 그 칸은 비어 있는 것과 같습니다. 읽는 사람이 알고 싶은 것은 “주문 1건에 대해 이 테이블에 몇 행이 생기는가”, “취소된 주문도 여기 남는가” 같은 것입니다.
권고는 설명을 한 행의 정의로 쓰는 것입니다. “주문 상세”가 아니라 “한 주문에 포함된 상품 1종의 수량과 확정 단가. 취소 시 행을 지우지 않고 상태만 바꾼다”처럼 씁니다. 이 문장은 DB에서 절대 뽑을 수 없고, 그래서 정의서에만 있을 수 있습니다.
컬럼 정의서에 무엇을 적는가
컬럼 정의서는 한 줄에 컬럼 하나입니다. 정의서 중 실제로 가장 많이 읽히는 문서이고, 항목도 가장 많습니다.
| 항목 | 예 | 비고 |
|---|---|---|
| 테이블 논리명 | 주문 | 정렬·필터 기준이라 매 행에 반복해 넣습니다 |
| 테이블 물리명 | ORDER | 위와 같은 이유입니다 |
| 컬럼 논리명 | 주문상태코드 | 표준 용어와 일치해야 합니다 |
| 컬럼 물리명 | ORD_STAT_CD | |
| 데이터 타입 | VARCHAR(2) | 길이·정밀도까지 포함합니다 |
| 도메인 | 상태코드 | 타입·길이의 근거입니다 |
| PK / FK | Y / N | |
| NULL 허용 | N | |
| 기본값 | '01' | |
| 설명 | 01 접수, 02 결제완료, 03 배송중, 09 취소 | 코드 값의 의미를 적습니다 |
여기서도 마지막 칸이 전부입니다. 코드성 컬럼의 설명에 유효 값 목록이 없으면, 다음 사람은 결국 SELECT DISTINCT를 돌려서 알아냅니다. 그렇게 알아낸 목록에는 한 번도 쓰이지 않은 정상 코드가 빠지고, 잘못 들어간 값이 포함됩니다. 즉 실제 데이터로부터 코드 목록을 역추적하는 것은 원리적으로 틀릴 수 있는 방법이고, 그래서 이 칸은 사람이 적어야 합니다.
몇 가지 더 권고합니다.
도메인 칸을 비워 두지 않습니다. 같은 성격의 값에 서로 다른 타입이 붙는 것은 대부분 도메인이 없어서 생깁니다. 도메인이 무엇이고 어떻게 정하는지는 데이터 표준화 글에서 단어사전·용어사전과 함께 정리했습니다.
NULL 허용과 기본값은 함께 봅니다. NOT NULL인데 기본값이 없는 컬럼은 애플리케이션이 반드시 값을 넣어야 한다는 뜻이고, 그 사실은 인수인계에서 자주 누락됩니다.
논리명은 표준 용어여야 합니다. 정의서에 적힌 논리명이 용어사전에 없으면 그 컬럼은 표준 밖에 있는 것입니다. 정의서는 이 사실을 드러내는 가장 좋은 자리인데, 대개 그냥 물리명을 한글로 옮겨 적는 칸으로 쓰입니다.
적지 말아야 할 것
이제 반대쪽입니다. 아래 항목들은 흔히 정의서 양식에 들어 있지만, 손으로 채우는 순간 정의서의 수명을 줄입니다.
첫째, DB에서 뽑을 수 있는 값을 손으로 적지 않습니다. 타입·길이·NULL 여부·기본값·PK 여부는 전부 DB가 정답을 갖고 있습니다. 이것을 손으로 옮겨 적으면 사본이 하나 생기고, 사본은 원본과 갈라집니다. 적지 말라는 뜻이 아니라 손으로 적지 말라는 뜻입니다. 뽑아내면 됩니다.
둘째, 작성자·작성일·버전 칸을 행마다 두지 않습니다. 컬럼이 800개면 이 칸은 800번 낡습니다. 실제로는 아무도 갱신하지 않아 전 행이 같은 날짜로 남고, 그 날짜는 문서 전체가 그날 이후 방치됐다는 사실만 알려 줍니다. 이력은 행이 아니라 파일 단위로, 그것도 문서가 아니라 형상관리에 남기는 편이 낫습니다.
셋째, 화면 ID·프로그램 ID를 정의서에 넣지 않습니다. 넣고 싶은 마음은 이해되지만 이 관계는 다대다이고 개발 중에 가장 빨리 바뀝니다. 컬럼 하나에 화면 세 개가 걸리면 칸에 쉼표로 나열하게 되고, 그때부터 이 열은 검색도 정렬도 안 되는 텍스트가 됩니다.
넷째, “비고” 칸을 만들지 않습니다. 비고는 정의되지 않은 칸이라 사람마다 다른 것을 적습니다. 어떤 행에는 코드 목록이, 어떤 행에는 담당자 이름이, 어떤 행에는 “확인 필요”가 들어갑니다. 적을 것이 있으면 항목을 만들고, 항목을 만들 만큼 반복되지 않으면 설명에 적습니다.
다섯째, 다이어그램을 정의서에 붙여 넣지 않습니다. 이미지로 붙은 ERD는 스키마가 바뀌어도 티가 나지 않는 유일한 산출물입니다. 다이어그램은 별도 산출물로 두고, 정의서는 표로 둡니다.
정의서가 실제와 어긋나기 시작하는 지점
어긋남은 대개 다음 순서로 옵니다.
- 정의서를 만든 뒤 컬럼 하나가 추가됩니다. DDL은 반영되고 정의서는 안 됩니다. 오늘은 아무 일도 일어나지 않습니다.
- 다음 달 다른 사람이 컬럼 두 개를 더 추가합니다. 이 사람은 정의서에 자기 컬럼이 없다는 것을 알지만, 앞의 컬럼도 없는 것을 보고 갱신 대상이 아니라고 판단합니다.
- 검수 일정이 잡히면 DB에서 목록을 다시 뽑아 표를 통째로 갈아끼웁니다. 이때 손으로 적었던 설명이 함께 사라집니다. DB에서 뽑은 목록에는 설명이 없기 때문입니다.
- 다음 판 정의서는 형식은 완전하지만 설명 칸이 비어 있습니다. 그리고 그 상태로 검수를 통과합니다. 검수는 대개 항목의 존재를 보지 내용의 깊이를 보지 않기 때문입니다.
3번이 이 경로에서 가장 비싼 지점입니다. 정의서에서 유일하게 값이 있는 정보가, 갱신 과정에서 구조적으로 가장 먼저 버려집니다. 손으로 만든 정의서를 손으로 갱신하는 한 이 손실은 반복됩니다.
같은 종류의 어긋남이 논리 ERD에서도 일어납니다. 그 경로는 논리 모델과 물리 모델 글에서 단계별로 따라가 봤습니다.
정의서를 작성물이 아니라 파생물로 만들기
해법은 “정의서를 성실히 갱신하자”가 아닙니다. 그 결심은 이미 여러 번 실패했습니다. 구조를 바꿔야 합니다.
설명을 정의서가 아니라 모델에 답니다. 컬럼의 설명이 엑셀 파일에만 있으면 그 설명은 표를 갈아끼울 때 사라집니다. 모델에 붙어 있으면 표를 몇 번을 다시 뽑아도 따라옵니다. 이것이 3번 손실을 없애는 유일한 방법입니다.
나머지 열 칸은 계산되게 둡니다. 물리명·타입·PK·NULL·기본값은 모델이 이미 아는 값입니다. 사람이 채워야 하는 칸이 설명 하나로 줄면, 정의서 작성은 며칠짜리 작업이 아니라 평소 모델링의 일부가 됩니다.
정의서는 버튼 한 번으로 다시 뽑습니다. 다시 뽑는 비용이 0에 가까우면 사람들은 자주 뽑습니다. 비용이 반나절이면 검수 직전에 한 번만 뽑습니다. 갱신 주기는 의지가 아니라 비용이 정합니다.
Sqemo는 이 전제로 만든 ERD 도구입니다. 논리명과 물리명이 하나의 모델 안에 함께 있고, 엔터티·컬럼·인덱스·관계 정의서를 각각 CSV로 내보냅니다. 컬럼 정의서에는 위 표의 항목이 그대로 들어갑니다. 엔터티 논리명·물리명, 컬럼 논리명·물리명, 데이터 타입, 도메인, PK, FK, NULL 허용, 기본값, 설명 — 이 중 사람이 적는 것은 설명뿐이고 나머지는 모델에서 계산됩니다. 가입 없이 브라우저에서 바로 쓸 수 있고, 정의서 내보내기는 무료 기능입니다.

설명이 어디에 붙어 있는지는 용어사전 화면에서 보입니다. 속성마다 단 정의가 모델 안에 용어 단위로 모여 있고, 정의서 CSV의 설명 칸은 여기서 나옵니다 — 표를 몇 번을 다시 뽑아도 사라질 자리가 없습니다.

정직하게 세 가지 한계를 적어 둡니다. 첫째, 내보낸 CSV의 헤더는 영어입니다 — 제출 양식이 한글 머리글을 요구하면 첫 행을 바꾸는 작업이 한 번 필요합니다. 둘째, .xlsx가 아니라 CSV입니다 — 엑셀에서 열어 서식을 입히는 단계는 남습니다. 셋째, 행 단위 변경 이력 칸은 없습니다 — 위에서 두지 말라고 권한 항목이라 의도적으로 없지만, 제출 양식이 요구한다면 그 칸은 직접 채우셔야 합니다.
실제로 내보낸 컬럼 정의서의 머리글과 한 행은 이렇게 생겼습니다.
Entity Logical Name,Entity Physical Name,Column Logical Name,Column Physical Name,Data Type,Domain,PK,FK,Nullable,Default Value,Description
주문,ORD,주문 상태 코드,ORD_STAT_CD,VARCHAR(2),상태코드,N,N,N,'01',"01 접수, 02 결제완료, 03 배송중, 09 취소"
정의서 양식을 다시 손보기 전에 먼저 해 볼 일이 있습니다. 지금 산출물 폴더의 컬럼 정의서를 열어 설명 칸이 비어 있거나 컬럼명을 한글로 옮겨 적기만 한 행이 몇 %인지 세어 보시기 바랍니다. 그 비율이 이 문서의 실제 가치입니다. 나머지 열 칸은 DB에서 언제든 다시 뽑을 수 있고, 그쪽이 항상 더 정확하기 때문입니다.
쓰던 DDL이 있다면 브라우저에서 바로 열어 가져온 뒤 정의서를 한 번 내보내 보셔도 좋습니다. 지금 문서와 실제 스키마가 어디서 갈라져 있는지 몇 분 만에 확인하실 수 있습니다.