본문 바로가기

개발자정보

Apex 트리거

반응형

Apex 트리거 입문

학습 목표

이 단원을 완료하면 다음을 수행 할 수 있습니다.

  • Salesforce 개체의 트리거를 생성한다.
  • 트리거 컨텍스트 변수를 사용한다.
  • 트리거에서 클래스 메소드를 호출한다.
  • 트리거 sObject addError () 메소드를 사용하여 저장 조작을 제한한다.

Apex 트리거 만들기

Apex 트리거를 사용하면 Salesforce 레코드에 대한 이벤트 (삽입, 업데이트, 삭제) 이전이나 이후에 사용자 지정 작업을 실행할 수 있습니다. 데이터베이스 시스템에서 트리거가 지원되는 것과 마찬가지로, Apex에서도 레코드를 관리하기 위해 트리거를 지원하고 있습니다.

일반적으로 트리거를 사용하는 것은 특정 조건에 따라 작업을 수행하는 경우 관련 레코드를 변경하거나 특정 작업의 실행을 제한하는 경우입니다. SOQL 및 DML을 실행하거나 사용자 정의 Apex 메소드의 호출 등 Apex에서 실시 할 수있는 모든 트리거를 사용하여 실행할 수 있습니다.

트리거를 사용하는 것은 Salesforce 사용자 인터페이스의 포인트 앤 클릭 도구에서 수행 할 수없는 작업을 수행하는 경우입니다. 예를 들어 레코드의 항목 값의 검증 및 항목의 업데이트를하려면 유효성 검사 및 워크 플로 규칙을 사용합니다.

트리거를 정의 할 수는 Account, Contact 같은 최상위 표준 개체 사용자 지정 개체 일부 하위 표준 개체입니다. 트리거는 만들 때 기본적으로 활성화됩니다. Salesforce는 지정된 데이터베이스 이벤트가 발생했을 때 유효한 트리거가 자동으로 실행됩니다.

트리거 구문

트리거 정의 구문은 클래스 정의의 구문과는 다릅니다. 트리거 정의는trigger키워드로 시작합니다. 그런 다음 트리거 이름 트리거가 연결된 Salesforce 개체 트리거를 실행하는 조건이 계속됩니다. 트리거 구문은 다음과 같습니다.

trigger TriggerName on ObjectName (trigger_events) {
   code_block
}

삽입, 업데이트, 삭제, 복원 작업 전후에 트리거를 실행하는 경우 쉼표로 구분 된 목록에서 여러 트리거 이벤트를 지정합니다. 지정할 수있는 것은 다음의 이벤트입니다.

  • before insert
  • before update
  • before delete
  • after insert
  • after update
  • after delete
  • after undelete

다음의 간단한 트리거는 거래처를 삽입하기 전에 실행 디버그 로그에 메시지를 씁니다.

  1. 개발자 콘솔에서 [File (파일)] | [New (새로 만들기)] | [Apex Trigger (Apex 트리거)] 를 클릭합니다.
  2. 트리거 이름에 " HelloWorldTrigger"를 입력하여 sObject에 [Account]를 선택합니다. Submit (제출)] 을 클릭합니다.
  3. 기본 코드를 다음 코드로 바꿉니다.
    trigger HelloWorldTrigger on Account (before insert) {
    System.debug('Hello World!');
    }
  4. 저장하려면 [Ctrl + S] 키를 누릅니다.
  5. 트리거를 테스트하려면 거래처를 만듭니다.
    1. [Debug (디버그)] | [Open Execute Anonymous Window (실행 익명 창 열기)] 을 클릭합니다.
    2. 새 창에서 다음 코드를 추가 한 후 Execute (실행)] 을 클릭합니다.
      Account a = new Account(Name='Test Trigger');
      insert a;
  6. 디버그 로그에서Hello World!문을 찾습니다. 로그에는 트리거가 실행 된 것을 의미하기도합니다.

트리거 유형

트리거에는 다음의 2 종류가 있습니다.

  • before 트리거 는 레코드가 데이터베이스에 저장되기 전에 레코드 값을 갱신 또는 검증하는 경우에 사용합니다.
  • after 트리거 는 시스템에 의해 설정된 항목 값 (레코드Id 항목 또는 LastModifiedDate항목 등)에 액세스하거나 다른 레코드의 변경에 영향을 미치는 경우에 사용합니다. after 트리거 를 실행 레코드는 참조 전용입니다.

