레코드 트리거형 자동화

Salesforce Platform은 복잡한 비즈니스 프로세스의 요구를 충족하기 위해 자동화 아키텍처를 지속적으로 향상했습니다. 이전 세대(워크플로 규칙 및 프로세스 빌더)는 이벤트 중심 논리의 초기 단계를 제공하여 이벤트 중심 논리의 자동화 기능을 확장하고 더 광범위한 빌더에게 도달 범위를 확대했습니다.

이러한 발전은 다음의 두 가지 보완적인 기둥에 중점을 둔 고성능 통합 아키텍처로 끝났습니다. 레코드 트리거 플로우 및 Apex 트리거.

이 문서에서는 트리거 자동화를 설계할 때 정보에 근거한 결정을 내릴 수 있는 프레임워크 및 지침을 제공합니다. Salesforce 레코드 변경 사항으로 인해 트리거되는 올바른 자동화 접근 방식을 선택하도록 안내하는 세 가지 주요 결정 지점에 대한 사용 사례 요구 사항의 균형을 맞춥니다.

플로 Salesforce Flow는 강력한 포인트 앤 클릭 자동화 도구로 사용자가 코드를 작성하지 않고 Flow Builder를 사용하여 복잡한 비즈니스 프로세스, 화면 및 논리를 시각적으로 구축할 수 있습니다. 데이터 업데이트, 이메일 보내기, 사용자 안내와 같은 과업을 자동화하여 화면 플로(사용자 상호 작용) 및 트리거 플로(레코드/예약 이벤트)와 같은 유연성을 제공합니다.
Apex Salesforce Apex는 Java와 유사한 Salesforce 플랫폼의 독점적이고 개체 지향 프로그래밍 언어로, 사용자 지정 비즈니스 논리를 구축하고 프로세스를 자동화하며 선언적 도구를 넘어 핵심 CRM 기능을 확장합니다.

Salesforce Platform에서 확장 가능하고 유지보수가 용이하며 고성능의 레코드 트리거형 자동화를 구축하려면 체계적이고 아키텍처 중심의 접근 방식이 필요합니다. Flow와 Apex 사이의 선택과 각각의 구현은 명확한 원칙 집합에 따라 결정됩니다. 이러한 사항은 이러한 원칙을 요약하고 현대 자동화 설계의 기본 규칙 역할을 합니다.

  • Salesforce 개체 자동화 밀도에 따라 작업에 적합한 도구를 선택합니다.

    • Salesforce 개체에 대한 레코드 트리거형 플로를 사용하여 저밀도 자동화를 수행합니다.

    • 중간 밀도 자동화의 경우, 호출 가능한 Apex로 레코드 트리거형 플로 논리를 보완합니다.

    • Salesforce 개체에 대한 Apex 트리거를 사용하여 고밀도 자동화를 수행합니다.

  • 비동기 프로세스를 트리거할 때 주의하십시오.
    이 규칙은 레코드 트리거 플로에서 비동기 프로세스를 호출하거나 Apex에서 큐어블 작업을 큐에 추가하는 경우에 적용됩니다. 이 패턴은 작업을 오프로드하는 데 유혹적일 수 있지만, 복잡한 오류 처리 시나리오를 초래하고 거버너 제한에 도달할 위험을 높일 수 있습니다.

  • Salesforce 개체당 하나의 입력 지점을 사용합니다.
    지정된 Salesforce 개체의 경우 한 메커니즘을 자동화의 진입점으로 사용합니다. 동일한 개체에 대한 입력 지점으로 Flow 및 Apex 트리거를 혼합하지 마십시오.

고려해야 할 세 가지 주요 결정 사항이 있습니다.

  • 선언적 및 프로그래밍 방식 구현 비교
  • 자동화 밀도
  • 밀도 선택 매트릭스

플로와 Apex는 공통의 기본 기능 집합을 공유합니다. 각 도구는 레코드를 쿼리하고, 조건부 논리를 실행하고, 변수를 할당하며, 레코드 생성, 업데이트, 삭제와 같은 DML 작업을 지정된 순서대로 수행할 수 있습니다.

그러나 이 기능적 겹침은 도구를 상호 교환할 수 있다는 의미는 아닙니다. 아키텍처 선택은 과업을 수행할 수 있는지 여부가 아니라 과업을 수행하는 방법 및 성능, 확장성, 유지 관리에 미치는 장기적인 영향에 관한 것입니다. 플로는 선언적 명확성과 간단한 프로세스 구현 속도에서 뛰어나며, Apex는 복잡한 솔루션에 필요한 세밀한 제어와 강력한 기능을 제공합니다.

자동화 밀도은 특정 Salesforce 개체에 배치되는 로드입니다. 이는 개체의 최적 구현을 결정하기 위한 휴리스틱 역할을 합니다. 자동화 밀도가 증가함에 따라 트랜잭션 제한을 위반할 가능성이 증가합니다.

볼륨 및 복잡성의 세 가지 특정 치수를 검사하여 자동화 밀도를 계산합니다.

  • 자동화 수량: 단일 DML(데이터 조작 언어) 이벤트 동안 실행되는 고유한 자동화 메타데이터 항목(플로, 트리거 작업 등)의 원시 수입니다.

  • 레코드 볼륨: API 로드 또는 대량 배치 처리를 통해 처리되는 트랜잭션당 레코드이며, 이는 성능이 매우 중요합니다.

  • 의존성 확산: 초기 CRUD 작업으로 트리거된 다운스트림 DML 작업의 측정값입니다. 이는 하나의 업데이트가 관련 개체에 대한 업데이트로 연쇄적으로 이어질 때, 그 그래프의 깊이를 정량화합니다(예: 사례 → 계정 → 연락처 → 사용자 정의 롤업).

자동화 밀도 치수

Salesforce 애플리케이션의 범위와 복잡성이 증가함에 따라 단일 기본 진입점(레코드 트리거형 플로 또는 Apex 트리거 중 하나)으로 정하십시오. 단일 Salesforce 개체에서 자동화를 여러 메커니즘으로 분할하면 유지보수가 어려워지고 관리가 분산됩니다. 따라서 이를 피해야 합니다.

이 매트릭스를 사용하여 Salesforce 개체에 대한 필수 아키텍처 표준을 결정합니다.

  • 레코드 트리거형 플로는 낮은 자동화 밀도에 권장되는 솔루션입니다. 이는 강력한 기능과 접근성의 균형을 제공하여, 간단하고 서로 독립적인 자동화에 이상적입니다.

  • **하이브리드 패턴(레코드 트리거형 플로우와 호출 가능한 Apex)**은 복잡성이 증가하는 중간 밀도의 자동화에 강력하고 유지보수가 용이한 선택입니다. 이 패턴을 사용하면 팀이 계산 집약적인 작업을 Apex에 위임하면서, 선언적 플로우에서 질서 있는 조율을 유지할 수 있어 접근성과 성능의 균형을 맞출 수 있습니다.

  • Apex 트리거는 고밀도 자동화를 지원하는 견고한 아키텍처 기반을 구축하는 데 필요한 필수 구성 요소입니다. Apex 성능, 세분화된 제어, 개체 지향적 추상화 및 다형성은 이러한 시나리오의 복잡성과 규모를 관리하는 데 더 적합합니다.

