arko_renual/개인정보보호_개발진행현황.md
infraurp f2029a00a0 개인정보보호 기능개선 2차 구현 — 접속기록 안정화·솔트 인증·관리자 화면 4종
접속기록(SFR-004/#33):
- AccessLogQueue 포화 방어. 종전 offer(timeout) 무한 반복은 컨슈머 정지 시
  요청 스레드가 영구 대기해 WAS 스레드 풀 고갈 → 사이트 전면 정지로 이어졌다.
  대기를 3회로 제한하고 포화 차단기(saturated)를 도입해 지속 포화 시 즉시 판정한다.
- 유실은 조용히 넘기지 않는다. recordDrop 이 누적 집계 + 초기 20건/이후 100건 표본
  ERROR 로그로 남긴다(법정 보관 대상이므로 사후 추적 가능해야 함).
- 컨슈머 루프가 Exception 이 아닌 Throwable 까지 흡수한다. Error 하나로 컨슈머가
  죽으면 running=true 인 채 이후 전 요청이 포화 대기에 빠졌다.
- 자체 데몬 워치독(30초) 추가 — 컨슈머 사망 시 재기동, 적체 경고, 차단기 자동 해제.
  task:annotation-driven 활성화 여부와 무관해야 하므로 @Scheduled 를 쓰지 않는다.
- 해시체인 순번 보장을 위한 단일 컨슈머 전제는 유지(병렬화 금지).

인증정보 보호(SER-001/SER-003/#27):
- EgovFileScrty 사용자별 랜덤 솔트(S1: 형식) 도입, matches() 로 검증 일원화 —
  기존 무솔트 계정과 공존한다.
- 비밀번호 변경 시 현재 비밀번호 검증 복구. 종전에는 DB 값을 자기 자신과 비교해
  항상 true 였고, 입력한 oldPassword 가 어디에도 쓰이지 않았다.
- 평문 비밀번호 println 제거.

관리자 화면: 접속기록 조회, 업무구분 매핑 관리, 권한변경 이력, 미사용계정 현황.
계정 파기(AccountDelete) 서비스 및 DDL/DML 추가.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-07 15:05:03 +09:00

50 KiB
Raw Blame History

문화품앗이 개인정보보호 기능개선 사업 — 개발 진행현황

발주기관: 한국문화원연합회 | 사업기간: 계약일~2026.12.18 | 대상: 문화품앗이(csv.culture.go.kr) 근거: 개인정보보호위원회 「고유식별정보 안전조치 관리실태 점검」 결과통보(2025.11.21.) 작성일: 2026-07-21 | 갱신: 2026-07-22(URL 접근제어·2차 인증 진짜완료 재확인) | 기준: 개인정보보호_개발항목.docx(61개 개발항목) 대비 소스 실측


1. 종합 진행률 대시보드

단계 상태 비고
요구사항 분석·설계 ✅ 완료 제안서 Ⅲ장 + 개발항목 61개 정리 + 디자인 브리프(10개 화면)
자동화 하네스 구축 ✅ 완료 arko-privacy-* 에이전트 3종 + 스킬 4종 + 리뷰어 확장
코드 구현 🟡 진행 (42 / 61, 69%) 2026-07-21 7파 각 6개 — 1~6차 36개 + 7차(#9·#10·#11·#13·#36·#44) — 아래 §1-1
시험·검증(Ⅲ-5) ⬜ 대기 구현 후 진행
적용·안정화(Ⅲ-6) ⬜ 대기 구현 후 진행

개발항목 61개 코드 구현 기준 진행률: 42개 완료 (2026-07-21 당일, 7파 각 6개 — 69%)

  • 분석·설계 및 하네스는 완료되어 바로 구현 단계 진입 가능한 상태.
  • 현재 워킹트리의 소스 변경(EgovSpringSecurityLoginFilter.java, pom.xml)은 로컬 개발 IP 허용(127.0.0.1) 추가로, 본 사업 산출물이 아님 — 진행률에서 제외.

[2026-07-22 갱신] URL 접근 제어·2차 인증 "진짜 완료" 재확인 — #1·#2(URL 접근제어), #14·#15·#16(2차 인증) 5개 항목의 코드·로직을 재확인해 "✅ 진짜완료"로 표시함(구현 완결 확인). ⚠단, 두 인터셉터의 운영 강제(AuthorityInterceptor urlRoleMapping 등록 / SecondFactorInterceptor enforce=true)는 배포 단계에서 별도 활성 필요 — "코드 완결(진짜완료)"과 "운영 강제 활성"은 구분해 기록함. 운영 강제 활성은 화면(#52)·인증수단(#18~20) 완료 후 진행 예정.


1-1. 오늘의 작업 (2026-07-21, ~17:00 목표)

fork 3개를 병렬로 투입해 자체 완결적·파일 충돌 없는 기반 항목 6개를 당일 완료 목표로 착수한다. (발주기관 확정 대기 #12·#19, 운영환경 실측 선행 #55~58, 대규모 화면 #45~54는 오늘 범위에서 제외.)

Fork 영역 대상 # 산출물 상태
A 권한관리 #1 getAuthorities() 구현 EgovUserDetailsSessionServiceImpl + 신규 sqlmap/DDL ✅ 완료
A 권한관리 #4 AUTHOR_CHANGE_HISTORY DDL 신설 신규 .sql DDL(3년 보관) ✅ 완료
B 접속기록 #30 PERSONAL_DATA_ACCESS_LOG DDL 신규 .sql(무결성 컬럼+월 파티셔닝) ✅ 완료
B 접속기록 #39 SHA-256 해시체인 유틸 신규 util .java(HASH_VAL/PREV_HASH_VAL) ✅ 완료
C 인증체계 #17 AuthMethodService 인터페이스 설계 신규 인터페이스 + 3종 구현 스텁 ✅ 완료
C 인증체계 #27 비밀번호 해시 알고리즘 점검 EgovFileScrty.encryptPassword() 점검노트 ✅ 완료

파일 충돌 방지: Fork A만 sql-map-config/기존 ServiceImpl 수정, Fork B·C는 신규 파일만 생성. 진행현황 MD 기록은 오케스트레이터 단독 수행.

착수 로그

  • 2026-07-21 착수: Fork A/B/C 병렬 투입, 대상 6개 항목 🟡 진행중 전환.
  • 2026-07-21 Fork C 완료 (#17, #27): 인증수단 인터페이스 4파일 + 비밀번호 해시 점검노트 생성. 실측 확인 후 ✅ 전환. 후속 발견: 무솔트·무반복 해시, 해시값 로그출력(#27 보완 권고), 인증수단 빈 등록(#21 후속).
  • 2026-07-21 Fork B 완료 (#30, #39): 접속기록 DDL(월 파티셔닝) + 해시체인 유틸(javac+실행 검증) 생성. 실측 확인 후 ✅ 전환. 후속 연계: 파티션 자동증설·730일 파기 배치(#37), 단일스레드 순차적재 전제(#33).
  • 2026-07-21 Fork A 완료 (#1, #4): #1 getAuthorities() 5계층 배선(ServiceImpl→DAO→sqlmap→config→빈주입) 완료·실측 정합 확인. Fork A가 #4 DDL 착수 직후 API 오류로 중단되어, #4 AUTHOR_CHANGE_HISTORY DDL은 오케스트레이터가 직접 완료(컬럼명 오타 CHG_RESN 정정 포함). → 1차 목표 6개 항목 전부 ✅.

2차 작업 (2026-07-21, 추가 6개 목표)

1차 기반(#1·#4·#17·#30·#39) 위에 쌓이는 항목. 공용 config 수정은 Fork A에 단독 집중해 충돌 차단.

Fork 영역 대상 # 산출물 상태
A 배치(config 단독소유) #5 권한 이력 파기 배치 AUTHOR_CHANGE_HISTORY DAO/sqlmap + @Scheduled(1,095일) ✅ 완료
A 배치(config 단독소유) #40 해시체인 무결성 검증 배치 HashChainService.verifyChain 재계산 배치 + 관리자 통보 ✅ 완료
B util(신규파일만) #34 IP 취득 로직 보정 ClientIpResolver(XFF→Proxy-Client-IP→getRemoteAddr) ✅ 완료
B util(신규파일만) #16 세션 재발급(세션고정 차단) SessionRegenerator util ✅ 완료
C resolver+분석 #21 AuthMethodResolver 구현 #17 인터페이스 기반 인증수단 분기 ✅ 완료
C resolver+분석 #38 COMTNSYSLOG 7일 삭제 분리 기존 7일 삭제 SQL 진단 + 접속기록 미적용 분리 노트 ✅ 완료
  • 2026-07-21 2차 착수: Fork A/B/C 병렬 재투입, 대상 6개 🟡 진행중 전환. 1q2w3e!Q

3차 작업 (2026-07-21, 추가 6개 목표 — 통합 단계)

1·2차 산출물(#1·#16·#17·#21·#30·#34·#39)을 실제로 연결·활용. 공용 config는 fork별로 배타 소유(A=egov-com-servlet.xml, B=sql-map-config+AOP, C=impl java만).

Fork 영역 대상 # 산출물 상태
A 인터셉터(servlet.xml 단독) #2 AuthorityInterceptor 등록 URL·메뉴 권한 대조 차단(#1 getAuthorities 활용) ✅ 완료
A 인터셉터(servlet.xml 단독) #14 SecondFactorInterceptor 등록 2차 인증 판정(#16 SessionRegenerator+#21 Resolver) ✅ 완료
B 접속기록수집(sqlmap+AOP 단독) #31 PersonalDataLogAspect 개인정보 서비스 한정 AOP 수집(#34 IP+#39 해시) ✅ 완료
B 접속기록수집(sqlmap+AOP 단독) #32 업무유형 매핑 테이블 URL패턴→업무코드 DDL+로더 ✅ 완료
C 인증수단(impl java만) #18 OtpAuthService(TOTP) #17 스텁 채움, TOTP 자체구현·비밀키 암호화 ✅ 완료
C 인증수단(impl java만) #20 CertAuthService #17 스텁 채움, GPKI 기존자산 위임 ✅ 완료
  • 2026-07-21 3차 착수: Fork A/B/C 병렬 재투입, 대상 6개 🟡 진행중 전환.

4차 작업 (2026-07-21, 추가 6개 목표)

접근통제·계정잠금 + 접속기록 배치/비동기 + 세션/마스킹. 로그인 흐름은 Fork A 단독 소유로 충돌 차단.

Fork 영역 대상 # 산출물 상태
A 로그인흐름(sql-map-config 단독) #22 인증실패이력 활성경로 이설 LOGIN_HISTORY/LOGIN_LOCK_COUNT 재사용, actionLogin 활성 ✅ 완료
A 로그인흐름(sql-map-config 단독) #24 계정 잠금 10→5회 임계값 5 + 해제 관리자화면 전환·해제이력 적재 ✅ 완료
B 접속기록배치(자기sqlmap·스케줄러 단독) #33 비동기 적재 큐 로그적재↔업무txn 분리(단일컨슈머 순번보장) ✅ 완료
B 접속기록배치(자기sqlmap·스케줄러 단독) #37 보관 730일 파기 배치 월1회 파티션 DROP(개별 DELETE 미사용) ✅ 완료
C 세션·마스킹(web.xml+util 단독) #25 세션 타임아웃 60→30분 web.xml session-config + 정책 훅 ✅ 완료
C 세션·마스킹(web.xml+util 단독) #29 2차인증 화면 마스킹 휴대폰번호 마스킹 util ✅ 완료
  • 2026-07-21 4차 착수: Fork A/B/C 병렬 재투입, 대상 6개 🟡 진행중 전환.

5차 작업 (2026-07-21, 추가 6개 목표)

미사용계정 휴면(첫 착수) + 접속기록 조회·점검 + 접근통제 마무리(#23 핸드오프 해소). 로그인/인터셉터는 Fork C 단독.

Fork 영역 대상 # 산출물 상태
A 휴면계정(umt·휴면 sqlmap 단독) #7 휴면 대상 취급자 확장 휴면 체인 S→P를 COMTNEMPLYRINFO까지 ✅ 완료
A 휴면계정(umt·휴면 sqlmap 단독) #8 MariaDB 휴면배치 statement 정비 Oracle에만 있던 배치 statement MariaDB 추가 ✅ 완료
B 접속기록조회·점검(자기sqlmap·스케줄러 단독) #41 접속기록 조회·검색 개선 접속자ID 등 신규 검색조건(현행 LIKE+날짜뿐) ✅ 완료
B 접속기록조회·점검(자기sqlmap·스케줄러 단독) #43 정기점검 리포트 생성 배치 월1회 이상징후·무결성·처리현황·다운로드 집계 ✅ 완료
C 접근통제마무리(로그인·servlet.xml 단독) #23 계정 열거 방지 실패 메시지 존재여부 무관 일관화(#22 핸드오프 해소) ✅ 진행중
C 접근통제마무리(로그인·servlet.xml 단독) #26 인터셉터 3단 순서 확정 인증→SecondFactor→Authority 순서 확정·검증 ✅ 완료
  • 2026-07-21 5차 착수: Fork A/B/C 병렬 재투입, 대상 6개 🟡 진행중 전환.

6차 작업 (2026-07-21, 추가 6개 목표 — 2개 영역 완결)

권한관리(1~6)·접근통제(22~29) 완결 목표. 공용 config는 fork별 배타 소유(A=sql-map-config, B=BatchScheduler+등록된sqlmap, C=servlet.xml).

Fork 영역 대상 # 산출물 상태
A 권한관리완결(sql-map-config 단독) #3 권한 신청·승인 워크플로 신청R→승인A/반려J 테이블+서비스, 승인시 권한반영+#4이력 단일TX ✅ 완료
A 권한관리완결(sql-map-config 단독) #6 권한 이력 조회·검색·다운로드 #4 이력 양방향검색 + 다운로드 사유필수·다운로드이력 ✅ 완료
B 접속기록마무리(스케줄러·등록sqlmap 단독) #35 비정상 접근 탐지 5유형 비인가/대량조회/비정상시간대/계정공유의심/인증실패반복 ✅ 완료
B 접속기록마무리(스케줄러·등록sqlmap 단독) #42 다운로드 사유·이력 관리 접속기록 다운로드 사유필수+다운로드자·일시·IP·건수 이력 ✅ 완료
C 인증판정·정책(servlet.xml·인터셉터 단독) #15 2차인증 적용대상·경로 판정 취급자 한정, 외부 필수/내부 정책(#14 확장) ✅ 완료
C 인증판정·정책(servlet.xml·인터셉터 단독) #28 신규 인증정보 저장정책 적용 OTP암호화/인증번호미저장/인증서 식별값만 점검·확정 ✅ 완료
  • 2026-07-21 6차 착수: Fork A/B/C 병렬 재투입, 대상 6개 🟡 진행중 전환.

7차 작업 (2026-07-21, 추가 6개 목표 — 2개 영역 완결)

미사용계정(SFR-002) 완결 + 접속기록(SFR-004) 15/15 완결. 미사용계정 4개는 공유파일 충돌로 Fork A 단독, 접속기록 2개는 파일 분리(B=aspect, C=report).

Fork 영역 대상 # 산출물 상태
A 미사용계정완결(휴면/정책·sql-map-config 단독) #9 휴면 기준일수 정책값화 365 하드코딩→정책테이블 ✅ 완료
A 미사용계정완결 #10 휴면 전 관리자 알림 D-30/D-7/D-Day 현재 본인메일 2단계→3단계+관리자 ✅ 완료
A 미사용계정완결 #11 장기 미사용 계정 현황 조회(백엔드) ID·성명·소속·최종로그인·미접속일수·상태·휴면예정일 ✅ 완료
A 미사용계정완결 #13 계정 관리 정책 설정(백엔드) 기준일수·알림시점·삭제보존기간·배치주기 정책 CRUD ✅ 완료
B 처리기록확장(aspect·AOP context 단독) #36 처리기록 적재 범위 확장 2개 Controller→전 처리지점, TRGET_ID 규약(sqlmap 무변경) ✅ 완료
C 점검결과보관(report·등록sqlmap 단독) #44 점검결과 입력·보관(백엔드) 점검자·일시·결과·조치사항 입력→PDAL_INSPECTION_REPORT ✅ 완료
  • 2026-08-05 #22-1 완료 (인증 실패 이력 IP 기록·보관기간·조회화면): #22 이설로 적재는 살아났으나 IP 미기록 + 성공 시 당일 이력 DELETE 로 흔적이 소멸하던 것을 보완. 신규 6파일(privacy/lock/LoginFailHistory{VO,DAO,Service,ServiceImpl,Controller}, PrivacyLoginFailHistory_SQL_Mysql/Oracle) + JSP 1 + DDL/메뉴DML 2 + 기존 8파일 수정. 핵심 함정: insertFailHistory가 컬럼목록 없는 VALUES(3값) 이라 DDL 단독 배포 시 ERROR 1136 으로 로그인 실패 적재가 깨진다 — sqlmap 동반 배포 필수. 잠금 동작은 selectFailCount가 RESET_YN='N'만 세도록 해 종전과 동일.
  • 2026-08-05 #22-1 로컬 활성화 완료: JDK8 mvn compile BUILD SUCCESS(종전 "javac 미검증" 해소). 로컬 DB에 privacy.install_mysql.sql 전체 적용(privacy 7테이블 + LOGIN_HISTORY.CONECT_IP/RESET_YN+인덱스 2종 + LOGIN_HIST_KEEP_DAY=730 + 메뉴 9100035~9100039, 한글 HEX() 무결성 확인). 파일 델타 19건 반영 후 Tomcat 재기동 → 컨텍스트 정상 기동(= iBatis sqlMap 등록·파싱 성공), listView.do 302→로그인(대조군 404로 매핑 실재 확인). 산출물: _workspace/deploy/20260805_1800/{DELTA.md,APPLY_LOG.md,sql/}.
    • 함정 2건 실측: ① 로컬 3307 도커(urpai-mysql)가 2026-07-30 재생성되며 csv DB 소실 → 실제 csv 는 MySQL80 3306, 배포본 globals-live.properties 포트 변경으로 복구. ② 배포본 sql-map-config 의 BizApplyMileage(소문자) ↔ 소스 BizApplyMIleage(대문자) drift 실재 — 통째 교체 시 전체 404, 신규 1줄만 병합해야 한다.
    • 미완: 개발서버 미반영(SSH 권한 차단). 관리자 계정이 없어 좌측메뉴 노출·목록 렌더·IP 적재·RESET_YN 소프트 리셋 실동작 검증은 미수행.
  • 2026-07-21 7차 착수: Fork A/B/C 병렬 재투입, 대상 6개 🟡 진행중 전환.
  • 2026-07-21 Fork B(7차) 완료 (#36): 처리기록 pointcut 5→16 서비스 확장 + TRGET_ID 식별자 추출 규약(본문 미적재, fail-safe). 실측 확인 후 ✅(XML well-formed·헬퍼 배선·sqlmap 미변경).
  • 2026-07-21 Fork C(7차) 완료 (#44): 점검결과 입력·보관(InspectionResult 3파일+INSPECT_DT+statement 3종). 실측 확인 후 ✅(미입력 차단·양쪽 XML well-formed·sql-map-config 미변경). 접속기록 영역(30~44) 15/15 완결. 배포된 테이블엔 INSPECT_DT ALTER 필요(핸드오프).
  • 2026-07-21 Fork A(7차) 완료 (#9,#10,#11,#13): 정책테이블(ACCOUNT_MNG_POLICY)+정책값화+D-30/7/Day 알림+현황조회, 10파일·javac EXIT=0. 실측 확인 후 ✅(365→정책 서브쿼리·sql-map-config 등록·알림 스케줄러 확인). → 미사용계정 영역 6/7 완결(#12 발주대기만). 7차 6개 전부 ✅ (누적 42/61, 69%).
  • 2026-07-21 Fork C(6차) 중단→완결 (#15, #28): Fork C가 #15(SecondFactorInterceptor 확장) 완료 후 #28 점검노트 착수 직전 API 오류 중단. #15는 실측 확인(외부필수/내부정책 판정·enforce=false·xml well-formed·중괄호 75/75)→✅. #28 점검노트는 오케스트레이터가 직접 완결(3종 저장정책 실측, 위반 0건, OTP URI 주의)→✅. → 접근통제 영역(22~29) 8/8 완결.
  • 2026-07-21 Fork B(6차) 완료 (#35, #42): 비정상 탐지 5유형(6파일, 표준컬럼 집계) + 다운로드 사유필수·이력(DDL+4파일). 실측 확인 후 ✅(#43 리포트 자리표시→실집계 summarize()/countByPeriod() 교체, 양쪽 XML well-formed).
  • 2026-07-21 Fork A(6차) 완료 (#3, #6): 권한 신청·승인 워크플로(단일TX) + 권한이력 조회·다운로드(사유필수). 실측 확인 후 ✅(10파일·DDL·sql-map-config 등록·approveRequest 단일TX·다운로드 차단 확인). → 권한관리 영역(1~6) 6/6 완결. 6차 6개 전부 ✅ (누적 36/61, 59%).
  • 2026-07-21 Fork C(5차) 완료 (#23, #26): 계정 열거 방지(조건부 문구 제거→단일 메시지) + 인터셉터 3단 순서 확정·문서화. 실측 확인 후 ✅(문구 제거·순서·xml well-formed 확인). 4차 #22 핸드오프(계정열거) 해소 완료. ①authenticInterceptor 재활성은 운영 협의 후속.
  • 2026-07-21 Fork B(5차) 중단→분할 완결: Fork B가 #41 Java 4파일까지 만들고 API 오류로 중단(누락 sqlmap·#43 미착수). #41은 오케스트레이터가 누락 sqlmap statement(Mysql/Oracle) 완결(DAO statement id 정합·XML well-formed 검증)→✅. #43은 전용 fork 재투입(진행중).
  • 2026-07-21 Fork A(5차) 완료 (#7, #8): 휴면 취급자 확장(MBER_TY_CODE 분리) + MariaDB 휴면 statement 5종 이설. 실측 확인 후 ✅ — 핵심 발견: MariaDB sqlmap에 휴면 statement 전무해 실운영 휴면배치가 불능이던 것을 복구(#56 착수전 확인사항과 직결). DAO↔sqlmap id·javac EXIT=0 확인.
  • 2026-07-21 #43 재투입 fork 완료: 정기점검 리포트 배치(PDAL_INSPECTION_REPORT+집계 3종+스케줄러). 실측 확인 후 ✅(파일·서비스·XML well-formed). #35 이상징후·#42 다운로드는 자리표시(후속 실집계 교체). → 5차 목표 6개 전부 ✅ (누적 30/61 — 절반 근접).
  • 2026-07-21 Fork C(4차) 완료 (#25, #29): web.xml 세션타임아웃 30분 + MaskingUtil(휴대폰/이메일/이름). 실측 확인 후 ✅(web.xml:218=30, javac 통과). 후속: 세션타임아웃 관리자 설정화면.
  • 2026-07-21 Fork A(4차) 완료 (#22, #24): 운영 로그인 경로(EgovLoginController.actionLogin) 실패이력·잠금 이설 + ACCOUNT_UNLOCK_HISTORY 해제이력. 실측 확인 후 ✅ — 참조 서비스 7메서드·VO 3게터 인터페이스 실재 검증, fail-safe로 로그인 무손상. 핸드오프: 필터 활성 시 이중카운트 정리, #23 실패메시지 완전통일(현재 존재계정에만 "현재 N회" 부가).
  • 2026-07-21 Fork B(4차) 완료 (#33, #37): 비동기 적재 큐(단일컨슈머 순번보장) + 730일 파티션 파기·선행증설 배치. 실측 확인 후 ✅(Aspect enqueue 전환·파티션 DROP/ADD statement·BatchScheduler 등록 확인). → 4차 목표 6개 전부 ✅ (누적 24/61).
  • 2026-07-21 Fork A(3차) 완료 (#2, #14): 인터셉터 2종 신규+egov-com-servlet.xml 등록(순서 #26 반영), javac 통과·xml well-formed. 운영 안전 확인: SecondFactor enforce=false·Authority urlRoleMapping 공백=둘 다 fail-open이라 현재 사이트 무손상. 실측 확인 후 ✅. 핵심 실측: 이 프로젝트는 selectAnnotaionMapper가 /**/*.do 전체 적용(mvc:interceptors 미사용)·기존 authenticInterceptor 비활성 → 스코프/잠금방지를 인터셉터 내부에서 처리. 후속: #52·#18~20 후 enforce=true, urlRoleMapping 운영 등록.
  • 2026-07-21 Fork C(3차) 완료 (#18, #20): OtpAuthService(TOTP RFC6238 자체구현, RFC 테스트벡터 일치) 5파일 + CertAuthService(기존 GPKI actionCrtfctLogin 위임). 스텁→실구현, javac+실행 검증. 실측 확인 후 ✅(UnsupportedOperationException 0건, SmsAuth#19 미변경 유지). 후속: OTP 비밀키 영속화 테이블, CertProcessFilter 재활성.
  • 2026-07-21 Fork B(3차) 완료 (#31, #32): PersonalDataLogAspect 수집 파이프라인 10클래스+DDL+sqlmap 6+AOP context, javac EXIT=0. 실측 확인 후 ✅(pointcut 개인정보 서비스 5개 한정 확인=과수집 방지, 기존 COMTNSYSLOG 광역 블록 주석 유지). 후속: #33 비동기 큐, #36 TRGET_ID 규약. → 3차 목표 6개 전부 ✅ (누적 18/61).
  • 2026-07-21 Fork B(2차) 완료 (#34, #16): ClientIpResolver(신뢰CIDR 검증) + SessionRegenerator 생성, javac+단위검증 통과. 실측 확인 후 ✅. 후속: 신뢰대역 운영값(#57), #14 인터셉터 연동 배선.
  • 2026-07-21 Fork C(2차) 완료 (#21, #38): AuthMethodResolver 4종(javac 통과) + 시스템로그 삭제정책 분리노트. 실측 확인 후 ✅(7일 삭제 SQL EgovSysLog_SQL_Mysql.xml:159 실제와 정합, 스케줄러 비활성 확인). 후속: #18~20 구현체·빈등록.
  • 2026-07-21 Fork A(2차) 완료 (#5, #40): 파기·무결성검증 배치 2종(배치 클래스+DAO+sqlmap 6파일) + BatchScheduler @Scheduled 2메서드 + sql-map-config 등록. 실측 확인 후 ✅(파기 SQL이 실제 DDL 컬럼 CHG_DT 사용 정합). 핵심 핸드오프: 전역 task:annotation-driven이 양쪽 context에 주석 처리→@Scheduled 현재 무동작(기존 배치도 동일). 활성화·crontab 경합은 운영 협의 필요. → 2차 목표 6개 전부 ✅ (누적 12/61).

2. 영역별 진행 요약

영역 요구사항 ID 항목(구간) 담당 완료 진행중 미착수
Ⅰ. 권한관리 ✅ SFR-001 1~6 arko-privacy-authctrl 6 0 0
Ⅰ. 미사용계정관리 SFR-002 7~13 arko-privacy-authctrl 6 0 1
Ⅱ. 인증체계 SFR-003 / IAR-001 14~21 arko-privacy-authctrl 7 0 1
Ⅱ. 접근통제·인증정보 ✅ SER-001 / SER-003 22~29 arko-privacy-authctrl 8 0 0
Ⅲ. 접속기록 ✅ SFR-004 / DBR-001 / SER-002 30~44 arko-privacy-auditlog 15 0 0
Ⅳ. 신규 화면(UI) - 45~54 arko-frontend 0 0 10
Ⅴ. 착수전 확인 - 55~58 arko-privacy-analyst 0 0 4
Ⅵ. 보안·품질 SER-004 59~61 arko-reviewer 0 0 3
합계 61 42 0 19

범례: ✅ 완료 · 🟡 진행중 · ⬜ 미착수


3. 항목별 상세 진행현황

Ⅰ. 권한관리 (Ⅲ-2, SFR-001·SFR-002) — arko-privacy-authctrl

1) 권한 신설·변경·회수 및 역할별 차등 적용 (SFR-001)

# 개발항목 상태 소스 실측 / 비고
1 getAuthorities() 구현 ✅ 진짜완료 [2026-07-22 진짜완료 — 코드·로직 재확인] [Fork A] EgovUserDetailsSessionServiceImpl 세션 LoginVO.uniqId→EgovUserAuthorityDAO.selectAuthoritiesByUniqId→PrivacyAuthority_SQL_Mysql.xml(COMTNEMPLYRSCRTYESTBS 조회). sql-map-config 등록 + 빈 DAO 주입 배선 완료. 미인증 시 빈 목록(fail-safe)
2 AuthorityInterceptor 신규 등록 ✅ 진짜완료 [2026-07-22 진짜완료 — 코드·로직 재확인. ⚠운영 강제(urlRoleMapping 등록)는 배포 시 별도 활성] [Fork A] cmm/privacy/interceptor/AuthorityInterceptor.java + egov-com-servlet.xml 등록. /mnt/ 한정, EgovUserDetailsHelper.getAuthorities()(#1) 대조 미허용 403. urlRoleMapping 기본 비어있음=fail-open(전경로 통과) → 운영에서 매핑 점진 등록
3 권한 신청·승인 워크플로 구현 ✅ 완료(화면 #46 포함) [Fork A] AUTHOR_CHANGE_REQUEST(DDL)+5계층(AuthorWorkflow*). approveRequest() 승인 시 스냅샷→권한반영(COMTNEMPLYRSCRTYESTBS)→상태A→#4이력을 단일TX(context-transaction AOP, 예외 시 롤백). **화면 #46 구현: AuthorWorkflowController에 listView.do/registView.do(JSP 뷰명 반환·@ModelAttribute authorChangeRequestVO·PaginationInfo) 페이지진입 추가 + site/mnt/sec/authorRequest/{list,regist}.jsp(JstlView, 검색·목록·ui:pagination, 승인/반려 jQuery AJAX(approve/reject.do)·반려사유 모달, 신청등록 폼). 기존 jsonView 엔드포인트 병존. 메뉴 등록: src/script/mysql/dml/privacy.menu_author_request_insert_mysql.sql(COMTNPROGRMLIST+COMTNMENUINFO'개인정보보호'그룹+COMTNMENUCREATDTLS 권한매핑, NOT EXISTS 재실행안전·기존 권한관리 노출권한 상속). ⚠운영 DB 적용 필요(메뉴번호 충돌·관리자 AUTHOR_CODE 배포 시 확인).
4 AUTHOR_CHANGE_HISTORY 이력 테이블 신설 ✅ 진짜완료 [2026-07-28 진짜완료 — DB 실측 재확인] src/script/mysql/ddl/privacy.author_change_history_create_mysql.sql. 변경자/변경일시/변경전후권한(BEFORE/AFTER_AUTHOR)/변경구분/승인자/IP + 3년(1,095일) 보관 전제. Fork A 중단→오케스트레이터 완료. 로컬 csv DB에 author_change_history 테이블 실제 생성 확인(information_schema, 12개 컬럼 DDL과 일치) + AuthorWorkflowServiceImpl.approveRequest() 단일TX를 통해 실이력 2건 적재 확인(digital 계정 권한부여·변경 승인 건, HIST_ID 1·2)
5 권한 이력 파기 배치 구현 ✅ 완료 [Fork A] cmm/privacy/batch/(Service/Impl/PurgeDAO) + PrivacyAuthorHistoryPurge_SQL(DELETE WHERE CHG_DT<cutoff, 1,095일). BatchScheduler.purgeAuthorChangeHistoryScheduler() @Scheduled(매월1일 04:00). config 등록 완료. ⚠전역 task:annotation-driven 비활성→활성화는 운영협의
6 권한 이력 조회·검색·다운로드 화면 ✅ 진짜 완료 [Fork A] AuthorHistoryService/DAO+VO+컨트롤러. #4 이력 대상자·변경자 양방향 검색+구분/기간+페이징. 다운로드 사유 미입력 IllegalArgumentException 차단+AUTHOR_HIST_DOWNLOAD_HISTORY(다운로드자·IP·사유·건수). 화면 #46 후속

2) 장기 미사용 계정 관리 (SFR-002)

# 개발항목 상태 소스 실측 / 비고
7 휴면 대상 확장(취급자 COMTNEMPLYRINFO까지) ✅ 진짜 완료 [Fork A] COMTNDIAPAUSEMBER.MBER_TY_CODE(DDL, DEFAULT 'GNR') + insertDiapauseEmplyr/selectDiapauseListEmplyr(Mysql/Oracle, LAST_LOGIN_DT 365일). EgovLoginServiceImpl.insertDiapause가 일반+취급자 처리(processDiapauseList 공통화), 기존 selectDiapauseList엔 GNR 필터. 매일01:00 기존 스케줄 재사용
8 MariaDB sqlmap 휴면배치 statement 정비 ✅ 진짜 완료 [Fork A] AS-IS: 휴면 statement 5종이 Oracle sqlmap에만→MariaDB 운영 시 휴면배치 불능. EgovLoginUsr_SQL_Mysql.xml에 insertDiapause/selectDiapauseList/updateDiapauseMber/selectToken/inputToken 이설(NVL→IFNULL, SYSDATE→NOW() 등). MariaDB 휴면배치 복구
9 휴면 기준일수 정책값화 ✅ 진짜 완료 [Fork A] 휴면 sqlmap 4개 WHERE의 >365→>(SELECT IFNULL(MAX(DORMANT_DAY),365) FROM ACCOUNT_MNG_POLICY)(Mysql/Oracle). 미설정 시 365 fallback, Java 시그니처 무변경
10 휴면 전 관리자 알림 확장(D-30/D-7/D-Day) ✅ 진짜 완료 [Fork A] DormantAlertService — 정책 ALERT_D1/2/3(기본 30/7/0)일 전 대상 조회→본인+관리자(ADMIN_EMAIL) 메일(EgovSndngMail 재사용, fail-safe). BatchScheduler.dormantPreAlertScheduler() @Scheduled(매일 06:00)
11 장기 미사용 계정 현황 조회 화면 신규 ✅ 진짜 완료 [Fork A] DormantAccountStatusService/DAO+VO. 취급자(COMTNEMPLYRINFO) 계정ID·성명·소속·직위·최종로그인·미접속일수(DATEDIFF)·상태·휴면예정일 복합검색+페이징. 일반회원 UNION·화면 후속
12 계정 삭제 기능 구현 ✅ 진짜 완료 ⚠ 보존기간 발주기관 확정 필요
13 계정 관리 정책 설정 화면 ✅ 진짜 완료 [Fork A] ACCOUNT_MNG_POLICY(DDL, DORMANT_DAY·ALERT_D1/2/3·DELETE_PRESERVE_DAY·BATCH_CYCLE·ADMIN_EMAIL 단일행+시드) + AccountMngPolicyService/DAO/VO/Controller. 미설정 시 기본값 fallback. #9/#10이 이 테이블 참조. 화면 후속

Ⅱ. 인증체계 (Ⅲ-3, SFR-003·IAR-001·SER-001·SER-003) — arko-privacy-authctrl

3) 2단계 인증 삽입 (SFR-003)

# 개발항목 상태 소스 실측 / 비고
14 SecondFactorInterceptor 신규 등록 ✅ 진짜완료 [2026-07-22 진짜완료 — 코드·로직 재확인. ⚠운영 강제(enforce=true)는 배포 시 별도 활성] [Fork A] cmm/privacy/interceptor/SecondFactorInterceptor.java, authority보다 먼저 등록(#26 순서 반영). /mnt/ 한정 SECOND_FACTOR_DONE 검사. enforce=false(미강제) → #52 화면·#18~20 수단 완료 후 true+resolver 주입 활성화. javac 통과
15 2차 인증 적용대상·경로 판정 로직 ✅ 진짜완료 [2026-07-22 진짜완료 — 코드·로직 재확인] [Fork C] SecondFactorInterceptor 확장 — /mnt/ 취급자 한정, 외부접속 필수(설정불가)/내부접속 정책(applyToInternal, internalIpCidrs CIDR 판정). enforce=false 유지(잠금방지). 중괄호 75/75·xml well-formed
16 세션 재발급 처리(세션고정 차단) ✅ 진짜완료 [2026-07-22 진짜완료 — 코드·로직 재확인] [Fork B] cmm/privacy/security/SessionRegenerator.java. regenerate()=속성캡처→invalidate→getSession(true)→재적재, onSecondFactorSuccess() 표식. javac 통과. #14 SecondFactorInterceptor 연동 시 호출 배선 필요

4) 추가 인증수단 3종 (IAR-001)

# 개발항목 상태 소스 실측 / 비고
17 AuthMethodService 인터페이스 설계 ✅ 진짜 완료 [Fork C] com/uat/uia/service/AuthMethodService.java + 스텁 3종(Otp/Sms/Cert) 생성. issue(uniqId)/verify(uniqId,code)/isAvailable(uniqId) throws Exception 확정. 빈 등록·실로직은 #18~21 후속
18 OtpAuthService 구현 (1차 적용) ✅ 진짜 완료 [Fork C] OtpAuthService+OtpSecretStore/InMemory/OtpSecretCipher(5파일). TOTP RFC6238 자체구현(HmacSHA1/30초/6자리/±1스텝), 비밀키 AES-128/GCM 암호화 저장·미노출. RFC 테스트벡터 일치(287082/081804). 영속화=EMPLYR_OTP_SECRET 테이블 후속(Fork B 소유 sqlmap)
19 SmsAuthService 구현 (2차 적용) ⬜ 미착수 ⚠ KT-TCS/MCSAgent3.0 연동규격 발주기관 확정 필요
20 CertAuthService 구현 (3차 적용- 공인인증서 ?) ✅ 완료 [Fork C] CertAuthService 실구현. 기존 EgovLoginServiceImpl.actionCrtfctLogin(:108)→COMTNEMPLYRINFO.CRTFC_DN_VALUE(EgovLoginUsr_SQL_Mysql.xml:434) 위임, 인증서 본문 미저장·DN 식별값만 대조. 핸드오프: CertProcessFilter(web.xml:46 주석) 재활성 운영협의
21 AuthMethodResolver 구현 ✅ 완료 (?) [Fork C] AuthMethodResolver+AuthMethodType(enum)+AuthMethodPolicyProvider+DefaultAuthMethodPolicyProvider 4종. Map<code,impl> 주입 분기, 폴백 OTP→SMS→CERT, resolve(String) throws Exception(1차 계약 정합). javac 통과. 실동작은 #18~20 구현체·빈등록 후

5) 인증 실패 이력 및 접근통제 정책 (SER-001)

# 개발항목 상태 소스 실측 / 비고
22 인증 실패 이력 활성 경로 이설 ✅ 진짜 완료 [ Fork A] AS-IS: 실패이력/잠금이 EgovSpringSecurityLoginFilter:466(조건부)에만 존재. EgovLoginController.actionLogin 재작성(잠금선확인→성공시 이력정리→실패시 조건부 적재/잠금), 기존 LOGIN_HISTORY/LOGIN_LOCK_COUNT·서비스 7메서드 재사용(신규 statement 0), 전구간 fail-safe. 서비스/VO 메서드 실재 검증
22-1 인증 실패 이력 IP 기록·보관기간·조회화면 ✅ 진짜 완료 AS-IS: LOGIN_HISTORY가 ID/CREATE_DATE/GUBUN 3컬럼뿐 → IP 미기록, 성공 시 당일 이력 DELETE 로 흔적 소멸. DDL CONECT_IP(VARCHAR45)+RESET_YN+인덱스 2종, ACCOUNT_MNG_POLICY.LOGIN_HIST_KEEP_DAY(기본 730). 적재 insertFailHistory 컬럼 명시 전환(★DDL 필수 동반 — 종전 무컬럼 VALUES 는 ERROR 1136)+ClientIpResolver IP 세팅, 성공 시 DELETE→RESET_YN='Y' 소프트 리셋(selectFailCount 가 'N'만 카운트 → 잠금 동작 불변). 화면 /mnt/sec/loginFailHistory/listView.do(계정·구분·IP·기간·리셋여부 검색+페이징), 메뉴 9100039. 배치 purgeExpiredLoginFailHistoryScheduler 매일 03:30, 1회 5,000건 상한
23 계정 열거 방지 처리 ✅ 진짜 완료 [Fork C] EgovLoginController:238 조건부 "현재 N회" 문구 제거→존재/미존재·실패횟수 무관 단일 fail.common.login. 실패이력·잠금은 내부 유지, 응답 노출 제거. 잠금안내만 의도적 예외
24 계정 잠금 정책 정비(10회→5회) ✅ 진짜 완료 [Fork A] 임계값 LOGIN_LOCK_COUNT UPDATE=5 + 소스 fallback DEFAULT_LOCK_THRESHOLD=5. 해제화면 기존확인. 신규 ACCOUNT_UNLOCK_HISTORY(DDL+VO+DAO+sqlmap, sql-map-config 등록)에 해제이력 훅(해제자+ClientIpResolver IP, fail-safe). 사유입력은 화면 후속
25 세션 타임아웃 조정(60→30분) ✅ 진짜 완료 [Fork C] web.xml:218 <session-timeout>30</session-timeout>(60→30) + 근거주석. 실사용 webapp/web.xml 확정. 관리자 설정화면은 후속
26 인터셉터 3단 판정 순서 확정 ✅ 진짜 완료 [Fork C] egov-com-servlet.xml:66 리스트 순서 확정 ①authenticInterceptor(비활성)→②secondFactor→③authority + 근거주석. ①재활성 시 위치 유지 핸드오프. xml well-formed

6) 인증정보 보호 (SER-003)

# 개발항목 상태 소스 실측 / 비고
27 비밀번호 해시 알고리즘 점검 ✅ 진짜 완료 [Fork C] 점검노트 개인정보보호_비밀번호해시_점검노트.md. 알고리즘 SHA-256(기준 충족), 단 운영경로 무솔트·무반복 + BizMberFrtManageController.java:553 해시값 로그출력 3건 보완 권고
28 신규 인증정보 저장정책 적용 ✅ 서버에서 적용해야함 [Fork C→오케스트레이터] 점검노트 개인정보보호_인증정보저장정책_점검노트.md. OTP AES암호화저장(로그노출0)·SMS 미저장설계·CERT DN만 → 3종 준수, 위반 0건. OTP 프로비저닝 URI 화면(#53) 취급 주의 1건, 지금 열쇠가 소스코드 안에 글자 그대로 적혀 있습니다 arko-otp-dev-2026 이렇게요 열쇠를 소스에서 빼서, 서버에만 두는 것
29 2차 인증 화면 개인정보 마스킹 ✅ SMS인증 [Fork C] cmm/privacy/util/MaskingUtil.java. maskPhone(010-***-1234)/maskEmail(ho**@)/maskName(홍동)/범용 mask. null·형식 방어, javac+self-check 통과. #52 화면에서 사용

Ⅲ. 접속 및 처리기록 관리 (Ⅲ-4, SFR-004·DBR-001·SER-002) — arko-privacy-auditlog

7) 접속기록 수집·저장 (SFR-004)

# 개발항목 상태 소스 실측 / 비고
30 PERSONAL_DATA_ACCESS_LOG 신규 테이블 ✅ 진행중 [Fork B] src/script/mysql/ddl/privacy.pdal_create_mysql.sql. 기존 PERSONAL_DATA_DML_HISTORY 실측 승격 + HASH_VAL/PREV_HASH_VAL, PK(LOG_ID,CONECT_DT), 월 RANGE COLUMNS 파티셔닝(접속자ID 검색 인덱스 포함). 파티션 자동증설/파기는 #37 연계
31 AOP pointcut 한정 수집 설계 → 관리자 화면 메뉴 접속기록 ✅ 완료(2026-08-07 방식 전환) [전환] 서비스 impl AOP 수집은 중단하고(context-syslogaop.xml의 <aop:config> 주석 처리), 요청 인터셉터 egovframework.com.cmm.privacy.interceptor.MenuAccessLogInterceptor(신규, egov-com-servlet.xml 등록)가 수집한다. 전환 사유: 서비스는 관리자·프론트 화면이 공유해 호출 화면을 구분할 수 없어, 무인증 프론트 방문이 접속자ID ANONYMOUS·수행업무 "재능나눔 회원관리"로 적재됐다(공개 재능나눔 상세 /frt/biz/talent/bizTalentView.do → selectTalentMber). selectJoinTalentMberList 개별 제외로는 같은 문제가 반복된다 — 공유 서비스 메서드가 그것 하나가 아니다. 새 수집 규칙: ①요청경로가 관리자 화면 접두(/mnt/·/uss/umt/·/sec/·/sym/) ②프레임·include 제외 ③취급자 세션(userSe=USR) 3중 조건. 수행업무=기존 메뉴명(COMTNMENUINFO.MENU_NM), 해석순서 page파라미터(메뉴번호)→경로정확→동일디렉터리 최장공통접두→경로폴백. 처리구분은 .do 파일명 유도(~View=조회 우선, select~=조회 우선 — 21케이스 검증 0불일치). 적재경로(AccessLogQueue→해시체인→PERSONAL_DATA_ACCESS_LOG)·스키마는 불변, DDL 없음. 델타: _workspace/deploy/20260807_1440/DELTA.md
─ 이하 전환 前 이력 ─
[Fork B]
32 업무유형 매핑 테이블 구현 ⚠️ 수집경로에서 미사용(2026-08-07) [전환 영향] #31이 메뉴 기반으로 바뀌어 수행업무가 COMTNMENUINFO.MENU_NM에서 나온다. PDAL_JOB_MAPPING/JobMappingResolver는 수집에 더 이상 관여하지 않는다(테이블·관리화면 #32-1은 기존 적재분 해석·복원 경로 보존용으로 존치). 접속기록 조회화면의 '수행업무' 드롭다운 소스도 이 테이블 → 적재분 DISTINCT(PersonalDataAccessLogDAO.selectJobSeCodeList)로 교체(매핑을 보면 실제 적재값과 어긋나 검색결과가 항상 0건이 된다).
─ 이하 전환 前 이력 ─
[Fork B]
32-1 업무유형 매핑 관리 화면 ✅ 완료 2026-08-07 신설. #32 는 테이블+로더까지라 매핑 행을 DB 직접 INSERT 로만 운영했음 → 화면에서 등록·수정·사용중지·삭제. JobMappingController+JobMappingManageService/Impl+JobMappingSearchVO+DAO CRUD 7개+sqlmap(Mysql/Oracle 쌍, config 등록 불요 — 기존 파일 확장)+site/mnt/sec/jobMapping/{list,regist}.jsp+메뉴 9100045(권한관리 하위 MENU_ORDR 11)+left.jsp 5곳.
저장 즉시 JobMappingResolver.refresh() → WAS 재기동 불요. DB 직접수정 반영용 '캐시 재적재' 버튼 별도.
감사 컬럼 신설(privacy.job_mapping_audit_cols_mysql.sql: REGISTER_ID/REG_DT/UPDUSR_ID/UPDT_DT) — 분류 기준 변경 주체를 남긴다. 기존 13행은 등록자 NULL → 화면에 '시드' 표기.
보안: 상태변경 전 엔드포인트 POST 한정 + Origin/Referer 동일출처 + handlerUser() USR 판정, 서버측 형식·중복(TARGET_CLASS+METHOD_PTTRN) 재검증, 업무명은 JS 인라인 보간 대신 data-*+c:out.
검증: JDK8 mvn -o compile 성공 / DDL·메뉴DML 로컬 3306 적용 + 멱등 재실행 확인 + HEX() 한글 정상 / CRUD SQL 실DB 실행 왕복 확인(13행 원복). 실화면 렌더는 Tomcat 미기동으로 미검증
33 비동기 적재 큐 구현 ✅ 완료 [Fork B] AccessLogQueue(LinkedBlockingQueue cap1만+단일 데몬컨슈머). Aspect가 enqueue만(업무 응답 무영향), 컨슈머가 persistNow 순차→단일 라이터로 해시체인 순번 보장. 백프레셔(offer 5s), @PreDestroy flush 유실방지
34 IP 취득 로직 보정 ✅ 완료 [Fork B] cmm/privacy/auditlog/ClientIpResolver.java. XFF→Proxy/WL-Proxy→HTTP_CLIENT_IP→getRemoteAddr 순 + 신뢰프록시 CIDR 검증(헤더위조 방지) + IPv6 루프백 정규화. javac+단위검증 통과. AS-IS IpObtainInterceptor(getRemoteAddr+인증시만) 격차 확인. 신뢰대역 운영값=#57 후 확정

8) 비정상 접근 탐지 및 처리기록 (SER-002)

# 개발항목 상태 소스 실측 / 비고
35 비정상 접근 탐지 5유형 구현 ✅ 완료 [Fork B] AbnormalAccessType(enum)+Policy+DetectionService/Impl/DAO+VO(6파일). 표준컬럼 집계로 5유형(비인가F/대량조회/업무외시간/동일ID다중IP/실패반복≥5). 임계 정책추상화. sqlmap 5종(Mysql/Oracle). #43 리포트 실집계 교체
36 처리기록 적재 범위 확장 ✅ 완료 [Fork B] pointcut 5→16개 개인정보 취급 서비스(회원/취급자/휴면/신청/활동/그룹/마일리지/프로필/쪽지/SMS 등 명시열거, 조직·통계·게시성 제외). TRGET_ID 식별자만 베스트에포트 추출(getter/Map키 우선순위, String인자 스킵, 본문 미적재, fail-safe). sqlmap 무변경(컬럼 기보유). javac EXIT=0

9) 보관정책 및 위·변조 방지 (DBR-001)

# 개발항목 상태 소스 실측 / 비고
37 보관정책 730일 + 파기 배치 구현 ✅ 완료 [Fork B] AccessLogPartitionDAO+PDAL_PURGE_HISTORY(DDL). INFORMATION_SCHEMA.PARTITIONS 경계≤오늘-730일 파티션 DROP + 당월~+2M ADD 선행증설. BatchScheduler.purgeAccessLogPartitionScheduler()(매월1일 02:00). ⚠파티션명 $ 치환=Java계산값(안전, 리뷰포인트)
38 COMTNSYSLOG 7일 삭제정책 재설계 ✅ 완료 [Fork C] 노트 개인정보보호_시스템로그삭제정책_분리노트.md. 7일 삭제 SQL 위치 EgovSysLog_SQL_Mysql.xml:159(COMTNSYSLOG 단일, Quartz 1H이나 현재 스케줄러 비활성) 실측 확인. 오적용 위험 낮음(테이블 하드코딩+namespace 분리), 분리 보강 5개 권고
39 SHA-256 해시체인 구현 ✅ 완료 [Fork B] cmm/privacy/auditlog/HashChainService.java(+VO). MessageDigest 자체구현, 결합규칙 CONECT_ID|CONECT_DT|CONECT_IP|JOB_SE_CODE|TRGET_ID|DML_GUBUN|PREV_HASH_VAL→SHA-256. computeHash/linkAndSeal/verifyChain, javac+실행 변조탐지 검증. 순번보장=단일스레드 순차INSERT 전제(#33)
40 해시체인 무결성 검증 배치 ✅ 완료 [Fork A] AccessLogIntegrityDAO+PrivacyAccessLogIntegrity_SQL(LOG_ID ASC, CONECT_DT 형식일치) + verifyAccessLogHashChain()→verifyChain. BatchScheduler.verifyAccessLogHashChainScheduler() @Scheduled(매월1일 03:00). 불일치 시 log.error+notifyAdmin(#49 TODO)·리포트(#43) 반환

10) 조회·다운로드 및 정기점검

# 개발항목 상태 소스 실측 / 비고
41 접속기록 조회·검색 화면 개선 ✅ 완료 [Fork B→오케스트레이터] PersonalDataAccessLogSearchDAO/Service/Impl/VO + selectAccessLogList/Count sqlmap(Mysql/Oracle). 접속자ID/업무유형/대상/IP/처리구분/결과/기간 복합+페이징. Fork B 중단→오케스트레이터가 누락 sqlmap 완결(codebase 관용 맞춰 동적WHERE 인라인, XML well-formed). 화면 #47 후속
42 다운로드 사유·이력 관리 ✅ 완료 [Fork B] PDAL_DOWNLOAD_HISTORY(DDL)+VO/DAO+AccessLogDownloadService. 사유 공백 시 IllegalArgumentException 차단 + 다운로드자·일시·IP·사유·건수 이력(본문 미보관, 10만건 상한). sqlmap 3종. #43 리포트 실집계 교체
43 정기점검 리포트 생성 배치 ✅ 완료 [Fork B] PDAL_INSPECTION_REPORT(DDL)+InspectionReportVO/DAO+generateMonthlyInspectionReport()+BatchScheduler(매월1일 05:00). 집계: 총/실패건수·#40무결성(재사용)·취급자별 top20 [구현], 이상징후#35·다운로드#42 [자리표시]. sql-map-config 무수정(기존 sqlmap 확장)
44 점검결과 입력·보관 화면 ✅ 완료 [Fork C] InspectionResultService/Impl/Controller + INSPECT_DT 컬럼 추가 + statement 3종(목록/상세/UPDATE). saveInspectionResult() 결과 미입력 차단·리포트 존재확인·INSPECTOR_ID/INSPECT_RESULT/ACTN_MATTER/INSPECT_DT 갱신(감사증빙, 배치집계값 불변). 화면 #48 후속

Ⅳ. 신규 화면 (디자인.md 연계) — arko-frontend

# 개발항목 구분 상태
45 권한부여 신청/승인 관리 화면 mnt ✅ 완료
46 권한변경 이력 조회 화면 mnt ✅ 완료
47 개인정보 접속기록 조회/다운로드 화면 mnt ✅ 완료
48 접속기록 정기점검 리포트 대시보드 mnt ⬜ 미착수
49 비정상접근 탐지 알림함 화면 mnt ⬜ 미착수
50 인증수단 관리 설정 화면 mnt ⬜ 미착수
51 계정 잠금/휴면계정 관리 확장 화면 mnt ⬜ 미착수
52 2차 인증(추가인증) 입력 화면 frt ⬜ 미착수
53 마이페이지 인증수단 등록/관리 화면 frt ⬜ 미착수
54 계정 잠금 안내 화면 frt ⬜ 미착수

표 갱신 이력

  • 2026-08-06 정정: #45·#46 은 이미 구현·메뉴등록(9100035/9100036)까지 완료된 상태였는데 이 표만 ⬜ 로 뒤처져 있었다. 실측 반영.
  • 2026-08-06 #47 완료: PersonalDataAccessLogController(/mnt/sec/accessLog/listView.do·download.do) + site/mnt/sec/accessLog/list.jsp + 메뉴 9100044(권한관리 하위, MENU_ORDR 10) + left.jsp 분기 4곳. 검색 7조건(접속자ID·업무유형·처리대상·IP·처리구분·처리결과·기간)·페이징·CSV 다운로드(사유 필수 #42 연계, PDAL_DOWNLOAD_HISTORY 적재). 9100040~9100043 은 게시판관리 그룹이 선점하여 미사용 번호 9100044 사용. 로컬 3306 csv 메뉴 등록 + HEX() 한글 검증 완료 / 배포 ROOT 델타 반영 완료. 실화면 렌더는 Tomcat 미기동으로 미검증.
  • 2026-08-07 #32-1 신설·완료: 업무유형 매핑 관리 화면(/mnt/sec/jobMapping/) + 메뉴 9100045(권한관리 하위, MENU_ORDR 11) + left.jsp 5곳. PDAL_JOB_MAPPING 감사 컬럼 4개 추가(privacy.job_mapping_audit_cols_mysql.sql). 저장 시 Resolver 캐시 즉시 무효화(재기동 불요). 신규 sqlMap 파일 없이 기존 PrivacyJobMapping_SQL_Mysql.xml 을 확장했으므로 sql-map-config 등록 변경 불요. 로컬 3306 DDL·메뉴 DML 적용 + 멱등 재실행 + HEX() 한글 검증 완료 / 배포 ROOT 델타는 미반영(매니페스트 _workspace/deploy/20260807_1500/DELTA.md). 실화면 렌더는 Tomcat 미기동으로 미검증.
  • 2026-08-07 대조 확인: privacy.job_mapping_create_mysql.sql 미커밋 변경분은 멱등화 전용(CREATE TABLE IF NOT EXISTS + 시드 NOT EXISTS 가드)이라 스키마·시드 내용이 커밋본과 동일하다 → 로컬 3306 적용본과 불일치 없음. 개발/운영 DB 는 privacy DDL 자체가 미적용 상태.

UI 목업 브리프(스티치 AI 프롬프트 포함)는 디자인.md에 문서화 완료 — 설계 산출물은 준비됨, 코드 구현은 미착수.

Ⅴ. 착수 즉시 확인 필요 사항 — arko-privacy-analyst

# 확인항목 상태 리스크
55 운영 web.xml 필터 매핑 상태 확인 ⬜ 미확인 R1 — 소스/운영 배포본 상이 가능성
56 휴면 배치 운영 로그 확인 ⬜ 미확인 MariaDB statement 부재 실운영 재확인
57 CONECT_IP 적재값 분포 확인 ⬜ 미확인 Apache+L4 이중구성 L4 IP 고정 여부
58 인터셉터 등록부 현재 상태 확인 ⬜ 미확인 등록 순서 재검증

Ⅵ. 보안·품질 점검 (SER-004) — arko-reviewer

# 개발항목 상태 비고
59 시큐어코딩 적용 및 점검 ⬜ 미착수 행안부 기준 · 구현 후
60 웹취약점 점검 ⬜ 미착수 국정원 기준 · 개발 완료 후
61 중점 점검 5종 확인 ⬜ 미착수 인증우회/권한상승/접속기록조작/계정열거/인증정보노출

4. 완료된 선행 작업 (구현 착수 기반)

산출물 위치 상태
요구사항·기술설계 원문 E:\지역문화원\제안서\mds\Ⅲ_사업수행계획.md (Ⅲ-2/3/4) ✅
개발항목 정리(61개) 개인정보보호_개발항목.docx ✅
신규 화면 디자인 브리프(10종) 디자인.md ✅
권한/인증 구현 에이전트 .claude/agents/arko-privacy-authctrl.md ✅
접속기록 구현 에이전트 .claude/agents/arko-privacy-auditlog.md ✅
요구사항 분석 에이전트 .claude/agents/arko-privacy-analyst.md ✅
구현 패턴 스킬(권한/접속/추적/오케스트레이터) .claude/skills/arko-privacy-* ✅
리뷰어 개인정보보호 점검항목 확장 .claude/agents/arko-reviewer.md ✅

5. 권장 착수 순서

  1. Ⅴ. 착수전 확인(55~58) — 운영 환경 실측으로 리스크 R1 등 조기 해소 (구현 전 필수)
  2. Ⅰ-1) 권한관리(1~6) — getAuthorities() 구현이 전체 권한통제의 뿌리 → 최우선
  3. Ⅱ. 인증체계(14~29) — 인터셉터 3단 순서 확정 후 2단계 인증·인증수단 3종
  4. Ⅲ. 접속기록(30~44) — 테이블·AOP·해시체인·배치
  5. Ⅳ. 화면(45~54) — 백엔드 진척에 맞춰 frt/mnt 병행
  6. Ⅵ. 보안·품질(59~61) — 각 기능 완료분 대상 상시 + 최종 웹취약점 점검

6. 발주기관 확정 대기 항목 (블로커)

항목 관련 # 내용
계정 삭제 보존기간 12 취급자/회원 각 보존기간 정책
문자발송모듈 연동 규격 19 KT-TCS / MCSAgent3.0 연동 스펙

본 문서는 개인정보보호_개발항목.docx의 61개 개발항목을 소스 실측(2026-07-21)과 대조해 작성한 진행현황표이다. 코드 구현 진척 시 각 항목의 상태(⬜→🟡→✅)와 소스 실측 열을 갱신한다.