자동 실행이 안 되면 Apps Script 왼쪽의 Executions(실행)에서 해당 시각 기록부터 찾으세요. 기록이 없으면 Triggers의 함수·이벤트·소유 계정이 맞는지 확인합니다. Failed나 Timed out이 있으면 오류와 실행 시간·서비스 할당량을 봅니다. 설치형 트리거는 만든 계정의 권한으로 동작하고, 스크립트/API가 값을 바꾼 일은 편집 이벤트 트리거를 자동으로 일으키지 않습니다. 문제를 분리하기 전에는 운영 트리거를 여러 개 다시 만들지 마세요.
“트리거가 안 돈다”를 네 가지 결과로 나눕니다
Apps Script는 실행 기록 없이 결과 시트만 보고 멈췄다고 판단하기 쉽습니다. 먼저 문제가 난 시각, 실행을 기대한 함수, 실제 입력 방식, 예상한 결과를 적고 아래 중 어디에 해당하는지 고릅니다. 이 분류를 하면 코드를 바꾸기 전에 트리거 설정인지 실행 중 오류인지 구분할 수 있습니다.
| 관찰한 상태 | 우선 볼 곳 | 다음 조치 |
|---|---|---|
| 기대 시각에 Executions 행이 전혀 없음 | Triggers, 트리거 계정, 이벤트 조건, 스크립트 프로젝트 | 다른 계정·다른 프로젝트에 트리거를 만들었는지, 사람이 한 편집이 실제 이벤트인지 확인 |
| 실행 행이 Failed 또는 Timed out | Executions 행의 오류 메시지·시각·실행 유형, 실패 알림 메일 | 표시된 권한·잘못된 값·서비스 한도·실행 시간 오류를 먼저 해결 |
| Completed인데 셀·메일 결과가 없음 | 대상 파일·시트·범위, 분기 조건, 입력 행 | 기록에 남은 함수가 올바른 파일을 읽는지, 필터 조건이 너무 좁지 않은지 복사본으로 검수 |
| 메일·행 업데이트가 두 번 이상 발생 | 같은 함수의 트리거 수, 여러 계정에서 만든 트리거, 재시도 코드 | 소유 계정마다 Triggers를 확인하고 중복 원인을 확인한 뒤 하나만 남김 |
Executions에서 먼저 실패 행과 실행 유형을 확인하세요
- 문제가 있는 Apps Script 프로젝트를 엽니다. 스프레드시트에서 확장 프로그램 → Apps Script를 열거나 script.google.com 대시보드의 프로젝트 목록에서 선택합니다.
- 왼쪽의 Executions(실행)을 누르고 문제가 발생한 시간 범위를 찾습니다. 시작 시간·실행 시간·상태를 확인합니다.
- 실행 유형이 Time Driven 또는 Trigger인지 확인합니다. 편집기에서 직접 눌러 실행한 Editor 기록과 혼동하지 마세요.
- Failed 행을 열어 오류 전문에서 오류 종류와 함수·행 번호를 기록합니다. 개인정보·이메일 주소·시트 내용을 그대로 다른 사람에게 붙여 보내지 않습니다.
- 설치형 트리거가 화면에 없을 때는 만든 계정으로 발송되는 실패 요약 메일도 확인합니다. 실행 실패는 사용자가 시트에 없어도 발생하므로 화면 알림만 기다리지 마세요.
실행 기록은 코드가 실제로 시작했는지를 알려 줍니다. 기록이 없다는 사실만으로 함수 오류를 추정하지 말고, 트리거가 등록된 계정과 조건부터 봅니다. 실행은 완료됐는데 결과만 다르면 코드의 조건·대상 범위를 조사하세요.
함수·이벤트 유형·소유 계정이 맞는 트리거인지 확인합니다
Apps Script 왼쪽 Triggers(트리거) 화면에서 함수 이름, 이벤트 소스와 이벤트 유형, 시간 기반 주기를 대조합니다. 예를 들어 sendDailyDigest를 실행하려는데 트리거가 이름이 비슷한 sendDigest를 가리키면 일정이 있어도 다른 함수가 실행됩니다. 편집 트리거에는 스프레드시트 편집, 양식 제출에는 연결된 Sheets 또는 Forms 이벤트처럼 실제 입력 경로에 맞는 유형이 필요합니다.
누가 트리거를 만들었는지도 확인하세요. 설치형 트리거는 만든 계정의 권한으로 실행되고, 다른 계정이 만든 트리거는 내 화면에서 보이지 않을 수 있습니다. 동료가 파일을 열거나 편집해도 발신자·서비스 권한은 트리거를 만든 계정에 연결됩니다. 공유 파일을 담당하는 계정이 바뀌었다면 기존 주인의 Triggers 목록과 실행 기록을 따로 확인한 뒤, 새 책임 계정에서 시험용 트리거를 만들지 운영 트리거를 넘길지 결정합니다.
중복 발송 주의: 같은 이벤트에 각 사용자가 설치형 트리거를 하나씩 만들면 계정별 실행이 겹칠 수 있습니다. 팀 자동화는 하나의 소유 계정과 담당자를 정하고, 다른 소유 계정의 트리거도 확인하세요.
단순 트리거로 가능한 작업인지 설치형이 필요한지 구분하세요
| 방식 | 예 | 적합한 경우와 제한 |
|---|---|---|
| 단순 트리거 | onOpen(e), onEdit(e) | 간단한 편집·메뉴 작업. 승인 대화상자가 필요한 서비스에는 제한이 있어 이메일·외부 서비스 호출 용도에 맞지 않을 수 있음 |
| 설치형 편집·열기·제출 트리거 | Sheets 편집, Forms 제출, 문서 열기 | 승인이 필요한 서비스와 더 많은 이벤트 유형을 사용할 때. 만든 계정 권한으로 실행 |
| 시간 기반 트리거 | 매일 메일 대기열 점검, 매시간 데이터 갱신 | 정해진 간격으로 점검하는 흐름. 셀 편집 자체가 원인이 아니며, 실행 시각은 분 단위 약속과 다를 수 있음 |
Google은 단순 onEdit 트리거가 최대 2개의 이벤트만 대기열에 둘 수 있다고 안내합니다. 짧은 시간에 여러 번 편집하는 흐름은 이 대기열을 넘을 수 있으므로 모든 셀 편집이 각각 처리된다고 전제하지 마세요. 변화가 잦은 시트는 처리할 행에 대기 상태를 기록하고 시간 기반 트리거가 미처리 행을 묶음으로 읽게 하는 방식과 비교합니다.
권한 오류는 트리거를 만든 계정으로 재승인합니다
Executions에 Authorization is required to perform that action, 접근 거부, 범위 승인 오류가 있다면 자동 실행 중 권한 창이 나타나지 못한 경우일 수 있습니다. 새로 사용한 Google 서비스가 승인되지 않았거나 기존 권한이 취소·만료된 경우에도 발생합니다.
- 실패한 트리거의 소유 계정으로 Apps Script 편집기를 엽니다. 실행 기록이 다른 계정에 있다면 해당 계정으로 로그인합니다.
- 실패한 트리거 함수가 필요한 서비스를 실제로 호출하는지 확인하고, 외부 사용자에게 메일을 보내는 동작을 피할 시험 함수가 있으면 그 함수를 실행합니다.
- 편집기에서 수동 실행할 때 나타나는 승인 화면에서 필요한 권한을 검토하고, 업무에 필요한 권한만 허용합니다. 조직 계정에서 관리자가 앱을 제한하면 Workspace 관리자에게 정책을 확인합니다.
- 성공한 실행 기록을 확인한 다음 Triggers에서 같은 함수·이벤트 유형이 하나만 있는지 봅니다. 트리거가 삭제되었거나 설정이 잘못된 경우에만 올바른 소유 계정에서 다시 추가합니다.
수동 실행을 승인하더라도 트리거 설정이 자동으로 생기는 것은 아닙니다. 반대로 기존 트리거를 먼저 삭제하면 문제가 해결되기 전까지 자동 작업 자체가 멈춥니다. 승인 완료, 시험 실행, 트리거 한 개만 유지 순서로 확인하세요.
편집기에서 실행한 테스트와 실제 이벤트는 다릅니다
onEdit(e)처럼 이벤트 객체를 받는 함수는 실제 스프레드시트 편집에서 e를 전달받습니다. 편집기에서 실행 버튼을 누르면 그 이벤트가 발생한 것이 아니므로 e가 없습니다. 코드가 e.range를 읽을 때 오류가 나더라도 트리거 자체가 잘못된 증거는 아닙니다.
또한 설치형 트리거는 Apps Script 코드나 API 요청이 값을 바꾼 경우 그 편집을 다시 감지하지 않습니다. 사람이 시트 UI에서 값을 바꿨을 때만 실행해야 하는지, 폼 제출·시간 기반 검사·명시적 함수 호출 중 무엇이 필요한지 정합니다. 테스트는 실제 이벤트를 작은 복사본에서 발생시켜 확인하세요.
시간대와 시간 기반 트리거의 실행 창을 확인합니다
- Apps Script 편집기의 Project Settings에서 프로젝트 시간대를 확인합니다. 실행하려는 업무의 현지 시간과 일치하는지 봅니다.
- Triggers에서 주기·요일·시간대를 대조합니다. 매일 아침을 원한다면 시간 기반 트리거가 올바른 함수를 가리키는지 확인합니다.
- 정각 실행을 가정하지 않습니다. Google은 반복 시간 트리거의 실행 시각을 약간 무작위로 정할 수 있다고 안내합니다. 9시 트리거 예시는 9시부터 10시 사이의 시간을 선택하고 이후 그 시각을 유지합니다.
- 특정 분에 전송되어야 하는 회의·마감 안내라면, 트리거 시간이 조금 달라져도 안전한 범위인지 먼저 정합니다. 화면에 보이는 시각만으로 중복 트리거를 추가하지 않습니다.
시트에 적힌 날짜와 시간 값이 기대한 날짜에서 하루 밀려 보인다면 실행 시간과 저장된 날짜 자료형을 함께 확인합니다. 날짜를 문자열로 만들어 비교하기보다는 시간대가 지정된 날짜 값을 비교하고, 시험 자료로 월말·자정 경계도 검산하세요.
할당량·실행 시간·중복 처리를 분리해 봅니다
오류에 Service invoked too many times, 이메일 한도 초과, Service using too much computer time for one day가 나타나면 트리거 주기가 아니라 해당 서비스의 사용량과 실행 기록을 먼저 확인합니다. Google Apps Script 할당량은 개인 계정과 Workspace 계정에 따라 다를 수 있고 변경될 수 있습니다. 숫자를 오래된 블로그에서 가져오지 말고 현재 공식 할당량 표에서 계정 유형과 서비스별 한도를 확인하세요.
- 메일을 보낸다면 실행 중
MailApp.getRemainingDailyQuota()로 남은 수신자 한도를 확인할 수 있습니다. 이는 현재 실행 시점의 남은 값이지 내일도 같은 값이라는 보장은 아닙니다. - 한 번에 읽고 쓰는 셀 범위를 줄이고, 행마다 API나 메일을 호출하는 반복문은 묶음 처리할 수 있는지 봅니다.
- 한도를 넘은 작업을 매 분마다 다시 실행하게 만들면 실패 기록과 재시도가 쌓입니다. 오류 원인을 처리하고 다음 허용 시간에 안전하게 재개되게 합니다.
- 이메일을 보낸 뒤 상태값을 기록하는 자동화는 전송 직후 스크립트가 중단되면 성공 여부가 모호할 수 있습니다. 같은 행을 무조건 다시 보내지 말고 발송 키·상태를 확인하고 수동 재처리 범위를 정합니다.
현재 계정에서 보이는 트리거만 안전하게 기록합니다
다음 진단 함수는 현재 스크립트 프로젝트와 현재 실행 계정에서 조회되는 트리거의 함수·유형만 로그에 남깁니다. 시트 데이터나 수신자 주소는 기록하지 않습니다. 다른 계정이 만든 트리거는 현재 목록에 나오지 않을 수 있으므로 필요한 경우 각 책임 계정으로 확인해야 합니다.
function auditMyTriggers() {
const rows = ScriptApp.getProjectTriggers().map(trigger => ({
handler: trigger.getHandlerFunction(),
eventType: String(trigger.getEventType()),
source: String(trigger.getTriggerSource())
}));
console.log(JSON.stringify(rows, null, 2));
}
- Apps Script 편집기에서
auditMyTriggers를 선택해 수동 실행하고 필요한 권한을 승인합니다. - Execution log에 나타난 함수·이벤트·소스를 기대 설정과 비교합니다. 함수 이름이나 실행 시각이 다른지 확인합니다.
- 로그에 값이 없더라도 다른 소유 계정의 트리거까지 삭제하지 않습니다. 해당 계정에서 별도로 목록을 확인합니다.
- 확인 뒤 불필요한 중복을 정리할 때는 대상 함수와 트리거를 기록한 뒤 하나씩 삭제합니다.
이 함수는 트리거를 만들거나 지우지 않습니다. getProjectTriggers()는 현재 사용자 계정이 볼 수 있는 프로젝트 트리거를 확인하는 용도입니다.
운영 파일이 아닌 복사본에서 이벤트를 재현합니다
트리거는 자동 메일·행 수정·외부 API 호출을 실행할 수 있으므로 실제 고객 목록에서 시험하지 마세요. 먼저 파일 사본이나 테스트 스프레드시트를 만들고 다음 순서로 범위를 제한합니다.
- 운영 시트의 파일 ID와 탭 이름을 바꾸지 말고 복사본을 만들고, 합성된 이름·주소·주문 행만 넣습니다.
- 테스트 계정 본인에게만 메일을 보내거나, 메일 전송 함수를 잠시 비활성화하고 로그에 예정 수신자 수만 남깁니다.
- 복사본의 Apps Script에서 실제 사용자가 수행할 이벤트를 재현합니다. 편집 트리거라면 테스트 셀을 UI에서 수정하고, 폼 제출 트리거라면 시험 폼을 제출합니다.
- Executions의 실행 유형·상태와 실제 결과 행 수를 맞춰 봅니다. Completed라도 올바른 탭·행에 반영됐는지 확인합니다.
- 같은 입력을 두 번 시험해도 메일·데이터가 중복되지 않는지 확인합니다. 재시도할 때 중복이 가능하면 고유 작업 ID와 처리 상태를 기록합니다.
- 운영 코드에 반영한 뒤 하나의 소유 계정에서 트리거를 한 개 설치하고, 다음 실행 기록을 확인합니다.
증상별로 바로 볼 화면
| 증상·기록 | 원인 후보 | 확인·수정 |
|---|---|---|
| 예약 시각인데 기록이 없음 | 트리거 미등록, 다른 프로젝트·계정, 시간 기반 대신 편집 이벤트 선택 | 문서 소유자와 자동화 책임 계정에서 Triggers를 각각 확인 |
| 수동 실행만 성공하고 자동은 실패 | 이벤트 객체 부재, 자동화 계정 승인 문제, 다른 소유 계정 | Executions에서 실행 유형을 대조하고 실제 이벤트로 복사본 시험 |
Authorization is required | 필요 권한 미승인·취소, 신규 서비스 스코프 | 트리거를 만든 계정으로 편집기에서 필요한 함수를 실행해 승인한 뒤 재검증 |
| 시트에서 직접 고치면 알림, 수식/API 수정은 무반응 | 편집 트리거의 이벤트 범위 | 스크립트/API 변경은 편집 트리거를 발생시키지 않을 수 있음. 시간 기반 점검이나 호출 함수로 설계 |
| 오전 9시 정각이 아닌 조금 뒤 실행 | 시간 기반 트리거의 실행 창 | 프로젝트 시간대와 선택한 시간을 확인하고 허용 실행 범위를 조정 |
| 같은 행에 메일이 중복 발송됨 | 다른 계정의 트리거, 중복 등록, 재실행 가능한 발송 코드 | 각 계정의 트리거를 확인하고 처리 키·상태 기록 뒤 시험 |
| 메일·서비스 호출 한도 오류 | 계정 유형별 서비스 할당량·트리거 총 실행 시간 | 실패 메시지와 공식 quota 표, 남은 메일 수신자 수를 확인 |
Apps Script 트리거 문제 자주 묻는 질문
편집기에서 함수를 실행하면 되는데 시간 트리거는 왜 실패하나요?
편집기 실행은 현재 사용자와 수동 실행 흐름이고, 설치형 트리거는 트리거를 만든 계정의 권한과 예약된 조건으로 실행됩니다. Executions의 실행 유형과 오류, Triggers의 소유 계정·이벤트를 비교하세요.
한 사람이 트리거를 다시 만들면 기존 설정도 바뀌나요?
자동으로 정리되지 않습니다. 다른 계정이 만든 트리거는 보이지 않을 수 있고 각 계정의 트리거가 별도로 실행될 수 있습니다. 책임 계정마다 확인한 뒤 중복 원인을 정리하세요.
Apps Script나 API가 셀을 수정해도 onEdit가 실행되나요?
일반적인 스크립트 실행과 API 요청은 편집 이벤트 트리거를 발생시키지 않습니다. 변경 방식이 코드·연동 서비스라면 시간 기반 점검이나 호출 함수처럼 입력 경로에 맞는 설계를 검토하세요.
매일 오전 9시에 꼭 실행되게 할 수 있나요?
시간 기반 트리거는 특정 시간대를 골라도 분 단위 정각 실행을 보장하는 방식이 아닙니다. Google 문서는 반복 9시 트리거가 9시부터 10시 사이의 시각을 선택할 수 있다고 설명합니다. 몇 분의 지연도 허용되지 않는 작업이면 다른 스케줄링 수단과 요구 조건을 비교하세요.
Google Sheets 자동화 이어보기
Google 공식 도움말
- Simple Triggers — 단순 트리거 종류, 제한, 이벤트 실행
- Installable Triggers — 소유 계정, 설치·시간 기반 트리거, 제한과 실패 알림
- Event Objects — 이벤트 객체와
triggerUid, 셀 편집 범위 - Trigger class — 진단 코드에서 사용하는 함수·이벤트·소스 조회 메서드
- Apps Script Dashboard — Executions 실행 상태·유형 확인
- Logging — Execution log·Cloud Logging·오류 기록
- Quotas for Google Services — 계정별·서비스별 현재 한도
- Troubleshooting — 권한 승인 오류와 서비스 예외
- MailApp — 남은 일일 이메일 수신자 수 확인