Skip to content
isdnetworks
Go back

모든 테이블의 감사 컬럼 네 개

(수정됨)

인계받은 DLP 고도화 쪽 PostgreSQL 스키마의 모든 테이블에 같은 네 개의 컬럼이 있었다. created_at·created_by·updated_at·updated_by, 즉 등록한 시각과 사람, 수정한 시각과 사람이다.

Table of contents

Open Table of contents

배경 — 쉰여덟 번 반복된 네 줄

같은 네 줄이 테이블 수만큼 반복돼 있으니 schema.sql 이 그만큼 길어진다. 새 테이블을 만들 때마다 그 네 줄을 다시 적어야 하고 적는 것을 잊으면 그 테이블만 빠진다.

반복을 없애는 방법을 찾아보다가 이 문제가 방법 선택의 문제라는 것을 알게 됐다. 어느 방법을 골라도 무언가를 포기하게 된다.

비교 — 반복을 없애는 세 방법

첫째는 DB 쪽에 BEFORE INSERT OR UPDATE 트리거를 걸어서 자동으로 채우는 것이다. PostgreSQL 11 매뉴얼에 따르면 행 단위 BEFORE 트리거가 돌려주는 행이 실제로 들어갈 행이 되므로, updated_at 에 now() 를 채우는 것은 어느 경로로 들어와도 반드시 된다. 대신 그 로직이 코드 밖에 있어서 안 보이고, updated_by 에 넣을 사람이 누구인지는 DB 가 모른다 — current_user 는 접속 계정이지 로그인한 사용자가 아니다.

둘째는 코드 쪽에서 공통 부모 BaseRepository 를 두고 insert()·update() 가 네 값을 채우게 하는 것이다. 코드는 깔끔해지지만 그 계층을 안 거치고 직접 넣는 경로에서는 안 채워진다.

판단 기준 — 방법마다 다른 것을 포기한다

셋째는 지금처럼 그냥 반복해서 적는 것인데 무엇이 어디 있는지가 명시적으로 보인다. 대신 빠뜨려도 아무도 안 알려 준다.

셋 다 완전한 것이 없으므로 무엇을 포기할지를 정하는 문제였다. 우리는 BaseRepository 쪽을 골랐다. 이유는 네 값 가운데 사람 둘은 어차피 앱만 알아서, DB 트리거로는 절반밖에 못 채우기 때문이다. 그 계층을 안 거치는 경로는 따로 목록으로 관리하기로 했다.

검증 — 컬럼과 값의 구분

방법을 고르고 나서 지금 실제로 값이 들어가고 있는지를 집계했다. 컬럼이 있다는 것과 감사가 되고 있다는 것은 다른 말이기 때문이다.

count(*) 와 count(updated_by) 를 나란히 세어 보니 몇 테이블은 updated_by 가 거의 비어 있었다. 비어 있는 것이 아무도 안 건드렸다는 뜻일 수도 있지만 그 경로가 값을 안 채웠다는 뜻일 수도 있었다.

원인 — 배치 경로가 값을 안 채웠다

확인해 보니 후자였고, 밤에 psql 로 도는 갱신 스크립트가 UPDATE … SET status = … 만 하고 updated_by 를 안 채우고 있었다. 컬럼만 보고 감사가 되고 있다고 생각했으면 그 사실을 몰랐을 것이다.

재발 방지 — 빠진 테이블을 찾는 검사

그래서 네 컬럼이 없는 테이블을 information_schema.columns 에서 NOT EXISTS 로 찾는 조회와, 값이 안 채워지는 경로를 찾는 집계를 검사로 두었다. 어느 방법을 택하든 빠진 것을 찾는 장치는 따로 필요했다.

정리


Share this post on:

Previous Post
웹 루트 아래의 업로드 폴더
Next Post
운영에 올린 dev 빌드의 대가