밀도 수준 자동화 수량 데이터 용량(배치 크기) 종속성 확산 아키텍처 표준
낮음 < 15
자동화
표준
사용자 중심 UI 상호 작용 또는 소규모 API 로드(1~200개 레코드)
분리형
자체 로직. 동일한 개체 또는 관련 개체에 대한 다운스트림 DML 작업 0~1개입니다.
레코드 트리거 플로우
중간 15–30
자동화
중간
표준 배치 처리(주의 깊게 대량 처리해야 하는 논리 사용)
커플링됨
상위/하위 업데이트: 다운스트림 DML 작업 2~4개. 반복 위험
하이브리드 패턴
레코드 트리거형 플로우 + 호출 가능한 Apex
높음 > 30
자동화
높음
대량 API 로드가 있는 대용량 데이터(2,000 – 10,000개 이상의 레코드)
복잡하고 반복적임
복잡한 종속성 그래프 (다운스트림 DML 작업 5개 이상). 삼각형 반복 루프의 위험
Apex 트리거 메타데이터 프레임워크
실제 아키텍처를 결정하려면 자동화 밀도의 모든 차원을 종합적으로 고려해야 합니다. 주어진 Salesforce 개체에 대한 자동화 메커니즘을 선택할 때 잠재적인 미래 범위를 고려하십시오.

또한 Salesforce는 멀티테넌트 환경에서 공유 자원 관리와 거버너 제한을 적용하여 런웨이 자동화가 공유 자원을 독점하지 않도록 하기 때문에 일일 총 DML 작업 수를 고려하십시오. 일일 DML 용량이 많은 Salesforce 개체는 주의를 기울여 자동화를 선택해야 합니다. 예를 들어, CPU 시간(60,000ms) 및 힙 크기(12MB)에 대한 비동기 제한은 동기 제한보다 높습니다. 또한 비동기 실행에 대한 조직 전체 24시간 제한(250,000 또는 사용자 라이선스의 200배)은 런타임 예외를 피하기 위해 아키텍처 설계에 일일 총 DML 작업 수를 고려해야 합니다.

레코드 트리거형 플로는 레코드 트리거형 자동화를 위한 플랫폼의 주요 선언적 도구입니다. 플로의 사용 편의성과 내장된 플랫폼 보안을 통해 팀은 확장 가능하고 신뢰할 수 있는 솔루션을 쉽게 구축할 수 있습니다. Salesforce Platform에 솔루션을 구축하는 대부분의 팀에게 이상적인 선택입니다.

Apex는 이 플랫폼의 독점적이며 강력한 타입의 객체 지향 프로그래밍 언어입니다. 자동화 밀도가 높은 Salesforce 개체와 고성능, 정교한 논리 또는 트랜잭션을 세밀하게 제어해야 하는 사용 사례에는 Apex를 사용하세요.

의사결정 과정을 지원하기 위해, 이 매트릭스는 주요 아키텍처 기능 전반에 걸쳐 Flow와 Apex를 직접 비교합니다.

기능 레코드 트리거형 플로 Apex 트리거
제공 및 유지 보수 속도 권장
Flow Builder의 시각적 사용자 인터페이스를 사용하면 관리자 및 기타 선언적 빌더가 Apex 코드를 작성, 테스트 및 배포하는 것보다 빠르게 자동화를 만들고 수정할 수 있습니다. 이 인터페이스를 사용하면 광범위한 팀 구성원이 비즈니스 가치를 전달하고 간단한 과업을 위한 전문 개발자 자원에 대한 의존성을 줄일 수 있습니다.
전문 지식 필요
Apex 코드를 구현, 테스트, 유지 관리하려면 적절한 기술을 갖춘 소프트웨어 개발자가 필요합니다.
모듈성 가용
레코드 트리거 플로는 기본적으로 모듈식입니다. 팀은 모놀리식 논리가 아닌 특정 요구 사항에 대한 개별 플로우를 구축하고 플로 트리거 탐색기를 사용하여 함께 통합합니다. 이 모듈성은 독립적인 수정과 간단한 확장을 가능하게 하여 장기적인 소유 비용을 크게 줄여줍니다.
가용
Apex는 설계상 기능 모듈로 분할되어 있습니다. 각 Apex 클래스는 단일 기능 모듈을 구현하도록 고안되었습니다.
가시성 및 거버넌스 권장
Flow의 시각적 특징은 비즈니스 논리를 직관적으로 표현합니다. Flow 트리거 탐색기는 개체에 대한 모든 Flow의 통합 보기를 제공하므로 설계자 및 관리자가 코드를 읽지 않고도 쉽게 이해하고 관리하며 문제를 해결할 수 있습니다.
전문 지식 필요
메타데이터 프레임워크를 사용하여 트리거를 구성하는 것은 유용하지만, 코드를 체계적으로 유지하고 관리하려면 Apex는 체계적인 개발 팀이 필요합니다.
고성능 대량 데이터 처리 권장 안 함
복잡한 논리 또는 대용량 데이터를 처리할 때 거버너 제한에 도달할 위험이 증가합니다.
권장
Apex 코드는 플랫폼의 핵심 서비스와 더 가까이 실행되며 개발자에게 쿼리 최적화, 데이터 처리, 알고리즘 효율성에 대한 향상된 제어 기능을 제공합니다. 따라서 특히 대용량 데이터와 관련된 복잡한 시나리오에서 성능과 확장성이 향상됩니다.
강력한 논리 및 데이터 구조 가용
플로 변환 요소는 몇 가지 복잡한 처리 작업에 도움이 될 수 있습니다. 그러나 Flow에는 기본 Map과 Set 데이터 구조가 없으므로 복잡한 데이터 처리가 번거롭고 계산상 효율적이지 않습니다.
권장
Apex는 Map, Set, 그리고 프로그래밍 루프에 대한 완전한 접근을 제공하여 매우 효율적이고 대량 처리가 안전한 데이터 조작을 지원합니다. 전체 기능을 갖춘 프로그래밍 언어로서 Apex 유지 관리 가능한 효율적인 방식으로 복잡한 비즈니스 문제를 해결하는 데 도움이 되는 복잡한 논리 구조, 데이터 구조, 설계 패턴에 대한 액세스 권한도 제공합니다. Apex에는 선언적 도구에서 현재 사용할 수 없는 고급 함수(예: BusinessHours, Crypto)가 포함된 풍부한 표준 라이브러리가 있습니다.
트랜잭션 관리 사용 불가
플로는 부분 트랜잭션 커밋 또는 롤백에 대해 `Database.savepoint`, `Database.rollback` 또는 부분적으로 성공한 DML 작업에 대한 액세스 권한을 제공하지 않습니다.
사용 가능
Apex는 트랜잭션 무결성과 복잡한 오류 복구 시나리오를 완벽하고 세부적으로 제어할 수 있습니다.
이메일 배포 권장
레코드 트리거 플로에서 미리 구성된 이메일 경고를 보내는 것은 쉽고 확장 가능합니다. 런타임 시 사용자 정의 이메일 경고를 작성하고 배포할 수 있습니다. 사용자 지정 이메일에는 일일 이메일 보내기 제한이 적용됩니다.
사용 가능
Apex는 사용자 정의 이메일 메시지를 생성하고 보낼 수 있습니다. Apex에서 보낸 모든 이메일은 일일 이메일 보내기 제한이 적용됩니다.
플랫폼 보호 적용 권장
플로에는 자동 대량 처리 및 자동 재시도와 같은 기본 보호 기능이 포함되어 있습니다. 이러한 보호 기능은 가치를 빠르게 실현할 수 있도록 하며, 복잡한 수동 코딩이 필요한 성능 문제를 방지합니다.
수동 구현 필요
대량 처리와 같은 보호 조치는 명시적으로 코딩되어야 합니다(예: 컬렉션 관리 및 루프 내 SOQL 방지). 자동 재시도는 트리거에 기본적으로 적용되지 않으며 구현하려면 복잡한 사용자 정의 논리가 필요합니다.
비동기식 처리 사용 가능
플로는 비동기 경로에서 별도의 트랜잭션이 필요한 자동화를 위한 간편한 메커니즘을 제공합니다. 이러한 자동화에는 일일 제한이 적용됩니다.
사용 가능
Apex는 Change Data Capture와 분리된 트리거 구독자가 처리하는 Queueable 이벤트를 통해 완전한 제어가 가능합니다.
예약된 처리 권장
플로의 예약 경로는 고유하고 강력한 예약 기능을 제공합니다(예: "마감 날짜 3일 전 실행"). 이 기능에는 레코드의 데이터가 변경될 경우 자동 취소 및 재예약이 포함됩니다. 이러한 자동화에는 일일 제한이 적용됩니다.
사용 불가
Apex 트리거는 자동 취소를 통해 시간별 레코드별 이벤트를 기본적으로 예약할 수 없습니다. 예약된 Apex가 존재하지만, 이는 특정 시간에 실행되며 트리거의 일부로 개별 레코드를 처리하는 동안에는 예약되지 않는 근본적으로 다른 메커니즘입니다.
실행 순서 및 조율 사용 가능
플로 트리거 탐색기를 사용하면 관리자가 동일한 개체의 여러 플로에 대한 상대 실행 순서를 정의할 수 있습니다.
사용 가능
트리거 프레임워크는 자동화의 정확한 순서를 세부적으로 제어합니다.
같은 레코드 필드 업데이트 사용 가능 (저장 전)
레코드 트리거 플로는 초기 DML 커밋 전에 트리거 레코드를 업데이트하는 데 가장 효과적인 선언적 옵션입니다.
사용 가능 (저장 전)
Apex는 최소한의 오버헤드로 최고 수준의 성능을 제공합니다.
교차 개체 CRUD 사용 가능 (저장 후)
플로는 복잡성이 낮고 간단한 교차 개체 DML 작업에 적합합니다.
사용 가능 (저장 후)
Apex는 교차 개체 DML 작업에 대한 중복 제거, 오류 처리, 성능을 탁월하게 제어합니다.
비용이 많이 드는 연산의 중복 제거 사용 가능
플로는 자동 대량 처리를 통해 중복 쿼리 및 DML 문을 제거하는 데 뛰어납니다. 그러나 각기 다른 플로 트리거 또는 단일 트랜잭션 내에서 동일한 플로의 여러 호출에서 상태를 캐시하거나 공유할 수 없습니다. 이 제한 사항은 극한의 성능 시나리오에서 중요해질 수 있습니다.
권장
Apex는 비용이 많이 드는 작업의 중복 제거를 위한 메커니즘을 제공합니다. 개발자는 정적 속성 및 변수를 사용하는 트랜잭션 캐싱과 플랫폼 캐시를 사용하는 플랫폼 수준 캐싱을 활용하여 데이터를 저장하고 재사용할 수 있습니다. 이러한 기술은 SOQL 쿼리와 같은 트랜잭션 거버너 제한의 소비를 줄이고 고성능 및 확장성을 보장하는 데 중요합니다.
사용자 정의 오류 처리 사용 가능
CustomError 요소는 저장 작업을 차단하고 사용자에게 메시지를 표시할 수 있습니다.
권장
addError() 메서드는 유연한 필드 수준 및 조건부 오류 메시지를 제공합니다.

