안녕하세요, 루카입니다. 오늘은 가상 학원 Luka MCA Lab의 데이터 모델을 org에 만들고 가상 데이터를 넣어 보겠습니다.


Salesforce CLI는 파일로 정의한 오브젝트를 org에 배포하고, 데이터 파일의 레코드를 한 번에 넣는 명령줄 도구입니다.

시연 org는 만료되므로, 새 org에서도 같은 오브젝트와 데이터를 명령 몇 줄로 다시 세울 수 있어야 합니다.

착수, 데이터, 마케팅, 운영, 제품 다섯 단계가 이어진 진행 지도에서 데이터 단계를 강조하고 이번 편을 오브젝트 배포와 가상 데이터로 표시한 그림
프로젝트 진행 지도

 

이런 독자에게: 정해 둔 데이터 모델을 시연 org에 세워야 하는 Salesforce 관리자와 구축 컨설턴트에게 맞습니다.

준비할 것

  • org와 CLI: Salesforce CLI로 로그인한 org가 필요합니다. 준비는 PRJ-02와 같습니다. 이 글의 명령은 org 별칭으로 my-org를 씁니다.
  • Marketing Cloud Next: Prospect 오브젝트를 쓰려면 Marketing Cloud Next가 켜진 org여야 합니다.
  • 권한: 오브젝트 배포와 권한 집합 할당을 할 수 있는 시스템 관리자 권한이 필요합니다. Campaign을 넣을 사용자는 Marketing User 표시가 켜져 있어야 합니다. 이 org의 관리자는 이미 켜져 있었습니다.
  • 데이터 모델: 오브젝트 3개와 그 사이의 참조는 PRJ-03에서 정했습니다.

완료 확인: 오브젝트별 COUNT 조회 결과가 계획한 수와 같고, 과정 레코드 화면의 관련 목록에 관심 과정과 수강 신청이 보이면 끝입니다.

세우는 방법

오브젝트와 필드는 소스로 배포하고, 서로 참조하는 가상 데이터는 넣을 순서를 적은 계획 파일로 넣습니다.

소스는 오브젝트와 필드의 정의를 담은 sfdx 프로젝트의 파일입니다. 배포는 그 소스를 org에 올리는 일입니다. 계획 파일은 레코드를 넣을 순서를 적은 JSON입니다. 레코드를 org에 만드는 일은 이 글에서 넣기라고 부릅니다.

오브젝트와 필드는 소스로 씁니다. Setup 화면에서 손으로 만들면 새 org에서 다시 세울 때 빠뜨리기 쉽습니다.

오브젝트를 어떻게 세울지 묻고, Setup 화면에서 만들기, 화면에서 하나 만든 뒤 회수해 본뜨기, 소스로 직접 쓰기 세 선택지를 비교한 뒤, 소스를 고른 이유와 대가를 정리한 판단 카드
판단 카드: 오브젝트를 세우는 방법

 

가상 데이터는 Campaign, Account, Contact, Prospect, 과정, 관심 과정, 수강 신청 일곱 오브젝트에 넣습니다. 이 가운데 Contact, 과정, 관심 과정, 수강 신청은 앞에서 넣은 레코드를 가리킵니다. 오브젝트마다 따로 넣으면 그 레코드의 ID를 손으로 옮겨야 하므로 계획 파일로 넣습니다.

도움말에 따르면 Prospect는 Data Import Wizard를 지원하지 않습니다. Prospects 탭의 Import로는 CSV 파일의 Prospect만 넣을 수 있습니다.

가상 데이터를 어떻게 넣을지 묻고, Data Import Wizard, Prospects 탭의 Import, External ID와 upsert bulk, 계획 파일 네 선택지를 비교한 뒤, 계획 파일을 고른 이유와 대가를 정리한 판단 카드
판단 카드: 가상 데이터를 넣는 방법

 

일의 대부분은 소스와 데이터 파일을 쓰는 것입니다. 파일을 쓴 뒤에는 명령 네 개를 실행합니다. 명령의 \는 bash에서 줄을 잇는 기호이고, 다른 셸에서는 한 줄로 이어 씁니다.

  • 검증: 배포 전에 소스가 맞는지 확인합니다.
  • 배포: 소스를 org에 올립니다.
  • 권한 집합 할당: 새 필드를 쓸 수 있게 합니다.
  • 넣기: 계획 파일의 레코드를 넣습니다.

