Google Apps Script Service invoked too many times 오류 해결 흐름

Apps Script 할당량 오류는 반복 호출 구조와 트리거 실행 간격을 함께 확인해야 합니다.


Google Apps Script에서 Service invoked too many times 오류가 발생했다면 먼저 같은 서비스를 너무 자주 호출하고 있는지 확인해야 합니다. 코드 문법이 틀렸다기보다 SpreadsheetApp, GmailApp, DriveApp, UrlFetchApp 같은 서비스를 반복문 안에서 과도하게 실행하거나, 시간 기반 트리거가 너무 자주 돌면서 할당량 제한에 걸릴 때 자주 발생합니다.


해결 순서는 실행 로그 확인, 오류가 난 서비스 확인, 트리거 중복 점검, getValue()·setValue() 반복 호출을 getValues()·setValues() 방식으로 바꾸기, 한 번에 처리하는 데이터 수 줄이기 순서로 보면 됩니다. 최신 할당량 수치와 정책은 계정 유형과 Google 정책에 따라 달라질 수 있으므로 발행 전 Google Apps Script 공식 Quotas 문서를 확인하는 것이 안전합니다.


📑목차[보기]

오류 메시지 원문

Apps Script 할당량 관련 오류는 메시지 문구가 조금씩 다르게 표시될 수 있습니다. 특히 아래 문구가 보이면 특정 서비스 호출량, 하루 실행량, 트리거 실행량을 함께 확인해야 합니다.


Service invoked too many times

Service invoked too many times for one day

Service using too much computer time for one day

핵심 구분
Service invoked too many times는 특정 서비스 호출이 너무 많은 경우에 가깝고, Service using too much computer time for one day는 하루 동안 트리거 등으로 사용한 총 실행 시간이 많을 때 나타날 수 있습니다. 정확한 제한 수치는 바뀔 수 있으므로 공식 Quotas 문서에서 최신 기준을 확인해야 합니다.


Service invoked too many times 오류가 발생하는 이유

이 오류는 Google Apps Script가 연결된 Google 서비스나 외부 요청을 너무 많이 호출할 때 발생합니다. 구글시트 자동화라면 SpreadsheetApp, 메일 자동 발송이라면 GmailApp, 파일 정리 자동화라면 DriveApp, RSS나 외부 API 수집이라면 UrlFetchApp 호출이 원인이 되는 경우가 많습니다.


상황 자주 보이는 원인 처리 방향
구글시트 데이터 정리 셀마다 getValue(), setValue() 실행 getValues(), setValues()로 일괄 처리
Gmail 자동 발송 GmailApp.sendEmail() 반복 실행 발송 대상 분할, 발송 완료 표시 컬럼 추가
RSS·API 수집 UrlFetchApp을 짧은 간격으로 반복 호출 수집 간격 늘리기, 캐시·중복 확인 로직 추가
시간 기반 트리거 트리거가 너무 자주 실행되거나 중복 등록됨 트리거 목록 점검, 실행 간격 조정

먼저 확인할 것

오류를 고치기 전에 어느 서비스에서 제한에 걸렸는지부터 확인해야 합니다. 같은 메시지라도 원인이 구글시트 호출인지, Gmail 발송인지, 외부 API 호출인지에 따라 수정 위치가 달라집니다.


  1. Apps Script 편집기에서 실행 기록 또는 로그를 확인합니다.
  2. 오류가 발생한 함수 이름과 줄 번호를 확인합니다.
  3. SpreadsheetApp, GmailApp, DriveApp, UrlFetchApp 중 어느 서비스 호출 직후 멈췄는지 봅니다.
  4. 트리거 메뉴에서 같은 함수가 여러 번 등록되어 있는지 확인합니다.
  5. 최근에 데이터 행 수, 발송 대상 수, API 요청 수가 늘었는지 확인합니다.
  6. 실행 시간 초과 오류인지, 서비스 호출량 초과 오류인지 메시지를 구분합니다.

주의할 점
트리거를 삭제하거나 코드를 크게 바꾸기 전에는 현재 트리거 이름, 실행 주기, 연결된 함수 이름을 먼저 메모해 두는 것이 좋습니다. 자동 발송이나 데이터 수정 스크립트는 잘못 수정하면 중복 발송 또는 중복 입력이 생길 수 있습니다.


구글시트 자동화에서 자주 나는 잘못된 코드