결정 지점을 사용하여 결정을 안내하는 방식을 효과적으로 보여주기 위해, 다음의 사용 사례와 관련 분석 포인트를 고려해 보십시오.

이 표는 제시된 기능을 바탕으로 일반 사용 사례에 대한 최적의 권장 사항을 제공합니다. 궁극적으로 이 문서의 관련 모범 사례 섹션에 포함된 경우와 같이 특정 시나리오에 가장 적합한 시나리오를 찾으려면 추가 고려 사항을 고려해야 합니다. 여기에서 플로와 Apex의 특정 조합이 가장 적합한 접근 방식을 제공하는 경우에 대해 자세히 알아볼 수 있습니다.

사용 사례 설명 베스트 맞춤 근거
고성능 배치 처리 수천 개의 레코드를 효율적으로 처리해야 하는 모든 자동화 Apex Apex는 플랫폼과의 인터페이스를 위한 다양한 API와 뛰어난 처리 속도를 제공합니다.
복잡한 데이터 처리 고급 데이터 조작이 필요한 시나리오 Apex Apex 플로에서 기본적으로 사용할 수 없는 지도 및 설정과 같은 데이터 구조를 제공하며, 성능이 뛰어난 대량 안전한 코드를 작성하는 데 중요할 수 있습니다.
트랜잭션 제어 세이브포인트, 롤백, 부분 커밋과 같은 제어 메커니즘 Apex Apex Database.savepoint 및 Database.rollback과 같은 메커니즘에 대한 액세스 권한을 제공하며 부분적으로 성공적인 DML 작업을 처리할 수 있습니다.
고급 맞춤형 검증 레코드의 여러 필드에서 데이터 유효성 검사 Apex 플로는 `CustomError` 요소로 저장을 방지할 수 있지만, 하위 플로를 포함한 모든 플로 유형에서는 사용할 수 없습니다. Apex addError() 메서드는 트리거 처리를 수행하는 동안 언제든지 레코드에 추가할 수 있는 여러 필드별 오류 메시지를 제공합니다.
간단한 프로세스 내에서 다소 복잡한 논리 단순한 프로세스의 일부로서, 고급 함수의 표준 라이브러리로 간소화된 중간 정도의 복잡성을 가진 논리 및 데이터 조작 플로 + Apex 레코드 트리거형 플로는 오케스트레이션 계층으로 작동하며, 복잡도가 높은 작업은 Invocable Apex에 캡슐화됩니다.
단순에서 다소 복잡한 논리까지 복잡성이 낮거나 보통인 데이터 조작, 기본 및 관련 데이터 개체 모두에 대한 트리거 업데이트 플로 플로는 관리자와 개발자가 모두 액세스할 수 있는 선언적 모델을 기반으로 하므로 일반적으로 사용 가능 옵션입니다.
고지 및 아웃바운드 메시지 아웃바운드 이메일 및 메시지 보내기 플로 플로를 사용하면 레코드 변경 시 이메일 경고와 아웃바운드 메시지를 손쉽게 보낼 수 있으며, 높은 확장성을 제공합니다.
예약된 처리 향후 동적 날짜의 자동화(예: 마감 날짜 3일 전) 플로 예약 경로는 플로에 고유한 강점이므로 플랫폼이 레코드의 데이터가 변경될 경우 해당 경로의 예약, 취소, 재예약을 자동으로 처리합니다.