오브젝트 배포

Prospect에는 커스텀 필드를 배포할 수 있었지만, 커스텀 오브젝트에서 Prospect를 가리키는 Lookup 필드는 검증에서 거절됐습니다.

1. 소스를 씁니다

오브젝트마다 정의 파일을 하나 둡니다. 필드마다 파일을 하나씩 둡니다. Prospect는 표준 오브젝트라 필드 파일만 둡니다.

force-app/main/default/
  objects/
    LUKA_Course__c/
      LUKA_Course__c.object-meta.xml
      fields/
    LUKA_CourseInterest__c/
    LUKA_Enrollment__c/
    Prospect/
      fields/
  layouts/
  permissionsets/
data/
  plan.json
  Course.json …
sfdx-project.json

과정 오브젝트, 권한 집합, 계획 파일, 과정 데이터 파일의 전문은 이 글의 접기에 실었습니다. 나머지 오브젝트와 데이터 파일은 같은 형식으로 씁니다.

Prospect에는 문의 유형과 관심 과정 코드 필드를 만듭니다. MCN 양식(Form)은 참조 필드를 쓸 수 없습니다. 그래서 문의자가 고른 관심 과정을 코드로 받습니다.

더보기
오브젝트 필드 유형 메모
과정 LUKA_Course__c 과정 이름(Name) Text(80) 데이터 파일이 넣습니다
  과정 코드 LUKA_Code__c Text(20), Unique, External ID 양식이 받는 값이자 고유 키에 들어가는 코드
  개강일 LUKA_StartDate__c Date  
  지점 LUKA_Branch__c Picklist(강남, 분당, 온라인) 지점은 과정의 필드
  캠페인 LUKA_Campaign__c Lookup(Campaign), 삭제 시 비움 과정마다 캠페인 하나
관심 과정 LUKA_CourseInterest__c 관심 과정 번호(Name) Auto Number CI-{0000} 데이터 파일에 넣지 않습니다
  과정 LUKA_Course__c Lookup(과정), 필수, 삭제 제한  
  Contact LUKA_Contact__c Lookup(Contact), 삭제 시 비움 이번 데이터에는 넣지 않았습니다
  고유 키 LUKA_UniqueKey__c Text(120), Unique, External ID 값은 문의자 이메일, 세로 막대, 과정 코드 순
수강 신청 LUKA_Enrollment__c 수강 신청 번호(Name) Auto Number EN-{0000}  
  과정 LUKA_Course__c Lookup(과정), 필수, 삭제 제한  
  수강생 LUKA_Student__c Lookup(Contact), 삭제 시 비움 관계 이름 LUKA_StudentEnrollments
  연락 대상 LUKA_ContactPerson__c Lookup(Contact), 삭제 시 비움 관계 이름 LUKA_ContactEnrollments. 14세 미만은 학부모
  마지막 수강일 LUKA_LastAttendedDate__c Date  
Prospect(표준) 문의 유형 LUKA_InquiryType__c Picklist(개인, 기업)  
  관심 과정 코드 LUKA_InterestCourse__c Text(20)  

수강 신청은 Contact를 두 번 참조하므로 관계 이름을 따로 붙였습니다. 참조 필드는 모두 Lookup입니다. 관심 과정의 Contact처럼 비어 있을 수 있는 참조가 있어서 Master-Detail은 쓰지 않았습니다.

관심 과정은 Prospect를 Lookup으로 가리키지 않습니다. 이 org에서 관심 과정에 둔 Prospect Lookup 필드는 검증 단계에서 거절됐습니다. 그래서 PRJ-03에서 정한 Prospect 참조를 이메일이 든 고유 키로 바꿨습니다.

문의자와 관심 과정을 어떻게 이을지 묻고, Prospect 참조, Prospect ID를 텍스트 필드에 저장, 이메일이 든 고유 키 세 선택지를 비교한 뒤, 이메일이 든 고유 키를 고른 이유와 대가를 정리한 판단 카드
판단 카드: 문의자와 관심 과정을 잇는 방법

 

고유 키는 문의자 이메일과 과정 코드를 |로 이은 값입니다. 같은 문의자가 같은 과정을 두 번 고르는 일도 이 키가 막습니다.

더보기

