점검 종류마다 따로 만든 시스템과 양식을 하나로 합치려면, 공통 항목과 점검별 특화 항목을 함께 담는 구조가 필요하다. 파일럿에서는 속성 추가와 화면 필터로 버텼고, 통합 설계에서는 공통 컬럼과 JSON 특화 컬럼을 나눈 하이브리드 모델을 택했다.
문제
점검마다 항목이 다름. 새 점검이 생길 때마다 테이블이나 속성을 추가해야 함
원인
점검별 양식을 그대로 옮기면 테이블이 계속 늘고, EAV로 일반화하면 조회와 집계가 어려움
해결
모든 점검에 있는 항목은 정규 컬럼, 일부 점검에만 있는 항목은 JSON 컬럼에. 특화 항목 정의는 메타데이터 테이블로 관리
세 가지 방식 비교
| 구분 | 점검별 테이블 | EAV | 하이브리드 |
|---|---|---|---|
| 구조 | 점검마다 테이블 | 항목 하나가 행 하나 | 공통 컬럼 + JSON 컬럼 |
| 새 점검 추가 | 테이블 추가 | 정의 행 추가 | 정의 행 추가 |
| 전체 집계 | UNION 필요 | 피벗 필요, 느림 | 공통 컬럼으로 바로 |
| 특화 항목 조회 | 쉬움 | 조인 많음 | JSON 함수 사용 |
| 파일럿에서 쓴 방식 | 기존 테이블에 속성 추가 + 화면별 조건 필터 | ||
구조
정의
inspection_type점검 종류
spec_field점검 종류별 특화 항목 정의, 표시 순서, 필수 여부
항목 정의
트랜잭션
inspection점검 1회, 공통 컬럼
issue공통 컬럼 + spec_json
SQL (MySQL)
CREATE TABLE issue (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
inspection_id BIGINT NOT NULL,
detect_date DATE,
site_id INT, building_id INT, floor_id INT,
location_detail VARCHAR(200),
category_id INT, -- 공통 분류
details TEXT,
due_date DATE,
clear_status VARCHAR(20), -- 개선예정, 개선중, 개선완료, 제외요청
clear_person_id VARCHAR(40), -- 값 복사 (당시 담당자 보존)
clear_person_nm VARCHAR(50),
clear_date DATE,
photo_path VARCHAR(255), -- 파일 경로만
spec_json JSON, -- 점검별 특화 항목
src_system VARCHAR(30), -- 이관 출처
src_id VARCHAR(40),
migrated_at DATETIME,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (inspection_id) REFERENCES inspection(id)
);설계 원칙
| 원칙 | 내용 |
|---|---|
| 공통과 특화 기준 | 통합 대상 점검 모두에 있으면 공통, 일부에만 있으면 특화 |
| 상태값 통합 | 점검마다 다르던 조치 상태를 4개 값으로 통일 |
| 담당자는 값 복사 | 인사 이동이 있어도 당시 담당자가 남도록 ID와 이름을 함께 저장 |
| 이름 마스킹 | DB에는 원본, 화면에서 권한별로 가림 |
| 사진 분리 | DB에는 경로만, 파일은 별도 저장 |
| 이관 추적 | 원본 시스템과 원본 ID를 남겨 재실행해도 중복되지 않게 |
특화 항목 조회
SQL (MySQL)
-- 특정 점검의 특화 항목 꺼내기
SELECT id,
JSON_UNQUOTE(JSON_EXTRACT(spec_json, '$.grade')) AS 등급,
JSON_UNQUOTE(JSON_EXTRACT(spec_json, '$.factorType')) AS 요인유형
FROM issue
WHERE inspection_id IN (SELECT id FROM inspection WHERE type_code = 'TYPE_B');
-- 자주 쓰는 특화 항목은 생성 컬럼 + 인덱스로
ALTER TABLE issue
ADD COLUMN spec_grade VARCHAR(10)
GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(spec_json, '$.grade'))) STORED,
ADD INDEX ix_issue_spec_grade (spec_grade);NULL 정책
- 이관 단계새로 생긴 분류, 유형 컬럼은 NULL 허용. 과거 데이터가 새 기준에 맞지 않음
- 운영 안정화 후필수 컬럼을 NOT NULL로 변경
이관은 리허설부터이관 스크립트는 같은 파일을 두 번 돌려도 중복이 생기지 않게 만들고, 행 단위로 오류를 격리했다. 먼저 SQLite로 돌려 오류 0건을 확인한 뒤 운영 DB에 적재했다.
점검 목록
- 공통과 특화를 나누는 기준이 문서로 정해져 있는가
- 전체 집계에 필요한 항목이 모두 공통 컬럼에 있는가
- 자주 조회하는 특화 항목에 인덱스 전략이 있는가
- 이관 데이터의 출처를 추적할 수 있는가
시리즈 목차 16편
- PI 담당자가 로우코드로 사내 시스템을 직접 만들고 운영한 기록
- Mendix Datagrid2 대신 HTMLSnippet과 JS로 목록 화면 만들기
- Mendix SPA에서 HTMLSnippet JS가 꼬이는 이유: 이벤트 중복과 DOM 공존
- Mendix mx.data.commit이 조용히 실패할 때
- Mendix Java heap OOM 추적기: base64 이미지 컬럼
- Mendix 커밋 롤백, 용량 문제가 아니었다: FileDocument 전환기
- Mendix 첫 접속 지연 줄이기: 워밍업과 캐시
- Mendix SAML SSO 자동 로그인과 딥링크 유지
- Mendix Studio Pro에서 안 바뀌는 스타일 main.scss로 바꾸기
- Mendix MPK 파일 열어서 마이크로플로우 구조 보기
- SSO 로그 테이블로 MAU와 재방문율 구하는 SQL
- Mendix DateTime이 BI 도구에서 하루 빠르게 보이는 이유
- 대시보드 숫자가 틀렸을 때 확인하는 순서
- 보기 좋은 대시보드에서 할 일을 알려주는 대시보드로
- 여러 점검 시스템을 하나로 합치는 데이터 모델 (현재 글)
- 데이터 비전공자에게 분석 결과 보고하기