Salesforce Apex 초보자용 튜토리얼

⚡ 스마트 요약

Apex 프로그래밍은 Salesforce 개발자에게 객체 지향적이고 강력한 형식의 언어를 제공하여 CRM에 사용자 정의 비즈니스 로직을 추가할 수 있도록 합니다. 클래스, 트리거 및 배치 작업을 지원하며, 가버너 제한을 통해 공유 멀티테넌트 플랫폼의 안정성을 유지합니다.

  • 🧱 Foundation: Apex는 대소문자를 구분하지 않는 언어입니다. JavaSalesforce Lightning Platform에서 기본적으로 실행되는 유사한 구문입니다.
  • 🗃️ 데이터 접근: SOQL 쿼리와 DML 문을 사용하면 코드가 Salesforce 데이터베이스에서 sObject 레코드를 직접 읽고 쓸 수 있습니다.
  • 🛠️ 구현 : 클래스, 속성 및 트리거는 레코드 삽입, 업데이트, 삭제 및 기타 시스템 이벤트에 사용자 지정 로직을 연결합니다.
  • 📦 규모 : Apex 배치 처리 및 기타 비동기 옵션은 플랫폼 제한을 초과하지 않고 수백만 개의 레코드를 청크 단위로 처리합니다.
  • 🚦 주지사 제한: 100개의 동기식 SOQL 쿼리 및 150개의 DML 문과 같은 트랜잭션별 제한은 공유 리소스를 보호합니다.
  • 품질 : 제품 배포 전에 Apex 코드의 최소 75%에 대해 단위 테스트를 완료해야 합니다.

APEX Salesforce 프로그래밍 개요

Salesforce의 Apex란 무엇입니까?

Apex Apex는 Salesforce에서 개발한 객체 지향적이고 강력한 타입의 프로그래밍 언어로, 서비스형 소프트웨어(SaaS) 및 고객 관계 관리(CRM) 애플리케이션 구축에 사용됩니다. Apex는 개발자가 타사 SaaS 애플리케이션을 만들고 백엔드 데이터베이스 지원 및 클라이언트-서버 인터페이스를 통해 시스템 이벤트에 비즈니스 로직을 추가할 수 있도록 지원합니다.

Apex는 개발자가 버튼 클릭, 관련 레코드 업데이트, Visualforce 페이지와 같은 시스템 이벤트에 비즈니스 로직을 추가할 수 있도록 도와줍니다. Apex의 구문은 다음과 유사합니다. Java. Salesforce에 등록 CRM이 어떻게 작동하는지 배우기 위해서입니다.

Apex 프로그래밍 언어의 특징

Salesforce Apex의 중요한 기능은 다음과 같습니다.

  • Apex는 대소문자를 구분하지 않는 언어입니다.
  • Apex를 사용하면 sObject 레코드에 대해 INSERT, UPDATE, UPSERT 및 DELETE와 같은 DML 작업을 수행할 수 있습니다.
  • Apex에서 SOQL(Salesforce Object Query Language) 및 SOSL(Salesforce Object Search Language)을 사용하여 sObject 레코드를 쿼리할 수 있습니다.
  • 생성할 수 있습니다. 단위 테스트 그리고 실행하여 검증하십시오. 코드 커버리지 Apex 코드의 효율성.
  • Apex는 다중 테넌트 환경에서 실행됩니다. 세일즈 포스 Salesforce는 사용자가 공유 리소스를 독점하는 것을 방지하기 위해 거버너 제한을 정의했습니다. Salesforce 거버너 제한을 초과하는 코드는 실행이 실패하고 오류가 표시됩니다.
  • Salesforce 객체는 Apex에서 데이터 유형으로 사용할 수 있습니다. 예를 들면 다음과 같습니다.
    Account acc = new Account();

    여기서 Account는 표준 Salesforce 객체입니다.

  • Apex는 모든 Salesforce 릴리스마다 자동으로 업그레이드됩니다.

개발자는 언제 Apex를 선택해야 할까요?

Salesforce에서 제공하는 사전 구축된 포인트 앤 클릭 기능을 사용하여 구현하기에는 비즈니스 시나리오가 너무 복잡한 경우에만 Apex 코드를 작성해야 합니다.

다음은 Apex 코드를 작성해야 하는 몇 가지 시나리오입니다.

  • Salesforce를 다른 응용 프로그램과 통합하는 웹 서비스를 만듭니다.
  • sObject에 사용자 지정 유효성 검사를 구현하려면 다음과 같이 합니다.
  • DML 작업이 수행될 때 사용자 지정 Apex 로직을 실행하려면 다음과 같이 합니다.
  • Flow와 같은 기존 선언적 자동화 도구로는 구현할 수 없는 기능을 구현하기 위해서입니다.
  • 설정하기 이메일 서비스 수신 이메일의 내용, 헤더 및 첨부 파일을 처리하는 프로그램입니다.

