1. 개요
Actions on Google 개발자 플랫폼을 사용하면 스마트 스피커, 스마트폰, 자동차, TV, 헤드폰 등 10억 대 이상의 기기에서 Google의 가상 개인 비서인 Google 어시스턴트의 기능을 확장하는 소프트웨어를 만들 수 있습니다. 사용자는 어시스턴트와의 대화를 통해 식료품 구매, 택시 예약과 같은 작업을 할 수 있습니다. (가능한 작업의 전체 목록은 작업 디렉터리를 참고하세요.) 개발자는 Actions on Google을 사용하여 사용자와 서드 파티 서비스 간의 즐겁고 효과적인 대화 환경을 쉽게 만들고 관리할 수 있습니다.
이 Codelab은 고급 Codelab 모듈로, 이미 Google 어시스턴트 작업을 빌드한 경험이 있는 개발자를 대상으로 합니다. 이전에 Actions on Google을 사용하여 개발해 본 적이 없다면 Google의 입문 Codelab ( 레벨 1, 레벨 2, 레벨 3)에 따라 플랫폼을 숙지하는 것을 적극 권장합니다. 이 고급 모듈에서는 작업의 기능을 확장하여 잠재고객을 확대하는 데 도움이 되는 일련의 기능을 안내합니다.
작업의 성공을 측정하는 중요한 방법 중 하나는 사용자 참여 또는 첫 번째 상호작용 후 사용자를 다시 유도하는 작업의 효과입니다. 이를 더 쉽게 할 수 있도록 작업에 사용자가 대화로 돌아갈 수 있는 경로를 제공하는 여러 기능을 구현할 수 있습니다.
이 Codelab에서는 Google 어시스턴트 앱의 사용자 참여 기능과 권장사항을 다룹니다.

빌드할 항목
이미 빌드된 기능을 다음과 같이 사용 설정하여 기능을 개선합니다.
- 사용자가 탭하여 작업과 대화할 수 있는 일일 업데이트를 전송합니다.
- 사용자에게 작업으로 연결되는 푸시 알림 전송
- 사용자를 모바일 웹브라우저에서 작업으로 연결하는 링크 만들기
학습할 내용
- 사용자 참여란 무엇이며, 작업의 성공에 왜 중요한가요?
- 사용자 참여도를 높이도록 작업을 수정하는 방법
- 다양한 종류의 작업에서 사용할 사용자 참여 기능
- Actions API를 사용하여 어시스턴트를 통해 알림을 보내는 방법
필요한 항목
다음 도구가 있어야 합니다.
- 원하는 IDE/텍스트 편집기(예: WebStorm, Atom, Sublime)
- Node.js, npm, git이 설치된 셸 명령어를 실행하는 터미널
- 웹브라우저(예: Chrome)
- Firebase 명령줄 인터페이스가 설치된 로컬 개발 환경
- 어시스턴트가 설치된 모바일 기기 (Android 또는 iOS)(이 프로젝트를 빌드하는 데 사용할 Google 계정으로 어시스턴트에 로그인해야 함)
웹훅 코드를 이해하려면 JavaScript (ES6)를 능숙하게 다루는 것이 좋지만, 필수사항은 아닙니다.
2. 프로젝트 설정
이 섹션에서는 이전에 빌드한 완전한 작업에 사용자 참여 기능을 추가하는 방법을 보여줍니다.
샘플 이해
이 Codelab의 샘플은 'Action Gym'이라는 가상 헬스장의 간단한 작업입니다. 이 작업은 매일 바뀌는 수업 목록을 비롯해 헬스장에 관한 정보를 제공합니다. 이와 같은 정보 제공 작업은 매일 바뀌는 수업 목록이 유용한 정보를 제공하므로 모든 사용자 참여 기능에 적합합니다.
다음 다이어그램은 Action Gym 샘플의 대화 흐름을 보여줍니다.

추가하는 참여 기능에 맞게 대화상자를 약간 수정합니다. 하지만 대화의 일반적인 디자인은 크게 변경되지 않습니다.
기본 파일 다운로드
다음 명령어를 실행하여 Codelab의 GitHub 저장소를 클론합니다.
git clone https://github.com/actions-on-google/user-engagement-codelab-nodejs
프로젝트 및 에이전트 설정
작업 프로젝트와 Dialogflow 에이전트를 설정하려면 다음 단계를 완료하세요.
- Actions 콘솔을 엽니다.
- 새 프로젝트를 클릭합니다.
- 프로젝트 이름(예:
engagement-codelab)을 입력합니다. - 프로젝트 만들기를 클릭합니다.
- 카테고리를 선택하는 대신 옵션 더보기 섹션으로 스크롤하여 대화형 카드를 클릭합니다.
- 작업 빌드를 클릭하여 옵션을 펼치고 작업 추가를 선택합니다.
- 첫 번째 작업 추가를 클릭합니다.
- 작업 만들기 대화상자에서 맞춤 인텐트를 선택한 다음 빌드를 클릭하여 Dialogflow 콘솔을 실행합니다.
- Dialogflow 콘솔의 에이전트 만들기 페이지에서 만들기를 클릭합니다.
- 왼쪽 탐색에서
(톱니바퀴 아이콘)을 클릭합니다. - 내보내기 및 가져오기를 클릭한 다음 ZIP 파일에서 복원을 클릭합니다.
- 이전에 다운로드한
/user-engagement-codelab-nodejs/start/디렉터리에서agent.zip파일을 업로드합니다. RESTORE를 입력하고 복원을 클릭합니다.- 완료를 클릭합니다.
처리 배포
이제 Actions 프로젝트와 Dialogflow 에이전트가 준비되었으므로 Firebase Functions CLI를 사용하여 로컬 index.js 파일을 배포합니다.
기본 파일 클론의 /user-engagement-codelab-nodejs/start/functions/ 디렉터리에서 다음 명령어를 실행합니다.
firebase use <PROJECT_ID>
npm install
firebase deploy
몇 분 후에 'Deploy complete!'가 표시되어 웹훅이 Firebase에 배포되었음을 나타냅니다.
배포 URL 가져오기
Dialogflow에 클라우드 함수의 URL을 제공해야 합니다. 이 URL을 가져오려면 다음 단계를 따르세요.
- Firebase Console을 엽니다.
- 옵션 목록에서 작업 프로젝트를 선택합니다.
- 왼쪽 탐색 메뉴에서 개발 > 함수로 이동합니다. '데이터 공유 설정 선택' 메시지가 표시되면 나중에 하기를 클릭하여 이 옵션을 무시할 수 있습니다.
- 대시보드 탭에 트리거 아래에 URL이 있는 'fulfillment' 항목이 표시됩니다. 이 URL을 저장합니다. 다음 섹션에서 Dialogflow에 복사해야 합니다.

