데이타베이스/PostgreSQL

PostgreSQL의 핵심: 트리거와 규칙으로 데이터베이스를 완벽하게 제어하기

shimdh 2025. 10. 29. 09:05
728x90

PostgreSQL을 사용해 데이터베이스를 관리하거나 애플리케이션을 개발하는 분이라면, 데이터 무결성을 유지하고 작업을 자동화하며 성능을 최적화하는 데 트리거(Trigger)와 규칙(Rule)이 필수적이라는 사실을 알고 계실 겁니다. 이 두 기능은 단순한 데이터 저장을 넘어 데이터베이스가 비즈니스 로직에 따라 '능동적으로' 반응하도록 만들어줍니다. 이 글에서는 트리거와 규칙의 기본 개념부터 실전 예시, 그리고 언제 어떤 것을 선택할지까지 자세히 알아보겠습니다. 초보자부터 DBA까지 유용한 팁을 가득 담았으니, 끝까지 읽어보세요!

트리거: 데이터 이벤트에 대한 자동 응답 시스템

트리거는 데이터베이스 이벤트(INSERT, UPDATE, DELETE)가 발생할 때 자동으로 실행되는 '특수 함수'입니다. 마치 방아쇠를 당기면 총알이 발사되듯, 데이터 변경이 감지되면 미리 정의된 동작이 즉시 수행되죠. 트리거는 데이터 무결성을 강화하고, 반복적인 작업을 자동화하는 데 핵심 역할을 합니다. 특히 복잡한 비즈니스 규칙을 애플리케이션 코드가 아닌 데이터베이스 레벨에서 처리할 수 있어, 유지보수성을 높여줍니다.

트리거의 작동 방식

트리거는 이벤트 발생 시점에 따라 두 가지 유형으로 나뉩니다:

  • BEFORE 트리거: 이벤트가 실제로 발생하기 전에 실행됩니다. 데이터 검증이나 수정에 최적화되어 있어요. 예를 들어, 삽입 전에 값이 유효한지 확인하거나, 기본값을 자동 설정할 수 있습니다. 만약 조건이 맞지 않으면 작업을 취소(RAISE EXCEPTION)할 수도 있죠.

  • AFTER 트리거: 이벤트가 이후에 실행됩니다. 변경 후 추가 작업, 예를 들어 감사 로그 기록이나 캐시 업데이트에 적합합니다. 여러 테이블 간 연동이 필요할 때도 유용해요.

트리거는 테이블 단위로 정의되며, FOR EACH ROW 옵션으로 각 행에 대해 개별 실행할 수 있습니다. (전체 테이블에 대한 FOR EACH STATEMENT도 가능하지만, 행별 처리가 더 일반적입니다.)

트리거의 실제 예시: 이메일 변경 이력 추적

사용자 테이블(users)에서 이메일이 변경될 때마다 email_log 테이블에 자동으로 기록하는 기능을 구현해보죠. 이는 감사(Audit)나 규정 준수(Compliance)를 위해 필수적인 기능입니다.

  1. 테이블 생성:

    CREATE TABLE users (
        id SERIAL PRIMARY KEY,
        name VARCHAR(100),
        email VARCHAR(100) UNIQUE  -- 이메일 중복 방지
    );
    
    CREATE TABLE email_log (
        log_id SERIAL PRIMARY KEY,
        user_id INT REFERENCES users(id),
        old_email VARCHAR(100),
        new_email VARCHAR(100),
        changed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    );
  2. 트리거 함수 생성:
    PL/pgSQL 언어를 사용해 함수를 만듭니다. OLDNEW는 트리거에서 제공되는 특수 변수로, 변경 전후 값을 참조합니다.

    CREATE OR REPLACE FUNCTION log_email_change()
    RETURNS TRIGGER AS $$
    BEGIN
        -- 이메일이 실제로 변경된 경우에만 로그 기록
        IF OLD.email IS DISTINCT FROM NEW.email THEN
            INSERT INTO email_log(user_id, old_email, new_email)
            VALUES (NEW.id, OLD.email, NEW.email);
        END IF;
    
        RETURN NEW;  -- 변경된 행을 반환하여 업데이트 완료
    END;
    $$ LANGUAGE plpgsql;
  3. 트리거 연결:

    CREATE TRIGGER after_email_update
    AFTER UPDATE OF email ON users
    FOR EACH ROW EXECUTE FUNCTION log_email_change();