Apex가 적합한 선택인 경우를 알게 되면, 다음 단계는 코드를 저장한 후 어떤 일이 발생하는지 이해하는 것입니다.

Apex의 작동 구조

다음은 Apex 코드의 동작 흐름입니다.

  • 개발자 조치: 개발자가 플랫폼에 코드를 저장하면 모든 Apex 코드는 Apex 런타임 인터프리터가 이해할 수 있는 명령어 집합으로 컴파일되고, 이러한 명령어는 플랫폼에 메타데이터로 저장됩니다.
  • 최종 사용자 조치: 사용자 이벤트가 Apex 코드를 실행하면 플랫폼 서버는 메타데이터에서 컴파일된 명령어를 가져와 Apex 인터프리터를 통해 실행한 후 결과를 반환합니다.

아래 다이어그램은 개발자와 최종 사용자의 작업이 Lightning Platform 애플리케이션 서버와 상호 작용하는 방식을 보여줍니다.

Apex의 작동 구조

Apex 개발 환경

Apex 코드는 Salesforce의 샌드박스 환경이나 개발자 에디션 조직에서 개발할 수 있습니다.

아래 그림과 같이 샌드박스 환경에서 코드를 개발한 후 프로덕션 환경에 배포하는 것이 가장 좋은 방법입니다.

Apex 개발 환경

Apex 코드 개발 도구: Salesforce의 모든 에디션에서 Apex 코드를 개발하는 데 사용할 수 있는 세 가지 도구는 다음과 같습니다.

  • 개발자 콘솔
  • Visual Studio Code Salesforce 확장 팩(단종된 Force.com IDE를 대체함)을 사용하면 됩니다.
  • Code Salesforce 설정 사용자 인터페이스의 편집기

개발 환경이 준비되었으니 이제 데이터 유형부터 시작하여 언어 자체의 구성 요소를 살펴보겠습니다.

Apex의 데이터 유형

다음은 Apex에서 지원하는 데이터 유형입니다.

원시적 인

정수, DoubleLong, Date, Datetime, Decimal, Time, Blob, String, ID 및 Boolean은 기본 데이터 유형으로 간주됩니다. 모든 기본 데이터 유형은 참조가 아닌 값으로 전달됩니다.

Collections

Apex에서는 세 가지 유형의 컬렉션을 사용할 수 있습니다.

  • 명부: 인덱스를 기반으로 정렬된 기본 데이터 유형, sObject, 컬렉션 또는 Apex 객체 모음입니다.
  • 설정 중복을 포함하지 않는 고유한 요소들의 순서 없는 모음입니다.
  • 지도: 이는 단일 값에 매핑되는 고유 키들의 모음이며, 해당 값은 기본 데이터 유형, sObject, 컬렉션 또는 Apex 객체일 수 있습니다.

객체

이는 Salesforce의 특수 데이터 유형입니다. 의 테이블과 비슷합니다. SQL SQL의 컬럼과 유사한 필드를 포함하고 있습니다.

열거 형

Enum은 절대값입니다.tract는 지정된 식별자 집합 중 하나의 값을 저장하는 데이터 유형입니다.

클래스, 객체 및 인터페이스

사용자 정의 Apex 클래스와 인터페이스도 데이터 유형으로 사용할 수 있습니다. 여기서 객체는 Apex에서 지원하는 모든 데이터 유형의 인스턴스를 나타냅니다.

Apex 구문

변수 선언

Apex는 강력한 타입 언어이므로 Apex에서는 변수를 선언할 때 반드시 데이터 타입을 지정해야 합니다.

예 :

Contact con = new Contact();

여기서 변수 con은 데이터 형식이 Contact로 선언되었습니다.

SOQL 쿼리

SOQL은 Salesforce Object Query Language의 약자입니다. SOQL은 Salesforce 데이터베이스에서 sObject 레코드를 가져오는 데 사용됩니다. 예를 들면 다음과 같습니다.

Account acc = [SELECT Id, Name FROM Account LIMIT 1];

위 쿼리는 Salesforce 데이터베이스에서 계정 레코드를 가져옵니다.

루프 문

반복문은 리스트의 레코드를 순회하는 데 사용됩니다. 반복 횟수는 리스트에 있는 레코드 수와 같습니다. 예를 들면 다음과 같습니다.

List<Account> listOfAccounts = [SELECT Id, Name FROM Account LIMIT 100];
// iteration over the list of accounts
for(Account acc : listOfAccounts){
	//your logic
}

위 코드 조각에서 listOfAccounts는 List 데이터 형식의 변수입니다.

흐름 제어 문

흐름 제어문은 특정 조건에 따라 일부 코드 줄을 실행하려는 경우에 유용합니다.

예 :