확장성은 구현을 설계할 때 중요한 고려 사항입니다. 레코드 트리거형 자동화의 비즈니스 논리가 복잡하거나 장기적으로 실행되거나 데이터 용량이 많은 경우, Salesforce 플랫폼의 핵심 거버너 제한이 아키텍처 상의 제약 요인이 됩니다. 대량 데이터 업데이트, 복잡한 API 콜아웃 또는 대량 계산과 같은 작업은 단일 데이터베이스 트랜잭션 내의 총 CPU 시간 또는 DML 문 수와 같은 제한을 위반할 위험을 높입니다. 제한 예외로 인해 동기 트리거에 실패하면 사용자의 전체 저장 트랜잭션이 롤백되므로 사용자 환경이 좋지 않고 잠재적인 데이터 손실이 발생합니다. 이 기본적인 위험은 복잡한 작업을 오프로드하기 위한 아키텍처 패턴을 요구합니다.

이 경우 비동기 자동화가 필수적입니다. 설계자는 비동기 메커니즘을 활용하여 장기 실행 또는 대용량 작업을 주 동기식 레코드 저장 트랜잭션과 효과적으로 분리할 수 있습니다. 저장 작업은 빠르고 신뢰성 있게 완료되며, 무거운 처리는 이후에 실행되는 별도의 플랫폼 관리 트랜잭션으로 위임됩니다. 분리하면 안정성이 향상되고 트랜잭션 실패를 방지하며 확장 가능한 엔터프라이즈 응용 프로그램을 구축하는 데 매우 중요합니다. 플랫폼은 신뢰성, 볼륨, 복잡성과 관련하여 각각 고유한 혜택과 제약을 제공하는 몇 가지 특수한 도구를 제공합니다.

레코드 트리거형 플로 내의 ‘Run Asynchronously’ 경로는 ‘fire and forget’ 방식의 비동기 로직을 구현하는 가장 간단한 메커니즘을 제공합니다. 이 경로는 원래 레코드 저장 트랜잭션이 데이터베이스에 성공적으로 커밋된 후 별도의 트랜잭션으로 실행됩니다.

  • 이상적인 사용 사례: 즉시 실행하거나 사용자 정의 오류 처리가 필요하지 않은 과업에 적합합니다. 예를 들어 이메일 알림 보내기, 팔로우업 과업 만들기 또는 외부 시스템에 대한 간단한 콜아웃을 수행할 수 있습니다.

  • 제한 사항: 이 메커니즘은 다른 비동기 플로 실행과 동일한 일일 거버너 제한을 공유합니다. 매우 대용량 처리에 고안되지 않았습니다.

변경 데이터 캡처(CDC)는 대용량 시나리오에서 레코드 변경에 의해 트리거되는 비동기 로직을 처리하기 위한, 고처리량과 확장성, 그리고 복원력이 뛰어난 패턴입니다. 이 모델에서 트리거의 유일한 책임은 레코드를 동기식으로 저장하는 것입니다. 그러면 플랫폼이 대용량 이벤트 버스에 레코드의 변경 사항을 포함하는 자세한 이벤트 메시지를 게시합니다. 별도의 전용 Apex 트리거가 이 변경 이벤트를 구독합니다. 복잡한 장기 실행 또는 비동기 작업을 수행합니다.

  • 혜택: 이 패턴은 초기 사용자 트랜잭션에서 비동기 프로세스를 분리합니다. 비동기식 처리에 실패하면 사용자의 레코드 저장이 롤백되지 않습니다. 또한 패턴은 여러 내부 구독자 또는 외부 시스템에서 사용할 수 있는 지속적인 이벤트 스트림을 제공하며 최대 72시간 동안 이벤트를 재생할 수 있어 강력한 복원 능력을 제공합니다.

  • 제한 사항: 변경 데이터 캡처 (CDC) 이벤트 메시지에는 Apex Trigger.oldMap에 상응하는 레코드의 이전 상태가 포함되어 있지 않습니다. 이벤트 페이로드에는 새 필드 값만 포함되며, 변경 전의 값은 포함되지 않습니다. 따라서 특정 상태 전환을 기반으로 논리를 구현하는 것이 어려워집니다(예: Status__c가 “보류 중”에서 “승인됨”으로 변경된 경우에만 실행). 이벤트 구독자에서 개체의 필드 내역을 쿼리하여 이를 완화할 수 있지만, 이를 통해 프로세스에 복잡성이 추가되고 특정 관심 필드에 필드 내역 추적을 사용할 수 없습니다. 따라서 CDC에 오프로드할 수 있는 자동화 유형을 제한할 수 있습니다.

기본적으로 최대 5개의 Salesforce 개체에 대해 CDC를 활성화할 수 있습니다. 더 많은 개체에 대해 필요로 하는 조직은 이 제한을 제거하고 이벤트 배달 할당량을 늘리는 추가 기능 라이선스를 구매할 수 있습니다.

트리거에서 직접 대기 가능한 Apex 작업을 대기열에 추가하는 것은 위험한 패턴으로 간주되어야 하며, Apex에서 제공하는 제어가 필요한 경우(예: 복잡한 논리 또는 사용자 정의 재시도 메커니즘)이고 변경 데이터 캡처 (CDC)가 실행 가능한 옵션이 아닐 때만 사용해야 합니다.

대기 가능한 Apex가 필요한 경우, 구현에는 적절한 보안 조치가 포함되어야 합니다.

  • 제한 점검: 코드는 다른 작업을 추가하기 전에 트랜잭션에 이미 대기열에 있는 작업 수를 확인해야 합니다.

  • 컨텍스트 인식: 코드는 일괄 처리 작업(System.isBatch())과 같은 비동기 컨텍스트 내에서 실행 중인지 감지하고, 해당 컨텍스트에서 더 엄격한 ‘트랜잭션당 하나의 작업’ 제한을 준수하도록 동작을 수정해야 합니다.

동기식 트리거에서 비동기식 Apex 호출하면 안정성 위험이 발생합니다. 조직 수준 영향(예: 제한 초과)을 방지하려면 이 패턴을 엄격하게 설계하고 테스트해야 합니다.

  • 비동기식 Apex 실행(Batch, Queueable, @Future)의 일일 제한은 조직 전체에서 공유됩니다(일반적으로 250,000개 또는 사용자 라이선스를 기반으로 계산됨). 20,000개의 레코드를 대량으로 로드하면 트리거가 200개씩 청크로 실행되어 100번의 별도 트리거 호출이 발생합니다. 대량 배치 크기가 200개 미만이면 호출 횟수는 더 많아집니다. 각 호출이 비동기 작업을 대기열에 추가하는 경우, 단일 데이터 로드에서 일일 제한의 상당 부분이 소모될 수 있습니다. 이러한 소비로 인해 다른 중요한 비즈니스 프로세스가 비동기 자원을 충분히 활용하지 못할 수 있습니다.

  • 작업을 대기열에 추가하는 거버너 한도는 컨텍스트에 따라 크게 다릅니다. UI에서 사용자 작업에 의해 실행되는 트리거(동기식 트랜잭션)에서 최대 50개의 대기 가능한 작업을 대기열에 지정할 수 있습니다. 그러나 배치 Apex 클래스의 execute 메서드(비동기 트랜잭션) 내에서 실행되는 트리거의 경우 하나의 대기 가능한 작업만 대기열에 추가할 수 있습니다. 이 차이를 고려하지 못하는 것은 일반적이면서도 치명적인 실패 지점이며, 대용량 데이터 작업 중에 LimitException 오류가 발생할 수 있습니다.

  • 트리거 컨텍스트에서 직접 Schedulable Apex(System.schedule) 또는 Batch Apex(Database.executeBatch)를 호출하는 것은 안티 패턴입니다. 이러한 메서드는 트리거 컨텍스트에서 호출되도록 설계되지 않았습니다. 이렇게 하면 비동기 Apex 할당량이 빠르게 소진되어 한도 예외가 발생할 수 있습니다.

