이 문서에서는 앱 또는 서비스가 이벤트가 발생할 때 Google Workspace Studio에 알리고 흐름 실행을 시작할 수 있도록 하는 시작 조건을 빌드하는 방법을 설명합니다. API에서 스타터는 workflowTriggers라고 합니다.
시작 조건은 플로우를 시작하는 반면 단계는 플로우를 포함하는 태스크 시퀀스의 단일 태스크입니다. 시작 조건을 빌드하면 사용자가 앱 또는 서비스의 실시간 이벤트에 반응하는 자동화된 흐름을 설정할 수 있습니다.
스타터 빌드에는 부가기능 매니페스트 파일에서 스타터를 선언하고 Google Apps Script에서 수명 주기 콜백을 구현하거나 Google Workspace Studio API 엔드포인트에 페이로드를 게시하여 스타터를 실행하는 작업이 포함됩니다.
기본 요건 및 OAuth 승인
Workspace Studio API 엔드포인트와 통신하려면 앱 또는 서비스가 OAuth 2.0을 사용하여 인증해야 합니다. 앱은 승인 중에 사용자에게 다음 전용 OAuth 범위를 요청해야 합니다.
https://www.googleapis.com/auth/workspace.studio.trigger
이 범위는 앱이 Workspace Studio API를 호출하고 사용자가 해당 시작 조건에 대해 구성한 플로우를 실행하도록 승인합니다.
오프라인 사용 및 갱신 토큰
스타터는 사용자가 흐름을 구성한 후 몇 시간, 며칠 또는 몇 달이 지날 수 있는 외부 서비스에서 이벤트가 발생하면 Workspace Studio에 비동기식으로 알리므로 서비스가 API 엔드포인트를 호출할 때 유효한 OAuth 2.0 액세스 토큰을 제공해야 합니다.
Google에서 부가기능 이벤트 객체에 제공하는 액세스 토큰 (예: 스타터 구성 또는 수명 주기 콜백 요청 중)은 수명이 짧으며 1시간 동안만 유효합니다. 향후 비동기식으로 시작 조건 이벤트를 실행하는 데는 충분하지 않습니다. 시간이 지남에 따라 Workspace Studio API를 호출하려면 서비스에서 필요에 따라 새 액세스 토큰을 생성할 수 있는 오프라인 갱신 토큰이 필요합니다.
승인을 처리하고 갱신 토큰을 획득하는 방법은 부가기능 런타임에 따라 다릅니다.
HTTP 부가기능 (대체 런타임): HTTP 부가기능의 경우 백엔드 서비스는 오프라인 액세스(
access_type=offline)를 요청하고 갱신 토큰을 수신하기 위해 기본 제공 부가기능 승인과 독립된 별도의 OAuth 2.0 승인 흐름을 구현해야 합니다.사용자가 Workspace Studio에서 시작 조건을 구성할 때 로그인 또는 승인 카드를 표시하여 사용자가 이 연결을 승인하도록 유도할 수 있습니다. 승인 카드 반환 및 OAuth 흐름 처리에 관한 자세한 내용은 Google Workspace 부가기능을 서드 파티 서비스에 연결하기 (Google Workspace를 연결할 서드 파티 서비스로 취급)를 참고하세요.
백엔드 서비스는 갱신 토큰을 안전하게 저장하고 (예: 서비스의 데이터베이스에
triggerId와 함께) 이를 사용하여 스타터의notifyUri또는triggers.fireAPI 엔드포인트에 요청을 보내기 전에 이벤트가 발생할 때마다 새 액세스 토큰을 가져와야 합니다.Google Apps Script 부가기능: 예약된(시간 기반) 트리거를 사용하여 이벤트를 폴링하는 Google Apps Script 기반 부가기능은 독립적인 OAuth 흐름을 구현하지 않아도 됩니다. 예약된 트리거는 Google Apps Script 런타임 환경 내에서 직접 실행되므로 Google Apps Script는 매니페스트에 선언된 범위를 사용하여 OAuth 토큰을 자동으로 관리하고 새로고침합니다.
매니페스트 파일에서 시작 조건 정의
시작 프로그램을 정의하려면 addOns.studio.flows.workflowElements 블록 내의 부가기능 매니페스트 파일 (appsscript.json)에 추가합니다. 이 구성은 Apps Script 및 HTTP 런타임(대체 런타임) 모두에 필요합니다. 단계를 정의할 때 사용되는 workflowAction 대신 요소를 workflowTrigger로 구성합니다. 자세한 내용은 Google Workspace 부가기능의 매니페스트 구조를 참고하세요.
workflowTrigger 블록 내에서 다음을 지정합니다.
inputs: 구성 카드에서 사용자가 구성하는 변수 (예: 프로젝트 이름, 리소스 필터 등)입니다.outputs: 흐름의 다운스트림 단계에 스타터가 반환할 수 있는 변수입니다.onConfigFunction: 사용자 구성 인터페이스를 표시하는 콜백 함수의 이름입니다.onManageFunction: Google에서 호출하여 스타터 구독 생성 및 삭제를 처리하는 콜백 함수의 이름입니다.
다음 코드 샘플은 이벤트 스타터의 매니페스트 정의 예를 보여줍니다.
JSON
{
"timeZone": "America/Los_Angeles",
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8",
"addOns": {
"common": {
"name": "Trigger App",
"logoUrl": "https://fonts.gstatic.com/s/i/short-term/release/googlesymbols/start/default/24px.svg",
"useLocaleFromApp": true
},
"studio": {
"flows": {
"workflowElements": [
{
"id": "triggerDemo",
"state": "ACTIVE",
"name": "Event Trigger",
"description": "Fires when a event occurs in the app.",
"workflowTrigger": {
"inputs": [
{
"id": "projectId",
"description": "The project identifier to watch.",
"cardinality": "SINGLE",
"dataType": {
"basicType": "STRING"
}
}
],
"outputs": [
{
"id": "eventName",
"description": "The name of the triggered event.",
"cardinality": "SINGLE",
"dataType": {
"basicType": "STRING"
}
},
{
"id": "eventMessage",
"description": "Detailed event message description.",
"cardinality": "SINGLE",
"dataType": {
"basicType": "STRING"
}
}
],
"onConfigFunction": "onConfigTrigger",
"onManageFunction": "onManageTrigger"
}
}
]
}
}
}
}
스타터 정기 결제 수명 주기 처리
사용자가 스타터를 포함하는 흐름을 구성하고 사용 설정하거나 흐름이 사용 중지되거나 삭제되면 Google은 매니페스트에 선언된 onManageFunction 콜백 함수를 사용하여 부가기능을 호출합니다.
수명 주기 이벤트 객체
콜백 함수는 작업 컨텍스트가 포함된 WorkflowEventObject를 수신합니다. 우선 다음이 포함됩니다.
트리거 생성 (
event.workflow.triggerCreation): 흐름이 게시되거나 사용 설정될 때 실행됩니다.triggerId: 이 스타터 등록 인스턴스를 식별하는 고유한 UUID 문자열입니다.notifyUri: 이 스타터 등록과 연결된 고유한 REST API 엔드포인트 URL입니다 (예:https://workspacestudio.googleapis.com/v1/triggers/YOUR_TRIGGER_ID:fire).inputs: 사용자가 카드에서 구성한 변수 입력입니다.
트리거 삭제 (
event.workflow.triggerDeletion): 시작 조건이 플로우에서 삭제되거나 전체 플로우가 사용 중지 또는 삭제될 때 실행됩니다.triggerId: 정리할 구독 인스턴스의 고유 UUID 문자열입니다.
Alternate Runtimes (HTTP API) 구독 수명 주기
대체 런타임을 사용하여 빌드된 부가기능의 경우 정기 결제 수명 주기 알림은 onManageFunction 콜백 함수로 지정된 작업 이름과 함께 부가기능의 구성된 HTTP 엔드포인트 URL에 HTTP POST 요청을 사용하여 전송됩니다. 페이로드는 WorkflowEventObject의 JSON 표현과 일치합니다.
대체 런타임에 관한 자세한 내용은 HTTP 엔드포인트를 사용하여 Google Workspace 부가기능 빌드를 참고하세요.
Apps Script에서 수명 주기 콜백 구현
다음 Apps Script 예에서는 사용자 인터페이스 카드를 구성하고, onManageTrigger를 사용하여 구독 수명 주기 이벤트를 처리하고, 이벤트가 발생하면 스타터 요청을 Google에 다시 전송하는 방법을 보여줍니다.
Apps Script
/**
* Generates and returns the user configuration card to collect inputs.
*/
function onConfigTrigger() {
const projectInput = CardService.newTextInput()
.setFieldName("projectId")
.setTitle("Project ID")
.setHint("Enter the project identifier to watch");
const section = CardService.newCardSection()
.setHeader("Configure Event Trigger")
.addWidget(projectInput);
const card = CardService.newCardBuilder()
.addSection(section)
.build();
return card;
}
/**
* Handles subscription lifecycle events sent from Google Workspace Studio.
*
* @param {Object} event The Workspace Studio event object.
*/
function onManageTrigger(event) {
const triggerCreation = event.workflow.triggerCreation;
const triggerDeletion = event.workflow.triggerDeletion;
if (triggerCreation) {
const triggerId = triggerCreation.triggerId;
const notifyUri = triggerCreation.notifyUri;
const inputs = triggerCreation.inputs;
// Extract input values configured by the user.
const projectId = inputs["projectId"].stringValues[0];
// TODO: Save triggerId, notifyUri, and projectId in your database/service.
// Your backend service listens for events related to 'projectId'
// and calls notifyUri when those events occur.
console.log("Trigger subscription created: " + triggerId +
", Notify URI: " + notifyUri +
", Match Project: " + projectId);
} else if (triggerDeletion) {
const triggerId = triggerDeletion.triggerId;
// TODO: Remove references to triggerId from your database and stop
// sending future event notifications to the associated notifyUri.
console.log("Trigger subscription deleted: " + triggerId);
}
}
/**
* Mock function showing how your backend service fires the trigger.
* This logic runs on your service when a watched event occurs.
*
* @param {string} notifyUri The stored notifyUri associated with the trigger.
* @param {string} triggerId The stored triggerId.
* @param {string} userAccessToken The OAuth 2.0 access token for the user
* (obtained using your stored refresh token).
*/
function simulateEventFire(notifyUri, triggerId, userAccessToken) {
// A unique UUID version 4 is recommended as the requestId for idempotency.
const requestId = Utilities.getUuid();
const payload = {
"name": "triggers/" + triggerId,
"outputs": {
"eventName": { "stringValues": ["EventOccurred"] },
"eventMessage": { "stringValues": ["Hello from the service!"] }
},
"requestId": requestId
};
const options = {
"method": "POST",
"contentType": "application/json",
"headers": {
"Authorization": "Bearer " + userAccessToken
},
"payload": JSON.stringify(payload),
"muteHttpExceptions": true
};
const response = UrlFetchApp.fetch(notifyUri, options);
const responseCode = response.getResponseCode();
if (responseCode === 200) {
console.log("Trigger successfully fired!");
} else if (responseCode === 404) {
// 404 means the trigger registration is invalid or deleted.
console.log("Trigger not found. Stop sending events for this trigger.");
// TODO: Clean up the trigger from your backend database.
} else if (responseCode === 429 || responseCode >= 500) {
console.log("Temporary error (" + responseCode + "). Retry using exponential backoff.");
} else {
console.log("Failed to fire trigger. HTTP Code: " + responseCode + " - " + response.getContentText());
}
}
Workspace Studio API 사용
Workspace Studio API(workspacestudio.googleapis.com)를 사용하여 시작 이벤트에 대해 Google에 프로그래매틱 방식으로 알릴 수 있습니다.
엔드포인트는 기본 경로 https://workspacestudio.googleapis.com/v1 아래에 있습니다.
시작 이벤트 알림
triggers.fire 메서드를 사용하여 시작 조건을 실행하여 플로우의 실행을 시작합니다.
- HTTP 메서드:
POST - 경로:
/v1/triggers/{triggerId}:fire(여기서{triggerId}은 트리거 구독 생성 중에 가져온 고유 식별자임) - OAuth 범위:
https://www.googleapis.com/auth/workspace.studio.trigger
다음 코드 샘플은 요청에서 시작 조건을 실행하는 방법을 보여줍니다.
요청
{
"name": "triggers/TRIGGER_ID",
"outputs": {
"eventName": {
"stringValues": [
"EventOccurred"
]
},
"eventMessage": {
"stringValues": [
"Hello from the service!"
]
}
},
"log": {
"textFormatElements": [
{
"text": "An event occurred in the app."
}
]
},
"requestId": "UNIQUE_REQUEST_ID"
}
name(문자열, 필수): 시작 조건의 리소스 이름입니다.triggers/{triggerId}형식으로 지정됩니다.outputs(map, 선택사항): 이벤트 데이터를 나타내는 시작 프로그램 출력 변수의 맵입니다. 각 값은 유형이 지정된 목록(예:stringValues,booleanValues,integerValues)을 지원하는VariableData객체입니다.log(객체, 선택사항): Workspace Studio 실행 활동 로그에 표시되는TextFormat마크업 표현입니다.requestId(문자열, 선택사항): 재시도 시 API의 멱등성을 보장하기 위한 최대 36개의 ASCII 문자로 구성된 고유 식별자 (UUID v4 권장)입니다.
응답
성공하면 응답은 빈 JSON 객체 {}를 반환합니다.
Workspace Studio API 할당량
workspacestudio.googleapis.com 서비스로 전송되는 트래픽은 시스템 과부하를 방지하고, 리소스의 공정한 사용을 장려하며, 전반적인 Google Workspace 성능을 보호하기 위해 제한됩니다.
적용되는 할당량은 다음과 같습니다.
| 할당량 유형 | 할당량 |
|---|---|
| 프로젝트별 분당 | 1,000개의 시작 요청 |
| 사용자별 분당 | 100개의 시작 조건 요청 |
할당량 유형은 다음과 같습니다.
- 프로젝트별 분당: 단일 개발자의 Google Cloud 프로젝트에서 실행되는 모든 사용자의 시작 조건에서 실행된 누적 시작 조건 이벤트 수를 분당 요청 1,000개로 제한합니다.
- 사용자별 분당: 특정 Cloud 프로젝트에서 단일 최종 사용자의 누적 시작 조건 호출을 분당 100개 요청으로 제한합니다.
시간 기반 할당량 오류 처리
이 할당량을 초과하면 API에서 비율 할당량이 초과되었음을 나타내는 HTTP 429 Too Many Requests (또는 429 Resource Exhausted) 오류 코드를 반환합니다.
이러한 오류를 해결하려면 코드가 예외를 포착하고 잘린 지수 백오프 전략을 사용해야 합니다. 지수 백오프는 여러 클라이언트가 동시에 동기화되고 재시도하는 것을 방지하기 위해 무작위 지터 (각 반복에서 무작위 지연 시간 재계산)를 포함하여 시도 사이에 점진적으로 더 긴 지연 시간을 사용하여 실패한 요청을 재시도합니다.
- Workspace Studio API에 요청을 전송합니다.
429오류로 요청이 실패하면1 second + random_number_milliseconds를 기다린 후 다시 시도합니다.- 다시 실패하면
2 seconds + random_number_milliseconds동안 기다린 후 다시 시도하세요. - 다시 실패하면
4 seconds + random_number_milliseconds동안 기다린 후 다시 시도하세요. - 이 루프를 계속하여 지연 시간을
maximum_backoff임계값(일반적으로 32 또는 64초)까지 두 배로 늘립니다. - 최대 백오프 기간에 도달하면 최대 재시도 한도에 도달할 때까지 해당 상수 지연을 사용하여 재시도한 후 중지하고 오류를 로깅합니다.
권장사항
스타터를 설계하고 구현할 때는 다음 권장사항을 고려하세요.
일괄 목록 대신 단일 이벤트 내보내기
항목의 배치 또는 목록을 포함하는 단일 이벤트를 내보내는 대신 각 개별 발생(예: 업데이트된 단일 레코드, 게시된 새 메시지, 할당된 작업)에 대해 개별 이벤트를 내보내도록 스타터를 설계하세요.
- 기본 제공 스타터와의 일관성: Workspace Studio에서 기본 제공 Google Workspace 스타터 (예: Gmail에서 이메일 수신 또는 Google Chat에서 사용자가 스페이스에 참여)는 단일 이벤트에서 트리거됩니다. 단일 항목 이벤트를 내보내는 것은 이 동작과 일치하며 모든 스타터에서 사용자에게 일관되고 예측 가능한 환경을 제공합니다.
- 간소화된 흐름 구성: 흐름의 다운스트림 단계는 일반적으로 한 번에 하나의 항목을 처리합니다. 단일 항목 이벤트를 내보내면 사용자가 배열을 반복하거나 목록을 파싱하는 복잡한 단계를 추가하지 않고도 변수를 직접 매핑할 수 있습니다.
- 폴링 및 일괄 변경을 개별적으로 처리: 백엔드 서비스가 외부 API를 폴링하고 단일 폴링 간격 중에 변경된 항목을 여러 개 감지하는 경우 항목을 하나의 일괄 이벤트로 번들링하는 대신 각 항목에 대해 개별 시작 이벤트를 실행합니다.
- 이벤트 비율 및 할당량 관리: 변경된 여러 항목에 대해 개별 이벤트를 발생시키면 요청이 갑자기 폭주할 수 있으므로 서비스가 Workspace Studio API 할당량(예: 사용자당 분당 요청 100개 제한)을 초과하지 않도록 하세요. 폴링 주기에서 많은 수의 항목 (예: 변경된 레코드가 100개 이상)이 생성되면
429 Too Many Requests오류를 방지하기 위해 시간이 지남에 따라 이벤트 디스패치를 페이싱하거나 제한하세요.
핵심 동작 및 특이 사례
스타터를 통합할 때 개발자는 특정 오류 동작과 런타임 기능을 처리해야 합니다.
- 테스트 실행 지원 없음: Workspace Studio는 초보자를 위한 테스트 실행을 지원하지 않습니다.
- 멱등성 및 리플레이 방지: 엄격하게 요구되지는 않지만 HTTP 또는 Apps Script 페이로드에 고유한
requestId(예: UUID)를 포함해야 합니다.requestId를 제공하면 API가 중복 알림을 감지하고 무시할 수 있으므로 단일 이벤트에 대해 흐름이 여러 번 실행되지 않도록 하여 멱등성을 보장할 수 있습니다. 흐름 사용 중지 및 다시 사용 설정: Workspace Studio에서 시작 조건을 포함하는 흐름이 사용 중지되면 Google에서
triggerDeletion수명 주기 이벤트를onManageFunction콜백으로 전송합니다. 또한 연결된FireTrigger메서드에 대한 호출은404 Not Found오류 반환 코드 (Requested entity was not found.)를 반환합니다. 서비스는 해당 시작 조건 인스턴스 ID에 대한 향후 활동 알림 전송을 중지하여404오류에 반응해야 합니다.사용자가 나중에 흐름을 다시 사용 설정하면 Google은 새
triggerId및notifyUri이 포함된 새triggerCreation이벤트와 함께onManageFunction콜백을 호출하여 새 정기 결제 수명 주기를 시작합니다. 이전triggerId는 영구적으로 사용 중지되며 다시 활성화되지 않으므로 서비스에서 이전 트리거 인스턴스가 다시 사용 설정되었는지 폴링하거나 확인해서는 안 됩니다. 자세한 내용은 스타터 구독 수명 주기 처리를 참고하세요.멱등성 구독 삭제:
onManageFunction콜백 함수는 Google의 스타터 삭제 요청을 멱등성으로 처리해야 합니다. Google에서 동일한triggerId에 대해 삭제 후크를 여러 번 호출하는 경우 (예: 일시적인 연결 손실로 인한 재시도 중) 함수는 성공적으로 반환되어야 합니다.흐름 할당량: Workspace Studio API 할당량 외에도 사용자 흐름에는 추가 내부 할당량 관리가 적용됩니다. 고빈도 루프 또는 과도한 이벤트 볼륨이 안전 기준을 초과하면 흐름이 자동으로 사용 중지될 수 있습니다.