제안요약서 slide 14~15 의 화면 시안을 열어보니 8차 구현과 어긋나 있었다.
시안은 좌측메뉴를 "접속기록·감사" 한 묶음으로 그리고 그 아래 4개를 두며,
이상행위를 별도 화면이 아니라 접속기록 목록의 "감사" 칸에 인라인으로 표시한다.
8차는 이 넷을 권한관리 하위에 낱개로 붙여 놓았다 — 기능은 같은데 배치가 달랐다.
· 메뉴 재편 — "접속기록 · 감사"(9100052) 그룹 신설
① 접속기록 조회(9100044) ② 개인정보 처리기록(9100053, 신설)
③ 이상행위 감사(9100049) ④ 정기 점검 리포트(9100048)
파기이력(9100050)은 시안에 메뉴가 없어 내렸다. 화면은 그대로 두고
정기 점검 리포트에서 버튼으로 연다(양방향 링크). 기능을 지운 게 아니라
노출 위치만 시안에 맞춘 것이다.
그룹 메뉴의 PROGRM_FILE_NM 은 NOT NULL 이고 기존 그룹이 모두 센티넬 'dir'
을 쓴다 — NULL 로 넣었다가 ERROR 1048 로 실패한 뒤 형제 행을 실측해 정정.
· 접속기록 조회 화면에 "감사" 칸 신설
이상(처리결과 F=차단·비인가)은 붉게, 점검(정상이나 대량조회·계정공유의심·
인증실패반복 대상 또는 업무시간 밖)은 노랗게 표시하고 해당 행을 강조한다.
요약 줄도 시안대로 "검색결과 N건 · 보관기간 730일 · 이상행위 N건 탐지".
판정값(auditFlag)은 저장하지 않는다 — 탐지 임계치는 정책값이라 적재해 두면
임계치를 조정한 뒤에도 과거 기준으로 굳은 값이 남는다.
감사 표시는 집계 5회라 기간 미지정 시 최근 30일로 잘라 계산하고,
실패해도 목록은 그대로 보여준다(PSR-001).
· ② 개인정보 처리기록 — 조회(S)를 뺀 등록·수정·삭제만
화면·검색조건은 ①과 공유하고 excludeSelect 조건 하나만 다르다.
같은 표를 두 벌 관리하지 않으려는 선택이다.
검증: mvn compile EXIT=0, JSP 4종 Jasper 오류 0건, 로컬 ROOT 반영 후 재기동
정상(25.4초), 신규 processLog 포함 5개 엔드포인트 302→로그인 / 대조군 404,
통합본 privacy.install_mysql.sql PART3 [8] 병합 후 전체 재실행 오류 0건(멱등).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
개인정보보호 기능개선 8차 — 관리자 화면 4종 신설
제안서·RFP 대비 화면이 없어 증빙을 낼 수 없던 항목을 채운다.
· 정기점검 리포트(SFR-004-7 #48)
InspectionResultController 가 JSON 엔드포인트만 갖고 있어 점검결과를
화면으로 입력·보관할 수 없었다. listView/saveResultView 를 추가하고
기존 JSON 계약은 그대로 병존시킨다. 배치 집계값은 화면에서 수정하지
않는다 — 감사 증빙이라 사후 변경되면 안 된다.
· 비정상접근 탐지(과업내용 다-① #49)
탐지 5유형 로직은 있었으나 호출처가 배치뿐이었다. AbnormalAccessResultVO
에 의심 대상 행(rows)을 실어 "누가 걸렸는지"를 요약 문자열 파싱 없이
보여주고, 각 항목에서 접속기록 화면으로 조건을 넘겨 원본을 확인한다.
탐지 결과를 적재하지 않는 이유는 컨트롤러 Javadoc 참조(임계치 변경 시
과거 기준이 굳는 문제).
· 접속기록 파기이력(SER-002-2 / DBR-001-2)
PDAL_PURGE_HISTORY 는 쌓이고 있었으나 볼 수 있는 곳이 없었다.
"보관기간 경과분을 규정대로 파기했고 그 외 경로로는 손대지 않았다"를
함께 입증하는 증빙이라 조회 전용으로만 연다.
· 회원정보 암호화 관리 CRUD(추가제안 Action4 / 제안서 슬라이드16)
복호화 조회·수정·파기·신규등록 + 사유 입력 + 재인증(10분 TTL).
목록은 항상 마스킹하고 평문은 사유를 남긴 상세 한 건에서만 보인다 —
목록에서 평문이 뜨면 사유를 받는 의미가 없다.
파기는 행을 지우지 않고 식별 항목만 비운다(신청·활동 기록이 참조 중).
MBER_CRYPTO_ACCESS_HISTORY 에 처리자·일시·IP·사유·변경항목명을 남기되
개인정보 본문은 담지 않는다.
재인증에 로그인 2차인증을 재사용하지 않은 이유는 MberCryptoReauth
Javadoc 참조(세션 내내 유지돼 재확인이 안 되고, OTP 미등록자가 잠긴다).
검증: JDK8 mvn compile EXIT=0, JSP 9종 Jasper 사전컴파일 오류 0건,
로컬 ROOT 반영 후 Tomcat 재기동 정상(신규 sqlMap 4건 기동시 파싱 통과),
신규 엔드포인트 6개 302→로그인 / 대조군 404 / frt/main.do 200.
DB: MBER_CRYPTO_ACCESS_HISTORY DDL + 메뉴 9100048~9100051
(privacy.install_mysql.sql PART1·PART3 에도 병합, 재실행 안전)
후속 발견: 기존 탈퇴 구문 mberManageDAO.updateDeleteMber_S 는 개인정보를
비우면서도 이름(MBER_NM/ENC/HASH)은 지우지 않는다 — 파기 누락 소지.
신설 화면의 파기는 이름까지 파기한다. 기존 경로 보정은 별도 판단 필요.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@
관리자 메뉴 9100045(업무유형 매핑 관리)·9100046(로그인 접속기록) 두 화면을
폐기하고 관련 5계층·sqlMap·JSP를 제거했다. 접속기록은 PERSONAL_DATA_ACCESS_LOG
경로로 일원화한다.
- JobMapping 5계층(Controller/DAO/Service/Impl/Resolver/SearchVO)과
ConectLog 5계층, PersonalDataLogAspect 제거
- PrivacyJobMapping_SQL_{Mysql,Oracle}.xml 제거 + sql-map-config 등록 라인 삭제
- left.jsp의 9100045/9100046 분기와 상위 하이라이트 조건 제거
- 메뉴 폐기 DML 신설(권한매핑→메뉴→프로그램 순, 멱등) — 종전 등록 DML 2건 대체.
JSP와 반드시 동반 배포해야 URL 직접 접근 경로가 남지 않는다
- privacy.install_mysql.sql에 PART 4(뷰 GNR 컷오버) 반영, 메뉴 번호 갱신
- MemberNmCryptoController 신설 — 회원 이름 암호화 백필 트리거
- SessionPolicyInterceptor에 stampLogin/clearLoginStamp 추가
(EgovLoginController가 참조 — 이게 없으면 컴파일되지 않는다)
- pom: mysql-connector를 5.1.17로 고정(8.0.20 비활성화). 배포 환경의
WEB-INF/lib 실측값과 일치시켜 WAR 배포 시 드라이버가 바뀌는 지뢰를 제거
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
미사용계정 현황(#11, 메뉴 9100037)이 대상이 개인정보취급자(EMP) 계정임을
화면·메뉴명에서 알 수 없어 오해 소지가 있었다. "장기 미사용 계정" →
"장기 미사용 관리자 계정"으로 명시(요약표/목록 캡션, 메뉴명, 프로그램 설명).
이미 배포된 환경을 위해 재실행 안전한 UPDATE 문을 DML에 추가.
목록 행별 "말소"/"잠금" 버튼은 시각적으로 과도하게 커서 축소(.btn3.mini).
상단 "선택 말소" 일괄 버튼은 그대로 둠.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
5개 세션에 걸쳐 쌓인 미커밋 변경분을 한 번에 정리한다. 주 산출물은 이번 세션의
접근통제 정책 적용(SER-001 요건 4·5)이고, 나머지는 앞선 세션들의 백로그다.
■ 접근통제 정책 적용 (SER-001 요건 4·5, 이번 세션)
「개인정보보호강화 파일럿 개발항목」 접근통제 정책 적용(Action2) 시안 반영.
- ACCESS_CONTROL_POLICY(단일행) + 관리자 화면 신규 (메뉴 9100047)
· 계정 잠금: 인증 실패 임계값(10 -> 5), 잠금 해제 방식(관리자화면+이력 / +사유필수)
· 자동 로그아웃: 미사용 시간(60 -> 30분), 만료 임박 안내 사용여부·시점
· 세션 재발급: 2차 인증 성공 시 세션 고정(Session Fixation) 차단 여부
- SessionPolicyInterceptor 신규 — /mnt/ 요청마다 정책값으로 세션 타임아웃 적용.
web.xml 재배포 없이 값이 바뀐다(2025.9 자료요청 3번 "시간 설정 기능 없음" 해소).
web.xml <session-timeout>30 은 이제 폴백값이다.
- 잠금 임계값 저장 시 인증 경로가 읽는 LOGIN_LOCK_COUNT 를 함께 동기화.
정책 테이블만 고치면 화면 숫자만 바뀌고 실제 인증은 옛 값을 계속 쓰기 때문이다.
- 관리자 상단(top.jsp): 로그인 후 경과시간 + 자동 로그아웃 잔여 카운트다운,
만료 임박 안내와 연장(/mnt/session/extend.do).
세션 상태를 주기 폴링하지 않는다 — 그 요청 자체가 세션을 갱신해
'미사용 자동 로그아웃'이 영원히 오지 않기 때문이다.
- 자동 로그아웃 시 로그인 화면 이동: actionLogout.do?expired=Y 로 세션 invalidate 후
로그인 화면 + 사유 안내. 수동 로그아웃(프론트 메인 이동)은 기존 동작 유지.
- 계정잠금관리: 정책이 '사유 필수'면 해제 사유 강제, ACCOUNT_UNLOCK_HISTORY 적재.
■ EgovLoginLogAspect fail-safe (회귀 수정)
접속기록 적재 예외가 @Before 어드바이스 밖으로 나가 로그인·로그아웃이 통째로 500 이
되고 있었다(로컬: MySQL 8 + mysql-connector 5.1.17 의 tx_isolation 조회 실패).
클래스 Javadoc 이 이미 fail-safe 를 명세하고 있었으나 구현이 따르지 않았다.
try/catch 로 인증 흐름을 살리되, 접속기록 유실은 SFR-004 직결이라 ERROR 로 남긴다.
■ 앞선 세션 백로그
- 접속기록(SFR-004): 조회·CSV 비동기 다운로드(PDAL_DOWNLOAD_JOB), 업무유형 매핑
- 로그인 접속기록(#62): COMTNLOGINLOG 접속IP·접속ID 유실 복구 + 접속위치 스냅샷
- 권한관리(SFR-001): 권한변경 이력 CSV 비동기 다운로드, 신청·승인 워크플로 화면 정리
- 미사용계정(SFR-002): 현황 화면 시안 반영(요약·역할·잠금/말소·조치 이력)
- 회원정보 암호화(추가제안 Action4): AES 암복호화·검색용 해시, 이관 배치와 사전 백업
■ 커밋 제외
font/(글꼴 설치본 22M), 제안서 문서(pptx/hwp), .claude/(하네스) 는 소스가 아니라 제외.
.claude/ 버전관리 여부는 별도 판단이 필요하다.
배포 산출물: _workspace/deploy/20260810_1300/ (DELTA.md, sql/, APPLY_LOG.md)
브라우저 검증(2단계 인증 필요)은 APPLY_LOG.md B1~B7 로 남겨둔다.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
접속기록(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>
#22(실패이력 활성 경로 이설)로 적재는 살아났으나 LOGIN_HISTORY가
ID/CREATE_DATE/GUBUN 3컬럼뿐이라 (1) 접속 IP 미기록 (2) 로그인 성공 시
당일 이력 DELETE로 무차별 대입 흔적 소멸 문제가 있었다.
- DDL: LOGIN_HISTORY에 CONECT_IP(45)/RESET_YN + 인덱스 2종,
ACCOUNT_MNG_POLICY.LOGIN_HIST_KEEP_DAY(기본 730일) 추가
- 적재: insertFailHistory 컬럼 명시 전환 + ClientIpResolver IP 세팅
(종전 무컬럼 VALUES(3값)은 컬럼 추가 시 ERROR 1136 — DDL과 한 쌍)
- 보존: 성공 시 DELETE -> RESET_YN='Y' 소프트 리셋.
selectFailCount가 RESET_YN='N'만 세므로 계정잠금 동작은 종전과 동일
- 화면: /mnt/sec/loginFailHistory/listView.do (계정·구분·IP·기간·리셋여부
검색 + 페이징), 메뉴 9100039 + left.jsp 분기
- 정책화면: 계정 관리 정책에 보관기간 입력 항목·검증 추가
- 배치: purgeExpiredLoginFailHistoryScheduler 매일 03:30, 1회 5,000건 상한
- Mysql/Oracle sqlmap 쌍 + sql-map-config 등록
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>