LUKA_Course__c.object-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
    <allowInChatterGroups>false</allowInChatterGroups>
    <compactLayoutAssignment>SYSTEM</compactLayoutAssignment>
    <deploymentStatus>Deployed</deploymentStatus>
    <enableActivities>false</enableActivities>
    <enableBulkApi>true</enableBulkApi>
    <enableFeeds>false</enableFeeds>
    <enableHistory>false</enableHistory>
    <enableReports>true</enableReports>
    <enableSearch>true</enableSearch>
    <enableSharing>true</enableSharing>
    <enableStreamingApi>true</enableStreamingApi>
    <label>과정</label>
    <nameField>
        <label>과정 이름</label>
        <trackHistory>false</trackHistory>
        <type>Text</type>
    </nameField>
    <pluralLabel>과정</pluralLabel>
    <searchLayouts></searchLayouts>
    <sharingModel>ReadWrite</sharingModel>
    <visibility>Public</visibility>
</CustomObject>

fields/LUKA_Code__c.field-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
    <fullName>LUKA_Code__c</fullName>
    <label>과정 코드</label>
    <externalId>true</externalId>
    <length>20</length>
    <required>false</required>
    <type>Text</type>
    <unique>true</unique>
</CustomField>

fields/LUKA_StartDate__c.field-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
    <fullName>LUKA_StartDate__c</fullName>
    <label>개강일</label>
    <required>false</required>
    <type>Date</type>
</CustomField>

fields/LUKA_Branch__c.field-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
    <fullName>LUKA_Branch__c</fullName>
    <label>지점</label>
    <required>false</required>
    <type>Picklist</type>
    <valueSet>
        <restricted>true</restricted>
        <valueSetDefinition>
            <sorted>false</sorted>
            <value>
                <fullName>강남</fullName>
                <default>false</default>
                <label>강남</label>
            </value>
            <value>
                <fullName>분당</fullName>
                <default>false</default>
                <label>분당</label>
            </value>
            <value>
                <fullName>온라인</fullName>
                <default>false</default>
                <label>온라인</label>
            </value>
        </valueSetDefinition>
    </valueSet>
</CustomField>

fields/LUKA_Campaign__c.field-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
    <fullName>LUKA_Campaign__c</fullName>
    <label>캠페인</label>
    <deleteConstraint>SetNull</deleteConstraint>
    <referenceTo>Campaign</referenceTo>
    <relationshipLabel>과정</relationshipLabel>
    <relationshipName>LUKA_Courses</relationshipName>
    <required>false</required>
    <type>Lookup</type>
</CustomField>

2. 검증하고 배포합니다

먼저 --dry-run을 붙여 검증하고, 통과하면 그 옵션을 빼고 배포합니다.

sf project deploy start --dry-run \
  -d force-app -o my-org \
  --api-version 67.0

sf project deploy start \
  -d force-app -o my-org \
  --api-version 67.0

이번 소스의 구성요소는 오브젝트 3개, 필드 13개, 레이아웃 3개, 권한 집합 1개로 모두 20개입니다. 검증과 배포에서 20개가 모두 통과했습니다.

3. 권한 집합을 할당하고 화면에서 확인합니다

이번 배포 직후에는 시스템 관리자에게도 새 필드의 권한이 없었습니다. 그래서 필드 권한을 담은 권한 집합을 소스에 함께 넣었습니다. 데이터를 넣기 전에 이 권한 집합을 할당합니다.

sf org assign permset \
  -n LUKA_MCA_Lab_Data -o my-org
더보기

필드 13개 가운데 필수 Lookup 필드 두 개는 필드 권한 목록에 없습니다. 관심 과정의 과정 필드와 수강 신청의 과정 필드입니다. 시연 데이터를 다루기 위해 세 오브젝트의 모든 레코드 보기와 수정도 켰습니다.