Dialogflow에서 웹훅 URL 설정
이제 fulfillment에 웹훅을 사용하도록 Dialogflow 에이전트를 업데이트해야 합니다. 힙 덤프를 분석하려면 다음 단계를 따르세요.
- Dialogflow 콘솔을 엽니다. 원하는 경우 Firebase 콘솔을 닫아도 됩니다.
- 왼쪽 탐색 메뉴에서 Fulfillment를 클릭합니다.
- 웹훅을 사용 설정합니다.
- 아직 표시되지 않은 경우 Firebase 대시보드에서 복사한 URL을 붙여넣습니다.
- 저장을 클릭합니다.
프로젝트가 올바르게 설정되었는지 확인
사용자는 영업시간이 포함된 하드 코딩된 텍스트 응답과 요일별 수업 일정을 나열하는 텍스트 응답 등 Action Gym에 관한 정보를 얻기 위해 작업을 호출할 수 있어야 합니다.
Actions 시뮬레이터에서 작업을 테스트하려면 다음 단계를 따르세요.
- Dialogflow 콘솔 왼쪽 탐색 메뉴에서 통합 > Google 어시스턴트를 클릭합니다.
- 변경사항 자동 미리보기가 사용 설정되어 있는지 확인하고 테스트를 클릭하여 Actions 프로젝트를 업데이트합니다.
- Actions 시뮬레이터가 작업 프로젝트를 로드합니다. 작업을 테스트하려면 Input 필드에
Talk to my test app을 입력하고 Enter 키를 누릅니다. - Action Gym에 오신 것을 환영한다는 응답이 표시됩니다. 프롬프트에 따라 대화를 계속하면서 풀필먼트에 각 입력에 대한 응답이 있는지 확인하세요.

3. 일일 업데이트 구독 추가
사용자를 참여시키는 일반적인 방법은 가장 유용할 때 정보를 제공하는 것입니다. 이는 사용자에게 인텐트의 일일 업데이트를 구독할 수 있는 옵션을 제공하여 달성됩니다. 이렇게 하면 해당 인텐트의 처리로 직접 연결되는 어시스턴트 알림이 사용자에게 전송됩니다.
이 단계에서는 일일 업데이트 구독에 대해 알아보고 이를 작업의 클래스 목록 인텐트에 추가합니다. 이 안내를 따르면 작업의 대화가 다음 다이어그램과 같이 표시됩니다.

사용자의 참여를 어떻게 유도할 수 있나요?
스마트폰 사용자는 앱 관련 정보와 업데이트를 제공하는 푸시 알림에 익숙할 것입니다. 매일 업데이트 구독은 업데이트를 전송하는 의도가 매일 사용자에게 가치를 제공하는 경우 어시스턴트 외부에서 휴대기기 사용자에게 액세스할 수 있는 간단한 방법입니다.
일일 업데이트는 유용한 참여 도구가 될 수 있지만 모든 작업에 반드시 포함해야 하는 것은 아닙니다. 작업에 일일 업데이트 구독을 추가할지 결정할 때는 다음 팁을 고려하세요.
- 매일 업데이트를 통해 사용자에게 유용한 정보가 매일 다르게 표시되도록 합니다. 일일 업데이트를 탭할 때마다 동일한 메시지가 표시되면 사용자는 며칠 후에 구독을 취소할 것입니다.
- 사용자가 일일 업데이트 인텐트로 바로 이동하는 경우 대화상자가 사용자에게 적절한지 확인합니다. 사용자가 대화의 처음부터 시작하지 않을 수도 있으므로 많은 맥락을 가지고 있다고 기대해서는 안 됩니다.
- 사용자에게 일일 업데이트 구독을 요청하기 전에 내 작업의 이점을 보여주세요. 구독 옵션이 제공될 때 사용자는 '이 콘텐츠를 매일 보고 싶어'라고 생각해야 합니다.
- 구독을 제안하는 메시지를 반복적으로 표시하여 사용자에게 부담을 주지 마세요. 사용자에게 구독할 항목을 표시한 직후에 일일 업데이트 구독을 제안하고 다른 곳에서 구독을 강요하지 마세요.
- 업데이트 의도가 트리거된 후에는 대화를 짧게 유지하세요. 대부분의 일일 업데이트는 단일 응답으로 구성되어야 하며 사용자 입력 없이 종료되어야 합니다.
일일 업데이트 사용 설정
일일 업데이트 구독은 사용자를 대화 시작 부분으로 안내하는 시작 인텐트 또는 대화 내 특정 위치로 딥 링크하는 더 구체적인 인텐트에 추가할 수 있습니다. 이 Codelab에서는 대화가 매일 변경되고 사용자가 어떤 수업이 있는지 알림을 받는 것이 유용할 수 있으므로 수업 목록 인텐트가 가장 적합합니다.
수업 목록 인텐트의 일일 업데이트를 사용 설정하려면 다음 단계를 따르세요.
- Actions 콘솔에서 Develop 탭을 클릭하고 왼쪽 탐색 메뉴에서 Actions를 선택합니다.
- 작업 목록에서 수업 목록을 클릭합니다.
- 사용자 참여 섹션에서 사용자에게 일일 업데이트를 제공하시겠습니까? 옵션을 전환합니다.
- 일일 업데이트를 설명하는 콘텐츠 제목을 설정합니다. 컨텍스트는 '매일 몇 시에 보내 드릴까요?'이므로 제목이 설명적이고 소리 내어 말할 때도 올바르게 들리는지 확인하세요. 이 예에서는 콘텐츠 제목을
list of upcoming Action Gym classes로 설정합니다. - 페이지 상단의 저장을 클릭합니다.

