-- ##################################################################### -- arko_renual 설치용 통합 SQL (개인정보보호 기능개선 사업 · arko 대비 변동분) -- 대상 DB : MySQL 5.7 / MariaDB (스키마 csv) -- 구성 : [PART 1] DDL(테이블 생성·변경) → [PART 2] DML(기준/시드 데이터) -- 실행순서: 반드시 PART 1 → PART 2 순서로 실행(테이블 생성 후 시드 적재) -- 주의 : 신규 설치용. 기존 테이블이 있는 환경 재실행 시 CREATE 중복 오류 가능 -- (IF NOT EXISTS 미지정 테이블). 그런 환경은 PART 2(DML)만 실행하세요. -- ##################################################################### -- ===================================================================== -- PART 1. DDL (테이블 생성 / 컬럼 확장) ※ 시드 INSERT는 PART 2로 분리 -- ===================================================================== -- ───────────────────────────────────────────────────────────── -- [privacy.account_mng_policy_create_mysql.sql] -- ───────────────────────────────────────────────────────────── -- ===================================================================== -- 계정 관리 정책 : ACCOUNT_MNG_POLICY (단일행 정책 테이블) -- 문화품앗이 개인정보보호 기능개선 사업 (SFR-002, 장기 미사용 계정 관리) -- 개발항목 #13(정책 설정) + #9(휴면 기준일수 정책값화) - 담당: arko-privacy-authctrl (Fork A) -- 작성일: 2026-07-21 DB: MySQL 8 / MariaDB -- --------------------------------------------------------------------- -- [용도] 휴면 기준일수·사전알림 시점·삭제 보존기간·배치주기 등 계정 관리 정책을 -- 하드코딩이 아닌 관리자 설정값으로 운영하기 위한 단일행 정책 테이블. -- [#9] 휴면 select(EgovLoginUsr_SQL_Mysql.xml)의 365 하드코딩을 -- (SELECT DORMANT_DAY FROM ACCOUNT_MNG_POLICY) 로 대체(미설정 시 365 fallback). -- [#10] ALERT_D1/D2/D3(기본 30/7/0) = 휴면예정 D-30/D-7/D-Day 사전알림 시점. -- ADMIN_EMAIL = 사전알림 관리자 수신 주소. -- ===================================================================== CREATE TABLE IF NOT EXISTS ACCOUNT_MNG_POLICY ( POLICY_ID INT NOT NULL DEFAULT 1 COMMENT '정책 식별자(단일행=1)', DORMANT_DAY INT NOT NULL DEFAULT 365 COMMENT '휴면 전환 기준 미접속 일수(#9)', ALERT_D1 INT NOT NULL DEFAULT 30 COMMENT '사전알림 1차(휴면 D-일수)', ALERT_D2 INT NOT NULL DEFAULT 7 COMMENT '사전알림 2차(휴면 D-일수)', ALERT_D3 INT NOT NULL DEFAULT 0 COMMENT '사전알림 3차(D-Day, 0=당일)', DELETE_PRESERVE_DAY INT NOT NULL DEFAULT 365 COMMENT '휴면/탈퇴 후 삭제 보존기간(일)', BATCH_CYCLE VARCHAR(20) NOT NULL DEFAULT 'DAILY' COMMENT '배치 주기(DAILY/WEEKLY/MONTHLY)', ADMIN_EMAIL VARCHAR(200) NULL COMMENT '사전알림 관리자 수신 이메일', UPD_ID VARCHAR(20) NULL COMMENT '최종 수정자', UPD_DT DATETIME NULL COMMENT '최종 수정일시', PRIMARY KEY (POLICY_ID) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='계정 관리 정책(개인정보보호 SFR-002, 단일행)'; -- 기본 정책 시드(없을 때만). 기준 365일·알림 D-30/7/0·보존 365일. -- ───────────────────────────────────────────────────────────── -- [privacy.account_unlock_history_create_mysql.sql] -- ───────────────────────────────────────────────────────────── -- ===================================================================== -- 계정 잠금 해제 이력 : ACCOUNT_UNLOCK_HISTORY -- 문화품앗이 개인정보보호 기능개선 사업 (SER-001, 계정 잠금 정책 정비) -- 개발항목 #24 - 담당: arko-privacy-authctrl (Fork A) -- 작성일: 2026-07-21 DB: MySQL 8 / MariaDB -- --------------------------------------------------------------------- -- [목적] 잠긴 계정 해제를 DB 직접조작이 아니라 관리자 화면(EgovAccountUnlockManage) -- 에서 처리하고, 해제자·해제일시·대상·사유를 이력으로 남긴다. -- [무결성] 애플리케이션 계층에 UPDATE/DELETE statement 미정의(INSERT/SELECT 한정). -- ===================================================================== CREATE TABLE ACCOUNT_UNLOCK_HISTORY ( UNLOCK_HIST_ID BIGINT NOT NULL AUTO_INCREMENT COMMENT '해제 이력 일련번호(PK)', TRGET_ID VARCHAR(50) NULL COMMENT '해제 대상 계정 ID(전체해제 시 NULL 가능)', TRGET_SE VARCHAR(10) NULL COMMENT '대상 회원구분 GNR/GRO/ENT/USR', UNLOCK_TY CHAR(1) NOT NULL DEFAULT 'I' COMMENT '해제 유형 I:개별 A:전체', UNLOCK_USER_ID VARCHAR(50) NULL COMMENT '해제 처리자(관리자) ID', UNLOCK_RESN VARCHAR(500) NULL COMMENT '해제 사유', UNLOCK_IP VARCHAR(45) NULL COMMENT '해제자 접속 IP(IPv6 대응)', UNLOCK_DT DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '해제 일시', PRIMARY KEY (UNLOCK_HIST_ID), KEY IX_AUH_TRGET (TRGET_ID, UNLOCK_DT), KEY IX_AUH_USER (UNLOCK_USER_ID, UNLOCK_DT), KEY IX_AUH_DT (UNLOCK_DT) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='계정 잠금 해제 이력(개인정보보호 SER-001 #24)'; -- ===================================================================== -- 계정 잠금 임계값 10회 → 5회 (#24) -- 임계값은 하드코딩이 아니라 LOGIN_LOCK_COUNT.LOCK_COUNT(단일행) 데이터에서 조회됨 -- (loginDAO.selectFailTotalCount). 아래 UPDATE 로 운영 정책값을 5회로 조정한다. -- ※ 소스(EgovLoginController)에는 값 부재 시 기본 5회 fallback 이 반영되어 있음. -- ===================================================================== UPDATE LOGIN_LOCK_COUNT SET LOCK_COUNT = 5; -- 행이 없을 경우 대비(최초 세팅): -- INSERT INTO LOGIN_LOCK_COUNT (LOCK_COUNT) SELECT 5 FROM DUAL -- WHERE NOT EXISTS (SELECT 1 FROM LOGIN_LOCK_COUNT); -- ───────────────────────────────────────────────────────────── -- [privacy.author_change_history_create_mysql.sql] -- ───────────────────────────────────────────────────────────── -- ===================================================================== -- 권한 변경 이력 테이블 : AUTHOR_CHANGE_HISTORY -- 문화품앗이 개인정보보호 기능개선 사업 (SFR-001, 역할별 차등 접근/권한 변경 추적) -- 개발항목 #4 - 담당: arko-privacy-authctrl (Fork A → 오케스트레이터 완료) -- 작성일: 2026-07-21 DB: MySQL 8 / MariaDB -- --------------------------------------------------------------------- -- [목적] 권한 신설·변경·회수(#1 getAuthorities 대상 COMTNEMPLYRSCRTYESTBS 등)의 -- 모든 변경을 변경자·변경일시·변경전/후 권한과 함께 이력으로 적재한다. -- 권한 신청·승인 워크플로(#3)의 승인 반영 시점에 권한반영과 단일 트랜잭션으로 적재. -- -- [보관·파기] 3년(1,095일) 이상 보관 전제. 월 1회 @Scheduled 파기 배치(#5)가 -- 보관기간(1,095일) 경과 이력만 선별 파기한다. 개별 삭제 API 미제공. -- 다운로드 시 사유 입력 필수 + 다운로드 이력 적재(#6)는 별도 처리. -- -- [무결성] 이력 위·변조 억제를 위해 변경전/후 권한을 함께 보관(사후 대사 가능). -- 애플리케이션 계층에 UPDATE statement 미정의(INSERT/SELECT/파기 DELETE 한정). -- ===================================================================== CREATE TABLE AUTHOR_CHANGE_HISTORY ( HIST_ID BIGINT NOT NULL AUTO_INCREMENT COMMENT '이력 일련번호(PK)', TRGET_UNIQ_ID VARCHAR(20) NOT NULL COMMENT '변경 대상자 고유식별자(ESNTL_ID)', TRGET_ID VARCHAR(20) NULL COMMENT '변경 대상자 계정ID(참고용)', CHG_SE_CODE CHAR(1) NOT NULL COMMENT '변경구분 G:부여(grant) R:회수(revoke) M:변경(modify)', BEFORE_AUTHOR VARCHAR(1000) NULL COMMENT '변경 전 권한(코드 CSV 또는 스냅샷)', AFTER_AUTHOR VARCHAR(1000) NULL COMMENT '변경 후 권한(코드 CSV 또는 스냅샷)', CHG_RESN VARCHAR(500) NULL COMMENT '변경 사유(신청/승인 워크플로 연계 #3)', APROVL_ID VARCHAR(20) NULL COMMENT '승인자 계정ID(승인 워크플로 #3)', CHANGER_UNIQ_ID VARCHAR(20) NOT NULL COMMENT '변경자(처리자) 고유식별자', CHANGER_ID VARCHAR(20) NULL COMMENT '변경자 계정ID(참고용)', CHANGER_IP VARCHAR(45) NULL COMMENT '변경자 접속 IP(IPv6 대응)', CHG_DT DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '변경 일시', PRIMARY KEY (HIST_ID), KEY IX_ACH_TRGET (TRGET_UNIQ_ID, CHG_DT), KEY IX_ACH_CHANGER (CHANGER_UNIQ_ID, CHG_DT), KEY IX_ACH_CHGDT (CHG_DT) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='권한 변경 이력(개인정보보호 SFR-001, 3년 이상 보관)'; -- ───────────────────────────────────────────────────────────── -- [privacy.author_workflow_create_mysql.sql] -- ───────────────────────────────────────────────────────────── -- ===================================================================== -- 권한 신청·승인 워크플로 + 권한이력 다운로드 이력 -- 문화품앗이 개인정보보호 기능개선 사업 (SFR-001, 권한 신설·변경·회수 승인통제) -- 개발항목 #3(신청·승인 워크플로) / #6(권한이력 조회·다운로드) - 담당: arko-privacy-authctrl (Fork A 6차) -- 작성일: 2026-07-21 DB: MySQL 8 / MariaDB -- --------------------------------------------------------------------- -- [#3] AUTHOR_CHANGE_REQUEST : 권한 변경 신청→승인/반려 워크플로. -- 승인(A) 시 권한 반영(COMTNEMPLYRSCRTYESTBS)과 이력 적재(AUTHOR_CHANGE_HISTORY)를 -- 단일 트랜잭션으로 처리한다(egovframework.com..*Impl AOP tx advisor). -- [#6] AUTHOR_HIST_DOWNLOAD_HISTORY : 권한이력 다운로드 증빙(사유 필수). -- ===================================================================== CREATE TABLE AUTHOR_CHANGE_REQUEST ( REQUEST_ID BIGINT NOT NULL AUTO_INCREMENT COMMENT '신청 일련번호(PK)', TRGET_UNIQ_ID VARCHAR(20) NOT NULL COMMENT '권한변경 대상자 고유식별자(ESNTL_ID)', TRGET_ID VARCHAR(20) NULL COMMENT '권한변경 대상자 계정ID(참고용)', REQUEST_SE CHAR(1) NOT NULL COMMENT '신청구분 N:신설(부여) C:변경 R:회수', BEFORE_AUTHOR VARCHAR(1000) NULL COMMENT '신청 시점 현재 권한(스냅샷)', AFTER_AUTHOR VARCHAR(1000) NULL COMMENT '신청 목표 권한(코드/CSV)', REQUEST_RESN VARCHAR(500) NOT NULL COMMENT '신청 사유(필수)', REQSTER_ID VARCHAR(20) NOT NULL COMMENT '신청자 계정ID', REQSTER_UNIQ_ID VARCHAR(20) NULL COMMENT '신청자 고유식별자', REQUEST_DT DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '신청 일시', CONFM_STTUS CHAR(1) NOT NULL DEFAULT 'R' COMMENT '처리상태 R:신청 A:승인 J:반려', CONFM_ID VARCHAR(20) NULL COMMENT '승인/반려 처리자 계정ID', CONFM_UNIQ_ID VARCHAR(20) NULL COMMENT '승인/반려 처리자 고유식별자', CONFM_DT DATETIME NULL COMMENT '승인/반려 일시', CONFM_RESN VARCHAR(500) NULL COMMENT '반려 사유', PRIMARY KEY (REQUEST_ID), KEY IX_ACR_TRGET (TRGET_UNIQ_ID, REQUEST_DT), KEY IX_ACR_STTUS (CONFM_STTUS, REQUEST_DT) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='권한 변경 신청·승인 워크플로(개인정보보호 SFR-001 #3)'; CREATE TABLE AUTHOR_HIST_DOWNLOAD_HISTORY ( DWLD_ID BIGINT NOT NULL AUTO_INCREMENT COMMENT '다운로드 일련번호(PK)', DOWNLOADER_ID VARCHAR(20) NOT NULL COMMENT '다운로드자 계정ID', DOWNLOADER_UNIQ_ID VARCHAR(20) NULL COMMENT '다운로드자 고유식별자', DOWNLOADER_IP VARCHAR(45) NULL COMMENT '다운로드자 접속 IP(IPv6 대응)', DWLD_RESN VARCHAR(500) NOT NULL COMMENT '다운로드 사유(필수·미입력 차단)', SEARCH_COND VARCHAR(1000) NULL COMMENT '다운로드 시 검색조건 스냅샷', DWLD_CNT INT NOT NULL DEFAULT 0 COMMENT '다운로드 건수', DWLD_DT DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '다운로드 일시', PRIMARY KEY (DWLD_ID), KEY IX_AHD_DWLD (DOWNLOADER_ID, DWLD_DT) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='권한이력 다운로드 증빙 이력(개인정보보호 SFR-001 #6)'; -- ───────────────────────────────────────────────────────────── -- [privacy.job_mapping_create_mysql.sql] -- ───────────────────────────────────────────────────────────── -- ===================================================================== -- 개인정보 처리 업무유형 매핑 테이블 : PDAL_JOB_MAPPING -- 문화품앗이 개인정보보호 기능개선 사업 (SFR-004 / SER-002) -- 개발항목 #32 - 담당: arko-privacy-auditlog (Fork B) -- 작성일: 2026-07-21 DB: MySQL 8 / MariaDB -- --------------------------------------------------------------------- -- [목적] 접속기록 수집(#31 PersonalDataLogAspect)이 가로챈 서비스 메서드를 -- 업무코드(JOB_SE_CODE)·업무명(JOB_SE_NM)으로 매핑한다. -- AOP pointcut 범위(개인정보 처리 서비스 패키지) 안에서 신규 화면이 추가되면 -- 이 테이블에 행만 등록하면 수집되며, Aspect/pointcut 소스 수정이 불요하다. -- -- [매칭 규칙] Aspect가 (대상클래스 단순명, 메서드명)으로 조회. -- - TARGET_CLASS : 서비스 impl 단순 클래스명(예: EgovMberManageServiceImpl) 또는 FQN -- - METHOD_PTTRN : 메서드명 접두 매칭(예: 'select','insertMber') 또는 '*'(전체) -- - DML_GUBUN : 지정 시 우선, NULL이면 메서드명 접두로 유도(insert*→I/update*→U/delete*→D/그외 S) -- - SORT_ORDR : 다중 매칭 시 낮은 값 우선(구체 규칙을 위로) -- -- ※ URL 패턴 기반 수집이 필요하면(서블릿 필터형) 동일 테이블에 URL_PTTRN 컬럼을 추가해 확장. -- ===================================================================== CREATE TABLE PDAL_JOB_MAPPING ( MAPPING_ID BIGINT NOT NULL AUTO_INCREMENT COMMENT '매핑 일련번호(PK)', TARGET_CLASS VARCHAR(200) NOT NULL COMMENT '대상 서비스 impl 단순 클래스명 또는 FQN', METHOD_PTTRN VARCHAR(100) NOT NULL DEFAULT '*' COMMENT '메서드명 접두 매칭(또는 * 전체)', JOB_SE_CODE VARCHAR(30) NOT NULL COMMENT '수행업무 유형 코드', JOB_SE_NM VARCHAR(100) NOT NULL COMMENT '수행업무 유형(화면·기능명)', DML_GUBUN CHAR(1) NULL COMMENT '처리구분 강제값 S/I/U/D (NULL=메서드명 유도)', SORT_ORDR INT NOT NULL DEFAULT 100 COMMENT '매칭 우선순위(낮을수록 우선)', USE_AT CHAR(1) NOT NULL DEFAULT 'Y' COMMENT '사용여부 Y/N', RM VARCHAR(300) NULL COMMENT '비고', PRIMARY KEY (MAPPING_ID), KEY IX_PJM_LOOKUP (USE_AT, TARGET_CLASS, SORT_ORDR) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='개인정보 처리 업무유형 매핑(접속기록 #31/#32)'; -- --------------------------------------------------------------------- -- 초기 매핑 시드 : 현행 개인정보 처리 서비스(#31 pointcut 대상과 일치) -- 신규 개인정보 화면 추가 시 아래 형식으로 행만 추가하면 수집된다. -- --------------------------------------------------------------------- -- ───────────────────────────────────────────────────────────── -- [privacy.download_history_create_mysql.sql] -- ───────────────────────────────────────────────────────────── -- ===================================================================== -- 개인정보 접속기록 다운로드 이력 : PDAL_DOWNLOAD_HISTORY -- 문화품앗이 개인정보보호 기능개선 사업 (SFR-004 / SER-002) -- 개발항목 #42 - 담당: arko-privacy-auditlog (Fork B) -- 작성일: 2026-07-21 DB: MySQL 8 / MariaDB -- --------------------------------------------------------------------- -- [목적] 개인정보 접속기록(PERSONAL_DATA_ACCESS_LOG) 조회결과 다운로드 시, -- 다운로드 사유(필수)·다운로드자·일시·IP·건수를 이력으로 남긴다. -- 사유 미입력 시 다운로드는 서비스 계층에서 차단(본 테이블 미적재). -- [원칙] 개인정보 본문 미적재 — 다운로드 검색조건 요약(SEARCH_COND)만 보관. -- 이 테이블은 INSERT/SELECT 만 수행(위·변조 방지, UPDATE/DELETE 미정의). -- ===================================================================== CREATE TABLE PDAL_DOWNLOAD_HISTORY ( DL_ID BIGINT NOT NULL AUTO_INCREMENT COMMENT '다운로드 이력 일련번호(PK)', DOWNLOADER_ID VARCHAR(20) NOT NULL COMMENT '다운로드자 계정ID', DOWNLOAD_DT DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '다운로드 일시', DOWNLOADER_IP VARCHAR(45) NULL COMMENT '다운로드자 접속 IP(IPv6 대응)', DL_REASON VARCHAR(500) NOT NULL COMMENT '다운로드 사유(필수 — 미입력 시 차단)', SEARCH_COND VARCHAR(1000) NULL COMMENT '다운로드 검색조건 요약(개인정보 본문 미포함)', RESULT_CNT INT NOT NULL DEFAULT 0 COMMENT '다운로드 건수', REG_DT DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '등록 일시', PRIMARY KEY (DL_ID), KEY IX_PDDH_DT (DOWNLOAD_DT), KEY IX_PDDH_USER (DOWNLOADER_ID, DOWNLOAD_DT) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='개인정보 접속기록 다운로드 이력(#42, SER-002)'; -- [Oracle] 시퀀스 필요: -- CREATE SEQUENCE PDAL_DOWNLOAD_HISTORY_SEQ START WITH 1 INCREMENT BY 1 NOCACHE; -- ───────────────────────────────────────────────────────────── -- [privacy.inspection_report_create_mysql.sql] -- ───────────────────────────────────────────────────────────── -- ===================================================================== -- 개인정보 접속기록 정기점검 리포트 : PDAL_INSPECTION_REPORT -- 문화품앗이 개인정보보호 기능개선 사업 (SFR-004 / SER-002) -- 개발항목 #43 - 담당: arko-privacy-auditlog (Fork B) -- 작성일: 2026-07-21 DB: MySQL 8 / MariaDB -- --------------------------------------------------------------------- -- [목적] 월 1회 정기점검 배치가 전월분 접속기록을 집계해 1행으로 적재한다. -- "월 1회 이상 점검 내역"을 화면 출력으로 제출(개인정보보호위 점검 대응). -- -- [집계원] PERSONAL_DATA_ACCESS_LOG(#30) + 해시체인 무결성 검증(#40) 재사용. -- [자리표시] 이상징후 5유형(#35)·다운로드 이력(#42)은 미구현 → 컬럼만 두고 배치가 0/요약만 적재. -- [화면입력] INSPECTOR_ID/INSPECT_RESULT/ACTN_MATTER 는 배치가 아닌 점검자가 화면(#48)에서 입력. -- ===================================================================== CREATE TABLE PDAL_INSPECTION_REPORT ( RPT_ID BIGINT NOT NULL AUTO_INCREMENT COMMENT '리포트 일련번호(PK)', RPT_YM CHAR(6) NOT NULL COMMENT '점검 대상 연월(전월, yyyyMM)', PERIOD_FROM DATETIME NOT NULL COMMENT '집계 시작일시', PERIOD_TO DATETIME NOT NULL COMMENT '집계 종료일시', TOTAL_LOG_CNT INT NOT NULL DEFAULT 0 COMMENT '총 접속기록 건수', FAIL_CNT INT NOT NULL DEFAULT 0 COMMENT '처리결과 F(실패/차단) 건수 = 이상징후 일부', ABNORMAL_SUMMARY VARCHAR(2000) NULL COMMENT '이상징후 5유형 요약(#35 연계 전 자리표시)', INTEGRITY_RESULT VARCHAR(20) NOT NULL DEFAULT 'OK' COMMENT '해시체인 무결성: OK / VIOLATION', INTEGRITY_MISMATCH_ID BIGINT NULL COMMENT '최초 불일치 LOG_ID(위반 시)', INTEGRITY_TOTAL_CNT INT NOT NULL DEFAULT 0 COMMENT '무결성 검증 대상 건수', HANDLER_SUMMARY VARCHAR(4000) NULL COMMENT '취급자별 처리현황 요약', DOWNLOAD_CNT INT NOT NULL DEFAULT 0 COMMENT '다운로드 이력 건수(#42 연계 전 0)', INSPECTOR_ID VARCHAR(20) NULL COMMENT '점검자 계정ID(화면 입력, #44)', INSPECT_RESULT VARCHAR(500) NULL COMMENT '점검결과(화면 입력, #44)', ACTN_MATTER VARCHAR(1000) NULL COMMENT '조치사항(화면 입력, #44)', INSPECT_DT DATETIME NULL COMMENT '점검일시(점검결과 입력 시각, #44 감사증빙)', REG_DT DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '리포트 생성일시', PRIMARY KEY (RPT_ID), UNIQUE KEY UX_PIR_YM (RPT_YM), KEY IX_PIR_REGDT (REG_DT) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='개인정보 접속기록 정기점검 리포트(#43, 월 1회)'; -- ───────────────────────────────────────────────────────────── -- [privacy.pdal_create_mysql.sql] -- ───────────────────────────────────────────────────────────── -- ===================================================================== -- 개인정보 접속기록 표준 테이블 : PERSONAL_DATA_ACCESS_LOG -- 문화품앗이 개인정보보호 기능개선 사업 (SFR-004 / DBR-001 / SER-002) -- 개발항목 #30 - 담당: arko-privacy-auditlog (Fork B) -- 작성일: 2026-07-21 DB: MySQL 8 / MariaDB -- --------------------------------------------------------------------- -- [설계 원칙] 신규 스키마 설계가 아니라 기존 표준 PERSONAL_DATA_DML_HISTORY 를 -- 표준 접속기록 테이블로 "승격" + 보관/무결성 컬럼 확장이다. -- -- [기존 PERSONAL_DATA_DML_HISTORY → PERSONAL_DATA_ACCESS_LOG 컬럼 매핑] -- CHG_USER_ID → CONECT_ID (① 사용자 식별자) -- CREATE_DATE → CONECT_DT (② 접속일시, SYSDATE()) -- CHG_CONECT_IP → CONECT_IP (③ 접속지 IP) * VARCHAR(45) IPv6 대응 -- UI_GUBUN → JOB_SE_CODE/NM (④ 수행업무 유형) * 업무유형 매핑 테이블로 코드/명 분리 -- ESNTL_ID → TRGET_ID (⑤ 처리대상 식별자) -- DML_GUBUN → DML_GUBUN (처리구분 S/I/U/D 그대로 계승) -- CHG_USER_SE → USER_SE (처리자 구분) -- [신규 확장 컬럼] -- TRGET_CN - 처리대상 건수/범위 (⑤ 보강) -- PROCESS_RESULT - 처리결과 S:성공 F:실패/차단 (비정상접근 탐지 5유형 적재 겸용) -- HASH_VAL - 위·변조 방지 해시 (SHA-256, 개발항목 #39) -- PREV_HASH_VAL - 직전 레코드 해시 (해시체인) -- -- [보관·파기] 730일 보관 전제. 월 단위 RANGE COLUMNS 파티셔닝으로 -- 파기 배치가 만료 파티션을 ALTER TABLE ... DROP PARTITION 으로 제거 -- (개별 DELETE 미사용). 애플리케이션 계층에 UPDATE/DELETE statement 미정의. -- [분리 원칙] COMTNSYSLOG 의 7일 삭제정책은 본 테이블에 절대 적용하지 않는다. -- ===================================================================== CREATE TABLE PERSONAL_DATA_ACCESS_LOG ( LOG_ID BIGINT NOT NULL AUTO_INCREMENT COMMENT '로그 일련번호', CONECT_ID VARCHAR(20) NOT NULL COMMENT '① 사용자 식별자(ID)', CONECT_DT DATETIME NOT NULL COMMENT '② 접속일시(파티션 키)', CONECT_IP VARCHAR(45) NOT NULL COMMENT '③ 접속지 정보(IP, IPv6 대응)', JOB_SE_CODE VARCHAR(30) NOT NULL COMMENT '④ 수행업무 유형 코드', JOB_SE_NM VARCHAR(100) NOT NULL COMMENT '④ 수행업무 유형 명(화면/기능명)', TRGET_ID VARCHAR(50) NULL COMMENT '⑤ 처리대상 식별자', TRGET_CN VARCHAR(200) NULL COMMENT '⑤ 처리대상 건수/범위', DML_GUBUN CHAR(1) NOT NULL COMMENT '처리구분 S:조회 I:등록 U:수정 D:삭제', PROCESS_RESULT CHAR(1) NOT NULL DEFAULT 'S' COMMENT '처리결과 S:성공 F:실패/차단', USER_SE VARCHAR(10) NULL COMMENT '처리자 구분', HASH_VAL VARCHAR(64) NOT NULL COMMENT '위·변조 방지 해시(SHA-256 Hex)', PREV_HASH_VAL VARCHAR(64) NULL COMMENT '직전 레코드 해시(해시체인)', PRIMARY KEY (LOG_ID, CONECT_DT), KEY IDX_PDAL_01 (CONECT_ID, CONECT_DT), -- 접속자 ID 검색 (현행 CONECT_MTHD LIKE 결함 해소) KEY IDX_PDAL_02 (CONECT_DT), -- 기간 검색 / 파티션 프루닝 KEY IDX_PDAL_03 (TRGET_ID, CONECT_DT), -- 처리대상 추적 KEY IDX_PDAL_04 (JOB_SE_CODE, CONECT_DT) -- 업무유형/이상탐지유형 집계 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='개인정보 접속기록 표준 테이블(PERSONAL_DATA_DML_HISTORY 승격, 730일 보관)' PARTITION BY RANGE COLUMNS(CONECT_DT) ( -- 파티션 키(CONECT_DT)를 PK에 포함해야 RANGE COLUMNS 파티셔닝 성립 (MySQL/MariaDB 제약) -- 월 단위 사전 생성. 유지보수 배치가 매월 다음 달 파티션을 ADD PARTITION 으로 선행 생성하고, -- 파기 배치(월 1회)가 보관기간(기본 730일) 경과 파티션을 DROP PARTITION 으로 제거한다. -- ※ MAXVALUE 파티션은 두지 않는다 — 만료 데이터가 catch-all 에 갇혀 DROP 불가해지는 것을 방지. PARTITION p202607 VALUES LESS THAN ('2026-08-01'), PARTITION p202608 VALUES LESS THAN ('2026-09-01'), PARTITION p202609 VALUES LESS THAN ('2026-10-01'), PARTITION p202610 VALUES LESS THAN ('2026-11-01'), PARTITION p202611 VALUES LESS THAN ('2026-12-01'), PARTITION p202612 VALUES LESS THAN ('2027-01-01'), PARTITION p202701 VALUES LESS THAN ('2027-02-01'), PARTITION p202702 VALUES LESS THAN ('2027-03-01') ) ; -- --------------------------------------------------------------------- -- [유지보수 참고] 월별 파티션 추가/삭제 예시 (배치가 동적으로 수행) -- -- -- 다음 달 파티션 선행 생성 -- ALTER TABLE PERSONAL_DATA_ACCESS_LOG -- ADD PARTITION (PARTITION p202703 VALUES LESS THAN ('2027-04-01')); -- -- -- 보관기간(730일) 경과 파티션 파기 -- ALTER TABLE PERSONAL_DATA_ACCESS_LOG DROP PARTITION p202607; -- --------------------------------------------------------------------- -- ───────────────────────────────────────────────────────────── -- [privacy.pdal_purge_history_create_mysql.sql] -- ───────────────────────────────────────────────────────────── -- ===================================================================== -- 개인정보 접속기록 파기·증설 이력 : PDAL_PURGE_HISTORY -- 문화품앗이 개인정보보호 기능개선 사업 (SFR-004 / DBR-001) -- 개발항목 #37 - 담당: arko-privacy-auditlog (Fork B) -- 작성일: 2026-07-21 DB: MySQL 8 / MariaDB -- --------------------------------------------------------------------- -- [목적] PERSONAL_DATA_ACCESS_LOG 의 보관정책(730일) 파기 배치가 수행한 -- 파티션 DROP(파기)·ADD(선행 증설) 내역을 증빙으로 기록한다. -- 개인정보 접속기록의 유일한 삭제 경로가 "파티션 DROP"임을 감사에서 입증하는 근거. -- -- [원칙] 접속기록 본문(PERSONAL_DATA_ACCESS_LOG)에는 UPDATE/DELETE 를 정의하지 않으며, -- 파기는 개별 DELETE 가 아니라 파티션 단위 DROP 으로만 수행한다(개발항목 #37). -- ===================================================================== CREATE TABLE PDAL_PURGE_HISTORY ( PURGE_ID BIGINT NOT NULL AUTO_INCREMENT COMMENT '이력 일련번호', PARTITION_NAME VARCHAR(64) NOT NULL COMMENT '대상 파티션명(예: p202607)', BOUNDARY_DT VARCHAR(30) NULL COMMENT '파티션 상한 경계값(LESS THAN, 예: 2026-08-01)', PURGE_TYPE VARCHAR(10) NOT NULL COMMENT '유형 DROP:파기 ADD:선행증설', PURGE_DT DATETIME NOT NULL COMMENT '수행 일시', NOTE VARCHAR(300) NULL COMMENT '비고(보관기간·사유)', PRIMARY KEY (PURGE_ID), KEY IDX_PDAL_PURGE_01 (PURGE_DT), KEY IDX_PDAL_PURGE_02 (PARTITION_NAME) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='개인정보 접속기록 파티션 파기·증설 이력(개발항목 #37, 파기 증빙)'; -- ───────────────────────────────────────────────────────────── -- [privacy.otp_device_create_mysql.sql] -- ───────────────────────────────────────────────────────────── -- ===================================================================== -- OTP(2단계 인증) 비밀키 영구 저장 테이블 -- 문화품앗이 개인정보보호 기능개선 사업 (SFR-003 / IAR-001, 추가 인증수단 1차 OTP) -- 개발항목 No.18 후속 - 담당: arko-privacy-authctrl -- 작성일: 2026-07-22 DB: MySQL 5.7/8 / MariaDB -- --------------------------------------------------------------------- -- [배경] OtpSecretStore 기본 구현이 InMemory(재기동 시 유실)라 이를 대체하는 -- DB 영속 저장소(DaoOtpSecretStore)가 사용하는 테이블. -- [보안] SECRET_ENC 는 OtpSecretCipher(AES-GCM) 암호문(Base64)만 저장한다. -- 평문 비밀키/OTP 코드는 저장하지 않는다(SER-003). -- [키] UNIQ_ID = 개인정보취급자 고유식별자(ESNTL_ID), 취급자당 1건(PK). -- ===================================================================== CREATE TABLE IF NOT EXISTS OTP_DEVICE ( UNIQ_ID VARCHAR(20) NOT NULL COMMENT '개인정보취급자 고유식별자(ESNTL_ID, PK)', SECRET_ENC VARCHAR(255) NOT NULL COMMENT 'OTP 비밀키 AES-GCM 암호문(Base64) - 평문 금지', REG_DT DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '등록(발급) 일시', LAST_VERIFY_DT DATETIME NULL COMMENT '최종 검증 성공 일시(참고용)', USE_CNT INT NOT NULL DEFAULT 0 COMMENT '검증 성공 누적 횟수(참고용)', DEVICE_LABEL VARCHAR(100) NULL COMMENT '기기/계정 라벨(참고용)', USE_YN CHAR(1) NOT NULL DEFAULT 'Y' COMMENT '사용여부 Y:사용 N:해지', PRIMARY KEY (UNIQ_ID) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='OTP 2단계 인증 비밀키 영구 저장(개인정보보호 SFR-003 No.18)'; -- ───────────────────────────────────────────────────────────── -- [privacy.diapause_emplyr_extend_mysql.sql] -- ───────────────────────────────────────────────────────────── -- ===================================================================== -- 휴면(장기 미사용) 대상 확장 : COMTNDIAPAUSEMBER 회원유형 구분 컬럼 추가 -- 문화품앗이 개인정보보호 기능개선 사업 (SFR-002, 장기 미사용 계정 관리) -- 개발항목 #7 - 담당: arko-privacy-authctrl (Fork A) -- 작성일: 2026-07-21 DB: MySQL 8 / MariaDB -- --------------------------------------------------------------------- -- [배경] 기존 휴면 대상은 일반회원(COMTNGNRLMBER)뿐이며, 휴면 테이블 -- COMTNDIAPAUSEMBER 에는 회원유형 구분 컬럼이 없다. 개인정보취급자 -- (COMTNEMPLYRINFO)를 휴면 대상에 포함(#7)하면서 일반회원 휴면/해제 -- 흐름과 혼선되지 않도록 회원유형 구분 컬럼을 신설한다. -- -- [안전] DEFAULT 'GNR'(일반회원)로 신설 → 기존 적재 행은 자동 'GNR' 처리되어 -- 기존 selectDiapauseList(일반회원 join COMTNGNRLMBER) 흐름 무영향. -- 취급자 휴면 행은 'EMP'로 적재하여 별도 select/notify 경로로 처리한다. -- -- [멱등] 재실행 안전을 위해 컬럼 존재 시 무시(수동 확인 후 실행). -- ===================================================================== ALTER TABLE COMTNDIAPAUSEMBER ADD COLUMN MBER_TY_CODE CHAR(3) NOT NULL DEFAULT 'GNR' COMMENT '회원유형 GNR:일반회원 EMP:개인정보취급자'; -- 조회 성능(취급자/일반 분리 조회) 보조 인덱스 ALTER TABLE COMTNDIAPAUSEMBER ADD INDEX IX_DIAPAUSE_MBERTY (MBER_TY_CODE, DIAPAUSE_STAT); -- ===================================================================== -- PART 2. DML (기준/시드 데이터) ※ 멱등: NOT EXISTS 가드로 중복 적재 방지 -- 수록: PDAL_JOB_MAPPING(업무유형 매핑 13행), ACCOUNT_MNG_POLICY(기본정책 1행) -- 미수록: OTP_DEVICE / PERSONAL_DATA_ACCESS_LOG / *_HISTORY = 런타임 적재(시드 없음) -- ===================================================================== -- 1) PDAL_JOB_MAPPING — 개인정보 처리 업무유형 매핑(접속기록 AOP 분류 기준, 필수) INSERT INTO PDAL_JOB_MAPPING (TARGET_CLASS, METHOD_PTTRN, JOB_SE_CODE, JOB_SE_NM, DML_GUBUN, SORT_ORDR, RM) SELECT * FROM ( SELECT 'EgovMberManageServiceImpl' AS TARGET_CLASS, 'select' AS METHOD_PTTRN, 'MBER_VIEW' AS JOB_SE_CODE, '회원관리-조회' AS JOB_SE_NM, 'S' AS DML_GUBUN, 10 AS SORT_ORDR, '회원 개인정보 조회' AS RM UNION ALL SELECT 'EgovMberManageServiceImpl', 'insert', 'MBER_REG', '회원관리-등록', 'I', 10, NULL UNION ALL SELECT 'EgovMberManageServiceImpl', 'update', 'MBER_MOD', '회원관리-수정', 'U', 10, NULL UNION ALL SELECT 'EgovMberManageServiceImpl', 'delete', 'MBER_DEL', '회원관리-삭제', 'D', 10, NULL UNION ALL SELECT 'EgovMberManageServiceImpl', '*', 'MBER_ETC', '회원관리-기타', NULL, 90, '미분류 폴백' UNION ALL SELECT 'EgovEntrprsManageServiceImpl', 'select', 'ENTRPRS_VIEW', '업체관리-조회', 'S', 10, '업체 담당자 개인정보 조회' UNION ALL SELECT 'EgovEntrprsManageServiceImpl', 'insert', 'ENTRPRS_REG', '업체관리-등록', 'I', 10, NULL UNION ALL SELECT 'EgovEntrprsManageServiceImpl', 'update', 'ENTRPRS_MOD', '업체관리-수정', 'U', 10, NULL UNION ALL SELECT 'EgovEntrprsManageServiceImpl', 'delete', 'ENTRPRS_DEL', '업체관리-삭제', 'D', 10, NULL UNION ALL SELECT 'EgovEntrprsManageServiceImpl', '*', 'ENTRPRS_ETC', '업체관리-기타', NULL, 90, '미분류 폴백' UNION ALL SELECT 'MberSsnServiceImpl', '*', 'MBER_SSN', '회원 고유식별정보 처리', NULL, 20, '주민등록번호 등 고유식별정보' UNION ALL SELECT 'BizMberMergeServiceImpl', '*', 'MBER_MERGE', '회원 통합/이관', NULL, 30, NULL UNION ALL SELECT 'BizTalentMberManageServiceImpl', '*', 'TALENT_MBER', '재능나눔 회원관리', NULL, 30, NULL ) seed WHERE NOT EXISTS (SELECT 1 FROM PDAL_JOB_MAPPING pjm WHERE pjm.JOB_SE_CODE = seed.JOB_SE_CODE); -- 2) ACCOUNT_MNG_POLICY — 장기 미사용 계정 관리 기본정책(단일행 POLICY_ID=1) INSERT INTO ACCOUNT_MNG_POLICY (POLICY_ID, DORMANT_DAY, ALERT_D1, ALERT_D2, ALERT_D3, DELETE_PRESERVE_DAY, BATCH_CYCLE, UPD_ID, UPD_DT) SELECT 1, 365, 30, 7, 0, 365, 'DAILY', 'SYSTEM', NOW() FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM ACCOUNT_MNG_POLICY WHERE POLICY_ID = 1); -- (부록) LOGIN_LOCK_COUNT — 기존 arko 테이블(변동분 아님). 미존재 신규 환경에서만 사용(기본 5): -- INSERT INTO LOGIN_LOCK_COUNT (LOCK_COUNT) -- SELECT 5 FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM LOGIN_LOCK_COUNT); -- ############################## END ##############################