구글시트 자동화에서 가장 흔한 실수는 반복문 안에서 셀을 하나씩 읽고 하나씩 쓰는 구조입니다. 데이터가 10행일 때는 문제가 없어 보이지만, 1,000행·5,000행으로 늘어나면 SpreadsheetApp 호출 횟수가 급격히 많아집니다.


아래 코드는 행마다 getValue()setValue()를 반복합니다. 작은 테스트에서는 통과해도 실제 데이터가 많아지면 느려지고 할당량 오류가 날 수 있습니다.


function badExample() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
  const lastRow = sheet.getLastRow();

  for (let row = 2; row <= lastRow; row++) {
    const name = sheet.getRange(row, 1).getValue();
    const score = sheet.getRange(row, 2).getValue();

    if (score >= 80) {
      sheet.getRange(row, 3).setValue(name + ' 통과');
    } else {
      sheet.getRange(row, 3).setValue(name + ' 확인 필요');
    }
  }
}

문제는 반복 횟수 자체보다 “반복문 안에서 Apps Script 서비스 호출이 계속 발생한다”는 점입니다. getRange(), getValue(), setValue()가 매 행마다 실행되면 호출 수가 빠르게 늘어납니다.


getValues와 setValues로 호출 횟수 줄이는 방법

구글시트 자동화는 데이터를 한 번에 읽고, 배열에서 계산한 뒤, 결과를 한 번에 쓰는 방식으로 바꾸는 것이 좋습니다. 이렇게 하면 시트 서비스 호출 횟수가 크게 줄어들고 실행 속도도 안정됩니다.


function goodExample() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
  const lastRow = sheet.getLastRow();

  if (lastRow < 2) return;

  const values = sheet.getRange(2, 1, lastRow - 1, 2).getValues();

  const results = values.map(function(row) {
    const name = row[0];
    const score = row[1];

    if (score >= 80) {
      return [name + ' 통과'];
    }

    return [name + ' 확인 필요'];
  });

  sheet.getRange(2, 3, results.length, 1).setValues(results);
}

위 방식은 시트에서 데이터를 한 번에 가져오고, 결과도 한 번에 입력합니다. 데이터가 많을수록 셀 단위 처리보다 배열 단위 처리가 유리합니다.


자동화가 중간에 끊기거나 다시 실행될 수 있다면 처리 완료 표시 컬럼을 두는 것도 좋습니다. 이미 처리된 행을 다시 처리하지 않으면 중복 발송, 중복 입력, 불필요한 서비스 호출을 줄일 수 있습니다.


function processWithStatusColumn() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
  const lastRow = sheet.getLastRow();

  if (lastRow < 2) return;

  const values = sheet.getRange(2, 1, lastRow - 1, 4).getValues();
  const output = [];

  values.forEach(function(row) {
    const email = row[0];
    const name = row[1];
    const status = row[3];

    if (status === '완료') {
      output.push(['완료']);
      return;
    }

    // 실제 발송 전에는 테스트 대상 1~2개로 먼저 확인하세요.
    // GmailApp.sendEmail(email, '안내 메일', name + '님, 안내드립니다.');

    output.push(['완료']);
  });

  sheet.getRange(2, 4, output.length, 1).setValues(output);
}

GmailApp, DriveApp, UrlFetchApp 사용 시 주의할 점

Service invoked too many times 오류는 구글시트에서만 생기지 않습니다. Gmail 자동 발송, Drive 파일 정리, RSS 수집, 외부 API 호출 자동화에서도 자주 발생합니다.


GmailApp.sendEmail은 발송 완료 표시가 중요합니다

Gmail 자동 발송은 같은 대상에게 여러 번 보내지 않도록 발송 완료 컬럼을 두는 것이 좋습니다. 스크립트가 중간에 실패한 뒤 다시 실행되면 이미 보낸 대상에게 메일이 다시 갈 수 있기 때문입니다. 발송 대상 수가 많다면 하루에 한 번에 처리하기보다 일정 수씩 나눠 처리하는 방식도 검토할 수 있습니다.


UrlFetchApp은 외부 API 제한도 함께 봐야 합니다

UrlFetchApp은 Apps Script 할당량뿐 아니라 호출 대상 API의 제한도 함께 영향을 받습니다. RSS, 뉴스 API, 사내 API를 반복 호출한다면 같은 URL을 짧은 시간에 계속 요청하고 있지 않은지 확인해야 합니다. 응답을 캐시하거나 이미 수집한 항목은 건너뛰는 구조가 도움이 됩니다.