Dialogflow 설정
Dialogflow 콘솔에서 다음 단계에 따라 일일 업데이트 구독 흐름의 인텐트를 만드세요.
사용자에게 구독을 요청
- 사용자가 일일 업데이트를 구독하도록 요청하는 것을 처리하는 새로운 인텐트를 설정합니다. Dialogflow 콘솔의 왼쪽 탐색 메뉴에서 인텐트 옆에 있는 + 버튼을 클릭하여 새 인텐트를 만듭니다.
- 새 인텐트의 이름을
Setup Updates로 지정합니다. - 학습 문구 섹션에서 다음 사용자 표현식을 추가합니다.
Send daily remindersReminderRemind meUpdatesUpcoming classes
- Fulfillment 섹션에서 Enable webhook call for this intent(이 인텐트의 웹훅 호출 사용 설정) 옵션을 전환합니다.
- 페이지 상단의 저장을 클릭합니다.

사용자의 결정 처리
- 일일 업데이트 구독 프롬프트에 대한 사용자의 응답을 처리할 새 인텐트를 설정합니다. 왼쪽 탐색에서 Intents 옆에 있는 + 버튼을 클릭하여 새 인텐트를 만듭니다.
- 새 인텐트의 이름을
Confirm Updates로 지정합니다. - 이벤트 섹션에서
actions_intent_REGISTER_UPDATE를 추가합니다. 이 Dialogflow 이벤트는 사용자가 일일 업데이트 구독 흐름을 완료할 때 트리거됩니다(구독 여부와 관계없음). - Fulfillment 섹션에서 Enable webhook call for this intent(이 인텐트의 웹훅 호출 사용 설정) 옵션을 전환합니다.
- 페이지 상단의 저장을 클릭합니다.

처리 구현
웹훅에서 처리를 구현하려면 다음 단계를 완료하세요.
종속 항목 로드
index.js 파일에서 actions-on-google 패키지의 RegisterUpdate 패키지를 추가하도록 require() 함수를 업데이트합니다. 가져오기는 다음과 같습니다.
index.js
const {
dialogflow,
Suggestions,
RegisterUpdate,
} = require('actions-on-google');
추천 칩 업데이트
index.js 파일에서 추천 칩 제목 목록에 DAILY 항목을 추가하여 Suggestion 정의가 다음과 같이 표시되도록 합니다.
index.js
// Suggestion chip titles
const Suggestion = {
HOURS: 'Ask about hours',
CLASSES: 'Learn about classes',
DAILY: 'Send daily reminders',
};
새 인텐트의 처리 추가
사용자가 구독을 원한다고 말하면 업데이트의 타겟 인텐트 (수업 목록) 및 유형 (DAILY)으로 RegisterUpdate 도우미를 호출하여 일일 업데이트 구독 흐름을 시작합니다. 구독 흐름이 완료되면 어시스턴트는 구독 성공 여부를 설명하는 status 인수를 사용하여 actions_intent_REGISTER_UPDATE 이벤트를 트리거합니다. 정기 결제 상태에 따라 달라지는 후속 프롬프트를 사용자에게 제공합니다.
index.js 파일에 다음 코드를 추가합니다.
index.js
// Start opt-in flow for daily updates
app.intent('Setup Updates', (conv) => {
conv.ask(new RegisterUpdate({
intent: 'Class List',
frequency: 'DAILY',
}));
});
// Confirm outcome of opt-in for daily updates
app.intent('Confirm Updates', (conv, params, registered) => {
if (registered && registered.status === 'OK') {
conv.ask(`Gotcha, I'll send you an update everyday with the ` +
'list of classes. Can I help you with anything else?');
} else {
conv.ask(` I won't send you daily reminders. Can I help you with anything else?`);
}
if (conv.screen) {
conv.ask(new Suggestions([Suggestion.HOURS, Suggestion.CLASSES]));
}
});
사용자에게 대체 프롬프트 제공
수업 목록 응답의 끝에 일일 업데이트 구독이 제공되지만 문제가 있습니다. 사용자가 일일 업데이트 알림을 탭할 때도 동일한 응답이 트리거되므로, 사용자가 방금 일일 업데이트를 확인했더라도 일일 업데이트를 구독하라는 메시지가 표시됩니다. 사용자가 다시 구독해야 한다고 생각하지 않도록 하려면 어떻게 해야 할까요?
다행히 conv 객체의 인수에는 사용자가 대화를 시작한 위치에 관한 정보가 포함되어 있습니다. conv 인수를 확인하여 UPDATES 섹션이 포함되어 있는지 확인합니다. 이는 사용자가 일일 업데이트 알림에서 대화를 시작했음을 나타냅니다. 이에 따라 응답을 변경할 수 있습니다. 이 대화 브랜치를 사용하여 수업 목록을 제공한 후 즉시 대화상자를 닫을 수도 있습니다. 이는 일일 업데이트를 짧게 유지하는 권장사항을 따르는 것입니다.
index.js 파일에서 다음 코드를 바꿉니다.
index.js
// Class list intent handler
app.intent('Class List', (conv, {day}) => {
if (!day) {
day = DAYS[new Date().getDay()];
}
const classes =
[...new Set(schedule.days[day].map((d) => `${d.name} at ${d.startTime}`))]
.join(', ');
const classesMessage =
`On ${day} we offer the following classes: ${classes}. ` +
`Can I help you with anything else?`;
conv.ask(classesMessage);
if (conv.screen) {
conv.ask(new Suggestions([Suggestion.HOURS]));
}
});
다음과 같이 바꿉니다.
index.js
// Class list intent handler
app.intent('Class List', (conv, {day}) => {
if (!day) {
day = DAYS[new Date().getDay()];
}
const classes =
[...new Set(schedule.days[day].map((d) => `${d.name} at ${d.startTime}`))]
.join(', ');
let classesMessage = `On ${day} we offer the following classes: ${classes}. `;
// If the user started the conversation from the context of a daily update,
// the conv's arguments will contain an 'UPDATES' section.
let engagement = conv.arguments.get('UPDATES');
// Check the conv arguments to tailor the conversation based on the context.
if (engagement) {
classesMessage += `Hope to see you soon at Action Gym!`;
conv.close(classesMessage);
} else {
classesMessage += `Would you like me to send you daily reminders of upcoming classes, or can I help you with anything else?`;
conv.ask(classesMessage);
if (conv.screen) {
conv.ask(new Suggestions([Suggestion.DAILY, Suggestion.HOURS]));
};
};
});
일일 업데이트 테스트
터미널에서 다음 명령어를 실행하여 업데이트된 웹훅 코드를 Firebase에 배포합니다.
firebase deploy
Actions 시뮬레이터에서 맞춤 프롬프트를 테스트하려면 다음 단계를 따르세요.
- Actions 콘솔에서 Test로 이동합니다.
- 입력 필드에
Talk to my test app를 입력하고 Enter 키를 누릅니다. Learn about classes을 입력하고 Enter 키를 누릅니다. 이제 작업의 응답에서 일일 알림을 전송하겠다고 제안해야 합니다.Send daily reminders을 입력하고 Enter 키를 누릅니다.- 업데이트를 확인할 시간을 입력하고 Enter 키를 누릅니다. 테스트를 위해 현재 시간보다 3~5분 늦게 응답해 보세요.

