Files
llm-wiki/raw/company-tech-blogs/vlad-mihalcea-postgresql-audit-logging-triggers.md
T

7.2 KiB

title, source_type, url, archive_url, related_branches, related_projects, tags, created
title source_type url archive_url related_branches related_projects tags created
PostgreSQL Audit Logging Using Triggers — Vlad Mihalcea company-tech-blog https://vladmihalcea.com/postgresql-audit-logging-triggers/
feature-persistence-auditing-contract
company-tech-blog
ca-tmpl
persistence
postgresql
audit-logging
2026-06-10

PostgreSQL Audit Logging Using Triggers — Vlad Mihalcea

Layer: raw/company-tech-blogs/ — 외부 기술 블로그의 원문 발췌·출처 기록. 검증된 요약은 /ingestwiki/concepts/ 에 별도 작성. 원본은 raw 에 영구 보관.

Parent / 활용 branch (필수)

Branch 이 자료가 정당화하는 결정
raw/branch-notes/feature-persistence-auditing-contract DB-level trigger auditing (standalone) 대안 기각: 애플리케이션 액터 ID 를 트리거로 넘기려면 매 DML 직전 SET LOCAL var.logged_user 세션 변수 주입 seam 이 필요하고, DB 타임소스가 앱 Clock bean 과 분리되어 감사 시각 통제권을 잃는다.

출처 / Source

왜 저장했는지 / Why archived

PostgreSQL 트리거 기반 감사 로깅 구현 시 애플리케이션이 매 DML 전에 세션 변수(var.logged_user)를 직접 주입해야 한다는 사실을 원문 인용으로 확보하기 위해 보관. 이 seam 의 존재가 "DB-level trigger 단독 사용" 대안을 기각하는 근거가 된다.

핵심 인용 / Key quotes (verbatim, 5문장)

[§ trigger function] "the dml_created_by column is set to the value of the var.logged_user PostgreSQL session variable, which was previously set by the application with the currently logged user"

[§ trigger function / SQL] current_setting('var.logged_user')

[§ SET LOCAL / connection pooling] "Notice that we used SET LOCAL as we want the variable to be removed after the current transaction is committed or rolled back. This is especially useful when using connection pooling."

[§ trigger definition] "In order for the book_audit_trigger_func function to be executed after a book table record is inserted, updated or deleted, we have to define the following trigger:"

[§ introduction] "In this article, we are going to see how we can implement an audit logging mechanism using PostgreSQL database triggers to store the CDC (Change Data Capture) records."

Claims Extracted / 추출된 주장

이 자료가 직접 말하는 것만 claim 으로 분리한다. 내 프로젝트에 적용한 결론은 여기 쓰지 않는다.

Claim ID Claim (이 자료가 직접 말하는 것) Evidence quote Strength Applies to Does not prove
C1 트리거가 감사 행위자를 식별하려면 세션 변수 var.logged_user 를 읽고, 그 값은 애플리케이션이 미리 설정해야 한다 [§ trigger function] "the dml_created_by column is set to the value of the var.logged_user PostgreSQL session variable, which was previously set by the application with the currently logged user" engineering-blog PostgreSQL AFTER 트리거가 DML 마다 실행되는 모든 환경 애플리케이션이 변수를 설정하지 않았을 때 트리거가 어떻게 동작하는지(에러/null) 는 이 글 단독으로 증명 안 됨
C2 트리거 함수 내부에서 current_setting('var.logged_user') 호출로 사용자 값을 읽는다 [§ trigger function / SQL] current_setting('var.logged_user') engineering-blog PostgreSQL PL/pgSQL 트리거 함수 current_setting 의 두 번째 인자(missing_ok) 동작은 이 코드만으로 확정 불가
C3 SET LOCAL 을 사용하면 트랜잭션 커밋/롤백 후 변수가 자동 소멸하며, 이는 커넥션 풀 환경에서 특히 유용하다 [§ SET LOCAL / connection pooling] "Notice that we used SET LOCAL as we want the variable to be removed after the current transaction is committed or rolled back. This is especially useful when using connection pooling." engineering-blog HikariCP 등 커넥션 풀을 사용하는 모든 Spring 앱 SET LOCAL 이 실제로 커넥션 풀 재사용 시 변수를 100% 소멸시킴을 PostgreSQL 공식 문서 수준으로 보증하지 않음 — 추가 확인 필요
C4 트리거는 AFTER INSERT OR UPDATE OR DELETE 로 정의된다(AFTER 트리거) [§ trigger definition] "In order for the book_audit_trigger_func function to be executed after a book table record is inserted, updated or deleted, we have to define the following trigger:" engineering-blog PostgreSQL 감사 로그 트리거 정의 BEFORE 트리거와의 trade-off 를 이 글이 명시적으로 비교하지 않음
C5 이 패턴은 PostgreSQL 트리거 + JSON 컬럼으로 CDC 레코드를 저장하는 감사 로깅 구현이다 [§ introduction] "In this article, we are going to see how we can implement an audit logging mechanism using PostgreSQL database triggers to store the CDC (Change Data Capture) records." engineering-blog PostgreSQL 트리거 기반 감사 로깅 구현 이 패턴이 JPA/Hibernate 감사(@EntityListeners) 나 Envers 보다 우월하다는 주장은 이 글 단독으로 증명 안 됨

Usage Boundaries / 적용 경계

  • 이 자료가 직접 증명하는 것:
    • C1, C2: 트리거가 직접 current_setting('var.logged_user') 를 읽고, 그 값은 애플리케이션이 매 DML 전 SET LOCAL 로 주입해야 한다 — 즉 애플리케이션-DB 간 세션 변수 propagation seam 이 불가피하다
    • C3: SET LOCAL 스코프는 트랜잭션 경계와 동기화되므로 커넥션 풀 환경에서 변수 누출을 방지한다 (단, engineering-blog 등급이므로 official 보증 아님)
    • C4: AFTER 트리거가 사용됨
  • 이 자료가 증명하지 않는 것:
    • JPA @EntityListeners / Spring Data Auditing / Hibernate Envers 와의 전면 비교
    • current_setting 이 변수 미설정 시 null 반환인지 예외 발생인지 (PostgreSQL 공식 문서 별도 확인 필요)
    • 이 패턴이 ca-tmpl 실제 HikariCP 설정 하에서 변수 누출 없이 동작함
  • 내 프로젝트에 적용하려면 추가 확인이 필요한 것:
    • PostgreSQL 공식 문서에서 current_setting(name, missing_ok) 동작 확인
    • ca-tmpl 의 HikariCP + SET LOCAL 조합에서 커넥션 반납 후 변수 완전 소멸 여부 로컬 검증

메모 / Notes

  • 이 글은 개인 전문가 블로그(engineering-blog) 등급이다. C3 의 SET LOCAL + 커넥션 풀 안전성은 공식 PostgreSQL 문서로 보강하기 전까지 needs-confirmation 취급.
  • 추가로 봐야 할 동일 출처: vladmihalcea.com/the-anatomy-of-connection-pooling/ (C3 보강 가능성)
  • Hibernate Envers, Debezium 대안이 언급되나 비교 상세는 이 글 범위 밖.