<?xml version="1.0" encoding="UTF-8"?>
<PermissionSet xmlns="http://soap.sforce.com/2006/04/metadata">
    <hasActivationRequired>false</hasActivationRequired>
    <label>LUKA_MCA_Lab_Data</label>
    <fieldPermissions>
        <editable>true</editable>
        <field>LUKA_Course__c.LUKA_Code__c</field>
        <readable>true</readable>
    </fieldPermissions>
    <fieldPermissions>
        <editable>true</editable>
        <field>LUKA_Course__c.LUKA_StartDate__c</field>
        <readable>true</readable>
    </fieldPermissions>
    <fieldPermissions>
        <editable>true</editable>
        <field>LUKA_Course__c.LUKA_Branch__c</field>
        <readable>true</readable>
    </fieldPermissions>
    <fieldPermissions>
        <editable>true</editable>
        <field>LUKA_Course__c.LUKA_Campaign__c</field>
        <readable>true</readable>
    </fieldPermissions>
    <fieldPermissions>
        <editable>true</editable>
        <field>LUKA_CourseInterest__c.LUKA_Contact__c</field>
        <readable>true</readable>
    </fieldPermissions>
    <fieldPermissions>
        <editable>true</editable>
        <field>LUKA_CourseInterest__c.LUKA_UniqueKey__c</field>
        <readable>true</readable>
    </fieldPermissions>
    <fieldPermissions>
        <editable>true</editable>
        <field>LUKA_Enrollment__c.LUKA_Student__c</field>
        <readable>true</readable>
    </fieldPermissions>
    <fieldPermissions>
        <editable>true</editable>
        <field>LUKA_Enrollment__c.LUKA_ContactPerson__c</field>
        <readable>true</readable>
    </fieldPermissions>
    <fieldPermissions>
        <editable>true</editable>
        <field>LUKA_Enrollment__c.LUKA_LastAttendedDate__c</field>
        <readable>true</readable>
    </fieldPermissions>
    <fieldPermissions>
        <editable>true</editable>
        <field>Prospect.LUKA_InquiryType__c</field>
        <readable>true</readable>
    </fieldPermissions>
    <fieldPermissions>
        <editable>true</editable>
        <field>Prospect.LUKA_InterestCourse__c</field>
        <readable>true</readable>
    </fieldPermissions>
    <objectPermissions>
        <allowCreate>true</allowCreate>
        <allowDelete>true</allowDelete>
        <allowEdit>true</allowEdit>
        <allowRead>true</allowRead>
        <modifyAllRecords>true</modifyAllRecords>
        <object>LUKA_Course__c</object>
        <viewAllRecords>true</viewAllRecords>
    </objectPermissions>
    <objectPermissions>
        <allowCreate>true</allowCreate>
        <allowDelete>true</allowDelete>
        <allowEdit>true</allowEdit>
        <allowRead>true</allowRead>
        <modifyAllRecords>true</modifyAllRecords>
        <object>LUKA_CourseInterest__c</object>
        <viewAllRecords>true</viewAllRecords>
    </objectPermissions>
    <objectPermissions>
        <allowCreate>true</allowCreate>
        <allowDelete>true</allowDelete>
        <allowEdit>true</allowEdit>
        <allowRead>true</allowRead>
        <modifyAllRecords>true</modifyAllRecords>
        <object>LUKA_Enrollment__c</object>
        <viewAllRecords>true</viewAllRecords>
    </objectPermissions>
</PermissionSet>

Setup의 Object Manager에서 LAST MODIFIED 열 머리를 두 번 눌러 최근 순으로 정렬합니다. 배포한 오브젝트 세 개가 맨 위에 보입니다.

Quick Find에 API 이름 앞부분인 LUKA를 넣었을 때는 결과가 없었습니다. 한글 라벨인 과정을 넣었을 때는 보였습니다.

Object Manager 목록을 마지막 수정 순으로 정렬한 화면에서 수강 신청, 과정, 관심 과정 세 커스텀 오브젝트의 행이 주황 상자로 강조되어 있다
Object Manager의 새 오브젝트 3개

 

과정의 Fields & Relationships에는 개강일, 과정 코드, 지점, 캠페인이 있습니다. 과정 코드의 데이터 유형에는 External ID와 Unique가 표시됩니다.

과정 오브젝트의 Fields and Relationships 목록에서 개강일, 과정 이름, 과정 코드, 지점, 캠페인 다섯 행이 주황 상자로 강조되어 있다
과정의 필드

 

Prospect의 Fields & Relationships에서 FIELD LABEL 열을 내림차순으로 정렬하면, 문의 유형과 관심 과정 코드가 표준 필드와 함께 위쪽에 보입니다.

Prospect 오브젝트의 Fields and Relationships 목록에서 문의 유형과 관심 과정 코드 두 필드가 주황 상자로 강조되어 있다
Prospect의 새 필드 2개

 


가상 데이터

데이터 파일이 앞 파일의 레코드를 참조 ID로 가리키므로, Campaign부터 수강 신청까지 89건을 레코드 ID 없이 명령 한 줄로 넣습니다.

1. 넣을 순서를 정합니다