DriveApp은 파일 목록 전체 스캔을 줄여야 합니다

Drive 자동화에서 폴더 전체 파일을 매번 처음부터 끝까지 훑는 방식은 비효율적입니다. 파일명, 수정일, 처리 상태를 저장해 두고 새로 처리할 대상만 좁히면 호출량을 줄일 수 있습니다.


트리거 중복과 실행 간격 점검

시간 기반 트리거가 중복 등록되어 있으면 같은 함수가 예상보다 여러 번 실행됩니다. 예를 들어 10분마다 실행되는 트리거를 실수로 3개 등록하면 실제로는 같은 자동화가 더 자주 실행되는 것처럼 동작할 수 있습니다.


트리거 점검 순서

□ Apps Script 편집기에서 트리거 메뉴를 엽니다.
□ 같은 함수가 여러 개 등록되어 있는지 확인합니다.
□ 시간 기반 트리거 실행 간격이 너무 짧지 않은지 확인합니다.
□ 테스트용 트리거가 남아 있지 않은지 확인합니다.
□ 실패 후 재시도 구조가 중복 실행을 만들고 있지 않은지 확인합니다.
□ 자동 발송 함수는 처리 완료 컬럼을 먼저 확인하도록 구성합니다.


트리거를 조정할 때는 바로 삭제하기보다 어떤 함수가 어떤 주기로 실행되는지 먼저 기록해 두는 것이 좋습니다. 운영 중인 자동화라면 트리거 변경 후 한두 번 실행 로그를 확인해 예상한 간격으로 실행되는지 점검합니다.


실행 시간 초과 오류와 할당량 초과 오류의 차이

Exceeded maximum execution timeService invoked too many times는 비슷해 보이지만 원인이 다릅니다. 전자는 한 번의 실행이 너무 오래 걸리는 문제이고, 후자는 특정 서비스 호출량이 너무 많은 문제입니다.


구분 주요 의미 우선 조치
Exceeded maximum execution time 한 번의 실행 시간이 너무 김 처리량 분할, 다음 실행으로 이어서 처리
Service invoked too many times 특정 서비스 호출이 너무 많음 반복 호출 제거, 배치 처리, 트리거 간격 조정
Service using too much computer time for one day 하루 동안 사용한 총 실행 시간이 많음 트리거 실행 횟수와 처리량 줄이기

두 오류는 함께 발생할 수 있습니다. 예를 들어 반복문 안에서 API를 계속 호출하면 실행도 오래 걸리고 호출량도 많아집니다. 이 경우에는 실행 시간을 줄이는 것과 서비스 호출 횟수를 줄이는 작업을 함께 해야 합니다.


재발 방지 체크리스트

한 번 오류를 해결했더라도 데이터가 늘어나면 같은 문제가 다시 생길 수 있습니다. 자동화는 처음부터 많은 데이터를 처리한다고 가정하고 구조를 잡는 것이 좋습니다.


재발 방지 체크리스트

□ 셀 단위 처리보다 배열 단위 처리로 바꿉니다.
getValue()·setValue() 반복을 getValues()·setValues()로 줄입니다.
□ 한 번에 처리할 행 수를 제한합니다.
□ 처리 완료 상태를 시트에 저장합니다.
□ 시간 기반 트리거 간격을 너무 짧게 잡지 않습니다.
□ 테스트할 때는 전체 데이터가 아니라 일부 데이터로 먼저 확인합니다.
□ Gmail 자동 발송은 발송 완료 컬럼을 둡니다.
□ 외부 API 호출은 중복 요청을 줄이고 응답 캐시를 검토합니다.
□ 공식 Quotas 문서에서 최신 제한 기준을 확인합니다.


가장 중요한 기준은 “반복문 안에서 외부 서비스 호출을 얼마나 줄였는가”입니다. 계산은 자바스크립트 배열 안에서 처리하고, Google 서비스와 통신하는 횟수는 최소화하는 방향으로 바꾸면 대부분의 할당량 오류를 줄일 수 있습니다.


공식 자료로 더 확인하기

Apps Script 할당량과 서비스별 제한은 변경될 수 있습니다. 숫자를 외워서 처리하기보다 오류가 발생한 서비스에 맞춰 공식 문서에서 최신 기준을 확인하는 것이 좋습니다.


Google Apps Script Quotas 공식 문서

Apps Script 서비스별 할당량, 오류 메시지 예시, 하루 사용량 제한 관련 기준을 확인할 수 있습니다.