이제 UPDATE users SET email = 'new@example.com' WHERE id = 1;을 실행하면, email_log에 자동으로 이력이 쌓입니다. 만약 이메일이 변경되지 않았다면 로그가 생기지 않아 효율적이에요. 이처럼 트리거는 데이터 흐름을 투명하게 추적할 수 있게 해줍니다.

규칙 (Rule): 쿼리 재작성을 통한 유연한 제어

규칙은 쿼리가 테이블에 도달하기 전에 쿼리를 재작성하거나 대체하는 기능입니다. 트리거가 '이벤트 후 응답'이라면, 규칙은 '쿼리 입력 단계'에서 개입하죠. 이는 뷰(View)를 통해 복잡한 쿼리를 간소화하거나, 애플리케이션 코드를 건드리지 않고 동작을 변경할 때 강력합니다. 규칙은 CREATE RULE로 정의되며, DO INSTEADDO ALSO로 원래 쿼리를 대체/추가할 수 있어요. 다만, 규칙은 트리거만큼 직관적이지 않아 최근에는 뷰와 트리거 조합이 더 추천되기도 합니다.

규칙의 실제 예시: 뷰를 통한 활성 사용자 관리

users 테이블에서 활성 사용자만 필터링하는 active_users 뷰를 만들고, 이 뷰를 통해 데이터를 삽입/업데이트할 때 is_active를 자동으로 TRUE로 설정하는 시나리오입니다. 뷰를 '쓰기 가능'하게 만드는 데 유용해요.

  1. 기본 테이블 및 뷰 생성:

    CREATE TABLE users (
        id SERIAL PRIMARY KEY,
        name VARCHAR(100),
        is_active BOOLEAN DEFAULT TRUE
    );
    
    CREATE VIEW active_users AS
    SELECT * FROM users WHERE is_active = TRUE;
  2. 규칙 생성:
    삽입 규칙: 뷰에 INSERT하면 실제 테이블에 is_active = TRUE로 삽입.

    CREATE RULE active_users_insert AS
    ON INSERT TO active_users
    DO INSTEAD
    INSERT INTO users (name, is_active)
    VALUES (NEW.name, TRUE);  -- is_active를 명시적으로 TRUE로 설정

    업데이트 규칙: 뷰 업데이트 시 활성 상태 유지.

    CREATE RULE active_users_update AS
    ON UPDATE TO active_users
    DO INSTEAD
    UPDATE users SET name = NEW.name WHERE id = OLD.id AND is_active = TRUE;

이제 INSERT INTO active_users (name) VALUES ('John Doe');를 실행하면, users 테이블에 is_active = TRUE로 데이터가 들어갑니다. 애플리케이션이 뷰만 사용하도록 하면, 코드 변경 없이 활성 사용자만 다루는 인터페이스를 제공할 수 있어요. (주의: 규칙은 쿼리 재작성으로 인해 디버깅이 까다로울 수 있으니, 테스트를 철저히 하세요!)

트리거와 규칙: 언제 무엇을 사용할까?

트리거와 규칙은 PostgreSQL의 고급 기능으로, 상호 보완적입니다. 아래 표로 비교해보죠:

기능 주요 용도 장점 단점 추천 시나리오
트리거 이벤트(DML) 후 자동 응답 세밀한 행별 제어, PL/pgSQL 지원 성능 오버헤드 가능 로깅, 검증, 캐시 업데이트
규칙 쿼리 재작성 (뷰/테이블) 코드 변경 없이 쿼리 수정 복잡성 높음, 디버깅 어려움 뷰를 통한 쓰기 지원, 쿼리 라우팅
  • 트리거 선택 시: 복잡한 비즈니스 로직(예: 다중 테이블 업데이트, 조건 검증)이 필요할 때. 데이터 무결성을 데이터베이스에서 강제합니다.
  • 규칙 선택 시: 쿼리 수준의 추상화(예: 뷰 접근 제어)가 필요할 때. 레거시 시스템 호환성에도 좋습니다.

이 두 도구를 적절히 활용하면, 애플리케이션과 데이터베이스의 결합이 더 견고해집니다. 실제 프로젝트에서 트리거로 80%의 자동화를, 규칙으로 나머지 20%의 유연성을 커버하세요!

마무리: PostgreSQL의 힘을 느껴보세요

트리거와 규칙은 PostgreSQL이 '오픈소스 RDBMS의 왕'으로 불리는 이유를 보여줍니다. 이 기능들을 마스터하면 데이터베이스 관리가 한층 수월해질 거예요. 실제로 적용해보고, pgAdmin이나 psql에서 테스트하며 익히세요.

728x90