계획 파일은 적힌 순서대로 데이터 파일을 넣습니다. 데이터 파일은 앞에서 넣은 레코드를 참조 ID(referenceId)로 가리킵니다. 그래서 가리키는 파일은 가리키는 대상보다 뒤에 둡니다.

Campaign, Account, Contact, Prospect, 과정, 관심 과정, 수강 신청 일곱 파일을 넣는 순서대로 번호와 건수(6, 8, 20, 15, 6, 20, 14)를 붙여 놓고, Contact가 Account를, 과정이 Campaign을, 관심 과정이 과정을, 수강 신청이 과정과 Contact를 참조 ID로 가리킨다고 파일마다 적은 그림
파일을 넣는 순서와 참조

 

과정 파일의 첫 레코드는 캠페인 필드에 @Camp1을 적습니다. 이 값은 참조 ID가 Camp1인 Campaign 레코드를 가리킵니다.

{
  "attributes": {
    "type": "LUKA_Course__c",
    "referenceId": "Cou1"
  },
  "Name": "LUKA_파이썬 기초 강남",
  "LUKA_Code__c": "GN-PY-2611",
  "LUKA_Campaign__c": "@Camp1"
}
더보기

계획 파일에 적은 나머지 데이터 파일도 과정 파일과 같은 형식입니다.

[
  {
    "sobject": "Campaign",
    "files": [
      "Campaign.json"
    ]
  },
  {
    "sobject": "Account",
    "files": [
      "Account.json"
    ]
  },
  {
    "sobject": "Contact",
    "files": [
      "Contact.json"
    ]
  },
  {
    "sobject": "Prospect",
    "files": [
      "Prospect.json"
    ]
  },
  {
    "sobject": "LUKA_Course__c",
    "files": [
      "Course.json"
    ]
  },
  {
    "sobject": "LUKA_CourseInterest__c",
    "files": [
      "CourseInterest.json"
    ]
  },
  {
    "sobject": "LUKA_Enrollment__c",
    "files": [
      "Enrollment.json"
    ]
  }
]
더보기
{
  "records": [
    {
      "attributes": {
        "type": "LUKA_Course__c",
        "referenceId": "Cou1"
      },
      "Name": "LUKA_파이썬 기초 강남",
      "LUKA_Code__c": "GN-PY-2611",
      "LUKA_StartDate__c": "2026-11-02",
      "LUKA_Branch__c": "강남",
      "LUKA_Campaign__c": "@Camp1"
    },
    {
      "attributes": {
        "type": "LUKA_Course__c",
        "referenceId": "Cou2"
      },
      "Name": "LUKA_데이터 분석 강남",
      "LUKA_Code__c": "GN-DS-2612",
      "LUKA_StartDate__c": "2026-12-07",
      "LUKA_Branch__c": "강남",
      "LUKA_Campaign__c": "@Camp2"
    },
    {
      "attributes": {
        "type": "LUKA_Course__c",
        "referenceId": "Cou3"
      },
      "Name": "LUKA_파이썬 기초 분당",
      "LUKA_Code__c": "BD-PY-2611",
      "LUKA_StartDate__c": "2026-11-16",
      "LUKA_Branch__c": "분당",
      "LUKA_Campaign__c": "@Camp3"
    },
    {
      "attributes": {
        "type": "LUKA_Course__c",
        "referenceId": "Cou4"
      },
      "Name": "LUKA_데이터 분석 분당",
      "LUKA_Code__c": "BD-DS-2701",
      "LUKA_StartDate__c": "2027-01-11",
      "LUKA_Branch__c": "분당",
      "LUKA_Campaign__c": "@Camp4"
    },
    {
      "attributes": {
        "type": "LUKA_Course__c",
        "referenceId": "Cou5"
      },
      "Name": "LUKA_파이썬 기초 온라인",
      "LUKA_Code__c": "ON-PY-2611",
      "LUKA_StartDate__c": "2026-11-23",
      "LUKA_Branch__c": "온라인",
      "LUKA_Campaign__c": "@Camp5"
    },
    {
      "attributes": {
        "type": "LUKA_Course__c",
        "referenceId": "Cou6"
      },
      "Name": "LUKA_생성형 AI 활용 온라인",
      "LUKA_Code__c": "ON-AI-2701",
      "LUKA_StartDate__c": "2027-01-18",
      "LUKA_Branch__c": "온라인",
      "LUKA_Campaign__c": "@Camp6"
    }
  ]
}
더보기