컨텍스트 변수 사용

트리거를 실행 레코드에 액세스하려면 컨텍스트 변수를 사용합니다. 예를 들어,Trigger.New 에 삽입 또는 갱신 트리거에 삽입 된 모든 레코드가 포함됩니다.Trigger.Old에 업데이트 트리거 업데이트되기 전에 sObject의 이전 버전 또는 삭제 트리거 삭제 된 sObject의 목록이 있습니다. 하나의 레코드가 삽입 된 경우 나 API 또는 Apex를 사용하여 다수의 레코드를 일괄 적으로 삽입 된 경우에 트리거가 실행됩니다. 따라서Trigger.New 같은 컨텍스트 변수는 하나의 레코드를 포함 할 수도 있고 여러 레코드가 포함될 수 있습니다.Trigger.New 에 반복하는 개별 sObject를 얻을 수 있습니다.

다음의 예는HelloWorldTrigger샘플 트리거를 변경 한 것입니다. for 루프의 각 거래처에 반복 처리를 각 설명 항목이 업데이트됩니다.

trigger HelloWorldTrigger on Account (before insert) {
    for(Account a : Trigger.New) {
        a.Description = 'New description';
    }   
}

메모

before 트리거를 실행 한 레코드는 트리거의 실행이 종료 된 후 시스템에 의해 저장됩니다. DML 삽입 또는 업데이트 작업을 명시 적으로 호출하지 않고 트리거 레코드를 변경할 수 있습니다. 이러한 레코드에 DML 문을 실행하면 오류가 표시됩니다.

다른 특정 컨텍스트 변수는 업데이트 이벤트 나 다른 어떤 이벤트에 의해 트리거가 실행되었는지 여부를 나타내는 Boolean 값을 반환합니다. 이러한 변수는 트리거에서 여러 이벤트를 결합 할 때 도움이됩니다. 예를 나타냅니다.

trigger ContextExampleTrigger on Account (before insert, after insert, after delete) {
    if (Trigger.isInsert) {
        if (Trigger.isBefore) {
            // Process before insert
        } else if (Trigger.isAfter) {
            // Process after insert
        }        
    }
    else if (Trigger.isDelete) {
        // Process after delete
    }
}

트리거 컨텍스트 변수

다음 표는 트리거에 사용 가능한 모든 컨텍스트 변수의 전체 목록입니다.

변수사용 방법

isExecuting Apex 코드의 현재 컨텍스트가 Visualforce 페이지, Web 서비스, 또는 executeanonymous () API 호출이 아닌 트리거 인 경우, true를 돌려줍니다.
isInsert 삽입 작업은 Salesforce 사용자 인터페이스, Apex 또는 API에서이 트리거가 실행 된 경우true 를 반환합니다.
isUpdate 업데이트 작업은 Salesforce 사용자 인터페이스, Apex 또는 API에서이 트리거가 실행 된 경우true 를 반환합니다.
isDelete 삭제 작업은 Salesforce 사용자 인터페이스, Apex 또는 API에서이 트리거가 실행 된 경우true 를 반환합니다.
isBefore 레코드가 저장되기 전에이 트리거가 실행 된 경우true 를 반환합니다.
isAfter 모든 레코드를 저장 한 후이 트리거가 실행 된 경우true 를 반환합니다.
isUndelete 레코드가 휴지통에서 복원 된 후이 트리거가 실행 된 경우true를 반환합니다. 이 복원은 Salesforce 사용자 인터페이스, Apex 또는 API에서 복원 작업 후에 만 ​​이루어집니다.
new 새로운 버전의 sObject 레코드 목록을 반환합니다.이 sObject 목록 insert 트리거update 트리거 및 undelete 트리거에서만 사용할 수 레코드는 before 트리거에서만 변경할 수 있습니다.
newMap 새로운 버전의 sObject 레코드의 ID 매핑입니다.이 매핑은 before update 트리거after insert 트리거after update 트리거 및 after undelete 트리거에서만 사용할 수 있습니다.
old 이전 버전의 sObject 레코드 목록을 반환합니다.이 sObject 목록 update 트리거 delete 트리거에서만 사용할 수 있습니다.
oldMap 이전 버전의 sObject 레코드의 ID 매핑입니다.이 매핑은 update 트리거 delete 트리거에서만 사용할 수 있습니다.
operationType 현재 작업에 해당하는 System.TriggerOperation 종류의 열거 값을 반환합니다.System.TriggerOperation 열거 값의 유효한 값은BEFORE_INSERT,BEFORE_UPDATE,BEFORE_DELETE,AFTER_INSERT,AFTER_UPDATE,AFTER_DELETE,AFTER_UNDELETE입니다. 트리거의 종류에 따라 다른 프로그래밍 로직을 사용하는 경우,switch 문을 사용하여 고유의 트리거 실행 열거 상태가 다른 순열을 지정하는 것을 고려하십시오.
size 이전 버전과 새 버전을 모두 포함하는 트리거 호출 레코드의 합계 수.