List<Account> listOfAccounts = [SELECT Id, Name FROM Account LIMIT 100];
// execute the logic if the size of the account list is greater than zero
if(listOfAccounts.size() > 0){
	//your logic
}

위 코드 조각은 데이터베이스에서 계정 기록을 조회하고 목록 크기를 확인합니다.

DML 선언문

DML은 데이터 조작 언어(Data Manipulation Language)의 약자입니다. DML 문은 Salesforce 데이터베이스에서 데이터를 조작하는 데 사용됩니다. 예를 들면 다음과 같습니다.

Account acc = new Account(Name = 'Test Account');
insert acc; //DML statement to create account record.

Apex Access 사양

다음은 Apex에서 지원하는 액세스 지정자입니다.

공공 영역

이 접근 지정자는 네임스페이스 내의 클래스, 메서드 또는 변수에 대한 접근 권한을 Apex에서 사용할 수 있도록 합니다.

프라이빗 투어

이 접근 지정자는 클래스, 메서드 또는 변수에 대한 접근 권한을 부여하여 해당 클래스, 메서드 또는 변수가 정의된 코드 영역 내에서만 사용할 수 있도록 합니다. 접근 지정자가 정의되지 않은 모든 메서드와 변수는 기본값인 `private` 접근 지정자를 사용합니다.

보호

이 접근 지정자는 정의하는 Apex 클래스 내의 모든 내부 클래스에서 사용할 수 있는 메서드 또는 변수에 대한 접근 권한을 부여합니다.

글로벌

이 접근 지정자는 Apex가 네임스페이스 내부뿐 아니라 외부에서도 클래스, 메서드 또는 변수에 접근할 수 있도록 합니다. 필요한 경우가 아니라면 `global` 키워드는 사용하지 않는 것이 좋습니다.

Apex의 키워드

공유와 함께

클래스가 이 키워드를 사용하여 정의되면 현재 사용자에게 적용되는 모든 공유 규칙이 적용됩니다. 이 키워드가 없으면 코드는 시스템 컨텍스트에서 실행됩니다.

예 :

public with sharing class MyApexClass{
// sharing rules enforced when code in this class executes
}

공유하지 않고

클래스가 이 키워드로 정의되면 현재 사용자에게 적용되는 공유 규칙이 적용되지 않습니다.

예 :

public without sharing class MyApexClass{
// sharing rules are not enforced when code in this class executes
}

정적인

static 키워드로 정의된 변수나 메서드는 한 번 초기화되어 클래스와 연결됩니다. 정적 변수와 메서드는 클래스의 인스턴스를 생성하지 않고도 클래스 이름으로 직접 호출할 수 있습니다.

`final` 키워드로 정의된 상수 또는 메서드는 재정의할 수 없습니다. 예를 들면 다음과 같습니다.

public class myCls {
static final Integer INT_CONST = 10;
}

이 INT_CONST 변수의 값을 덮어쓰려고 하면 System.FinalException: final 변수가 이미 초기화되었습니다. 예외가 발생합니다.

반품

이 키워드는 메소드에서 값을 반환합니다. 예를 들어:

public String getName() {
return 'Test';
}

null로

이는 널 상수를 정의하며 변수에 할당할 수 있습니다. 예를 들면 다음과 같습니다.

Boolean b = null;

온라인

클래스가 virtual 키워드로 정의되면 상속 및 재정의가 가능합니다.

ABStract

클래스가 절댓값으로 정의된 경우tract 키워드를 포함하는 경우, abs 키워드를 가진 메서드를 하나 이상 포함해야 합니다.tract, 그리고 해당 메서드는 시그니처만 가져야 합니다.

예 :

public abstract class MyAbstractClass {
abstract Integer myAbstractMethod1();
}

Apex 문자열

문자열은 문자 수에 제한이 없는 문자 집합입니다. 예를 들면 다음과 같습니다.

String name = 'Test';

Salesforce의 String 클래스에는 여러 가지 내장 메서드가 있습니다. 다음은 자주 사용되는 몇 가지 메서드입니다.

약어(maxWidth)

이 메서드는 문자열을 지정된 길이로 자르고, 주어진 문자열의 길이가 지정된 길이보다 길면 해당 문자열을 반환하고, 그렇지 않으면 원래 문자열을 반환합니다. maxWidth 변수의 값이 4보다 작으면 이 메서드는 런타임 예외(System.StringException: Minimum abbreviation width is 4)를 발생시킵니다.

예 :

String s = 'Hello World';
String s2 = s.abbreviate(8);
System.debug('s2: ' + s2); //Hello...

자본화 ()

이 메서드는 문자열의 첫 글자를 제목 케이스로 변환하여 반환합니다.

예 :

String s = 'hello';
String s2 = s.capitalize();
System.assertEquals('Hello', s2);

포함(하위 문자열)

이 메서드는 메서드를 호출하는 문자열에 지정된 부분 문자열이 포함되어 있으면 true를 반환합니다.

