핵심 인사이트 (3줄 요약)

  1. 본질: 스토어드 프로시저 (Stored Procedure)는 SQL (Structured Query Language)과 제어 로직을 데이터베이스 서버 안에 저장해 호출 단위를 모듈화하는 방식이고, 트리거 (Trigger)는 데이터 변경 이벤트에 반응해 자동 실행되는 데이터 근접형 자동화 장치다.
  2. 가치: 애플리케이션과 데이터베이스 사이 왕복 호출을 줄이고, 공통 검증·감사·권한 통제를 데이터 가까이에 고정해 트랜잭션 일관성과 재사용성을 높일 수 있다.
  3. 판단 포인트: 여러 시스템이 공통으로 따라야 하는 규칙이나 감사 기록에는 강하지만, 숨은 부작용·벤더 종속성·디버깅 난이도가 커지므로 핵심 비즈니스 흐름을 무조건 DB 안으로 밀어 넣는 선택은 피해야 한다.

Ⅰ. 개요 및 필요성

스토어드 프로시저는 데이터베이스 관리 시스템 (Database Management System, DBMS) 내부에 저장된 절차형 프로그램이고, 트리거는 INSERT, UPDATE, DELETE 같은 데이터 조작 언어 (Data Manipulation Language, DML) 이벤트에 묶여 자동 실행되는 특수한 프로그램이다. 둘 다 "데이터에 가장 가까운 위치에서 규칙을 실행한다"는 공통점이 있지만, 프로시저는 개발자나 애플리케이션이 명시적으로 호출하고 트리거는 데이터 변경이 발생할 때 데이터베이스가 스스로 발동한다는 점에서 성격이 다르다.

이 개념이 필요해진 이유는 같은 검증과 갱신 로직이 여러 애플리케이션에 중복되면 정합성이 쉽게 깨지기 때문이다. 예를 들어 계좌 이체, 재고 차감, 주문 상태 변경 같은 작업은 단일 SQL 한 줄로 끝나지 않고 검증, 다중 테이블 갱신, 이력 기록, 예외 처리까지 묶여야 한다. 이 로직을 응용 프로그램마다 따로 구현하면 누락과 버전 불일치가 생기기 쉽고, 네트워크 왕복도 늘어나 트랜잭션 경계가 흐려진다.

특히 트리거는 "개발자가 호출하지 않아도 반드시 실행되어야 하는 규칙"을 강제할 때 의미가 크다. 감사 로그 기록, 변경 이력 적재, 파생 컬럼 보정, 간단한 무결성 보조 로직은 애플리케이션 실수에 맡기기보다 데이터 변경 시점에 자동으로 실행하는 편이 더 안전할 수 있다. 다만 자동 실행이라는 장점은 곧 숨은 실행 경로라는 단점이 되므로, 필요성과 복잡도 균형이 중요하다.

  • 📢 섹션 요약 비유: 스토어드 프로시저는 은행 창구 직원에게 "이체, 수수료 계산, 영수증 출력까지 한 번에 처리해 주세요"라고 맡기는 업무 묶음이고, 트리거는 금고 문이 열리면 CCTV가 자동으로 녹화를 시작하는 안전장치와 같다.

Ⅱ. 아키텍처 및 핵심 원리

스토어드 프로시저의 핵심은 호출 인터페이스와 실행 위치를 분리하는 데 있다. 애플리케이션은 CALL transfer_funds(...)처럼 비교적 짧은 명령만 보내고, 실제 내부에서는 매개변수 검증, 여러 SQL 실행, 예외 처리, COMMIT 또는 ROLLBACK 판단이 데이터베이스 내부에서 이어진다. 이 구조는 SQL 파싱과 실행 계획 재사용, 네트워크 왕복 감소, 권한 캡슐화 측면에서 이점을 준다.