14세 미만 수강생의 수강 신청은 수강생과 연락 대상인 학부모를 서로 다른 Contact로 둡니다. 두 Contact는 같은 가구 Account를 가리킵니다.

{
  "attributes": {
    "type": "Contact",
    "referenceId": "Par5"
  },
  "FirstName": "서윤",
  "LastName": "LUKA_학부모05",
  "Email": "luka.parent05@example.com",
  "AccountId": "@Acc5"
}
{
  "attributes": {
    "type": "Contact",
    "referenceId": "Stu5"
  },
  "FirstName": "유나",
  "LastName": "LUKA_수강생05",
  "AccountId": "@Acc5"
}
{
  "attributes": {
    "type": "LUKA_Enrollment__c",
    "referenceId": "Enr5"
  },
  "LUKA_Course__c": "@Cou5",
  "LUKA_Student__c": "@Stu5",
  "LUKA_ContactPerson__c": "@Par5",
  "LUKA_LastAttendedDate__c": "2026-08-20"
}
더보기
오브젝트 수 내용
Campaign 6 이름이 LUKA_로 시작하며 과정마다 하나
과정 6 지점 3곳 × 2과정, 개강일은 2026년 11월부터 2027년 1월
Account 8 가구 Account
Contact 20 학부모 8, 14세 이상 수강생 4, 14세 미만 수강생 8(이메일 없음)
Prospect 15 개인 12, 기업 3(Company와 Title 입력)
관심 과정 20 Prospect 15명에게 1개나 2개, 고유 키 입력
수강 신청 14 수강생 12명, 마지막 수강일은 90일을 넘은 것과 넘지 않은 것을 섞음

사람 레코드의 성은 LUKA_로 시작합니다. 이메일은 example.com 주소입니다. 이 org의 Prospect에는 필수 통화 필드인 CurrencyIsoCode가 있습니다. 기본값이 USD라서 데이터 파일에는 통화를 쓰지 않았습니다.

2. 계획 파일로 넣습니다

계획 파일 하나로 Prospect까지 모두 들어갑니다. 이번 시험에서는 89건이 10여 초 만에 들어갔습니다.

sf data import tree \
  --plan data/plan.json \
  -o my-org --api-version 67.0
주의

레코드가 한 건씩인 작은 계획 파일로 두 번 넣어 보았습니다. 두 번째에는 Campaign과 Account가 한 건씩 더 생겼고, Contact는 표준 중복 규칙에 막혀 중단됐습니다. 데이터를 고쳐 다시 넣을 때는 먼저 넣은 LUKA_ 레코드를 지운 뒤 넣습니다.

3. 화면에서 확인합니다

과정에는 탭을 만들지 않았습니다. 그래서 과정 레코드는 주소 /lightning/r/LUKA_Course__c/<레코드 ID>/view로 엽니다. 관련 목록은 소스에 넣은 과정 레이아웃에 들어 있습니다.

Related 탭에는 그 과정을 가리키는 관심 과정과 수강 신청이 보입니다. 과정 코드가 GN-PY-2611인 과정에는 ① 관심 과정 4건과 ② 수강 신청 3건이 이어져 있습니다.

과정 레코드 화면의 Related 탭에서 관심 과정 4건과 수강 신청 3건의 관련 목록이 번호가 달린 주황 상자로 강조되어 있다
과정 레코드의 관련 목록

 

관심 과정 목록의 Contact 열은 이 데이터에 Contact 값을 넣지 않아 비어 있습니다. 채우는 방법은 별도 글에서 다룰 예정입니다.

Prospects 탭의 All Prospects에는 계획 파일로 넣은 Prospect 15건이 있습니다.

Prospects 탭의 All Prospects 목록에서 성이 LUKA_문의로 시작하는 Prospect 15건이 이름, 회사, 이메일, 전화, 만든 날짜 열과 함께 주황 상자로 강조되어 있다
Prospects 탭의 목록

 


지금 상태

오브젝트별 레코드 수가 계획과 같고 과정 화면에 관심 과정과 수강 신청이 이어져 보이면, 다음 단계로 넘어갑니다.

오브젝트마다 COUNT를 조회합니다. Campaign과 Account는 이름이 LUKA_로 시작하는 레코드만 셉니다. Contact와 Prospect는 성이 LUKA_로 시작하는 레코드만 셉니다.

