Skip to main content
Dreamforce가 9월 17일부터 19일까지 샌프란시스코에서 열립니다. 지금 바로 등록하셔서 DF24TRAIL20 코드를 사용해 20%의 할인 혜택을 받으세요

사용자 정의 컨트롤러 만들기 및 사용

학습 목표

이 유닛을 완료하면 다음을 수행할 수 있습니다.

  • 사용자 정의 컨트롤러가 무엇인지 설명하고 주요 속성을 설명할 수 있습니다.
  • 사용자 정의 컨트롤러 클래스를 만들 수 있습니다.
  • Visualforce 페이지에서 사용자 정의 컨트롤러를 사용할 수 있습니다.
참고

참고

한국어로 학습하시겠어요? 이 배지에서는 Trailhead 실습 과제 검증이 영어로 진행됩니다. 참조용 번역이 괄호로 제공됩니다. Trailhead Playground에서 (1) 로캘을 미국으로 바꾸고 (2) 언어를 영어로 바꾼 후 (3) 영문으로 표시된 값을 복사해 붙여 넣으세요. 여기에 나와 있는 지침을 따르세요.

원하는 언어로 Trailhead 사용하기 배지를 확인해 현지화된 Trailhead 경험을 활용하는 방법에 대해 자세히 알아보세요.

사용자 정의 컨트롤러 소개

Visualforce 페이지에 <apex:page> controller(컨트롤러) 속성의 컨트롤러 클래스의 이름을 참조하여 사용자 정의 컨트롤러를 추가합니다.

페이지에서 사용자 정의 컨트롤러를 사용하는 경우 표준 컨트롤러를 사용할 수 없습니다. 페이지는 다른 속성을 사용하여 사용자 정의 컨트롤러를 설정합니다.

  1. Developer Console을 열고 File(파일) | New(새로 만들기) | Visualforce Page(Visualforce 페이지)를 클릭하여 새 Visualforce 페이지를 만듭니다. 페이지 이름으로 ContactListWithController를 입력합니다.
  2. 편집기에서 모든 마크업을 다음으로 바꿉니다.
    <apex:page controller="ContactsListWithController">
        <apex:form>
            <apex:pageBlock title="Contacts List" id="contacts_list">
                <!-- Contacts List goes here -->
            </apex:pageBlock>
        </apex:form>
    </apex:page>
    이 페이지를 저장하려고 하면 ContactsListWithController가 아직 존재하지 않으므로 오류가 발생합니다. 걱정하지 마세요. 다음에 수정해 보겠습니다.

사용자 정의 컨트롤러 Apex 클래스 만들기

사용자 정의 컨트롤러는 Developer Console을 사용하여 직접 작성하는 Apex 클래스일 뿐입니다.

사용자 정의 컨트롤러 논리를 작성하는 데 도움이 되는 많은 시스템 및 유틸리티 클래스가 있지만 유일한 요구 사항 클래스가 사용자 정의 컨트롤러로 사용되기 위해서는 클래스가 있어야 합니다.

  1. Developer Console을 열고 File(파일) | New(새로 만들기) | Apex Class(Apex 클래스)를 클릭하여 새 Apex 클래스를 만듭니다. 클래스 이름에 ContactsListWithController를 입력합니다.

편집기에서 모든 코드를 다음으로 바꿉니다.

public class ContactsListWithController {
// Controller code goes here
}

Visualforce 페이지와 마찬가지로 변경 시 Apex에 변경 사항을 저장해야 합니다. 많지도 않고 아직 아무것도 하지 않고 있지만 Visualforce 페이지에서 오류가 사라지도록 합니다.

  1. Visualforce 페이지로 다시 전환하고 다시 저장합니다. 오류 메시지가 사라지고 페이지가 성공적으로 저장됩니다.
  2. Preview(미리보기)를 클릭하여 변경 시 볼 수 있는 페이지 미리보기를 엽니다. 표준 Salesforce 페이지 머리글 및 사이드바 요소를 표시하지만 아직 컨텐츠가 없는 새 창이 열려야 합니다.

즉, 이 두 개의 새로운 아이템은 그다지 흥미롭지 않아 보입니다. 하지만 90% 자리 표시자 코드이더라도 두 항목(Visualforce 페이지 및 Apex 컨트롤러)은 서로 연결되어 있습니다. 컨트롤러에 코드를 더 추가하자마자 페이지에서 사용할 수 있습니다.

추가 기본 정보

이 사용자 정의 컨트롤러 클래스가 다른 클래스에서 상속되지 않으며 Visualforce 컨트롤러의 요구 사항을 준수하도록 약속하는 인터페이스를 구현하지 않는다는 것을 눈치채셨을 것입니다. 복잡한 컨트롤러도 이러한 작업을 수행하지 않습니다. 상속할 클래스나 구현할 인터페이스가 없기 때문입니다. 따라서 Apex에 대한 익스피리언스가 늘어남에 따라 나만의 클래스와 인터페이스를 자유롭게 만들 수 있습니다.