String name1 = 'test1';
String name2 = 'test';
Boolean flag = name1.contains(name2);
System.debug('flag:: ' + flag); //true

같음(stringOrId)

이 메서드는 전달된 매개변수가 null이 아니고 메서드를 호출하는 문자열과 동일한 이진 문자열 시퀀스를 나타내는 경우 true를 반환합니다.

ID 값을 비교할 때 ID의 길이가 같지 않을 수 있습니다. 예를 들어, 15자 길이의 ID를 나타내는 문자열과 18자 길이의 ID를 나타내는 객체를 비교하는 경우에도 이 메서드는 여전히 true를 반환합니다. 예시:

String stringValue15 = '001D000000Ju1zH';
Id idValue18 = '001D000000Ju1zHIAR';
Boolean result = stringValue15.equals(idValue18);
System.debug('result: ' + result); //true

위 예시에서 equals 메서드는 15자리 객체 ID와 18자리 객체 ID를 비교하고, 두 ID가 동일한 이진 시퀀스를 나타내는 경우 true를 반환합니다.

대소문자를 구분하여 비교하려면 이 방법을 사용하십시오.

escapeSingleQuotes(stringToEscape)

이 메서드는 문자열 내의 모든 작은따옴표 앞에 이스케이프 문자(\)를 추가하고 결과를 반환합니다. 이 메서드는 동적 SOQL 쿼리를 생성할 때 SOQL 인젝션 공격을 방지합니다. 모든 작은따옴표가 데이터베이스 명령이 아닌 문자열을 감싸는 요소로 처리되도록 합니다.

예 :

String s = 'Hello \'Tom\'';
String escapedStr = String.escapeSingleQuotes(s);
System.debug(escapedStr); // Outputs Hello \'Tom\'

제거(하위 문자열)

이 메서드는 메서드를 호출한 문자열에서 지정된 부분 문자열을 모두 제거하고 결과 문자열을 반환합니다.

예 :

String s1 = 'Salesforce and force.com';
String s2 = s1.remove('force');
System.debug('s2: ' + s2); // 'Sales and .com'

하위 문자열(startIndex)

이 메서드는 startIndex에 있는 문자부터 시작하여 문자열의 끝까지의 부분 문자열을 반환합니다.

예 :

String s1 = 'hamburger';
String s2 = s1.substring(3);
System.debug('s2: ' + s2); //burger

역전()

이 메서드는 문자열의 모든 문자를 역순으로 바꾸어 반환합니다. 예를 들면 다음과 같습니다.

String s = 'Hello';
String s2 = s.reverse();
System.debug('s2:::: ' + s2); // olleH

손질()

이 메서드는 문자열에서 앞뒤의 모든 공백을 제거하고 이를 반환합니다.

valueOf(toConvert)

이 메서드는 전달된 객체의 문자열 표현을 반환합니다.

문자열, 클래스 및 키워드는 로직을 재사용 가능한 단위로 패키징하기 시작할 때 함께 사용되며, 이것이 바로 Apex 클래스의 목적입니다.

에이펙스 클래스

Apex 클래스는 객체를 생성하는 데 사용되는 설계도 또는 템플릿입니다. 객체는 클래스의 인스턴스입니다.

Salesforce에서 Apex 클래스를 생성하는 방법은 세 가지가 있습니다.

  • 개발자 콘솔
  • Visual Studio Code Salesforce 확장 팩 포함
  • 설정의 Apex 클래스 상세 페이지

Apex에서는 최상위 클래스라고도 하는 외부 클래스를 정의할 수 있으며, 외부 클래스 내부에 내부 클래스라고 하는 클래스를 정의할 수도 있습니다.

외부 클래스를 선언할 때는 global이나 public과 같은 접근 제한자를 반드시 사용해야 합니다.

내부 클래스를 선언할 때는 접근 제한자를 사용할 필요가 없습니다.

Apex 클래스는 `class` 키워드 뒤에 클래스 이름을 붙여 정의합니다.

`extends` 키워드는 Apex 클래스에서 기존 클래스를 확장하는 데 사용되고, `implements` 키워드는 Apex 클래스에서 인터페이스를 구현하는 데 사용됩니다.

Salesforce Apex는 다중 상속을 지원하지 않습니다. Apex 클래스는 하나의 기존 Apex 클래스만 상속할 수 있지만 여러 인터페이스를 구현할 수 있습니다.

Apex 클래스는 사용자 정의 생성자를 포함할 수 있으며, 사용자 정의 생성자를 사용할 수 없는 경우 기본 생성자가 사용됩니다. 생성자 내의 코드는 클래스의 인스턴스가 생성될 때 실행됩니다.

Apex 클래스의 구문:

public class myApexClass{
// variable declaration
//constructor
	public myApexClass(){
	}
//methods declaration
}