트리거는 여기에 이벤트 기반 실행이라는 축을 더한다. BEFORE 트리거는 데이터가 기록되기 전에 값 검증이나 보정에 쓰이고, AFTER 트리거는 이력 테이블 적재나 감사 로그에 자주 쓰인다. 뷰에 대한 INSTEAD OF 트리거는 직접 갱신이 어려운 논리 뷰를 갱신 가능하게 만드는 데 활용된다. 또한 행 단위 (Row-level) 트리거는 변경된 각 행마다 실행되고, 문장 단위 (Statement-level) 트리거는 SQL 문장 1회마다 실행되어 성능 특성과 부작용 범위가 다르다.

아래 그림은 프로시저와 트리거가 데이터 가까이에서 어떻게 다른 방식으로 개입하는지 보여 준다.

┌────────────────────────────────────────────────────────────────────┐
│ DB-side program flow                                               │
├────────────────────────────────────────────────────────────────────┤
│ Application -> CALL proc_transfer(10000)                           │
│                 │                                                  │
│                 ▼                                                  │
│            Stored Procedure                                        │
│            ├─ validate account / balance                           │
│            ├─ update source and target rows                        │
│            ├─ insert ledger history                                │
│            └─ COMMIT or ROLLBACK                                   │
│                                                                    │
│ INSERT / UPDATE / DELETE on table                                  │
│                 │                                                  │
│                 ▼                                                  │
│            Trigger                                                 │
│            ├─ BEFORE : normalize / reject bad data                 │
│            └─ AFTER  : audit log / derived update                  │
└────────────────────────────────────────────────────────────────────┘
구분스토어드 프로시저트리거
실행 방식명시적 호출이벤트 발생 시 자동 실행
주 용도다중 SQL 절차, 권한 캡슐화, 배치 처리감사, 자동 검증, 이력 적재
트랜잭션 관계호출자가 명시적으로 경계 설정 가능원본 DML 트랜잭션에 종속
가시성호출 코드에서 비교적 명확실행 경로가 숨겨지기 쉬움
성능 포인트왕복 감소, 계획 재사용과도하면 DML 지연과 연쇄 실행 발생
위험 요소벤더 종속, 로직 비대화숨은 부작용, 재귀 트리거, 디버깅 난이도

핵심 원리는 결국 "로직을 데이터 가까이에 둘수록 일관성은 올라가지만 가시성은 떨어진다"는 트레이드오프다. 따라서 프로시저는 명시적 업무 단위, 트리거는 자동화가 꼭 필요한 최소 규칙에 쓰는 식으로 역할을 분리해야 구조가 건강해진다.

  • 📢 섹션 요약 비유: 프로시저는 주문서를 받아 주방 안에서 코스 요리를 한 번에 완성하는 셰프의 작업표이고, 트리거는 오븐 문이 열리면 자동으로 환풍기가 켜지는 센서다. 둘 다 주방 안에 있지만, 하나는 요청형이고 다른 하나는 반응형이다.

Ⅲ. 비교 및 연결

스토어드 프로시저와 트리거를 제대로 이해하려면 사용자 정의 함수 (User Defined Function, UDF), 제약조건, 애플리케이션 서비스 로직과의 경계를 함께 봐야 한다. 프로시저는 부작용을 수반하는 절차형 작업에 적합하고, UDF는 보통 계산 결과를 반환하는 표현식 수준 재사용에 더 가깝다. 트리거는 자동 실행이 강점이지만, 같은 목적을 체크 제약조건 (Check Constraint)이나 외래 키 (Foreign Key)로 더 단순하게 표현할 수 있다면 그쪽이 우선이다.

비교 축스토어드 프로시저트리거UDF / 제약조건 / 앱 로직
호출 주체앱 또는 운영자DB 이벤트SQL 식, 스키마 정의, 앱 코드
적합한 역할업무 절차 묶음자동 반응 규칙계산, 단순 무결성, 복잡한 도메인 흐름
부작용 허용높음높음UDF는 보통 제한적, 제약조건은 선언적
추적 용이성비교적 높음낮음앱 로직은 코드 추적 용이
이식성DB 언어 의존DB 언어 의존앱 로직이 가장 높고, 제약조건은 표준 친화적