각 비동기 메커니즘에는 성능, 거버너 제한, 신뢰성과 관련된 특정 트레이드오프가 있습니다. 이 결정 트리를 가이드로 삼아 이러한 옵션을 탐색하고 사용 사례에 적합한 메커니즘을 선택할 수 있습니다.

비동기 패턴 결정 트리

플로우차트에서 알 수 있듯이, 대용량 DML 작업이 있지만 변경 데이터 캡처를 사용할 수 없는 경우(예: 오브젝트 한도 등), 트리거 기반 프로세스를 완전히 피하는 것이 가장 좋은 아키텍처 선택입니다.

대신 예약된 프로세스를 사용하는 것이 좋습니다. 이는 예약된 플로우 또는 예약된 Apex를 사용할 수 있습니다. 필수 단계는 다음과 같습니다.

  1. 동기식 트리거에서 간단하고 비용이 적은 업데이트를 수행합니다. 예를 들어, Status__c 필드를 “처리 대기 중”으로 설정하거나 Chatter 게시 등 비용이 적은 관련 레코드를 삽입하여 해당 레코드가 처리되어야 함을 나타냅니다.

  2. 15분마다 또는 매시간 등 정기적으로 실행되는 예약 작업(예: 예약된 플로우 또는 예약된 Apex)을 만듭니다.

  3. 보류 중 상태인 모든 레코드에 대해 예약된 작업 쿼리를 만들어 제어되는 대용량 컨텍스트에서 복잡한 논리를 실행한 다음, 처리된 레코드를 업데이트합니다.

이 패턴은 사용자의 동기 저장에서 대량 처리를 완전히 분리하고, 트리거로 실행되는 배치의 트랜잭션당 하나의 작업 제한이 적용되지 않으며, 비실시간 요구 사항에 대해 확장 가능하고 관리 가능한 솔루션을 제공합니다.

예약 작업의 지연 시간이 비즈니스 요구 사항에 부합하지 않고, 여전히 CDC나 트리거로 실행되는 큐어블을 사용할 수 없는 경우, 이는 중대한 아키텍처 불일치가 있음을 나타냅니다. 이때 다른 메커니즘을 고려해야 합니다. 핵심 응용 프로그램 설계를 다시 평가하면 다음과 같은 특정 결론을 내릴 수 있습니다.

  • 추가 기능을 구매하여 CDC 개체 제한을 제거합니다.

  • 비즈니스 요구 사항 자체를 근본적으로 재검토하여, 실시간에 가까운 처리가 정말로 “필수”인지, 아니면 예약된 작업의 대기 시간이 플랫폼 안정성을 위한 허용 가능한 절충안인지를 판단합니다.

결정 지점 외에도 복잡성 및 표준과 같은 기능적이지 않은 고려 사항을 고려해야 합니다.

구현의 복잡성 수준은 솔루션의 총 소유 비용과 변화하는 비즈니스 요구 사항에 적응할 수 있는 능력의 일부입니다. 모범 사례를 따르지 않으면 복잡성이 구현에 영향을 미칠 수 있습니다. 이 문서의 관련 모범 사례 섹션에는 다음 패턴을 포함하여 솔루션의 복잡성을 줄이기 위한 권장 사항이 있습니다.

  • 하이브리드 패턴: 플로우의 복잡한 논리를 위한 호출 가능한 Apex

  • Apex 트리거에 대한 메타데이터 프레임워크 사용

  • 메가 플로와 다중 플로 비교

문서는 자동화 자체만큼이나 중요합니다. 문서는 유지 관리성을 보장할 뿐만 아니라, AI 및 에이전트 기반 도구에도 매우 중요합니다. 문서는 비즈니스 프로세스를 이해하고 관리하는 데 도움이 됩니다.

In Flow

  • 모든 요소 및 변수에 일관된 명명 규칙을 설정합니다.

  • 플로에 대한 설명 필드를 사용하여 전체적인 목적, 트리거 기준, 의도한 결과를 설명합니다.

  • 각 개별 요소에 대한 설명 필드를 사용합니다(예: Get Records, Action, Transform). 이 방법은 의도를 전달하는 가장 좋은 방법입니다. 특히 호출 가능한 작업 및 하위 플로우에서는 설명이 복잡한 논리를 전달하는 주된 수단이기 때문에 매우 중요합니다.

In Apex

  • 코드에 논리의 _왜_뿐만 아니라 _무엇_을 명확하게 주석을 달아 설명하세요.

  • 메타데이터 구동 프레임워크를 사용하는 경우, 메타데이터 레코드에 사람이 읽을 수 있는 설명 필드가 반드시 포함되어 있고, 각 처리기 클래스가 수행하는 작업과 실행 시점을 설명하도록 해당 필드를 채워야 합니다.

DevOps 및 소스 제어는 성숙한 개발 수명 주기의 일부입니다. 항상 Salesforce 프로젝트에는 Git과 같은 소스 제어 도구를 사용하십시오. Apex 클래스와 Salesforce 플로는 모두 비즈니스 논리를 정의하는 메타데이터이며 버전을 지정하고 관리해야 합니다.

레코드 트리거형 자동화 관리의 컨텍스트 내에서 최신 DevOps 파이프라인은 필수적인 이점을 제공합니다.

  • 자동 품질 점검: Salesforce Code Analyzer과 같은 도구를 파이프라인에서 자동으로 실행하도록 구성할 수 있습니다. 정적 분석은 두 자동화 도구에서 문제가 발생하기 전에 문제 패턴을 감지할 수 있으며, 이는 성능 저하의 일반적인 원인인 Flow 루프 내의 비효율적인 Get Records 요소 또는 Apex for 루프 내의 SOQL 쿼리와 같은 문제를 표시합니다.

  • 회귀 방지: 자동화 밀도가 증가함에 따라 하나의 Flow 또는 Apex 클래스로 변경하면 동일한 객체의 다른 자동화에 의도하지 않은 결과가 발생할 수 있습니다. 제안된 변경 사항에 대해 자동화된 Apex 테스트를 실행하는 강력한 DevOps 테스트 전략은 새로운 플로우 버전이 기존 Apex 논리를 중단하지 않도록 보장하는 가장 신뢰할 수 있는 방법입니다(그 반대로).

  • 공동 작업 및 가시성: 소스 제어는 “단일 신뢰할 수 있는 소스”입니다. 관리자와 개발자가 동일한 개체에 대한 자동화 작업을 병렬로 수행할 수 있습니다. 또한 프로덕션 프로세스가 중단되면 자동화를 변경한 사람, 변경한 시기, 커밋 메시지를 통해 변경한 이유를 즉시 확인할 수 있습니다.

DevOps Center는 통합 인터페이스를 제공하여 이러한 모든 단계를 구성할 수 있도록 도와주므로 팀의 모든 구성원이 확장 가능한 소스 제어 기반 개발 프로세스를 이용할 수 있습니다.

문서화 및 DevOps 이행의 결합은 조직의 장기적인 건강과 유지 관리를 보장하여, 당신을 따르는 모든 아키텍트와 관리자에게 큰 혜택을 제공합니다.

위의 결정 가이드는 구현을 계획하기 전에 가장 적합합니다. 사용 사례에 가장 적합한 제품을 선택할 수 있도록 지원합니다. 제품을 선택한 후 구현을 위한 기존 모범 사례를 이해하는 것이 중요합니다.

