구글 앱스 스크립트를 실행할 때 오류 메시지에
Service invoked too many times가 표시될 수 있습니다.
이 문구만 보고 무조건 일일 할당량이 끝났다고 판단하면 해결 방법을
잘못 선택할 수 있습니다.
오류 문구 뒤에 for one day가 있는지,
in a short time이 있는지에 따라 원인이 다릅니다.
서비스 호출 횟수가 아니라 트리거의 하루 총실행 시간이 문제가 되는 경우도
있습니다. 따라서 먼저 오류 메시지 전체를 확인해야 합니다.
이 글은 Google Apps Script의 공식 할당량, 실행 기록, 트리거와 CacheService 문서를 기준으로 작성했습니다. 할당량은 계정 종류와 서비스에 따라 다르며 Google이 예고 없이 변경할 수 있으므로 현재 공식 표를 함께 확인해야 합니다.
![]() |
| 오류 메시지의 전체 문구를 확인해 일일 한도, 짧은 시간의 호출 제한과 트리거 실행 시간 문제를 구분합니다. |
먼저 오류 메시지 전체를 복사하세요
비슷해 보이는 메시지라도 의미와 조치가 다릅니다. 실행 기록에서 오류 문구를 줄이지 말고 전체를 확인하세요.
해당 서비스를 하루 동안 너무 많이 호출한 경우입니다.
일일 한도가 아니라 짧은 시간에 호출이 몰린 경우입니다.
트리거로 실행된 스크립트의 하루 총실행 시간이 한도를 넘은 경우입니다.
사용자 계정에서 스크립트 실행이 짧은 시간에 너무 많이 시작된 경우입니다.
같은 계정에서 동시에 실행 중인 스크립트가 너무 많은 경우입니다.
실패한 실행 기록에서 원인을 확인하는 방법
시간 기반 트리거나 수정 트리거에서 오류가 발생했다면 화면에 오류 창이 나타나지 않을 수 있습니다. Apps Script 편집기의 실행 기록에서 확인해야 합니다.
- 문제가 발생한 스프레드시트를 엽니다.
- 확장 프로그램 → Apps Script를 선택합니다.
- 왼쪽 메뉴에서 실행을 선택합니다.
- 상태가 실패인 실행을 선택합니다.
- 오류 메시지와 실패한 함수 이름을 확인합니다.
- 실행을 시작한 유형이 수동 실행인지 트리거인지 확인합니다.
실패한 함수가 여러 개라면 어떤 함수에서 Gmail, Calendar, Drive, Spreadsheet 또는 UrlFetch 서비스를 호출했는지 확인하세요. 오류 메시지의 서비스 이름이 원인을 좁히는 기준이 됩니다.
현재 공식 문서에 표시된 주요 할당량
다음 값은 일반 계정과 Google Workspace 계정의 한도가 서로 다르다는 점을 보여주기 위한 주요 항목입니다. 고정된 영구 값이 아니므로 코드를 설계할 때는 Google 공식 할당량 페이지의 현재 값을 다시 확인해야 합니다.
| 항목 | 일반 계정 | Google Workspace |
|---|---|---|
| 이메일 수신자 | 하루 100명 | 하루 1,500명 |
| URL Fetch 호출 | 하루 20,000회 | 하루 100,000회 |
| 트리거 총실행 시간 | 하루 90분 | 하루 6시간 |
| 한 번의 스크립트 실행 시간 | 최대 6분 | 최대 6분 |
| 사용자별 동시 실행 | 사용자당 30개 | 사용자당 30개 |
| 설치 가능한 트리거 | 사용자·스크립트당 20개 | 사용자·스크립트당 20개 |
Apps Script 공식 안내에서는 사용자별 할당량이 첫 요청이 발생한 시점부터 24시간 후 재설정된다고 설명합니다. 오류가 발생한 시각부터 정확히 24시간을 기다리면 된다는 의미도 아니므로 첫 사용 시점과 서비스별 사용량을 함께 고려해야 합니다.
오류 문구에 ‘for one day’가 있는 경우
하루 할당량을 이미 소진했다면 같은 서비스를 즉시 다시 호출해도 해결되지
않습니다. Utilities.sleep()으로 몇 초 기다리는 방법도
일일 한도를 복구하지 못합니다.
이 경우에는 다음 순서로 처리합니다.
- 오류가 발생한 자동 트리거를 일시적으로 중지합니다.
- 같은 서비스를 반복 호출하는 코드 위치를 찾습니다.
- 불필요한 중복 호출을 제거합니다.
- 작업 대상을 여러 번 다시 읽지 않도록 데이터를 한 번에 가져옵니다.
- 할당량이 재설정된 후 자동 실행을 다시 시작합니다.
계정을 바꾸거나 같은 파일에 트리거를 여러 개 설치해 제한을 우회하는 방식은 안정적인 해결책이 아닙니다. 어떤 계정으로 트리거가 실행되고 있는지 파악하기도 어려워질 수 있습니다.
이메일 발송 오류라면 남은 수신자 수 확인
이메일 발송에 사용하는 MailApp은 현재 계정에서 그날 추가로
보낼 수 있는 수신자 수를 확인하는 메서드를 제공합니다.
function logRemainingEmailQuota() {
const remaining = MailApp.getRemainingDailyQuota();
console.log(
'오늘 추가로 보낼 수 있는 수신자 수: ' + remaining
);
}
코드를 실행한 뒤 Apps Script 편집기의 실행 로그에서 결과를 확인할 수 있습니다.
반환값은 이메일 발송 횟수가 아니라 추가로 발송할 수 있는 수신자 수입니다. 한 통의 이메일에 여러 명의 수신자가 포함되면 수신자 수를 기준으로 한도에 반영됩니다.
캐시는 외부 데이터를 반복해서 가져오는 횟수를 줄이는 데 사용할 수 있지만, 반드시 보내야 하는 이메일 수신자 자체를 줄여주지는 않습니다. 발송 대상을 나누거나 발송 시점을 조정해야 합니다.
오류 문구에 ‘in a short time’이 있는 경우
이 메시지는 하루 전체 한도를 소진했다기보다 짧은 시간에 서비스 호출이 몰렸다는 의미입니다.
Google의 오류 예시에는 호출 사이에 다음과 같은 지연을 두는 방법이 표시됩니다.
Utilities.sleep(1000);
숫자 1000은 1,000밀리초, 즉 1초입니다. 다만 모든 반복문에
무조건 넣어야 하는 코드는 아닙니다.
- 짧은 시간의 호출 집중을 완화할 때만 사용합니다.
- 이미 소진된 일일 한도를 복구하지는 않습니다.
- 지연을 너무 많이 넣으면 전체 실행 시간 한도에 가까워질 수 있습니다.
- 먼저 반복 호출 자체를 줄일 방법이 있는지 확인합니다.
Spreadsheet 서비스라면 셀을 한 개씩 읽고 쓰는 대신
getValues()와 setValues()로 범위를 한 번에
처리하는 것이 우선입니다. Calendar나 Drive 서비스도 같은 정보를 반복해서
요청하고 있지 않은지 확인해야 합니다.
같은 외부 API 데이터를 반복해서 가져온다면 캐시 사용
여러 사용자가 같은 환율, 상품 목록 또는 공개 데이터를 반복해서 불러오는 구조라면 CacheService로 외부 요청 횟수를 줄일 수 있습니다.
아래 예제의 주소는 설명용이므로 실제로 사용하는 API 주소로 바꿔야 합니다. 코드를 그대로 실행하는 완성형 서비스가 아닙니다.
function getExternalJsonWithCache() {
const cache = CacheService.getScriptCache();
const cacheKey = 'external_json_v1';
const cached = cache.get(cacheKey);
if (cached !== null) {
return JSON.parse(cached);
}
const url = 'https://api.example.com/data';
const response = UrlFetchApp.fetch(url, {
method: 'get',
muteHttpExceptions: true,
});
const status = response.getResponseCode();
const body = response.getContentText();
if (status < 200 || status >= 300) {
throw new Error(
'HTTP ' + status + ': ' + body.slice(0, 200)
);
}
const data = JSON.parse(body);
cache.put(
cacheKey,
JSON.stringify(data),
1800
);
return data;
}
이 예제는 캐시에 데이터가 있으면 외부 API를 호출하지 않고 저장된 값을 반환합니다. 캐시가 비어 있을 때만 외부 API에 요청하고 결과를 1,800초 동안 보관하도록 요청합니다.
지정한 만료 시간은 보관을 요청하는 시간이며, 데이터가 그 시간까지 반드시 남아 있는 것은 아닙니다. 따라서
cache.get()이
null을 반환하는 상황을 항상 처리해야 합니다.
로그인 사용자마다 다른 데이터를 반환하는 API라면 모든 사용자가 공유하는
getScriptCache()보다 사용자별
getUserCache()가 적절할 수 있습니다. 개인정보나 인증 토큰을
공용 캐시에 저장하지 마세요.
트리거 실행 시간이 하루 한도를 넘은 경우
오류 메시지가 다음과 같다면 호출 횟수보다 트리거로 실행된 스크립트의 하루 총실행 시간을 확인해야 합니다.
Service using too much computer time for one day.
Apps Script 편집기에서 다음 항목을 확인하세요.
- 왼쪽 메뉴에서 트리거를 선택합니다.
- 같은 함수를 실행하는 트리거가 중복으로 등록됐는지 확인합니다.
- 1분 또는 5분 간격으로 실행할 필요가 있는지 확인합니다.
- 더 이상 사용하지 않는 트리거를 삭제합니다.
- 실행 메뉴에서 각 실행에 걸린 시간을 확인합니다.
설치 가능한 트리거는 이를 만든 사용자의 계정 권한으로 실행됩니다. 여러 사람이 같은 파일에서 각각 트리거를 설치했다면 같은 작업이 여러 계정에서 중복 실행될 수 있습니다.
단순히 트리거 간격만 늘리는 것보다 한 번 실행될 때 불필요하게 반복하는 작업도 함께 줄여야 합니다. 전체 실행 한 번이 6분에 가까워진다면 별도의 실행 시간 초과 문제도 확인해야 합니다.
스크립트가 동시에 너무 많이 실행되는 경우
다음 메시지는 여러 스크립트가 동시에 실행되거나 사용자 정의 함수가 시트의 많은 셀에서 개별적으로 실행될 때 나타날 수 있습니다.
Script invoked too many times per second for this Google user account.
There are too many scripts running simultaneously for this Google user account.
다음 구조가 있는지 확인하세요.
- 같은 사용자 정의 함수를 수백 개 셀에 각각 입력한 경우
- 수정할 때마다 여러 설치형 트리거가 동시에 실행되는 경우
- 버튼을 짧은 시간에 여러 번 누를 수 있는 구조
- 함수가 실행 중인데 같은 함수가 다시 시작되는 경우
- 여러 파일에서 같은 계정의 자동화가 동시에 실행되는 경우
사용자 정의 함수는 셀 한 개씩 호출하기보다 하나의 범위를 인수로 받아 배열 결과를 반환하도록 설계하는 방법을 검토하세요. 트리거 작업은 중복 실행을 막기 위해 LockService가 필요한지 확인할 수 있습니다.
할당량 오류에서 하지 말아야 할 처리
-
일일 할당량 오류에
Utilities.sleep()만 추가하지 않습니다. - 다른 Google 계정을 계속 추가해 제한을 우회하지 않습니다.
- 실패한 트리거를 확인하지 않고 같은 트리거를 새로 만들지 않습니다.
- CacheService가 이메일이나 Calendar 일일 한도를 늘린다고 생각하지 않습니다.
-
모든 예외를
try...catch로 숨기고 정상 처리된 것처럼 표시하지 않습니다. - 현재 한도 수치를 영구적인 값으로 코드 안에 고정하지 않습니다.
오류 메시지별로 바로 해야 할 작업
트리거를 중지하고 호출 횟수를 줄인 뒤 할당량 재설정을 기다립니다.
반복 호출을 줄이고 필요한 경우 호출 사이에 지연을 둡니다.
중복 트리거, 실행 주기와 함수별 실행 시간을 확인합니다.
사용자 정의 함수의 개별 셀 호출과 중복 실행 구조를 줄입니다.
동일한 응답을 재사용할 수 있을 때만 CacheService를 적용합니다.
확인에 사용한 Google 공식 자료
공식 문서 확인일: 2026년 7월 27일

댓글 쓰기