실무적으로는 "무엇을 DB가 반드시 지켜야 하는가"를 기준으로 선을 긋는 것이 좋다. 예를 들어 금액 음수 입력 금지, 감사 이력 누락 방지, 특정 상태 전이 금지처럼 데이터 자체의 진실성을 직접 보장해야 하는 규칙은 DB 내부에 둘 근거가 있다. 반면 승인 프로세스, 외부 API 호출, 메시지 발행, 복잡한 화면별 예외 분기처럼 시스템 맥락을 많이 타는 업무는 애플리케이션 서비스 계층이 더 적합하다.

또한 최근에는 데이터 변경 캡처 (Change Data Capture, CDC)나 이벤트 스트리밍이 보급되면서, 과거에 트리거로 해결하던 일부 후처리를 더 느슨하게 분리하기도 한다. 즉 트리거는 만능 자동화가 아니라, 선언적 제약으로 부족하고 외부 이벤트 파이프라인으로 넘기기엔 너무 데이터 근접성이 중요한 영역에 쓰는 도구로 기억해야 한다.

  • 📢 섹션 요약 비유: 집 안 규칙 중 문이 닫히면 자동으로 불이 꺼지는 것은 센서가 잘하고, 가족 여행 계획처럼 사정에 따라 바뀌는 일은 사람이 직접 상의해야 한다. 트리거와 앱 로직의 경계도 바로 그 차이다.

Ⅳ. 실무 적용 및 기술사 판단

실무에서 스토어드 프로시저는 다수의 SQL을 하나의 트랜잭션 업무 단위로 묶어야 할 때 특히 강하다. 예를 들어 월말 정산, 포인트 차감과 적립, 계좌 이체, 대량 배치 정제처럼 여러 테이블을 묶어 같은 데이터베이스 안에서 빠르게 처리해야 한다면 프로시저가 명확한 이점을 준다. 실행 권한만 주고 테이블 직접 권한은 막는 방식도 보안상 자주 활용된다.

트리거는 더 보수적으로 써야 한다. 감사 테이블 적재, updated_at 자동 갱신, 단순 파생값 계산처럼 "누가 개발하든 절대 빠지면 안 되는 공통 후처리"에는 적합하지만, 메일 발송, 원격 HTTP 호출, 다단계 비즈니스 워크플로를 트리거에 넣으면 장애 전파 경로가 보이지 않게 된다. 특히 대량 DML에서 행 단위 트리거가 비싼 연산을 하면 성능 저하가 급격히 나타난다.

기술사 판단 체크리스트

  1. 이 규칙은 여러 애플리케이션이 공유해야 하는 데이터 근접형 규칙인가?
  2. 여러 SQL을 하나의 원자적 절차로 묶는 편이 네트워크 왕복과 정합성 측면에서 유리한가?
  3. 트리거가 없어도 제약조건, 기본값, 생성 열, CDC 등 더 단순한 대안이 가능한가?
  4. 장애 분석 시 실행 경로와 성능 비용을 관찰할 수 있는 모니터링 체계가 있는가?
  5. DB 벤더 변경이나 클라우드 이전 시 재작성 비용을 감당할 수 있는가?

자주 나오는 안티패턴

  • 프로시저 안에서 집합 처리보다 반복문 중심으로 작성해 SQL 엔진 장점을 버리는 경우
  • 트리거 안에서 외부 시스템 호출이나 긴 배치 로직을 실행하는 경우
  • 같은 검증 로직을 앱과 트리거 양쪽에 중복 구현해 책임 경계를 흐리는 경우
  • 연쇄 트리거와 재귀 실행을 통제하지 않아 장애 추적이 어려워지는 경우

결론적으로 기술사 답안에서는 "프로시저는 절차 캡슐화, 트리거는 이벤트 강제"라는 구분을 먼저 세우고, 성능·가시성·이식성의 대가를 함께 설명해야 설계 판단이 선다.

  • 📢 섹션 요약 비유: 금고 비밀번호 확인은 금고 문 자체가 해 주는 편이 안전하지만, 금고가 열릴 때마다 사무실 전체 방송이 울리게 만들면 일은 편해도 소란이 커진다. 트리거도 꼭 필요한 자동화만 남겨야 한다.