트리거에서 클래스 메소드의 호출

트리거에서 공개 유틸리티 메소드를 호출 할 수 있습니다. 다른 클래스의 메소드를 호출하여 코드를 재사용 할 수 트리거의 크기가 축소하고 Apex 코드의 유지 보수가 향상됩니다. 또한 객체 지향 프로그래밍을 사용할 수있게됩니다.

다음 트리거 예는 트리거에서 정적 메서드를 호출하는 방법을 보여줍니다. 삽입 이벤트에 의해 트리거가 실행 된 경우이 예에서는EmailManager 클래스에서 정적 sendMail ()메소드를 호출합니다. 이 유틸리티 메서드는 지정된 수신자에게 메일을 보내는 것으로, 삽입 된 거래처 책임자 레코드 수를 저장합니다.

메모

EmailManager클래스는 "Apex 활성화"단원의 클래스의 예에 포함됩니다. 이 트리거를 저장하기 전에EmailManager 클래스를 조직에 저장하여sendMail () 메소드를 정적으로 변경해야합니다.

  1. 개발자 콘솔에서 [File (파일)] | [New (새로 만들기)] | [Apex Trigger (Apex 트리거)] 를 클릭합니다.
  2. 트리거 이름에 " ExampleTrigger"를 입력하여 sObject에 [Contact (고객 책임자)] 를 선택합니다. Submit (제출)] 을 클릭합니다.
  3. 기본 코드를 다음 코드로 대체하여sendMail () 메일 주소의 자리 표시 자 텍스트를 자신의 이메일 주소로 변경합니다.
    trigger ExampleTrigger on Contact (after insert, after delete) {
        if (Trigger.isInsert) {
            Integer recordCount = Trigger.New.size();
            // Call a utility method from another class
            EmailManager.sendMail('Your email address', 'Trailhead Trigger Tutorial', 
                        recordCount + ' contact(s) were inserted.');
        }
        else if (Trigger.isDelete) {
            // Process after delete
        }
    }
  4. 저장하려면 [Ctrl + S] 키를 누릅니다.
  5. 트리거를 테스트하려면 거래처 책임자를 만듭니다.
    1. [Debug (디버그)] | [Open Execute Anonymous Window (실행 익명 창 열기)] 을 클릭합니다.
    2. 새 창에서 다음 코드를 추가 한 후 Execute (실행)] 을 클릭합니다.
      Contact c = new Contact(LastName='Test Contact');
      insert c;
  6. 디버그 로그 트리거가 실행되고 있는지 확인합니다. 로그의 마지막 부분에 유틸리티 메소드에 의해 작성된 디버그 메시지 (DEBUG | Email sent successfully)를 찾습니다.
  7. 본문에 "1 contact (s) were inserted."라고 기재된 메일을 수신했는지 확인합니다.새로운 트리거가 활성화되면, 1 개 이상의 거래처 책임자를 추가 할 때마다 메일을 수신합니다.

관련 레코드 추가

트리거는 종종 트리거 컨텍스트 레코드 (트리거 시작의 원인이 된 레코드) 관련 레코드 액세스 또는 관리에 사용합니다.

