감사 로그에 변경 전후 내용 캡처
목차
감사(Audit) 기능에 before/after JSON 캡처를 붙이면서, 조회 화면 UX도 함께 손봤다.
왜 이 작업이 필요했나
compliance 쪽 감사 로그는 이미 "누가 언제 어떤 메뉴를 건드렸다"는 이벤트 자체는 기록하고 있었다. 근데 실제 운영에서 감사 목적으로 로그를 들여다보면 결국 "그래서 뭐가 바뀐 건데?"가 항상 물음표로 남는 상황이었다. 변경 이벤트만 있고 변경 내용이 없으면 감사 로그는 사실상 반쪽짜리다.
회원 관련 처리, 파트너 관련 처리를 담당하는 관리자 web 레이어 클래스가 각각 이번 작업에 포함됐다. 두 도메인 모두 관리자가 직접 수정하는 흐름이 있고, 그 수정 시점에 before 상태와 after 상태를 JSON으로 직렬화해서 감사 레코드에 함께 저장하는 구조를 추가했다.
작업 내용 요약
크게 두 가지 축으로 나뉜다.
① before/after JSON 캡처 로직 추가
수정 요청이 들어오는 시점에, 처리 전 DB 조회 결과를 beforeJson으로, 처리 후 결과를 afterJson으로 직렬화해서 감사 테이블에 함께 쌓는 방식이다. 패턴 자체는 단순하지만 신경 쓸 포인트가 몇 가지 있다.
// 수정 전 상태 캡처
Object before = service.selectById(targetId);
String beforeJson = objectMapper.writeValueAsString(before);
// 실제 수정 처리
service.update(param);
// 수정 후 상태 캡처
Object after = service.selectById(targetId);
String afterJson = objectMapper.writeValueAsString(after);
// 감사 로그 저장
auditLog.setBeforeJson(beforeJson);
auditLog.setAfterJson(afterJson);
auditService.insertAuditLog(auditLog);
여기서 주의할 점은 예외 발생 시 감사 로그 처리 정책이다. 수정이 실패했을 때 감사 로그까지 같이 롤백할 것인가, 아니면 시도 자체를 기록으로 남길 것인가는 compliance 정책에 따라 다르게 가져가야 한다. 이번 케이스에서는 트랜잭션 범위를 명확히 해서 수정 성공 시에만 감사 레코드가 커밋되도록 처리했다.
또 한 가지 — VO에 민감 필드(비밀번호류, 마스킹 대상 등)가 섞여 있을 경우 그대로 JSON 직렬화하면 안 된다. 직렬화 대상에서 제외하거나, 마스킹 처리 후 저장하는 방향을 잡는 게 맞다.
② detail.jsp 조회 row UX 개선
detail.jsp는 감사 로그 상세 조회 화면이다. before/after JSON이 생겼다 해도 화면에서 그걸 읽기 편하게 보여주지 않으면 실효성이 없다. 기존에는 JSON raw 문자열을 그냥 뿌리는 수준이었던 걸, 행(row) 단위로 키-값을 비교해서 보여주는 방식으로 개선했다.
| 항목 | Before | After |
|---|---|---|
| 상태값 | ACTIVE |
SUSPENDED |
| 변경 일시 | — | 2026-05-07 10:23:11 |
이런 식으로 운영자가 눈으로 바로 뭐가 바뀌었는지 확인할 수 있게 했다. 감사 화면은 결국 실제로 들여다보는 사람이 편해야 의미가 있다.
회고
감사 로그는 "나중에 문제 생기면 보겠지"라는 마인드로 붙이다 보면 정작 필요할 때 쓸모없는 로그가 쌓여있는 경우가 많다. 이번처럼 before/after를 같이 남기는 방식이 사실 처음부터 설계에 들어갔어야 하는데, 뒤늦게 추가하다 보니 두 도메인(회원, 파트너) 각각의 web 클래스를 따로 손봐야 했다. 공통 AOP 혹은 인터셉터 레벨에서 캡처를 추상화했다면 나중에 세 번째, 네 번째 도메인이 추가될 때 훨씬 덜 고생했을 것이다.
코드리뷰 때도 이 부분을 팀 내에서 짚었다. 당장은 범위가 두 도메인이라 괜찮지만, 확장 가능성을 고려해서 next step으로 공통 감사 추상화 레이어를 검토해보자는 방향으로 의견을 모았다. 기능을 먼저 돌리고, 구조 개선은 다음 스프린트에 태우는 흔한 트레이드오프지만 — 이번엔 그 다음 스프린트를 진짜 잡아두기로 했다.
compliance 관련 기능은 "일단 돌아가면 됐다"가 제일 위험한 마인드다. 끝.
댓글 0
첫 댓글 달아줘.