[DB] Trigger

[verify$y]·2025년 8월 1일

CS핵심개념

목록 보기
14/35

트리거

트리거란?

설명

  • 테이블에 대한 이벤트에 반응해 자동으로 실행되는 작업(SQL 블록, 프로시저)을 의미한다.
  • 사용자가 직접 실행시키는 것이 아니라, 이벤트 기반(Event-driven)으로 동작한다.
  • 데이터베이스에서 데이터작업(특정 이벤트)가 발생한 경우 추가로 실행시키고자 하는 쿼리작업을 자동으로 수행되도록하는 것을 말한다.
  • 이떄 자동으로 실행되도록 트리거를 설정한다.

간단한 예시 : 계정정지, 복구 프로세스

어떤 클라이언트가 서비스 탈퇴를 신청하였다. 내부에서는 회원테이블에서 해당하는 계정을 삭제한다. 만약 일정 기간 이후 클라이언트가 서비스를 사용해야할 일이 생겨 계정을 다시 사용코자 가입을 하려는데 이미 가입된 이력이 있는 회원정보인 것이다. 이때 새로 생성이 아닌 계정복구를 한다.

  • 삭제와 등시에 자동으로 삭제회원테이블에 삭제된레코드에 대한 데이터를 입력저장한다.
  • 이때 사용되는것이 트리거이다.
  • 또는, 회원계정복구를 전 클라이언트가 요청했다면? 삭제된레코드를 회원테이블에 다시 등록해야한다. 복구 이벤트를 트리거로 회원데이터 입력 데이터 작업하는 sql을 자동으로 수행한다.



왜 트리거가 필요할까?

서비스에서는 단순히 회원 데이터를 저장하면 안된다. 복구도 가능하게 설계해야한다.

예를 들어 어떤 사용자가 서비스 탈퇴를 요청했다면, 회원 테이블에서 해당 사용자의 정보를 삭제하는 SQL을 실행하게 됩니다.

하지만 현실적으로는 이 사용자의 정보를 완전히 삭제해버리면 안된다. 왜냐하면

  • 향후 재가입 시 과거 기록이 필요할 수 있고,
  • 법적/운영상 보관해야 할 데이터일 수도 있으며,
  • 복구 요청이 들어올 수 있기 때문입니다.

이처럼 데이터 변경 이벤트가 발생할 때, 자동으로 필요한 작업을 수행해주는 것이 바로 트리거(Trigger)




트리거 예시 : 회원 탈퇴 → 삭제 이력 저장 → 복구 처리

1. 사용자가 탈퇴 요청

  • 사용자가 “회원 탈퇴”를 요청하면,
  • 서버에서는 member 테이블에서 해당 사용자의 정보를 DELETE

2. 트리거가 자동으로 작동

  • DELETE 문이 실행되는 순간, DB에 설정된 트리거가 자동 발동
  • 트리거는 삭제되는 데이터를 잡아내서, 그 정보를 member_deleted 테이블에 자동으로 저장
AFTER DELETE ON member

3. 결과

  • 이 과정을 통해 운영자는 사용자의 탈퇴 이력을 안전하게 보존

4. 사용자가 재가입하려 할 때

  • 시간이 지나 사용자가 다시 서비스에 가입하려고 시도합니다.
  • 그런데 가입하려는 이메일이 과거에 사용되었고, 아직 삭제 이력에 남아있는 경우…단순 회원 생성으로는 UNIQUE 제약 오류 발생 가능
  • 이때는 ‘신규 가입’이 아니라 ‘계정 복구’로 처리하는 것이 적절하다.



트리거 사용

  • 적용 시점
    • BEFORE(실행 전), AFTER(실행 후).
  • 단위(Level)
    • MySQL 에서는 FOR EACH ROW 행 단위 처리만 지원
    • PostgreSQL/Oracle/SQL Server:
      • 행 단위(FOR EACH ROW)
      • 문 단위(FOR EACH STATEMENT) 모두 지원
  • 각 SQL 작업별로 접근되는 변수(정해져있다)
    • NEW은 새로 입력되는 값, OLD는 기존 값
    • BEFORE/AFTER INSERT: NEW.*
    • BEFORE/AFTER UPDATE: OLD., NEW.
    • AFTER DELETE: OLD.*
  • 주의
    • TRUNCATE는 트리거가 실행되지 않음(대부분의 DBMS). 트랜잭션 제어문(명시적 COMMIT/ROLLBACK)은 트리거 내부에서 금지되는 경우가 많음.



Trigger설정

1. 테이블 설계

CREATE TABLE member (
  id CHAR(36) PRIMARY KEY,
  email VARCHAR(255) UNIQUE,
  name VARCHAR(100),
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE member_deleted (
  id CHAR(36),
  email VARCHAR(255),
  name VARCHAR(100),
  deleted_at DATETIME,
  original_created_at DATETIME,
  PRIMARY KEY (id, deleted_at)
);

2. 트리거 생성 (SQL)

  • 이제부터는 "Delete from member…”실행 시 트리거가 자동으로 삭제이력을 남기게된다.
  • 사용자는 탈퇴요청을 하고 데이터베이스에서는 삭제기록을 자동으로 관리한다.
DELIMITER $$

CREATE TRIGGER trg_member_after_delete
AFTER DELETE ON member
FOR EACH ROW
BEGIN
  INSERT INTO member_deleted (
    id, email, name, deleted_at, original_created_at
  )
  VALUES (
    OLD.id, OLD.email, OLD.name, NOW(), OLD.created_at
  );
END$$

DELIMITER ;



주의사항

  • TRUNCATE 명령어는 트리거를 발생시키지 않음 (대부분의 DBMS에서 적용 안 됨)

    • TRUNCATE는 DELETE와 달리 DDL(데이터 정의어)에 가까운 고속 테이블 초기화 명령입니다.
    • DBMS에서는 TRUNCATE를 내부적으로 DELETE가 아닌 페이지 단위의 빠른 삭제 방식으로 처리하며,
      트리거가 행을 기준으로 작동하기 때문에 연결않음
  • 트리거 내부에서는 명시적 트랜잭션 제어 불가

    • COMMIT, ROLLBACK 사용 금지 (에러 발생 가능)
    • 트리거는 상위 트랜잭션의 일부로 작동하므로 만약트리거 내부에서 트랜잭션을 명시적으로 커밋하거나 롤백하면, 상위 트랜잭션 흐름을 깨뜨린다.
  • 트리거 내부에서 부작용이 큰 로직 (예: 외부 API 호출, 복잡한 쿼리 반복 등)은 지양해야 함

    • 트리거는 자동 실행되므로, 로직이 복잡할수록 예상치 못한 성능 저하나 무한 루프, 데드락 등의 문제가 발생 가능
    • 외부 API작업을 따로 처리해야한다.
profile
welcome

0개의 댓글