객체당 하나의 도구 원칙은 고밀도 자동화 관리에 매우 중요하지만, 이를 순수 선언형 스택과 순수 프로그래밍형 스택 중 하나를 선택해야 하는 이분법적 선택으로 해석해서는 안 됩니다. 보다 효과적이고 유지 보수 가능한 아키텍처 패턴은 하이브리드 모델을 활용합니다. 레코드 트리거드 플로우를 오케스트레이션 계층으로 배치하고, 고복잡성 작업을 Invocable Apex 내에 캡슐화합니다.

하이브리드 패턴 다이어그램

레코드 트리거 플로는 비즈니스 프로세스의 오케스트레이션 계층 역할을 합니다. 그것은 입장 기준과 실행 컨텍스트 (_무슨_과 언제)를 소유합니다. 결정 논리와 라우팅을 이 계층 내에 유지함으로써 플로 트리거 탐색기를 통해 아키텍처의 프로세스 토폴로지를 투명하고 관리할 수 있어 중요 비즈니스 논리가 코드 내에서 숨겨지지 않도록 방지합니다.

복잡한 구성 요소의 일반적인 예는 사례 레코드에 대한 서비스 수준 계약(SLA) 계산 구현입니다. 비업무 시간 및 휴일을 제외한 정확한 계산에 중요한 BusinessHours 개체와 관련 논리가 Flow에서 기본적으로 액세스할 수 없으므로 전용 Apex 클래스가 사용됩니다. 이 클래스는 종종 ServiceLevelAgreementCalculator과 같은 이름으로 불리며, @InvocableMethod 어노테이션이 붙은 단일 정적 메서드를 사용하여 경과된 업무 시간을 계산하고 SLA가 ‘목표 범위 내’인지 ‘실패’인지를 판별하며, 구조화된 결과를 반환합니다. 이 접근 방식은 복잡하고 고성능의 논리를 Apex에 캡슐화하여, 이를 레코드 트리거 플로의 선언적 오케스트레이션 계층 내에서 원활하게 실행 및 통합할 수 있도록 합니다.

Apex ServiceLevelAgreementCalculator 클래스가 정의되면 레코드 트리거 플로 내에서 사용할 수 있습니다.

이 패턴은 우려 사항을 엄격하게 구분하는 것을 보여줍니다. 선언적 레이어는 트랜잭션 수명 주기 및 오케스트레이션을 관리하는 데 사용되며 코드는 복잡한 실행에 사용됩니다. 코드를 기초가 아닌 기능 유틸리티로 취급하여 성능과 서비스 점검의 균형을 맞춥니다.

모듈성: 이 결정은 전체 프로세스에 대해 Apex 또는 플로우만 사용하는 일원론적 접근에서 벗어납니다. 대신, 아키텍처는 복잡한 논리를 개별적이고, 대량 처리에 안전하며, 독립적으로 테스트할 수 있는 단위로 캡슐화합니다. 이러한 단위는 선언적 레이어에서 사용되는 재사용 가능한 구성 요소로 작동하므로 아키텍처 설계가 복잡하지 않고 자동화의 규모를 확장할 수 있습니다.

재사용성: 논리가 트리거 이벤트에서 분리됩니다. 잘 설계된 코드 유닛(예: InvocableMethod)은 한 번 작성되지만 여러 입력 지점에서 활용됩니다. 레코드 트리거 플로, 화면 플로 또는 외부 통합 이 코드를 재사용하면 중복 개발이 제거됩니다.

유지 관리성: 프로세스 플로 논리는 선언적 플로 내에서 계속 표시되고 관리할 수 있습니다. 이 중앙 집중화를 통해 디버깅 오버헤드가 크게 줄어들고 시스템의 실행 순서가 결정적이고 투명해집니다.

플로에서 호출 가능한 Apex를 사용하는 하이브리드 모델은 강력하지만, 만능 접근 방식은 아닙니다. 설계자는 하이브리드 솔루션을 적용하기 전에 특정 제한 사항 및 제약 사항을 알고 있어야 합니다.

  • 저장 전 지원 없음: 이는 가장 중요한 제한입니다. 호출 가능한 작업은 저장 후 컨텍스트(작업 및 관련 레코드용 플로)에서만 사용할 수 있습니다. 고성능 저장 전 컨텍스트(빠른 필드 업데이트용 플로)에서는 사용할 수 없습니다. 따라서 이 패턴을 사용하여 동일한 레코드 필드 업데이트를 위임할 수 없습니다. 저장 전 플로우 또는 저장 전 컨텍스트의 Apex 트리거 내에서 기본 플로우 요소를 사용하여 고성능 작업을 수행하세요.

  • 삭제 취소 후 지원 없음: 레코드 트리거 플로는 현재 삭제 취소 후 컨텍스트를 지원하지 않습니다. Salesforce 오브젝트에 휴지통에서 레코드를 복원할 때 자동화를 실행해야 하는 비즈니스 요구 사항이 있는 경우, Apex 트리거만이 해결책입니다.

  • 고용량 시나리오의 성능 오버헤드: 플로 런타임에서 Apex 런타임으로 전환하는 것은 비용이 들지 않는 작업이 아닙니다. 일반적으로 빠르지만, Flow 런타임에서 Invocable Action으로 진입하는 작업은 Apex 트리거 내에서의 기본 실행만큼 빠르지 않습니다. 대부분의 중간 밀도 자동화의 경우 이 마이크로 오버헤드는 접근성 향상을 위한 무시할 수 있을 정도로 작고, 가치 있는 대가입니다. 그러나 극한의 고성능 및 대용량 시나리오의 경우, 순수 Apex 전용 프레임워크가 순수 연산 속도에서 이점을 가집니다.

자동화 밀도 휴리스틱은 최신 그린필드 아키텍처에 대해 명확한 지침을 제공하지만, 엔터프라이즈 Salesforce 환경의 현실은 보다 미묘합니다. 성숙한 조직 환경에서는 동일한 Salesforce 오브젝트에서 작동하는 레코드 트리거 플로와 Apex 트리거를 찾는 것이 일반적입니다. 이 시나리오는 앞서 설명한 하이브리드 패턴과는 다릅니다. 여기서, 플로와 Apex 트리거는 결합되거나 함께 작동하도록 설계되지 않습니다.

이러한 공존은 플랫폼 기능이 발전하거나 기존 기술 부채로 인해 발생하는 경우가 많습니다. 이 상태는 허용되는 운영 상태이지만, 설계자는 최종 상태가 아닌 계산된 제약으로 취급해야 합니다.

조각화된 오케스트레이션은 상당한 거버넌스 및 유지 보수 오버헤드를 야기하므로 개발, 테스트, 사고 처리 활동이 분리되고 번거롭습니다. 이로 인해 해결 시간(TTR)과 운영 복잡성이 증가합니다.

  • 새 Salesforce 오브젝트의 경우 자동화 밀도 원칙을 기본 지침으로 삼으십시오.

  • 하이브리드 특성을 가진, 이중 Apex 트리거와 레코드 트리거 플로 진입점이 있는 기존 Salesforce 오브젝트의 경우, 밀도를 평가한 후 유지 관리 가능한 하이브리드 상태로 리팩터링하도록 설계합니다.

    • 밀도가 낮은 경우, Apex 트리거를 레코드 트리거 플로로 리팩터링하고 실행 순서를 지정하여 단일 자동화 진입점으로 만듭니다.

    • 중간 밀도의 경우, 복잡한 메가 플로를 올바른 실행 순서로 플로의 하위 집합으로 리팩터링합니다. 절대적으로 필요한 경우에만 Apex 트리거를 도입하세요(예: 삭제 취소 후 컨텍스트 지원 등).

    • 높은 밀도의 경우 Apex 트리거를 구현하는 것이 좋습니다.