Apps Script Quotas 문서 확인하기

Google Apps Script Triggers 공식 문서

시간 기반 트리거, 설치형 트리거, 자동 실행 구조를 확인할 수 있습니다. 트리거 중복이나 실행 간격을 점검할 때 함께 보면 좋습니다.

Apps Script Triggers 문서 확인하기

Google Apps Script Spreadsheet service 공식 문서

Range, Sheet, SpreadsheetApp 관련 메서드를 확인할 수 있습니다. getValues(), setValues() 구조를 점검할 때 참고하기 좋습니다.

Spreadsheet service 문서 확인하기

Google Apps Script Gmail service 공식 문서

GmailApp으로 메일을 작성·발송·관리하는 메서드를 확인할 수 있습니다. 자동 발송 스크립트의 호출 방식과 제한을 점검할 때 참고할 수 있습니다.

Gmail service 문서 확인하기

실행 시간이 길어질 때 함께 점검
할당량 오류와 실행 시간 초과 오류는 함께 나타날 수 있습니다. 한 번의 실행이 오래 걸리는 구조라면 처리량을 나누는 방식도 함께 확인해 보세요.
Google Apps Script Exceeded maximum execution time 해결

자동 실행이 멈출 때 트리거 점검
시간 기반 트리거가 중복되었거나 권한 문제로 멈춘 경우에도 자동화가 예상과 다르게 실행될 수 있습니다. 실행 간격과 권한 상태를 함께 확인하는 것이 좋습니다.
Google Apps Script 트리거 오류 해결

권한 오류와 할당량 오류 구분
Gmail, Drive, Sheets 서비스를 처음 사용할 때는 권한 승인 문제가 함께 나타날 수 있습니다. Authorization required 메시지가 보이면 먼저 권한 승인 흐름을 확인해야 합니다.
Google Apps Script 권한 오류 해결

구글시트 자동화 기본 흐름
Apps Script 자동화를 처음 만들고 있다면 구글시트에서 반복 작업을 줄이는 기본 구조부터 잡아두는 것이 좋습니다.
Google Apps Script 자동화 입문

자주 묻는 질문

Q1. Service invoked too many times 오류는 코드가 잘못됐다는 뜻인가요?

꼭 문법 오류를 뜻하는 것은 아닙니다. 같은 코드가 작은 데이터에서는 잘 실행되다가 데이터가 늘어난 뒤 실패하는 경우도 많습니다. 반복문 안에서 SpreadsheetApp, GmailApp, UrlFetchApp 같은 서비스를 너무 많이 호출하거나, 트리거가 자주 실행되어 하루 사용량 제한에 가까워질 때 발생할 수 있습니다.


Q2. getValue와 getValues는 무엇이 다른가요?

getValue()는 보통 한 셀 값을 가져올 때 쓰고, getValues()는 범위 안의 여러 값을 2차원 배열로 가져올 때 씁니다. 많은 행을 처리할 때 셀마다 getValue()를 반복하면 호출 횟수가 늘어납니다. 가능한 범위를 한 번에 읽고 배열에서 계산한 뒤 setValues()로 한 번에 쓰는 방식이 안정적입니다.


Q3. GmailApp.sendEmail 제한에 걸리면 어떻게 해야 하나요?

먼저 하루에 몇 명에게 보내는지, 같은 대상에게 중복 발송되고 있지 않은지 확인해야 합니다. 시트에 발송 완료 컬럼을 두고 이미 완료된 행은 건너뛰도록 구성하면 불필요한 발송을 줄일 수 있습니다. 정확한 발송 관련 제한은 계정 유형과 정책에 따라 달라질 수 있으므로 Gmail service와 Quotas 공식 문서를 확인하는 것이 좋습니다.


Q4. 트리거를 늘리면 할당량 오류가 해결되나요?

트리거를 늘리면 오히려 같은 함수가 더 자주 실행되어 호출량이 늘 수 있습니다. 할당량 오류가 났다면 트리거를 추가하기보다 중복 트리거가 있는지 확인하고, 실행 간격을 늘리며, 한 번에 처리할 데이터 수를 줄이는 방향이 안전합니다. 처리 완료 상태를 저장해 이미 처리한 행을 건너뛰는 구조도 함께 적용하는 것이 좋습니다.



Google Apps Script의 Service invoked too many times 오류는 반복문 안의 서비스 호출을 줄이고, 트리거 간격과 처리 완료 상태를 함께 점검하는 것이 핵심입니다.