개발 slecs

비밀번호 정책·출금 정지 변경 이력 관리자 화면에 추가

목차

history 영역에 비밀번호 정책 변경 이력과 출금 정지 변경 이력을 적재하는 기능을 추가했다. P0로 분류된 작업이라 다른 걸 밀고 먼저 처리했고, 변경 파일은 내부 클래스 2개, SQL 매퍼 2개, 뷰/스타일 2개다. 숫자만 보면 작아 보이는데 실제로는 쿼리 설계부터 화면 연동까지 전 레이어를 건드린 작업이었다.

왜 이력 적재가 P0인가

금융·결제 도메인에서 변경 이력이 없다는 건 감사 추적(audit trail)이 없다는 말이다. 비밀번호 정책이나 출금 정지 상태는 사용자 자금과 직결되기 때문에, "언제 누가 바꿨는가"를 재현할 수 없으면 분쟁이 생겼을 때 아무것도 증명할 수 없다. 기능 자체가 없었던 게 아니라 이력 적재가 빠진 채로 동작만 하고 있던 상태였는데, 그 공백이 운영 리스크로 쌓이고 있었다.

이런 류의 작업이 미뤄지는 이유는 대체로 비슷하다. 당장 눈에 안 보이고, 기능이 "되긴" 하니까. 근데 진짜 문제는 이력이 없으면 장애 대응 속도가 떨어진다는 거다. "출금 정지가 언제 풀렸지?"라는 질문이 나왔을 때 DB를 뒤져야 하거나, 심하면 답을 못 하게 된다.

구현: 어떻게 설계했나

핵심 설계 결정은 세 가지였다.

변경 전후 값을 모두 저장한다. before_valueafter_value를 함께 적재하지 않으면 이력의 가치가 반으로 줄어든다. "변경됐다"는 사실만 알고 "어떻게 변했는지"를 모르면 결국 추가 쿼리를 짜거나 다른 테이블을 뒤져야 한다. 처음부터 같이 넣는 게 맞다.

액터와 시각은 서버 사이드에서 찍는다. 클라이언트에서 넘어온 값을 신뢰하지 않는다. actor_id는 세션에서, changed_at은 서버 타임스탬프로. 이건 감사 로그에서 기본 중의 기본인데 놓치는 경우가 생각보다 많다.

트랜잭션 안에 묶는다. 정책 변경과 이력 INSERT가 별개의 트랜잭션이면 정책은 바뀌었는데 이력이 안 남는 상황이 발생할 수 있다. 둘 다 성공하거나 둘 다 롤백되어야 한다.

SQL 매퍼 쪽은 대략 이런 구조로 작성했다.

INSERT INTO admin_change_history (
    target_type,
    target_id,
    before_value,
    after_value,
    actor_id,
    changed_at
) VALUES (
    #{targetType},
    #{targetId},
    #{beforeValue},
    #{afterValue},
    #{actorId},
    NOW()
)

조회 쪽도 단순 SELECT가 아니라, 정책 타입별로 필터링하고 시간 범위를 줄 수 있게 만들었다. 관리자 화면에서 "이 사용자의 출금 정지 이력만 보고 싶다"는 요구가 반드시 나올 거라서 처음부터 조건절을 열어뒀다.

내부 클래스는 서비스 레이어에서 이력 적재를 담당하는 로직을 분리했다. 기존 정책 변경 로직에 인라인으로 박아 넣으면 나중에 테스트하기도, 다른 타입 이력을 추가하기도 어려워지기 때문이다. 별도 클래스로 빼두면 HistoryWriter.record(type, before, after, actor) 같은 형태로 재사용 가능하다.

검증하면서 체크한 것들

구현 후 직접 화면에서 동작을 확인했는데, 체크 포인트를 정리하면 아래와 같다.

확인 항목 방법
이력이 실제로 쌓이는지 정책 변경 후 DB 직접 조회
before/after 값이 정확한지 변경 전 값 메모 후 이력과 대조
기존 데이터 정합성 관련 화면 숫자 cross-check
권한 없는 접근 차단 일반 사용자 세션으로 API 호출 시도
NULL 처리 초기 상태(before 없음) 케이스 시나리오

NULL 처리가 생각보다 신경 쓰이는 부분이었다. 기존에 정책을 한 번도 명시적으로 설정하지 않은 사용자는 before_value가 없다. 이걸 NULL로 넣을지, 기본값 문자열로 넣을지 결정해야 했는데, NULL로 두면 조회 쿼리에서 처리가 번거로워질 수 있어서 기본값 표기를 명시적으로 남기는 쪽으로 정리했다.


사내 서비스를 만들다 보면 기능 하나가 단순히 화면에 버튼 하나 추가하는 것으로 끝나지 않는다는 걸 계속 체감한다. SQL 집계, 상태 변경, 예외 처리, 화면 렌더링, 권한 체크가 다 엮여 있어서 어느 하나만 빠뜨려도 숫자가 안 맞거나 특정 사용자에게 이상한 화면이 나타난다.

특히 금융 도메인은 숫자 하나, 이력 하나가 틀리면 신뢰가 무너질 수 있어서 꼼꼼함이 기본값이어야 한다. "대충 맞는 것 같다"로 넘어가면 나중에 반드시 다시 돌아온다. 이번 작업도 감사 이력이 없는 채로 계속 운영됐다면 언젠가 훨씬 큰 비용으로 다시 만나게 됐을 거다. 미뤄진 기술 부채는 이자를 붙여서 돌아온다는 걸 이 도메인에서 일하면서 계속 확인 중이다.

댓글 0

첫 댓글 달아줘.