Salesforce Platform에서 조직의 비즈니스 프로세스가 성숙해지면 레코드 트리거형 자동화의 용량과 복잡성이 불가피하게 증가합니다. 기본적인 모범 사례는 Salesforce 개체당 _한 개의 Apex 트리거_를 유지하는 것입니다. 플랫폼이 동일한 이벤트에 대해 동일한 개체에서 여러 트리거의 실행 순서를 보장하지 않으므로 이 규칙이 중요합니다. 이 제한은 결정적이지 않은 동작, 경쟁 조건 및 디버그하기 어려운 문제로 이어질 수 있습니다.

그러나 단일 트리거 원칙을 준수하면 관리 가능하고 확장 가능한 방식으로 단일 엔트리포인트에서 호출되는 모든 비즈니스 논리를 관리하고 오케스트레이션하는 아키텍처적인 도전이 발생합니다.

이 아키텍처의 첫 번째 진화는 Classic 트리거 처리기 패턴이었습니다. 이 접근 방식에서는 단일 Apex 트리거가 모든 논리를 해당 처리기 클래스(예: OpportunityTriggerHandler)에 위임합니다. 이 방법은 트리거 파일에서 논리를 분리하고 개발자가 처리기 클래스의 방법(예: afterInsert()) 내에서 실행 순서를 결정적으로 제어할 수 있도록 합니다.

이 패턴은 개선되었지만 종종 모노리틱 처리기 클래스로 이어집니다. 시간이 지남에 따라 더 많은 비즈니스 요구 사항이 추가되면 클래스가 크고 관리하기 어렵고 격리적으로 테스트하기 어렵게 됩니다. 모든 개별 프로세스의 실행 순서가 단일 메서드에 하드코딩되어 있어, 클래스가 병합 충돌에 취약해지고 대규모 엔터프라이즈 환경에서 거버넌스 및 유지 보수 오버헤드가 크게 증가합니다.

모듈화 및 오케스트레이션의 핵심 문제를 해결하기 위해 아키텍처는 메타데이터 중심 트리거 프레임워크로 전환합니다. 이는 실행 방법 및 시기에 대한 구성에서 자동화 논리 자체를 분리하는 중요한 아키텍처 단계입니다.

이 프레임워크는 다음 세 가지 주요 이점을 기반으로 구축됩니다.

  • 파티셔닝: 단일 처리기 클래스 대신, 핵심 비즈니스 논리는 작은, 원자적인 Apex 클래스(예: RecalculateAccountValues 클래스 또는 NotifySalesLeads 클래스)로 분할되며, 각 클래스는 _단일 책임 원칙_을 준수합니다. 이 모듈성을 통해 논리를 쉽게 테스트, 디버그, 이해할 수 있습니다.

  • 순서 및 오케스트레이션: 실행 순서는 더 이상 Apex 하드 코딩되지 않습니다. 대신 구성 레코드에 의해 선언적으로 정의되며, 일반적으로 사용자 정의 메타데이터 유형(예: TriggerAction__mdt)에 저장됩니다. 이렇게 하면 관리자가 배포 또는 코드 변경이 필요하지 않은 메타데이터 레코드를 수정하여 자동화 작업을 다시 정렬, 추가 또는 제거할 수 있습니다.

  • Bypass 기능: 프레임워크는 표준화된 세분화된 우회 기능을 제공합니다. 각 자동화 작업은 메타데이터 레코드를 통해 전역적으로 비활성화되거나, 특정 관리 사용자에 대해서는 사용자 정의 권한을 참조하여 우회 설정할 수 있습니다.

그런 다음, 개체에 대한 단일 Apex 트리거는 동적 발송자로만 작동합니다. 여기에는 비즈니스 논리가 포함되어 있지 않고, 대신 중앙 MetadataTriggerHandler 클래스를 인스턴스화합니다. 이 처리기는 사용자 지정 메타데이터 레코드를 쿼리하여 실행 순서를 동적으로 결정하고 지정된 순서대로 올바른 원자 Apex 클래스를 호출합니다. 자동화는 투명하고 관리 가능한 단일 계층 아래 통합됩니다.

강력한 프레임워크에서 Apex 사용하면 중복 작업을 제거하여 트랜잭션 상태를 관리하고 성능을 최적화할 수 있는 기능을 활용할 수 있습니다. 논리가 누적되면 저장 순서 내의 다양한 자동화가 동일한 비용이 많이 드는 작업을 독립적으로 실행하여 소중한 거버너 제한을 소모하고 DML 작업 시간을 늘리는 것이 일반적입니다.

프레임워크는 두 가지 기본 전략을 통해 이를 해결하도록 설계되었습니다.

  • 공유 상태 관리: 단일 Apex 트랜잭션 범위 내에서 정적 속성 및 변수가 캐시 데이터에 활용됩니다. 이렇게 하면 트리거의 다른 레코드 또는 단계에서 자동화 논리를 여러 번 호출하는 경우에도 구성 설정에 대한 SOQL 쿼리와 같은 비용이 많이 드는 작업이 한 번만 실행됩니다. 트랜잭션 제한 소비량이 현저하게 감소합니다.

  • 플랫폼 캐시 활용도: 단순한 트랜잭션 내 캐싱을 넘어서려면, 플랫폼 캐시를 사용하여 특정 데이터에 대해 전체 데이터베이스를 쿼리하는 것을 피할 수 있습니다. 이 관리형 인메모리 캐시는 기본형이 아니고, 코드베이스 전반에서 자주 읽히며, 트랜잭션 동안 변경되지 않는 데이터를(예: 프로필, 역할, 업무 시간) 조회하는 데 이상적입니다. Cache.CacheBuilder 인터페이스를 사용하면 시스템이 캐시를 먼저 확인하고 데이터가 없는 경우에만 데이터베이스 쿼리를 수행하여 성능과 확장성을 극대화합니다.

자동화가 트랜잭션을 시작하는 레코드의 필드 값만 변경해야 할 때는 항상 저장 전 업데이트를 사용하십시오. 이 내용은 플로우의 빠른 필드 업데이트(저장 전 실행)와 Apex 트리거의 저장 전 컨텍스트 로직(삽입 전, 업데이트 전) 모두에 적용됩니다.

이 패턴은 두 번째 DML 작업과 반복 저장 주기를 방지하므로, 어떤 도구를 사용하더라도 높은 성능을 보장합니다. 변경 사항은 레코드가 데이터베이스에 커밋되기 전에 메모리에 적용되며 원래 트랜잭션의 일부로 저장됩니다. 그렇지 않으면 전체 저장 순서를 다시 실행하고 모든 자동화를 다시 실행하는 두 번째 저장에 대한 오버헤드가 제거됩니다.