휴대기기에서 업데이트를 위해 지정한 시간에 어시스턴트의 알림이 표시됩니다. 이 알림이 표시되는 데 몇 분 정도 걸릴 수 있습니다. 알림을 탭하면 어시스턴트의 수업 목록 인텐트로 바로 연결되어 예정된 수업 목록이 표시됩니다.

4. 푸시 알림 추가
작업 외부에서 사용자의 참여를 유도하는 또 다른 방법으로 Actions API를 호출하여 사용자에게 푸시 알림을 보낼 수 있습니다. 일일 업데이트와 달리 이러한 알림은 어시스턴트에서 자동으로 예약하지 않으므로 원하는 대로 보낼 수 있습니다.
이 단계에서는 새로운 Class Canceled 인텐트를 추가하고 수업 취소를 알리는 알림을 사용자에게 전송하여 작업에 푸시 알림을 구현하는 방법을 알아봅니다. 또한 알림을 보내는 데 필요한 다음 세 가지 구성요소를 설정합니다.
- Actions API 계정 - API에
POST요청을 전송하여 사용자에게 알림을 보내므로 이 API와 상호작용하려면 서비스 계정과 사용자 인증 정보를 설정해야 합니다. - 권한 도우미 - 푸시 알림을 전송하는 데 필요한 사용자 ID에 액세스하려면 사용자의 권한이 필요합니다. 이 예에서는 클라이언트 라이브러리 함수를 사용하여 권한 도우미를 호출하고 이 ID를 요청합니다.
- 저장소 - 대화 외부의 사용자에게 푸시 알림을 보내려면 언제든지 호출할 수 있는 위치에 사용자 ID를 저장해야 합니다. 이 예에서는 각 사용자의 정보를 저장하는 Firestore 데이터베이스를 설정합니다.
이 안내를 따르면 작업의 대화에 다음 대화상자가 추가됩니다.

사용자의 참여를 어떻게 유도할 수 있나요?
스마트폰 사용자는 앱 관련 정보와 업데이트를 제공하는 푸시 알림에 익숙할 것입니다. 푸시 알림은 사용자가 사용 설정할 만한 충분한 이유가 있는 경우 어시스턴트 외부에서 휴대기기의 사용자에게 액세스할 수 있는 유연한 방법입니다. 일일 업데이트를 사용하면 사용자에게 매일 알림이 전송된다는 사실을 이미 알고 있습니다. 하지만 푸시 알림의 경우 사용자는 드문 알림을 수신하도록 선택하는지 아니면 하루에 여러 개의 알림으로 괴롭힘을 당하는지 알 수 없습니다.
푸시 알림은 유용한 참여 도구이지만 모든 작업에 반드시 포함해야 하는 것은 아닙니다. 동작에 푸시 알림을 추가할지 여부를 결정할 때 다음 팁을 고려하세요.
- 푸시 알림의 몇 가지 예시 일정을 계획합니다. 하루에 푸시 알림을 한 번만 보낼 계획이라면 일일 업데이트를 사용하는 것이 좋습니다.
- 푸시 알림을 받을 때마다 유용한 정보를 제공하는지 확인하세요. 알림은 Action의 인텐트 중 하나에 딥 링크될 수도 있으므로 인텐트가 유용하고 관련성이 있는지 확인하세요.
- 사용자에게 푸시 알림을 구독하도록 요청할 때는 명시적으로 요청하세요. 각 푸시 알림에 대해 예상되는 내용을 이해하고 알림이 전송되는 빈도를 어느 정도 파악해야 합니다.
Actions API 사용 설정
- Google Cloud 콘솔을 열고 드롭다운에서 Actions 프로젝트 이름을 선택합니다.