이 트리거는 새로운 거래처 나 업데이트 된 거래처에 아직 상담이 연결되어 있지 않은 경우, 각 거래처에 대한 상담을 추가합니다. 트리거는 먼저 SOQL 쿼리를 실행하여 트리거가 실행 된 거래처의 모든 자식 기회를 가져옵니다. 다음 트리거는Trigger.New에서 sObject의 목록을 반복하여 각 거래처의 sObject를 가져옵니다. 거래처 관련 상담 sObject이없는 경우는 for 루프가 1 건이 생성됩니다. 트리거에서 새로운 기회가 작성된 경우, 마지막 문에서 그 기회가 삽입됩니다.

  1. 개발자 콘솔을 사용하여 다음 트리거를 추가합니다 (HelloWorldTrigger예를 같이하지만, 트리거 이름에 「AddRelatedRecord」사용합니다).
    trigger AddRelatedRecord on Account(after insert, after update) {
        List<Opportunity> oppList = new List<Opportunity>();
        
        // Get the related opportunities for the accounts in this trigger
        Map<Id,Account> acctsWithOpps = new Map<Id,Account>(
            [SELECT Id,(SELECT Id FROM Opportunities) FROM Account WHERE Id IN :Trigger.New]);
        
        // Add an opportunity for each account if it doesn't already have one.
        // Iterate through each account.
        for(Account a : Trigger.New) {
            System.debug('acctsWithOpps.get(a.Id).Opportunities.size()=' + acctsWithOpps.get(a.Id).Opportunities.size());
            // Check if the account already has a related opportunity.
            if (acctsWithOpps.get(a.Id).Opportunities.size() == 0) {
                // If it doesn't, add a default opportunity
                oppList.add(new Opportunity(Name=a.Name + ' Opportunity',
                                           StageName='Prospecting',
                                           CloseDate=System.today().addMonths(1),
                                           AccountId=a.Id));
            }           
        }
        if (oppList.size() > 0) {
            insert oppList;
        }
    }
  2. 트리거를 테스트하려면 Salesforce 사용자 인터페이스에서 거래처를 만들고 「Apples & Oranges」이름을 지정합니다.
  3. 거래처 페이지에서 상담] 관련 목록에서 새로운 기회를 찾습니다. 트리거가이 상담이 자동으로 추가되어 있습니다.

고급 작업

추가 된 트리거는 트리거 컨텍스트에 속하는 모든 레코드를 반복합니다. 즉, for 루프가Trigger.New를 반복합니다. 그러나이 트리거 루프는 더 간소화 할 수 있습니다. 실제로 액세스 할 필요가있는 것은이 트리거 컨텍스트의 모든 거래처가 아니라 그 일부 (상담없이 거래처)입니다. 다음 단원에서는이 트리거를 더욱 효율적으로하는 방법을 설명합니다. "일괄 트리거 디자인 패턴"단원에서는 SOQL 쿼리를 변경하여 상담없이 거래처를 검색하는 방법을 학습합니다. 그런 다음 그 레코드를 반복하는 방법을 학습합니다.

트리거 예외 사용

특정 조건을 충족하면 기록이 저장되지 않도록하는 등 경우에 따라서는 특정 데이터베이스 작업에 제한을 가할 필요가있을 수 있습니다. 트리거에 기록이 저장되지 않도록하려면 문제의 sObject에서addError () 메소드를 호출합니다.addError ()메소드는 트리거에서 치명적인 오류를 생성합니다. 이 오류 메시지가 사용자 인터페이스에 표시되고 기록됩니다.

