현재 수량이 7개라는 사실만으로는 왜 6개에서 바뀌었는지 알 수 없다. 기록을 남기려면 언제 누구의 어떤 판단으로 변화가 생겼는지 다시 읽을 수 있어야 한다.

기존 글에서는 발송 당시 문서를 보존하는 이야기를 다뤘다. 이번에는 새 SQLite 실험에서 문서 변화와 사건 기록을 함께 저장하고, 그 이력이 설명할 수 있는 범위까지 살펴본다.

현재 문서를 과거의 설명으로 쓰지 않았다

현재 값은 다음 업무를 처리할 때 필요하다. 변경 이력은 그 값이 만들어진 과정을 설명한다. 둘을 같은 행으로 취급하면 문서를 고칠 때 과거의 이유까지 덮어쓸 수 있다. 나는 문서 테이블과 사건 테이블을 분리하고 각 성공한 전환에서 변경 전후의 합성 상태를 별도로 기록했다. 두 기록이 맡는 질문이 다르기 때문이다.

사건에는 문서 식별자, 회사 범위, 수행자, 행동과 사유가 들어간다. 변경 전후에는 저장 버전과 내용 버전도 남는다. 승인 대기로 바뀐 사건과 수량 자체를 고친 사건을 구별할 수 있다. 시간 문자열만 보고 순서를 추측하지 않도록 로컬 DB의 사건 순서 번호로 읽는다. 다른 시스템과의 전체 시간 순서를 보장하는 번호는 아니다.

차이를 보여 주는 것과 이유를 남기는 것

6개가 7개로 바뀌었다는 비교는 어떤 값이 달라졌는지 알려 준다. 고객의 요청 때문인지 입력 정정 때문인지는 비교만으로 알 수 없다. 그래서 이번 명령은 비어 있지 않은 짧은 사유를 받도록 했다. 실제 사용자 이름이나 업무 내용 대신 고정 합성 사유로 시험했지만, 값의 차이와 판단의 이유를 구분한 구조는 코드에서 확인할 수 있다.

실무 화면에서는 모든 내부 필드를 그대로 비교표에 펼칠 필요가 없다. 담당자가 이해할 이름과 단위를 붙이고, 자신이 볼 수 있는 필드만 보여 줘야 한다. 변경 사유에도 회사의 민감한 내용을 무제한으로 쓰게 해서는 안 된다. 기록의 목적과 접근 범위에 맞는 입력 정책이 추가로 필요하며 이번 패키지는 실제 고객의 변경 사유를 담지 않는다.

성공한 변경과 실패한 시도를 섞지 않았다

버전 충돌로 거절된 요청은 문서를 고치지 않았으므로 성공한 업무 사건으로 넣지 않는다. 같은 요청을 다시 받아 이전 결과를 돌려주는 경우에도 사건을 새로 만들지 않는다. 이 기준이 없으면 여러 번 누른 버튼이 여러 번 바뀐 문서처럼 보일 수 있다. 업무 변화의 이력과 요청 시도의 운영 기록은 목적에 맞게 나눠야 한다.

거절이나 실패를 전혀 기록하지 말자는 뜻은 아니다. 서버의 오류·요청 추적은 별도 정책으로 남길 수 있다. 다만 그 기록을 매출이나 승인 같은 업무 완료 사건으로 세지 않아야 한다. 이번 실험에서는 성공한 전환만 events에 들어가며, 거절 결과와 원본 보존은 테스트로 대조한다. 운영 로그 전체를 구현한 것은 아니다.

문서가 바뀌고 기록만 빠지는 순간을 막았다

문서 저장을 끝낸 뒤 별도 함수에서 이력을 넣으면 두 번째 작업이 실패할 수 있다. 반대로 이력만 먼저 남기고 문서 저장이 실패해도 실제와 다른 기록이 된다. 이번 코드는 한 SQLite 트랜잭션 안에서 문서 갱신과 사건 추가를 수행한다. 후속 대기 기록과 성공 요청 결과도 같은 경계에 포함했다.

중간에 강제로 오류를 발생시키는 검사에서 문서 버전은 처음 그대로였고 사건·요청 결과·대기 기록도 남지 않았다. 이는 로컬 합성 DB에서 확인한 원자성의 근거다. 모든 외부 시스템에 같은 보장이 생긴 것은 아니며, DB 관리자가 직접 기록을 수정하지 못한다는 변조 방지 보장도 아니다. API가 이력을 덧붙이는 방식과 증거의 신뢰 수준을 구별해 둔다.

다시 읽을 사람이 판단을 이어갈 수 있도록

직원은 자기 담당 자료의 이력만, 담당자와 대표는 같은 회사의 범위에서 읽도록 예시를 제한했다. 다른 회사의 사건을 조회하지 않는지도 검사했다. 실제 서비스에서는 서버가 확인한 사용자와 권한을 사용해야 하며, 합성 Actor 값을 외부 요청에서 그대로 받아서는 안 된다. 화면의 이력 탭만 숨기는 것으로 끝낼 수 없는 부분이다.

공유 패키지의 기록 뷰어에서 제출 전후와 승인 전후의 사건을 펼쳐 볼 수 있다. 실제 로컬 실행에서 생성한 자료이며 고객의 장부가 아니다. 회사에 적용할 때는 보관 기간, 민감한 필드, 사유 정책과 감사 주체를 더 정해야 한다. 나는 이력이 있다는 표시보다 어떤 변화가 어떤 근거로 남았는지를 설명하는 쪽을 제작 기록의 중심에 두었다.