레코드 검색에 메서드 추가

페이지에 표시할 레코드를 반환하는 SOQL 쿼리를 실행하는 getter 메서드를 만듭니다.

대부분의 컨트롤러의 주요 목적은 표시할 데이터를 검색하거나 데이터 업데이트를 처리하는 것입니다. 이 간단한 컨트롤러에서 연락처 레코드를 찾는 기본 SOQL 쿼리를 실행한 다음 Visualforce 페이지에서 해당 레코드를 사용할 수 있도록 합니다.

  1. ContactsListWithController 클래스에서 // Controller code goes here 코멘트 라인을 다음 코드로 변경합니다.
    private String sortOrder = 'LastName';
    public List<Contact> getContacts() {
        List<Contact> results = Database.query(
            'SELECT Id, FirstName, LastName, Title, Email ' +
            'FROM Contact ' +
            'ORDER BY ' + sortOrder + ' ASC ' +
            'LIMIT 10'
        );
        return results;
    }
    이 코드는 비공개 구성원 변수 하나인 sortOrder 및 하나의 공개 메서드인 getContacts() 이름을 가진 문자열을 추가합니다. sortOrder는 매우 이해하기 쉽고 연락처를 정렬할 필드의 이름일 뿐입니다. 또한 getContacts()는 상당히 간단하지만 이전에 Apex를 본 적이 없다면 처음에는 구문 분석이 어려울 수 있습니다. 메서드의 효과는 SOQL 쿼리를 수행하여 연락처 레코드 목록을 가져온 다음 해당 연락처 목록을 메서드 호출자에게 반환하는 것입니다. 그러면 발신자는 누구인가요? 물론 Visualforce 페이지입니다.
  2. ContactsListWithController 페이지에서 <!-- Contacts List goes here --> 코멘트 줄을 다음 마크업으로 변경합니다.
    <!-- Contacts List -->
    <apex:pageBlockTable value="{! contacts }" var="ct">
        <apex:column value="{! ct.FirstName }"/>
        <apex:column value="{! ct.LastName }"/>
        <apex:column value="{! ct.Title }"/>
        <apex:column value="{! ct.Email }"/>
    </apex:pageBlockTable>
    이 페이지를 저장하면 친숙한 연락처 정보 테이블이 표시됩니다. 사용자 정의 컨트롤러가 지원하는 연락처 목록

ContactsListWithController 페이지에 대한 마크업은 상당히 친숙할 수 있습니다. <apex:page> 태그의 controller 속성을 제외하면 표준 컨트롤러로 페이지를 만드는 데 사용하는 것과 거의 동일한 코드입니다.

다른 점은 {!contacts } 표현식을 평가할 경우와 같은 경우에 발생합니다. 이 페이지에서 Visualforce는 해당 표현식을 컨트롤러 getContacts() 메서드에 대한 호출로 변환합니다. 이 메서드는 <apex:pageBlockTable>이 정확하게 예상되는 연락처 레코드 목록을 반환합니다.

getContacts() 메서드는 getter 메서드라고 하는 일반적인 패턴이며 여기에서 Visualforce 마크업의 {!someExpression }에서 자동으로 컨트롤러의 getSomeExpression()이라 이름이 지정된 메서드에 연결합니다. 페이지가 표시해야 하는 데이터에 액세스할 수 있는 가장 간단한 방법입니다.

새 작업 메서드 추가

페이지의 사용자 입력에 응답하기 위해 사용자 정의 컨트롤러에서 작업 메서드를 만듭니다.

데이터 표시는 훌륭하지만 사용자 작업에 응답하는 것은 모든 웹 앱에 필수적입니다. 사용자 정의 컨트롤러를 사용하면 사용자 활동에 응답하는 작업 메서드를 작성하여 페이지에서 지원하려는 만큼 사용자 정의 작업을 만들 수 있습니다.

  1. ContactsListWithController 클래스에서 getContacts() 메서드 아래에 다음 두 가지 메서드를 추가합니다.
    public void sortByLastName() {
        this.sortOrder = 'LastName';
    }
    public void sortByFirstName() {
        this.sortOrder = 'FirstName';
    }
    이 두 가지 메서드는 sortOrder 비공개 변수의 값을 변경합니다. sortOrder를 변경하면 결과 순서를 변경하여 sortOrder는 연락처를 검색하는 SOQL 쿼리에 사용됩니다.
  2. ContactsListWithController 페이지에서 ct.FirstNamect.LastName에 대한 두 개의 <apex:column> 태그를 다음 마크업으로 변경합니다.
    <apex:column value="{! ct.FirstName }">
        <apex:facet name="header">
            <apex:commandLink action="{! sortByFirstName }"
                reRender="contacts_list">First Name
            </apex:commandLink>
        </apex:facet>
    </apex:column>
    <apex:column value="{! ct.LastName }">
        <apex:facet name="header">
            <apex:commandLink action="{! sortByLastName }"
                reRender="contacts_list">Last Name
            </apex:commandLink>
        </apex:facet>
    </apex:column>
    시각적 모양은 동일하게 유지되지만 지금 이름 및 성 열 머리글을 클릭하면 연락처 목록의 정렬 순서가 변경됩니다. 잘 하셨습니다.