`new` 키워드는 Apex 클래스의 인스턴스를 생성하는 데 사용됩니다. 다음은 Apex 클래스의 인스턴스를 생성하는 구문입니다.

myApexClass obj = new myApexClass();

Apex 게터 및 세터

Apex 속성은 Apex 변수와 유사합니다. Apex 속성에는 getter와 setter가 필수적입니다. getter와 setter를 사용하면 속성 값에 접근하거나 변경하기 전에 코드를 실행할 수 있습니다. get 접근자의 코드는 속성 값을 읽을 때 실행되고, set 접근자의 코드는 속성 값을 변경할 때 실행됩니다. get 접근자만 있는 속성은 읽기 전용, set 접근자만 있는 속성은 쓰기 전용, get 및 set 접근자를 모두 가진 속성은 읽기/쓰기가 가능합니다. Apex 속성의 구문은 다음과 같습니다.

public class myApexClass {
// Property declaration
	access_modifier return_type property_name {
	get {
			//code
		}
		set{
			//code
		}
	}
}

여기서 access_modifier는 속성의 접근 제한자이고, return_type은 속성의 데이터 유형이며, property_name은 속성의 이름입니다.

다음은 get 및 set 접근자를 모두 갖는 Apex 속성의 예입니다.

public class myApex{
	public String name{
		get{ return name; }
		set{ name = value; }
	}
}

여기서 속성 이름은 name이고, 공개 속성이며, 문자열 데이터 형식을 반환합니다.

get 및 set 블록에 코드를 반드시 작성해야 하는 것은 아닙니다. 이러한 블록은 비워두고 자동 속성을 정의할 수 있습니다. 예를 들면 다음과 같습니다.

public double MyReadWriteProp{ get; set; }

get 및 set 접근자는 자체 접근 제한자를 사용하여 정의할 수도 있습니다. 접근자가 제한자와 함께 정의되면 해당 속성의 접근 제한자를 재정의합니다. 예를 들면 다음과 같습니다.

public String name{private get; set;}// name is private for read and public for write.

클래스는 명시적으로 호출하는 재사용 가능한 로직을 정의합니다. 다음에 설명할 트리거는 레코드가 변경될 때마다 자동으로 실행됩니다.

에이펙스 트리거

Apex 트리거를 사용하면 DML 작업이 수행되기 전과 후에 사용자 지정 Apex 코드를 실행할 수 있습니다.

Apex는 다음 두 가지 유형의 트리거를 지원합니다.

트리거 이전: 이러한 트리거는 레코드가 데이터베이스에 저장되기 전에 필드 값을 검증하고 업데이트하는 데 사용됩니다.

트리거 이후: 이러한 트리거는 레코드가 데이터베이스에 커밋된 후 시스템에서 설정하는 필드 값(예: 레코드 ID 및 LastModifiedDate 필드)에 접근하는 데 사용됩니다. 이러한 필드 값은 다른 레코드를 수정하는 데 사용할 수 있습니다. 트리거 실행 후 생성되는 레코드는 읽기 전용입니다.

일괄 처리 트리거를 작성하는 것이 좋습니다. 일괄 처리 트리거는 단일 레코드뿐만 아니라 여러 레코드를 한 번에 처리할 수 있습니다.

Apex 트리거의 구문:

trigger TriggerName on ObjectName (trigger_events) {
	//Code_block
 }

여기서 TriggerName은 트리거의 이름이고, ObjectName은 트리거가 기록되는 개체의 이름이며, trigger_events는 쉼표로 구분된 이벤트 목록입니다.

Apex 트리거에서 지원하는 이벤트는 다음과 같습니다. 삽입 전, 업데이트 전, 삭제 전, 삽입 후, 업데이트 후, 삭제 후, 삭제 취소 후.

Apex 트리거에서는 정적 키워드를 사용할 수 없습니다. 내부 클래스에 적용 가능한 모든 키워드는 Apex 트리거에서 사용할 수 있습니다.

모든 트리거는 런타임 컨텍스트를 반환하는 암묵적인 변수를 정의합니다. 이러한 변수는 System.Trigger 클래스에 정의되며 컨텍스트 변수라고 합니다. 아래 두 스크린샷은 Apex 트리거에서 지원하는 컨텍스트 변수를 보여줍니다.

Apex 트리거 컨텍스트 변수

Apex 트리거 컨텍스트 변수(계속)

다음은 Apex 트리거에서 컨텍스트 변수를 사용할 때 고려해야 할 사항입니다.

  • DML 작업에서 trigger.new와 trigger.old를 사용하지 마십시오.
  • Trigger.new는 삭제할 수 없습니다.
  • Trigger.new는 after triggers에서 읽기 전용입니다.
  • Trigger.new는 이전 트리거에서만 동일한 객체의 필드 값을 변경하는 데 사용할 수 있습니다.