- 탐색 메뉴 (☰)에서 API 및 서비스 > 라이브러리로 이동합니다.
- Actions API를 검색하고 사용 설정을 클릭합니다.

서비스 계정 만들기
Actions API에는 인증이 필요하므로 요청을 보내려면 서비스 계정을 만들어야 합니다. 다음 단계에 따라 Actions API의 서비스 계정 키를 만들고 설치하세요.
- Google Cloud 콘솔의 탐색 메뉴 (☰)에서 API 및 서비스 > 사용자 인증 정보로 이동합니다.
- 사용자 인증 정보 만들기 > 서비스 계정 키를 클릭합니다.
- 서비스 계정 드롭다운 메뉴에서 새 서비스 계정을 선택합니다.
- 다음 정보를 입력합니다.
- 서비스 계정 이름:
service-account - 역할: 프로젝트 > 소유자
- 서비스 계정 ID:
service-account(@<project_id>.iam.gserviceaccount.com이 항상 뒤에 붙음) - 키 유형: JSON
- 만들기를 클릭합니다.
- 다운로드한 JSON 파일을 프로젝트의 /user-engagement-codelab/start/functions/ 디렉터리로 이동합니다.
- JSON 파일 이름을
service-account.json로 바꿉니다.

Firestore 사용 설정
대화 외부에서 알림을 전송하려면 알림 코드에서 참조할 수 있는 사용자 ID를 저장하는 방법이 필요합니다. 이 예에서는 Firestore 데이터베이스를 사용하여 구독한 사용자의 사용자 ID를 저장합니다.
다음 단계에 따라 작업의 Firestore 데이터베이스를 만드세요.
- Firebase Console에서 Actions 프로젝트 이름을 선택합니다.
- 왼쪽 탐색 메뉴에서 개발 > 데이터베이스로 이동하여 데이터베이스 만들기를 클릭합니다.
- 테스트 모드에서 시작을 선택합니다.
- 사용 설정을 클릭합니다.

Dialogflow 설정
Dialogflow 콘솔에서 다음 단계에 따라 푸시 알림 선택 흐름을 만드세요.
사용자에게 구독을 요청
- 취소된 수업에 대한 푸시 알림을 구독해 달라는 사용자의 요청을 처리하는 새로운 인텐트를 설정합니다. Dialogflow 콘솔의 왼쪽 탐색 메뉴에서 인텐트 옆에 있는 + 버튼을 클릭하여 새 인텐트를 만듭니다.
- 새 인텐트의 이름을
Setup Push Notifications로 지정합니다. - 학습 문구 섹션에서 다음 사용자 표현식을 추가합니다.
Subscribe to notificationsSend notificationNotify meSend class notificationsCancelled notifications
- Fulfillment 섹션에서 Enable webhook call for this intent(이 인텐트의 웹훅 호출 사용 설정) 옵션을 전환합니다.
- 페이지 상단의 저장을 클릭합니다.

사용자의 결정 처리
- 푸시 알림 구독 메시지에 대한 사용자의 응답을 처리하는 새 인텐트를 설정합니다. 왼쪽 탐색에서 Intents 옆에 있는 + 버튼을 클릭하여 새 인텐트를 만듭니다.
- 새 인텐트의 이름을
Confirm Push Notifications로 지정합니다. - 이벤트 섹션에서
actions_intent_PERMISSION를 추가합니다. 이 Dialogflow 이벤트는 사용자가 푸시 알림 구독 흐름을 완료할 때 트리거됩니다(구독 여부와 관계없음). - Fulfillment 섹션에서 Enable webhook call for this intent(이 인텐트의 웹훅 호출 사용 설정) 옵션을 전환합니다.
- 페이지 상단의 저장을 클릭합니다.

푸시 알림 처리
푸시 알림을 특정 인텐트에 연결하여 푸시 알림을 탭하는 사용자가 작업의 해당 인텐트로 바로 딥 링크되도록 할 수 있습니다. 이 예시에서는 취소된 수업에 관한 세부정보를 제공하는 푸시 알림을 위한 새로운 인텐트를 추가합니다.
사용자가 푸시 알림을 탭할 때 트리거되는 인텐트를 추가하려면 다음 단계를 따르세요.
- Dialogflow 콘솔의 왼쪽 탐색 메뉴에서 인텐트 옆에 있는 + 버튼을 클릭하여 새 인텐트를 만듭니다.
- 새 인텐트의 이름을
Class Canceled로 지정합니다. - 학습 문구 섹션에서
Cancelations를 사용자 표현식으로 추가합니다. - Fulfillment 섹션에서 Enable webhook call for this intent(이 인텐트의 웹훅 호출 사용 설정) 옵션을 전환합니다.
- 페이지 상단의 저장을 클릭합니다.

대화 중에 테스트 알림 보내기
프로덕션에서는 푸시 알림을 전송하는 스크립트가 작업 처리 코드와 별도로 있어야 합니다. 이 예에서는 작업을 통해 대화하는 동안 푸시 알림을 전송하기 위해 호출할 수 있는 인텐트를 만듭니다. 이 인텐트는 디버그 목적으로만 사용됩니다. 실제로 푸시 알림은 처리에서 처리하거나 작업의 대화의 일부로 트리거해서는 안 됩니다.
다음 단계에 따라 푸시 알림 테스트를 위한 인텐트를 만드세요.
- 테스트 및 디버깅 목적으로 구독 사용자에게 푸시 알림을 보낼 수 있는 새 인텐트를 설정합니다. Dialogflow 콘솔의 왼쪽 탐색 메뉴에서 인텐트 옆에 있는 + 버튼을 클릭하여 새 인텐트를 만듭니다.
- 새 인텐트의 이름을
Test Notification로 지정합니다. - 학습 문구 섹션에서
Test notification를 사용자 표현식으로 추가합니다. - Fulfillment 섹션에서 Enable webhook call for this intent(이 인텐트의 웹훅 호출 사용 설정) 옵션을 전환합니다.
- 페이지 상단의 저장을 클릭합니다.