Ⅴ. 기대효과 및 결론

스토어드 프로시저와 트리거를 적절히 쓰면 데이터베이스는 단순 저장소를 넘어 정책 집행 지점이 된다. 공통 로직 재사용, 트랜잭션 일관성, 감사 추적, 권한 최소화 측면에서 분명한 효과가 있고, 특히 데이터에 가장 가까운 규칙은 누락 없이 강제할 수 있다. 이는 여러 애플리케이션이 같은 데이터 자산을 공유하는 조직에서 큰 운영 안정성으로 이어진다.

하지만 이 장점은 로직 비대화와 DB 집중이라는 부작용을 동반한다. 프로시저가 서비스 계층을 대체하기 시작하면 DB 서버가 연산 병목이 되고, 트리거가 많아질수록 변경 영향 범위와 디버깅 비용이 커진다. 또한 오라클 PL/SQL, PostgreSQL PL/pgSQL 같은 벤더별 문법 차이는 장기적인 이식성 리스크가 된다.

따라서 이 주제는 "DB 안에 로직을 넣을 것인가"라는 흑백 문제가 아니라, 데이터에 붙어 있어야 하는 최소 규칙을 어디까지 맡길 것인가의 문제로 기억하는 것이 정확하다. 프로시저는 명시적 업무 단위, 트리거는 최소 자동화 장치라는 원칙을 지키면 가장 효과적이다.

  • 📢 섹션 요약 비유: 은행 금고 안에는 꼭 필요한 자동 잠금장치와 입출금 절차만 두는 것이 좋다. 안내 방송, 마케팅 행사, 외부 전화 연결까지 다 금고 안에 넣으면 금고는 안전해도 은행 전체가 답답해진다.

📌 관련 개념 맵

개념연결 포인트
트랜잭션 (Transaction)프로시저는 여러 SQL을 하나의 원자적 업무 단위로 묶는 대표 수단이다.
사용자 정의 함수 (User Defined Function, UDF)프로시저와 달리 계산 결과 반환 중심이며, 자동 실행 트리거와도 역할이 다르다.
제약조건 (Constraint)단순 무결성은 트리거보다 제약조건이 더 선언적이고 추적 가능하다.
감사 로그 (Audit Log)트리거가 자주 담당하는 대표 후처리 영역이다.
권한 캡슐화테이블 직접 권한 대신 프로시저 실행 권한만 부여하는 보안 설계와 연결된다.
CDC (Change Data Capture)트리거가 맡던 일부 후속 전달 역할을 외부 이벤트 파이프라인으로 분리하는 대안이다.

📈 관련 키워드 및 발전 흐름도

반복 SQL과 공통 규칙 증가
        │
        ▼
스토어드 프로시저 (Stored Procedure)
        │
        ├──────────────► 트랜잭션 절차 묶음
        ├──────────────► 권한 캡슐화
        ▼
트리거 (Trigger)
        │
        ├──────────────► BEFORE / AFTER 자동화
        ├──────────────► 감사 로그 · 무결성 보조
        ▼
CDC · 이벤트 기반 후처리 분리

이 흐름은 데이터 근접 로직이 재사용에서 자동화로 확장되고, 이후에는 더 느슨한 이벤트 기반 구조와 역할을 나누는 방향으로 성숙해 간다는 점을 보여 준다.

👶 어린이를 위한 3줄 비유 설명

  1. 스토어드 프로시저는 은행 아저씨에게 "이 일들을 한 번에 처리해 주세요"라고 맡기는 묶음 심부름이에요.
  2. 트리거는 문이 열리면 자동으로 불이 켜지는 센서처럼, 어떤 일이 생기면 저절로 움직이는 장치예요.
  3. 그래서 꼭 빠지면 안 되는 규칙은 DB 가까이에 둘 수 있지만, 너무 많은 일을 몰아넣으면 어디서 무슨 일이 일어나는지 보기 어려워져요.