아래 두 스크린샷은 다양한 트리거 이벤트에서 특정 작업에 대한 고려 사항을 보여줍니다.

Apex 트리거 이벤트 고려 사항

Apex 트리거 이벤트 고려 사항(계속)

트리거는 실시간 로직을 처리하지만, 일부 작업은 단일 트랜잭션으로 처리하기에는 너무 큽니다. 바로 이럴 때 배치 Apex가 유용합니다.

Apex의 배치 클래스

Salesforce에서 배치 클래스는 일반적인 방식으로 처리할 경우 Apex 거버너 제한을 초과할 수 있는 대량의 레코드를 처리하는 데 사용됩니다. 배치 클래스는 코드를 비동기적으로 실행합니다.

다음은 일괄 수업의 장점입니다.

  • 배치 클래스는 데이터를 청크 단위로 처리하며, 하나의 청크가 처리에 실패하더라도 성공적으로 처리된 청크는 롤백되지 않습니다.
  • 배치 클래스의 각 데이터 덩어리는 새로운 거버너 제한 세트로 처리되므로 코드가 거버너 실행 제한 내에서 실행되도록 보장합니다.

Apex 클래스가 배치 클래스로 사용되려면 Database.Batchable 인터페이스를 구현해야 합니다. 이 인터페이스는 배치 클래스에서 구현해야 하는 세 가지 메서드를 제공합니다.

1. 시작()

이 메서드는 `execute` 인터페이스 메서드에서 처리할 레코드 또는 객체의 범위를 생성합니다. 이 메서드는 배치 실행 중에 한 번만 호출됩니다. 이 메서드는 `Database.QueryLocator` 객체 또는 `Iterable` 객체를 반환합니다. `Database.QueryLocator` 객체를 사용하는 SOQL 쿼리로 검색할 수 있는 레코드 수는 50천만 개이지만, `Iterable`을 사용하는 경우에는 SOQL 쿼리로 검색할 수 있는 총 레코드 수가 50,000만 개로 제한됩니다. `Iterable`은 배치 클래스에 대한 복잡한 범위를 생성하는 데 사용됩니다.

시작 메서드의 구문:

global (Database.QueryLocator | Iterable<sObject>) start(Database.BatchableContext bc) {}

2. execute()

이 메서드는 각 데이터 청크를 처리하는 데 사용됩니다. execute 메서드는 각 레코드 청크에 대해 호출됩니다. 기본 실행 배치 크기는 200개 레코드입니다. execute 메서드는 두 개의 인수를 받습니다.

Database.BatchableContext 객체에 대한 참조,

List와 같은 sObject 목록 또는 매개변수화된 형식의 목록입니다. execute 메서드의 구문은 다음과 같습니다.

global void execute(Database.BatchableContext bc, List<P> records){}

3. finish()

finish 메서드는 배치 클래스 실행 중에 한 번 호출됩니다. finish 메서드에서는 후처리 작업을 수행할 수 있습니다. 예를 들어, 확인 이메일을 보낼 수 있습니다. 이 메서드는 모든 배치가 처리된 후에 호출됩니다. finish 메서드의 구문은 다음과 같습니다.

global void finish(Database.BatchableContext bc){}

Database.BatchableContext 객체

Database.Batchable 인터페이스의 각 메서드는 Database.BatchableContext 객체에 대한 참조를 가지고 있습니다.

이 객체는 다음과 같은 용도로 사용됩니다. track는 배치 작업의 진행 상황입니다.

다음은 BatchableContext에서 제공하는 인스턴스 메서드입니다.

  • getChildJobId(): 이 메서드는 현재 처리 중인 배치 작업의 ID를 반환합니다.
  • getJobId(): 이 메서드는 일괄 작업의 ID를 반환합니다.

다음은 배치 클래스의 구문입니다.

global class MyBatchClass implements Database.Batchable<sObject> {
	global (Database.QueryLocator | Iterable<sObject>) start(Database.BatchableContext bc) {
// collect the batches of records or objects to be passed to execute
}
global void execute(Database.BatchableContext bc, List<P> records){
// process each batch of records
}
global void finish(Database.BatchableContext bc){
// execute any post-processing operations
}
}

Database.executeBatch 메서드

Database.executeBatch 메서드는 배치 클래스를 실행하는 데 사용됩니다.

이 메서드는 처리할 배치 클래스의 인스턴스와 배치 크기를 지정하는 선택적 범위 매개변수, 이렇게 두 개의 매개변수를 받습니다. 범위 매개변수가 지정되지 않으면 기본값인 200이 사용됩니다.

Database.executeBatch의 구문:

Database.executeBatch(myBatchObject, scope)

MyBatchClass라는 이름의 배치 클래스를 실행합니다:

MyBatchClass myBatchObject = new MyBatchClass();
Id batchId = Database.executeBatch(myBatchObject, 100);