sf data query -o my-org -q \
  "SELECT COUNT() FROM LUKA_Course__c"
Total number of records retrieved: 6.

일곱 오브젝트의 수는 모두 계획과 같았습니다. 아래 세 참조도 모두 채워져 있었습니다.

  • 과정: 캠페인 참조가 있는 과정이 6건입니다.
  • 관심 과정: 과정 참조가 있는 관심 과정이 20건입니다.
  • 수강 신청: 수강생과 연락 대상 참조가 모두 있는 수강 신청이 14건입니다.
더보기
$ sf data query -o my-org -q "SELECT COUNT() FROM Campaign WHERE Name LIKE 'LUKA\_%'"
Total number of records retrieved: 6.
$ sf data query -o my-org -q "SELECT COUNT() FROM LUKA_Course__c"
Total number of records retrieved: 6.
$ sf data query -o my-org -q "SELECT COUNT() FROM Account WHERE Name LIKE 'LUKA\_%'"
Total number of records retrieved: 8.
$ sf data query -o my-org -q "SELECT COUNT() FROM Contact WHERE LastName LIKE 'LUKA\_%'"
Total number of records retrieved: 20.
$ sf data query -o my-org -q "SELECT COUNT() FROM Prospect WHERE LastName LIKE 'LUKA\_%'"
Total number of records retrieved: 15.
$ sf data query -o my-org -q "SELECT COUNT() FROM LUKA_CourseInterest__c"
Total number of records retrieved: 20.
$ sf data query -o my-org -q "SELECT COUNT() FROM LUKA_Enrollment__c"
Total number of records retrieved: 14.
$ sf data query -o my-org -q "SELECT COUNT() FROM LUKA_Course__c WHERE LUKA_Campaign__c != null"
Total number of records retrieved: 6.
$ sf data query -o my-org -q "SELECT COUNT() FROM LUKA_CourseInterest__c WHERE LUKA_Course__c != null"
Total number of records retrieved: 20.
$ sf data query -o my-org -q "SELECT COUNT() FROM LUKA_Enrollment__c WHERE LUKA_Student__c != null AND LUKA_ContactPerson__c != null"
Total number of records retrieved: 14.

이 org에는 이제 오브젝트 3개와 Prospect의 커스텀 필드 2개, 가상 레코드 89건이 있습니다. 이 데이터를 Data Cloud에 연결하는 스트림과 매핑은 별도 글에서 다룰 예정입니다.

더보기
  • 관심 과정의 Prospect 참조(검증): 참조 대상이 Prospect인 Lookup 필드를 두고 검증하자 아래 오류가 났습니다. 이 필드를 쓰는 레이아웃과 권한 집합의 항목도 함께 실패했습니다. 그래서 필드와 그 항목을 소스에서 뺐습니다.
referenceTo value of 'Prospect' does not resolve to a valid sObject type
  • 권한 집합 할당 전의 넣기(INVALID_FIELD): 배포한 뒤 권한 집합을 할당하기 전에 sf data create record로 과정 코드가 든 레코드 한 건을 넣어 보았습니다. 아래 오류가 났습니다. 할당한 뒤에는 같은 명령이 성공했습니다.
No such column 'LUKA_Code__c' on sobject of type LUKA_Course__c
  • 같은 고유 키(DUPLICATE_VALUE): 고유 키가 같은 관심 과정을 한 건 더 넣으면 거절됩니다. 과정 코드가 같은 과정을 넣을 때도 같은 형식의 오류가 납니다. 오류 속 필드 이름만 다릅니다.
duplicate value found: LUKA_UniqueKey__c duplicates value on record with id: <id>
  • 같은 계획 파일을 다시 실행: 작은 실험용 계획 파일의 두 번째 실행은 Contact에서 표준 중복 규칙에 막혀 중단됐습니다. 아래는 --json 출력의 상태 코드와 메시지입니다.
Data Import failed
StatusCode: DUPLICATES_DETECTED
Message: Use one of these records?
더보기
오브젝트를 파일로 쓰는 이유, 검증·배포·권한 집합 할당·넣기 네 명령, 오브젝트 3개와 필드 13개 등 20개의 배포와 거절된 Prospect 참조, 일곱 오브젝트 89건을 넣는 순서, 레코드 수와 과정 화면의 관련 목록 확인을 차례로 그린 그림
그림으로 쉽게 보는 요약

 

참고 문서