푸시 알림 사용
수업 취소됨 인텐트에 푸시 알림을 사용 설정하려면 다음 단계를 따르세요.
- Dialogflow 콘솔의 탐색 메뉴에서 통합으로 이동합니다.
- Google 어시스턴트 카드에서 통합 설정을 클릭합니다.
- 클래스 취소됨을 암시적 호출 인텐트로 추가합니다. 이 단계는 Dialogflow가 사용자가 푸시 알림을 탭하여 수업 취소됨 인텐트로 대화를 시작할 수 있음을 인식하는 데 필요합니다.
- 닫기를 클릭합니다.

- Actions 콘솔에서 Develop 탭을 클릭하고 왼쪽 탐색 메뉴에서 Actions를 선택합니다.
- 작업 목록에서 수업 취소됨을 클릭합니다.
- 사용자 참여도 섹션에서 푸시 알림을 보내시겠습니까? 옵션을 전환합니다.
- 푸시 알림을 설명하는 콘텐츠 제목을 설정합니다. 컨텍스트는 '푸시 알림을 보내 드려도 괜찮을까요?'이므로 제목이 설명적이고 소리 내어 말할 때도 올바르게 들리는지 확인하세요. 이 예에서는 콘텐츠 제목을
class cancelations로 설정합니다. - 페이지 상단의 저장을 클릭합니다.