데이터베이스.상태

배치 클래스는 기본적으로 상태를 저장하지 않습니다. execute 메서드가 호출될 때마다 객체의 새 복사본이 전달되고 클래스의 모든 변수가 초기화됩니다.

Database.Stateful은 배치 클래스가 상태를 유지하도록 구현되었습니다.

배치 클래스가 다음을 구현하는 경우 데이터베이스상태 저장 인터페이스이므로 모든 인스턴스 변수는 값을 유지하지만 정적 변수는 트랜잭션 간에 초기화됩니다.

배치 처리를 넘어선 비동기 Apex

배치 Apex는 코드를 비동기적으로 실행하는 여러 방법 중 하나일 뿐입니다. Salesforce는 네 가지 비동기 옵션을 제공하며, 적절한 옵션을 선택하는 것은 처리하는 데이터 양과 작업 연결 또는 예약 실행 필요 여부에 따라 달라집니다.

  • 미래 방법론: @future 어노테이션이 붙은 이러한 메서드는 외부 웹 서비스 호출과 같이 간단하고 실행 후 결과를 신경 쓰지 않아도 되는 작업에 가장 적합합니다.
  • 큐어블 에이펙스: Queueable 인터페이스를 구현하고, 복잡한 객체 유형을 허용하며, 작업 ID를 반환하고, 작업 간 연결을 지원합니다.
  • 배치 에이펙스: 위에서 설명한 대로 매우 큰 데이터 볼륨을 청크 단위로 처리합니다.
  • 예정된 Apex: 클래스가 특정 시간에 실행되도록 Schedulable 인터페이스를 구현합니다. 예를 들어 야간 정리 작업과 같은 특정 시간에 실행될 수 있습니다.
타입 가장 좋은 핵심 역량
미래 방법 간단한 설명 한 번 발사하고 잊어버리세요
대기 가능한 Apex 순차적 처리 작업 연결 및 모니터링
배치 에이펙스 수백만 건의 기록 청크 처리
예정된 정점 반복 작업 Cron 기반 타이밍

어떤 실행 모델을 선택하든 모든 거래는 아래에 나열된 플랫폼 전체 거버너 제한을 기준으로 측정됩니다.

Apex 거버너 제한

Apex 거버너 제한은 Apex 런타임 엔진에서 적용하는 제한으로, 폭주하는 Apex 코드 및 프로세스가 공유 리소스를 독점하거나 멀티테넌트 환경에서 다른 사용자의 처리를 방해하지 않도록 하기 위한 것입니다. 이러한 제한은 각 Apex 트랜잭션에 대해 검증됩니다. Salesforce에서 각 Apex 트랜잭션에 대해 정의한 거버너 제한은 다음과 같습니다.

기술설명 한도
동기 트랜잭션에서 수행할 수 있는 SOQL 쿼리 100
비동기 트랜잭션에서 실행할 수 있는 SOQL 쿼리 200
SOQL 쿼리로 검색할 수 있는 레코드 50,000
Database.getQueryLocator로 검색할 수 있는 레코드 10,000
Apex 트랜잭션에서 수행할 수 있는 SOSL 쿼리 20
SOSL 쿼리로 검색할 수 있는 레코드 2,000
Apex 트랜잭션에서 실행할 수 있는 DML 문 150
DML 문, Approval.process 또는 Database.emptyRecycleBin의 결과로 처리될 수 있는 레코드입니다. 10,000
Apex 트랜잭션에서 수행할 수 있는 콜아웃 100
Apex 트랜잭션에서 수행되는 모든 콜아웃에 대한 누적 시간 초과 제한 120 초
System.enqueueJob을 사용하여 큐에 추가할 수 있는 Apex 작업 수에 대한 제한 50
각 Apex 트랜잭션의 실행 시간 제한 10 분
Apex 클래스 및 트리거에서 사용할 수 있는 문자 수 제한 1 만
동기 트랜잭션에 대한 CPU 시간 제한 10,000 밀리 초
비동기 트랜잭션에 대한 CPU 시간 제한 60,000 밀리 초
전체 힙 크기 6MB(동기식) / 12MB(비동기식)

Apex에서 테스트 클래스를 작성하는 방법

Salesforce는 Apex 코드의 최소 75%가 단위 테스트로 커버되어야만 프로덕션 환경에 배포할 수 있도록 요구하며, 모든 트리거에 대해서도 일정 수준의 테스트 커버리지가 필요합니다. 따라서 테스트 클래스 작성은 선택 사항이 아닌 핵심적인 Apex 기술입니다.

테스트 클래스에는 `@isTest` 어노테이션이 지정되고, 각 테스트 메서드에도 `@isTest` 어노테이션이 표시됩니다. 테스트 메서드는 데이터베이스에 데이터를 커밋하지 않으며 대부분의 기존 조직 데이터를 볼 수 없으므로 각 테스트는 자체적으로 레코드를 생성합니다. `Test.startTest()` 및 `Test.stopTest()` 메서드는 테스트 대상 코드에 새로운 거버너 제한 값을 적용하고, 어설션을 통해 로직이 예상대로 동작하는지 검증합니다.