제어되지 않는 반복은 트리거의 논리가 DML 업데이트를 수행하여 동일한 트리거가 다시 실행되게 만드는, 후-업데이트 트리거에서 흔히 발생하는 문제입니다. 이로 인해 무한 루프가 생성되고, 결국 governor 제한 예외로 종료됩니다. 정적 불린 플래그나 처리된 레코드 ID 컬렉션이 과거에는 이러한 반복을 방지하는 데 사용되었지만, 더 정밀하고 견고한 패턴은 레코드 자체의 새 버전과 이전 버전의 필드 값을 비교하여 논리 실행을 제어하는 것입니다.

특정 관심 필드가 실제로 변경된 경우에만 논리를 실행합니다. 이렇게 하면 중요한 데이터가 변경되지 않은 동일한 트랜잭션 내의 이후 DML 작업에서 트리거의 로직 실행을 방지합니다.

레코드 트리거형 플로에서 레코드가 조건 요구 사항을 충족하도록 업데이트되는 경우에만 플로가 실행되도록 설정하여 제어되지 않는 반복을 방지합니다.

레코드 트리거형 플로우에서 재귀 제어

플로우의 진입 기준 수식을 사용하기로 선택하면, $Record 전역 변수(새 값을 나타냄)와 $RecordPrior 전역 변수(저장 이전의 원래 값을 나타냄)를 비교하여 무한 재귀를 방지할 수 있습니다. 예를 들어 기회의 금액 필드가 변경된 경우에만 플로가 실행되도록 하려면 항목 기준에서 다음을 사용합니다.

레코드의 새 버전인 Trigger.new의 필드 값을 레코드의 이전 버전인 Trigger.oldMap의 필드 값과 비교하여 특정 변경 사항이 발생했는지 확인합니다. 이 접근 방식을 통해 자동화가 동일하게 작동하고 필요한 경우에만 실행되므로 시스템의 효율성을 높이고 재해가 발생하는 반복 루프를 방지할 수 있습니다.

잘 설계된 Salesforce 조직은 자동화를 우회할 수 있도록 일관되고 신뢰할 수 있는 메커니즘이 필요합니다. 이는 선택적 기능이 아니라 데이터 무결성을 유지하고 관리 작업을 활성화하기 위한 핵심 운영 요구 사항입니다.

일부 시나리오에서는 다음과 같이 우회 프레임워크가 필수적입니다.

  • 대용량 데이터를 로드할 때 각 레코드마다 트리거가 실행되면 프로세스가 급격하게 느려지고, 제한 예외가 발생하며, 잘못된 관련 레코드 및 알림이 생성될 수 있습니다. 우회를 사용하면 데이터를 원활하고 효율적으로 삽입할 수 있습니다.

  • 통합 사용자는 레코드의 외부 시스템에서 데이터를 동기화해야 할 수 있습니다. 일반적으로 사용자 시작 변경(예: 이메일 보내기, 작업 생성)에 대해 실행되는 자동화는 변경이 다른 시스템에서 시작된 경우 바람직하지 않거나 중복될 수 있습니다.

  • 관리자 또는 지원 담당자가 레코드에 대한 수정 업데이트를 수행해야 할 수 있습니다. 우회 메커니즘을 사용하면 표준 비즈니스 자동화가 실행되지 않아 변경을 수행할 때 예기치 않은 결과를 초래할 위험을 줄일 수 있습니다.

사용자 정의 권한: 우회 논리를 구현하기 위한 최신 확장 가능한 표준은 사용자 정의 권한입니다. 이들은 여러 가지 이유로 이전 방식보다 우수합니다.

  • 유연성: 권한 집합을 통해 사용자에게 사용자 정의 권한을 할당할 수 있습니다. 이 방법은 최신 Salesforce 보안 및 액세스 모델과 일치하므로 세분화되고 유연한 할당을 수행할 수 있습니다. 특정 사용자에게 우회 권한을 부여하거나, 특정 만료 일자/시간이 있는 경우에 한해 일시적으로 허용할 수 있습니다.

  • 유지 관리성: 사용자 정의 권한을 사용하면 프로필 또는 사용자가 자동화 논리에 하드 코딩되지 않습니다. 사용자의 역할이 변경되거나 새 프로필에 우회 액세스가 필요할 경우, 변경 사항은 배포가 필요한 코드나 플로 수정 대신 간단한 권한 집합 할당으로 처리됩니다.

  • 확장성: 사용자 정의 권한은 복잡한 사용자 기반에서 예외를 관리할 수 있는 확장 가능한 프레임워크를 제공합니다. 권한 집합, 권한 집합 그룹 또는 프로필을 통해 사용자에게 할당할 수 있습니다. 권한 집합 또는 프로필에 대한 연결은 소스 메타데이터에서도 표시됩니다.

구현 패턴: 조직의 모든 레코드 트리거형 자동화에 일관된 우회 패턴을 적용합니다.

레코드 트리거 플로 우회: 플로가 실행되지 않도록 차단하는 것이 가장 효과적인 방법입니다. 플로의 항목 기준에 조건을 추가하면 이 작업을 수행할 수 있습니다.

  • 레코드 트리거 플로의 시작 요소에서 조건 요구 사항을 수식이 True로 평가됨으로 설정합니다.

    • 수식 빌더에서 $Permission 전역 변수를 사용하여 사용자 정의 권한에 대한 확인을 통합합니다. 기존 항목 기준과 확인을 결합합니다.

      • 수식 패턴:
    • 이 패턴을 사용하면 사용자에게 지정된 사용자 정의 권한이 할당되지 않은 경우에만 플로가 실행됩니다. 이 확인은 플로 인터뷰가 생성되기 전에 수행되므로 가장 성능이 뛰어난 접근 방식입니다.

Apex 트리거 프레임워크 우회: Apex 메타데이터 구동 트리거 프레임워크에 바로 우회 논리를 통합하여 세부적으로 제어할 수 있습니다.

  • TriggerAction__mdt 사용자 정의 메타데이터 유형에는 텍스트 필드(예: BypassPermission__c)가 포함되어야 합니다.

    • MetadataTriggerHandler 클래스에서 동적으로 작업을 실행하기 전에 코드는 이 필드의 값을 읽어야 합니다.

    • 필드가 채워지면 처리기가 FeatureManagement.checkPermission() 메서드를 사용하여 현재 실행 중인 사용자에게 지정된 사용자 정의 권한이 있는지 확인합니다.

    • checkPermission()이 true를 반환하면 처리기가 해당 특정 작업을 건너뛰고 순서대로 다음 작업으로 진행합니다.

    • 이 패턴은 전역 우회(모든 TriggerAction__mdt 레코드가 동일한 권한을 참조하는 경우)와 세분화된 작업별 우회(다른 레코드가 다른 권한을 참조하거나 일부 레코드에 우회 권한이 전혀 없는 경우)를 모두 허용하기 때문에 강력합니다.

이는 모든 개체 자동화를 하나의 대규모 메가 플로로 통합하는 것은 안티 패턴입니다. 하나의 플로에 통합하고 여러 조건이 적절한 플로로 논리를 분할해도 성능에 큰 영향을 미치지 않습니다. 가장 중요한 성능 향상 효과는 다음과 같습니다.

  • 동일한 레코드의 필드 업데이트에 대해서는 저장 전 플로를 사용합니다.

  • 정확한 입력 조건을 작성하여 특정 사용 사례에 영향을 미치지 않는 변경 사항에 대해 플로가 실행되지 않도록 합니다.

플로 트리거 탐색기를 사용하면 개체의 각 플로에 순서 값을 할당하여 순차 실행 순서를 보장할 수 있습니다.

플로 트리거 탐색기
Apex 플로 작업