처리 구현
웹훅에서 처리를 구현하려면 다음 단계를 완료하세요.
종속 항목 로드
index.js 파일에서 actions-on-google 패키지의 UpdatePermission 패키지를 추가하도록 require() 함수를 업데이트합니다. 가져오기는 다음과 같습니다.
index.js
const {
dialogflow,
Suggestions,
RegisterUpdate,
UpdatePermission,
} = require('actions-on-google');
추천 칩 업데이트
index.js 파일에서 추천 칩 제목 목록에 NOTIFICATIONS 항목을 추가하여 Suggestion 정의가 다음과 같이 표시되도록 합니다.
index.js
// Suggestion chip titles
const Suggestion = {
HOURS: 'Ask about hours',
CLASSES: 'Learn about classes',
DAILY: 'Send daily reminders',
NOTIFICATIONS: 'Get notifications',
};
새 가져오기 설정하기
Firestore 데이터베이스에 연결하려면 firebase-admin 패키지를 추가하고 데이터베이스에 저장된 필드의 상수를 추가합니다. 또한 google-auth-library 및 request 패키지를 가져와 인증 및 Actions API 요청을 처리합니다.
index.js 파일에서 가져오기에 다음 코드를 추가합니다.
index.js
// Firebase admin import
const admin = require('firebase-admin');
// Initialize Firestore
admin.initializeApp();
const db = admin.firestore();
// Firestore constants
const FirestoreNames = {
INTENT: 'intent',
USER_ID: 'userId',
USERS: 'users',
};
// Actions API authentication imports
const {auth} = require('google-auth-library');
const request = require('request');
수업 취소 알림 설정 제안
index.js 파일에서 다음 코드를 바꿉니다.
index.js
// Class list intent handler
app.intent('Class List', (conv, {day}) => {
if (!day) {
day = DAYS[new Date().getDay()];
}
const classes =
[...new Set(schedule.days[day].map((d) => `${d.name} at ${d.startTime}`))]
.join(', ');
let classesMessage = `On ${day} we offer the following classes: ${classes}. `;
// If the user started the conversation from the context of a daily update,
// the conv's arguments will contain an 'UPDATES' section.
let engagement = conv.arguments.get('UPDATES');
// Check the conv arguments to tailor the conversation based on the context.
if (engagement) {
classesMessage += `Hope to see you soon at Action Gym!`;
conv.close(classesMessage);
} else {
classesMessage += `Would you like me to send you daily reminders of upcoming classes, or can I help you with anything else?`;
conv.ask(classesMessage);
if (conv.screen) {
conv.ask(new Suggestions([Suggestion.DAILY, Suggestion.HOURS]));
};
};
});
다음과 같이 바꿉니다.
index.js
// Class list intent handler
app.intent('Class List', (conv, {day}) => {
if (!day) {
day = DAYS[new Date().getDay()];
}
const classes =
[...new Set(schedule.days[day].map((d) => `${d.name} at ${d.startTime}`))]
.join(', ');
let classesMessage = `On ${day} we offer the following classes: ${classes}. `;
// If the user started the conversation from the context of a daily update,
// the conv's arguments will contain an 'UPDATES' section.
let engagement = conv.arguments.get('UPDATES');
// Check the conv arguments to tailor the conversation based on the context.
if (engagement) {
classesMessage += `Hope to see you soon at Action Gym!`;
conv.close(classesMessage);
} else {
classesMessage += `Would you like to receive daily reminders of upcoming classes, subscribe to notifications about cancelations, or can I help you with anything else?`;
conv.ask(classesMessage);
if (conv.screen) {
conv.ask(new Suggestions([Suggestion.DAILY, Suggestion.NOTIFICATIONS,
Suggestion.HOURS]));
};
};
});
새 인텐트의 처리 추가
사용자가 푸시 알림을 구독하고 싶다고 말하면 UpdatePermission 도우미를 호출하여 사용자에게 권한을 요청합니다. 성공하면 PERMISSION 인수가 conv 객체의 인수에 추가되며 이를 확인하여 대화를 전환할 수 있습니다.
사용자의 권한을 얻은 후 conv 객체의 인수에서 사용자 ID를 가져와 데이터베이스에 저장합니다. 나중에 이 사용자 ID를 Actions API에 전송합니다. 이렇게 하면 어시스턴트가 알림을 받을 사용자를 결정할 수 있습니다.
마지막으로 푸시 알림을 탭하여 트리거되는 Class Canceled 인텐트의 처리를 추가합니다. 이 예에서 대답은 자리표시자 문자열이지만, 이 작업의 프로덕션 준비 버전에서는 알림 스크립트가 취소된 수업에 관한 더 동적인 정보를 제공합니다.
index.js 파일에 다음 코드를 추가합니다.
index.js
// Call the User Information helper for permission to send push notifications
app.intent('Setup Push Notifications', (conv) => {
conv.ask('Update permission for setting up push notifications');
conv.ask(new UpdatePermission({intent: 'Class Canceled'}));
});
// Handle opt-in or rejection of push notifications
app.intent('Confirm Push Notifications', (conv) => {
if (conv.arguments.get('PERMISSION')) {
let userId = conv.arguments.get('UPDATES_USER_ID');
if (!userId) {
userId = conv.request.conversation.conversationId;
}
// Add the current conversation ID and the notification's
// target intent to the Firestore database.
return db.collection(FirestoreNames.USERS)
.add({
[FirestoreNames.INTENT]: 'Class Canceled',
[FirestoreNames.USER_ID]: userId,
})
.then(() => {
conv.ask(`Great, I'll notify you whenever there's a class cancelation. ` +
'Can I help you with anything else?');
});
} else {
conv.ask(`Okay, I won't send you notifications about class cancelations. ` +
'Can I help you with anything else?');
}
if (conv.screen) {
conv.ask(new Suggestions([Suggestion.CLASSES, Suggestion.HOURS]));
}
});
// Intent triggered by tapping the push notification
app.intent('Class Canceled', (conv) => {
conv.ask('Classname at classtime has been canceled.');
});
테스트 알림 추가
사용자에게 푸시 알림을 보내려면 사용자 ID, 알림 제목, 타겟 인텐트와 함께 POST 요청을 Actions API에 전송합니다. 이 예에서 테스트 알림 인텐트를 트리거하면 Firestore 데이터베이스를 반복하고 알림을 구독한 모든 사용자에게 푸시 알림을 보냅니다.
이 예에서는 푸시 알림을 전송하는 코드를 웹훅 처리에서 포함하고 대화에서 테스트 인텐트를 호출하여 해당 코드를 트리거합니다. 게시하려는 작업에서 푸시 알림 코드는 이행과 별도의 스크립트에 있어야 합니다.
index.js 파일에 다음 코드를 추가합니다.
index.js
// Debug intent to trigger a test push notification
app.intent('Test Notification', (conv) => {
// Use the Actions API to send a Google Assistant push notification.
let client = auth.fromJSON(require('./service-account.json'));
client.scopes = ['https://www.googleapis.com/auth/actions.fulfillment.conversation'];
let notification = {
userNotification: {
title: 'Test Notification from Action Gym',
},
target: {},
};
client.authorize((err, tokens) => {
if (err) {
throw new Error(`Auth error: ${err}`);
}
// Iterate through Firestore and send push notifications to every user
// who's currently opted in to canceled class notifications.
db.collection(FirestoreNames.USERS)
.where(FirestoreNames.INTENT, '==', 'Class Canceled')
.get()
.then((querySnapshot) => {
querySnapshot.forEach((user) => {
notification.target = {
userId: user.get(FirestoreNames.USER_ID),
intent: user.get(FirestoreNames.INTENT),
};
request.post('https://actions.googleapis.com/v2/conversations:send', {
'auth': {
'bearer': tokens.access_token,
},
'json': true,
'body': {'customPushMessage': notification, 'isInSandbox': true},
}, (err, httpResponse, body) => {
if (err) {
throw new Error(`API request error: ${err}`);
}
console.log(`${httpResponse.statusCode}: ` +
`${httpResponse.statusMessage}`);
console.log(JSON.stringify(body));
});
});
})
.catch((error) => {
throw new Error(`Firestore query error: ${error}`);
});
});
conv.ask('A notification has been sent to all subscribed users.');
});
푸시 알림 테스트
터미널에서 다음 명령어를 실행하여 업데이트된 웹훅 코드를 Firebase에 배포합니다.
firebase deploy
Actions 시뮬레이터에서 알림을 테스트하려면 다음 단계를 따르세요.
- Actions 콘솔에서 테스트 탭으로 이동합니다.
- 입력 필드에
Talk to my test app를 입력하고 Enter 키를 누릅니다. Learn about classes을 입력하고 Enter 키를 누릅니다.Get notifications을 입력하고 Enter 키를 누릅니다.- 아직 작업에 푸시 알림을 보낼 권한을 부여하지 않은 경우
yes를 입력하고 Enter 키를 누릅니다. yes을 입력하고 Enter 키를 누릅니다. 이제 Google 계정에서 이 작업의 푸시 알림을 구독해야 합니다.

no를 입력하고 Enter 키를 눌러 종료합니다.Talk to my test app를 입력하고 Enter 키를 눌러 새 대화를 시작합니다.Test notification을 입력하고 Enter 키를 누릅니다.

몇 분 이내에 휴대기기에 'Action Gym의 테스트 알림' 어시스턴트 푸시 알림이 표시됩니다. 이 알림을 탭하면 작업의 수업 취소됨 인텐트로 딥 링크됩니다.