다음은 계정 생성 로직을 위한 간단한 테스트 클래스입니다.

@isTest
private class AccountHandlerTest {
    @isTest
    static void testCreateAccount() {
        Account acc = new Account(Name = 'Test Account');
        Test.startTest();
        insert acc;
        Test.stopTest();
        Account result = [SELECT Id, Name FROM Account WHERE Id = :acc.Id];
        System.assertEquals('Test Account', result.Name);
    }
}

시험 문제를 작성할 때는 다음 지침을 따르세요.

  • 클래스의 모든 테스트 메서드에 대해 공유 테스트 데이터를 한 번만 생성하려면 `@testSetup` 메서드를 사용하십시오.
  • 한 개만 삽입하지 말고 200개를 삽입하여 대량 삽입 동작을 테스트하세요.
  • 긍정적 시나리오, 부정적 시나리오, 그리고 사용자 제한 시나리오를 모두 다룹니다.
  • 항상 의미 있는 System.assert 문을 포함하십시오. 어설션이 없는 코드 커버리지는 아무것도 증명하지 못합니다.

Apex 최고의 사례

초보자들은 흔히 하나의 레코드에는 제대로 작동하지만 실제 대량 작업에서는 실패하는 Apex 코드를 작성합니다. 아래의 모범 사례를 따르면 코드가 가버너 제한 내에 유지되고 유지 관리가 더 쉬워집니다.

  • 모든 것을 대량 생산하세요: 트리거는 한 번에 최대 200개의 레코드를 처리할 수 있으므로 레코드 모음을 처리하는 로직을 작성해야 합니다.
  • SOQL과 DML 쿼리를 반복문에서 제외하세요: 반복문 전에 쿼리를 실행하고, 변경 사항을 목록에 수집한 다음, 반복문 실행 후에 하나의 DML 문을 실행합니다.
  • 객체당 하나의 트리거: 트리거에 로직을 넣지 말고 핸들러 클래스에 작업을 위임하여 실행 순서를 예측 가능하게 만드세요.
  • 공유와 함께 사용하세요: 시스템 컨텍스트에서 실행해야 할 명확한 이유가 없는 한, 레코드 수준 보안을 적용하십시오.
  • ID를 하드코딩하지 마세요: 샌드박스와 프로덕션 환경에서 레코드 ID가 다르므로, 레코드 ID를 조회하거나 사용자 지정 메타데이터를 사용하십시오.
  • 코드에서 모니터링 제한 사항 설정: Limits 클래스의 메서드(예: Limits.getQueries())를 사용하면 런타임에 리소스 사용량을 확인할 수 있습니다.

💡 Tip 배포하기 전에 샌드박스 환경에서 200개 레코드를 대상으로 코드를 실행해 보세요. 대부분의 거버너 제한 오류는 대량 처리 시에만 발생하므로, 프로덕션 환경에서 디버깅하는 것보다 초기에 발견하는 것이 훨씬 비용 효율적입니다.

자주 묻는 질문

아니요. Apex는 차용합니다. Java구문은 비슷하지만 대소문자를 구분하지 않고 Salesforce Lightning Platform에서만 실행되며 SOQL을 언어에 직접 통합하고 트랜잭션별 제한이 적용됩니다. Java 이 없습니다.

Salesforce 개발자 에디션 조직에 무료로 가입하세요. 이 조직에는 개발자 콘솔이 포함되어 있으며, 실습 예제를 따라해 볼 수 있습니다. 트레일 헤드세일즈포스의 공식 학습 플랫폼입니다.

Visualforce는 사용자 인터페이스 페이지를 구축하기 위한 마크업 언어이고, Apex는 이러한 페이지의 로직을 구현하는 서버 측 언어입니다. Visualforce 페이지는 종종 Apex 컨트롤러 클래스를 호출하여 데이터를 조회하고 업데이트합니다.

예. Agentforce for DevelopersSalesforce의 AI 비서 Visual Studio Code자연어 프롬프트에서 Apex 코드를 생성하고 설명합니다. AI가 생성한 코드는 배포하기 전에 항상 거버너 제한을 준수하는지 검토하고 테스트하십시오.

@InvocableMethod 어노테이션으로 표시된 Apex 클래스는 사용자 지정 작업으로 노출될 수 있으므로 Einstein 봇과 Agentforce 에이전트가 비즈니스 로직을 호출할 수 있으며, Apex는 플랫폼 API를 통해 Einstein 프롬프트 템플릿과 AI 모델을 호출할 수도 있습니다.

이 게시물을 요약하면 다음과 같습니다.