다음 트리거는 거래처 관련 상담이있는 경우에는 그 거래처가 삭제되지 않도록합니다. 기본적으로 거래처가 삭제되면 관련 레코드가 모두 계단식 삭제됩니다. 이 트리거는 상담이 계단식 삭제되지 않도록합니다. 이 트리거를 사용해보세요. 앞의 예제를 실행하면 조직에 "Apples & Oranges"라는 거래처와 관련된 상담이 존재합니다. 이 예에서 그 샘플 거래처를 사용합니다.

  1. 개발자 콘솔을 사용하여 다음 트리거를 추가합니다.
    trigger AccountDeletion on Account (before delete) {
       
        // Prevent the deletion of accounts if they have related opportunities.
        for (Account a : [SELECT Id FROM Account
                         WHERE Id IN (SELECT AccountId FROM Opportunity) AND
                         Id IN :Trigger.old]) {
            Trigger.oldMap.get(a.Id).addError(
                'Cannot delete account with related opportunities.');
        }
        
    }
  2. Salesforce 사용자 인터페이스에서 Apples & Oranges거래처 페이지로 이동하여 [삭제] 를 클릭합니다.
  3. 확인 팝업에서 [OK] 를 클릭합니다."Can not delete account with related opportunities."라는 사용자 지정 오류 메시지가 관련된 유효성 검사 오류가 표시됩니다.
  4. AccountDeletion트리거를 비활성화합니다. 이 트리거를 활성 상태로하면 문제를 확인할 수 없습니다.
    1. [Setup (설정)에서 「Apex Triggers 」(Apex 트리거)를 검색합니다.
    2. [Apex Triggers (Apex 트리거) 페이지에서 AccountDeletion 트리거 옆에있는 [Edit (편집)] 를 클릭합니다.
    3. [Is Active (활성화) 를 해제합니다.
    4. [저장] 을 클릭합니다.

고급 작업

트리거 addError () 를 호출하면 대량 DML 통화가 부분적으로 완료 한 경우를 제외하고 일련의 작업 전체가 롤백됩니다.

  • Apex의 DML 문이 트리거를 실행할 때 오류가 발생하면 전체 작업이 롤백됩니다. 그러나 런타임 엔진은 모든 레코드를 처리하여 전체 오류 목록을 컴파일합니다.
  • Lightning Platform API의 대량 DML 호출이 트리거를 실행하면 런타임 엔진은 잘못된 레코드를 제외합니다. 다음 런타임 엔진은 오류가 발생하지 않은 레코드를 저장하려고합니다.

트리거 및 콜 아웃

Apex를 사용하면 외부 Web 서비스에 대한 호출이 가능하며 Apex 코드를 외부 Web Services와 통합 할 수 있습니다. 외부 Web 서비스에 Apex 콜을 선이라고합니다. 예를 들어, 주가 정보 서비스에 콜 아웃을 실행하여 주식 정보를 얻을 수 있습니다. 트리거에서 콜 아웃을 실행할 때 외부 서비스의 응답을 기다리는 동안 트리거 프로세스에 의해 작업이 차단되지 않도록 콜 아웃을 비동기 적으로 수행해야합니다. 비동기 콜 아웃을 백그라운드 프로세스로 실행하여 외부 서비스에서 응답이 반환되면 수신합니다.

트리거에서 콜 아웃을 실행하려면 비동기 적으로 실행하는 클래스 메소드를 호출합니다. 이러한 메서드는 future 메서드라고,@future (callout = true)주석이 추가됩니다. 다음 클래스의 예로는 콜 아웃을 실행 future 메소드가 포함됩니다.

메모

이 예제는 설명 목적으로 가상의 엔드 포인트 URL을 사용하고 있습니다. 따라서 끝점을 유효한 URL로 변경하여 Salesforce에 엔드 포인트의 원격 사이트를 추가하지 않는 한이 예제를 실행 할 수 없습니다.

public class CalloutClass {
    @future(callout=true)
    public static void makeCallout() {
        HttpRequest request = new HttpRequest();
        // Set the endpoint URL.
        String endpoint = 'http://yourHost/yourService';
        request.setEndPoint(endpoint);
        // Set the HTTP verb to GET.
        request.setMethod('GET');
        // Send the HTTP request and get the response.
        HttpResponse response = new HTTP().send(request);
    }
}

다음 예제에서는 클래스에서 메서드를 호출하여 선을 비동기 적으로 실행하는 트리거를 보여줍니다.

trigger CalloutTrigger on Account (before insert, before update) {
    CalloutClass.makeCallout();
}

이 섹션은 콜 아웃 설명 만 제공, 선발은하지 않습니다. 자세한 내용은 " Apex 개발자 가이드 "의 "Apex를 사용하여 콜 아웃 호출" 을 참조하십시오.

자원

실습 Challenge

준비를 시작하자

이 challenge는 각자의 실무 조직에서 수행합니다. 

[시작] 을 클릭하여 시작하거나 조직의 이름을 클릭하여 다른 조직을 선택합니다.

영어 이외의 언어로 Trailhead를 이용하는 경우는 실습 Challenge와 동일한 언어로 설정하십시오. 

그렇지 않으면, challenge에 합격하지 못할 수 있습니다. Trailhead에서 실무 조직의 사용에 대한 자세한 내용은 Trailhead Playground Management 를 참조하십시오.

당신의 CHALLENGE

Create an Apex Trigger

Create an Apex trigger that sets an account 's Shipping Postal Code to match the Billing Postal Code if the Match Billing Address option is selected.

Fire the trigger before inserting an account or updating an account.

Pre-Work :
Add a checkbox field to the Account object :

  • Field Label : Match Billing Address
  • Field Name : Match_Billing_Address
    Note : The resulting API Name should be Match_Billing_Address__c.
  • Create an Apex trigger :
    • Name : AccountAddressTrigger
    • Object : Account
    • Events : before insert and before update
    • Condition : Match Billing Address is true
    • Operation : set the Shipping Postal Code to match the Billing Postal Code
반응형