5. 어시스턴트 링크 만들기
지금까지 사용자가 작업으로 돌아오도록 구현할 수 있는 참여 기능을 살펴봤습니다. 하지만 이러한 기능은 사용자가 작업을 발견하고 사용한다는 전제하에 작동합니다.
휴대기기 사용자를 어시스턴트의 작업으로 바로 연결하는 어시스턴트 링크를 만들 수 있습니다. 어시스턴트 링크는 표준 하이퍼링크이므로 웹사이트나 블로그, 소셜 미디어 게시물과 같은 웹 마케팅 자료에 추가할 수 있습니다.
이 단계에서는 어시스턴트 링크가 무엇인지, 작업의 시작 인텐트에 대한 링크를 만드는 방법, 테스트를 위해 간단한 웹사이트에 링크를 추가하는 방법을 알아봅니다.
사용자의 참여를 어떻게 유도할 수 있나요?
특히 사용자가 어시스턴트에서 작업을 명시적으로 호출해야 하는 경우 사용자를 작업으로 유도하는 것은 어려울 수 있습니다. 어시스턴트 링크는 사용자에게 작업으로 연결되는 직접 링크를 제공하여 이러한 불편함을 해소합니다. 사용자가 어시스턴트 지원 기기에서 어시스턴트 링크를 클릭하면 바로 내 작업으로 이동합니다. 사용자가 모바일 기기나 어시스턴트를 지원하지 않는 다른 기기에서 링크를 열더라도 작업 디렉터리 등록정보 (게시된 경우)로 연결되므로 링크를 통해 이러한 사용자에게 작업을 계속 홍보할 수 있습니다.
어시스턴트 링크는 유용한 참여 도구이므로 웹사이트나 소셜 미디어를 통해 작업을 광고할 계획이라면 링크를 만드는 것이 좋습니다. 어시스턴트 링크를 만들어 배포하기 전에 다음 팁을 참고하세요.
- 어시스턴트 링크는 작업이 게시된 후에만 작동합니다. 프로젝트가 초안 상태인 동안에는 링크가 내 기기에서만 작동합니다. 다른 사용자는 작업 디렉터리의 404 페이지로 이동합니다.
- 알파 또는 베타 환경에서 작업을 출시하여 게시하기 전에 사용자가 어시스턴트 링크를 테스트하도록 할 수 있습니다. 알파 또는 베타에 참여하는 사용자만 어시스턴트 링크를 테스트할 수 있습니다.
- 어시스턴트 링크의 대상 인텐트가 신규 사용자에게 좋은 첫인상을 남기도록 하세요. 시작 인텐트는 이미 작업을 잘 소개하므로 어시스턴트 링크의 기본 대상입니다.
어시스턴트 링크 사용 설정
다음 단계에 따라 시작 인텐트의 어시스턴트 링크를 만드세요.
- Actions 콘솔에서 Develop 탭을 클릭하고 왼쪽 탐색 메뉴에서 Actions를 선택합니다.
- 작업 목록에서 actions.intent.MAIN을 클릭합니다.
- 링크 섹션에서 이 작업에 URL을 사용 설정하시겠습니까? 옵션을 전환합니다.
- 동작을 설명하는 링크 제목을 설정합니다. 사용자가 작업을 통해 무엇을 할 수 있는지 설명하는 간단한 동사-명사 쌍으로 제품명을 만드세요. 이 예시에서는 링크 제목을
learn about Action Gym로 설정합니다. - 이 페이지 하단에서 HTML 스니펫을 복사하고 나중에 사용할 수 있도록 저장하세요.
- 페이지 상단의 저장을 클릭합니다.

테스트 웹사이트 배포
어시스턴트 링크를 테스트하려면 Firebase 도구를 사용하여 테스트 웹사이트를 풀필먼트와 함께 배포하면 됩니다. 이 예시를 위해 간단한 테스트 웹사이트가 이미 빌드되어 있으므로 어시스턴트 링크만 추가하면 됩니다.
이행의 /user-engagement-codelab-nodejs/start/public/ 디렉터리로 이동하여 텍스트 편집기에서 index.html 파일을 엽니다.
index.html 파일에서 어시스턴트 링크의 HTML 스니펫을 body 요소에 붙여넣습니다. 파일은 아래 스니펫과 같이 표시됩니다.
index.html
<body>
<p>
<a href="https://assistant.google.com/services/invoke/uid/000000efb5f2fd97">🅖 Ask my test app to learn about Action Gym
</a>
</p>
</body>
어시스턴트 링크 테스트
터미널에서 다음 명령어를 실행하여 테스트 웹사이트를 Firebase에 배포합니다.
firebase deploy
배포 명령어 실행이 완료되면 출력에서 호스팅 URL을 기록해 둡니다.

휴대기기의 웹브라우저에서 이 URL로 이동하면 테스트 웹사이트에 어시스턴트 링크가 표시됩니다. 휴대기기에서 이 링크를 클릭하면 어시스턴트의 작업 환영 인텐트로 이동합니다.

데스크톱 브라우저에서 호스팅 URL로 이동할 수도 있습니다. 작업이 게시되지 않았으므로 어시스턴트 디렉터리의 404 페이지로 이동합니다.
6. 다음 단계
수고하셨습니다.
이제 작업을 개발할 때 사용자 참여의 중요성, 플랫폼에서 사용할 수 있는 사용자 참여 기능, 각 기능을 작업에 추가하는 방법을 알아보았습니다.
추가 학습 자료
다음 리소스를 살펴보고 작업의 사용자 참여에 대해 자세히 알아보세요.
- 사용자 참여도 및 어시스턴트 링크 문서: 이 Codelab에서 설명하는 기능과 일반적인 사용자 참여도에 관한 공식 Actions on Google 문서입니다.
- 사용자 유지 분석: 게시된 작업의 사용자 유지를 보여주는 작업 콘솔의 분석 기능에 관한 문서입니다.
- 대화 설계 가이드라인: 사용자 참여 기능을 설계하는 방법에 관한 권장사항 및 가이드라인
- Actions on Google GitHub 저장소: 샘플 코드 및 라이브러리
- r/GoogleAssistantDev: 어시스턴트로 작업하는 개발자를 위한 공식 Reddit 커뮤니티
Twitter에서 @ActionsOnGoogle을 팔로우하여 최신 소식을 확인하고 #AoGDevs로 트윗을 보내 내가 빌드한 결과물을 공유하세요.
의견 설문조사
종료하기 전에 이 양식을 작성하여 의견을 알려주세요.