여러 점검 시스템을 하나로 합치는 데이터 모델

2026.10.04
  • 시리즈 15/16
  • PI
  • 데이터 모델
  • MySQL

점검 종류마다 따로 만든 시스템과 양식을 하나로 합치려면, 공통 항목과 점검별 특화 항목을 함께 담는 구조가 필요하다. 파일럿에서는 속성 추가와 화면 필터로 버텼고, 통합 설계에서는 공통 컬럼과 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 정책

  1. 이관 단계새로 생긴 분류, 유형 컬럼은 NULL 허용. 과거 데이터가 새 기준에 맞지 않음
  2. 운영 안정화 후필수 컬럼을 NOT NULL로 변경
이관은 리허설부터이관 스크립트는 같은 파일을 두 번 돌려도 중복이 생기지 않게 만들고, 행 단위로 오류를 격리했다. 먼저 SQLite로 돌려 오류 0건을 확인한 뒤 운영 DB에 적재했다.

점검 목록

  • 공통과 특화를 나누는 기준이 문서로 정해져 있는가
  • 전체 집계에 필요한 항목이 모두 공통 컬럼에 있는가
  • 자주 조회하는 특화 항목에 인덱스 전략이 있는가
  • 이관 데이터의 출처를 추적할 수 있는가
시리즈 목차 16편
  1. PI 담당자가 로우코드로 사내 시스템을 직접 만들고 운영한 기록
  2. Mendix Datagrid2 대신 HTMLSnippet과 JS로 목록 화면 만들기
  3. Mendix SPA에서 HTMLSnippet JS가 꼬이는 이유: 이벤트 중복과 DOM 공존
  4. Mendix mx.data.commit이 조용히 실패할 때
  5. Mendix Java heap OOM 추적기: base64 이미지 컬럼
  6. Mendix 커밋 롤백, 용량 문제가 아니었다: FileDocument 전환기
  7. Mendix 첫 접속 지연 줄이기: 워밍업과 캐시
  8. Mendix SAML SSO 자동 로그인과 딥링크 유지
  9. Mendix Studio Pro에서 안 바뀌는 스타일 main.scss로 바꾸기
  10. Mendix MPK 파일 열어서 마이크로플로우 구조 보기
  11. SSO 로그 테이블로 MAU와 재방문율 구하는 SQL
  12. Mendix DateTime이 BI 도구에서 하루 빠르게 보이는 이유
  13. 대시보드 숫자가 틀렸을 때 확인하는 순서
  14. 보기 좋은 대시보드에서 할 일을 알려주는 대시보드로
  15. 여러 점검 시스템을 하나로 합치는 데이터 모델 (현재 글)
  16. 데이터 비전공자에게 분석 결과 보고하기
  • #데이터모델링
  • #하이브리드스키마
  • #EAV
  • #JSON
  • #PI
  • #시스템통합

댓글