새 마크업은 두 개의 중첩된 구성 요소를 각 <apex:column> 구성 요소로 추가합니다. <apex:column>은 그 자체로 일반 텍스트 헤더가 있지만 헤더를 클릭하도록 설정할 수 있습니다. <apex:facet>를 사용하면 열 헤더의 내용을 원하는 대로 설정할 수 있습니다. 또한 올바른 작업 메소드를 호출하는 링크입니다. 링크는 컨트롤러의 작업 메서드를 참조하는 표현식으로 설정된 action 속성을 포함하여 <apex:commandLink> 구성 요소를 사용하여 만들었습니다. (getter 메서드와 달리 작업 메서드는 이를 참조하는 표현식과 이름이 동일합니다.)

링크를 클릭하면 컨트롤러에서 작업 메서드가 실행됩니다. 작업 메서드는 정렬 순서 개인 변수를 변경한 다음 테이블을 다시 렌더링합니다. 테이블이 다시 렌더링되면 {!contacts }은(는) 설정된 정렬 순서로 쿼리를 다시 실행합니다. 최종 결과는 테이블이 사용자의 클릭이 요청한 순서대로 재정렬된다는 것입니다.

추가 기본 정보

이름 및 성 열에 대한 헤더 텍스트는 이 마크업에서 하드 코딩됩니다. 하지만 모든 사용자가 영어를 사용하지 않는다면 어떻게 될까요? 표준 Salesforce 사용자 인터페이스에는 모든 표준 개체에 대해 번역된 버전의 필드 이름이 있으며 사용자 정의 개체에 대해 고유한 번역을 제공할 수 있습니다. 어떻게 액세스할 수 있나요? 일반 텍스트 대신 <apex:outputText value="{!$ObjectType.Contact.Fields.FirstName.Label }"/> 마크업을 사용해 보세요. 조직에서 모두 동일한 언어를 사용하더라도 필드 이름이 변경되면 자동으로 업데이트되기 때문에 필드 레이블을 참조하는 올바른 방법입니다.

추가 정보 알아보기

사용자 정의 컨트롤러와 Apex 언어를 사용하면 Visualforce 페이지에서 생각할 수 있는 거의 모든 작업을 수행할 수 있습니다.

Getter 메서드는 컨트롤러에서 페이지로 데이터를 가져옵니다. 페이지에서 컨트롤러로 값을 백업할 수 있도록 하는 해당 setter 메서드가 있습니다. getter 메서드와 마찬가지로 setter에 'set'을 접두사로 붙이고 그 외에는 인수를 받는 메서드일 뿐입니다.

getter 및 setter의 대안은 Apex 속성을 사용하는 것입니다. 속성은 변수를 getter 및 setter 메서드와 함께 더 명확하게 그룹화하는 구문과 함께 일종의 조합입니다. 사용자 정의 개체를 참조하는 간단한 속성은 다음과 같이 선언될 수 있습니다.

public MyObject__c myVariable { get; set; }

속성은 공개 또는 비공개일 수 있으며 get 또는 set을 생략하여 읽기 전용 또는 쓰기 전용이 될 수도 있습니다. 또한 단순히 값을 저장하고 검색하는 것 외에 추가 논리를 수행하려는 경우 get 또는 set 메서드에 대한 구현을 만들 수 있습니다.

속성은 Visualforce에만 국한되지 않는 Apex의 일반적인 기능입니다. Apex는 완전한 프로그래밍 언어이며 복잡한 Visualforce 페이지를 구축하기 위한 자연스러운 파트너일 뿐 아니라 다른 많은 Lightning Platform 개발 컨텍스트에서 사용됩니다. Apex를 완벽하게 사용하는 방법을 알아보는 다양한 방법에 대해서는 Apex 주제와 이 페이지 마지막에 있는 리소스를 참조합니다.

Visualforce 요청 및 응답의 수명 주기는 처음에는 복잡해 보일 수 있습니다. 특히 getter 또는 setter(또는 속성을 사용하는 경우 속성)가 호출되는 특정 순서가 없으므로 사이에 실행 순서 종속성을 도입해서는 안 된다는 점을 이해하는 것이 중요합니다. Visualforce 개발자 가이드의 관련 섹션, 특히 사용자 정의 컨트롤러 및 컨트롤러 확장 장에서 더욱 상세한 내용을 확인할 수 있습니다.

리소스