
Photo by Aerps.com on Unsplash
반복해서 분류하고 요약해야 할 데이터가 많다면 Google Apps Script와 AI API를 연결해 구글 시트 안에서 자동 처리할 수 있습니다. Google 계정과 편집 권한이 있는 시트, 사용할 AI API 키를 준비한 일반 IT 사용자를 대상으로 하며, Apps Script 편집기와 REST API의 기본 개념을 알면 충분합니다.
목차
시트와 Google Apps Script 구성
먼저 시트의 열을 설계합니다. 시트 이름은 코드에서 사용하는 ‘데이터’로 만들고, A열은 원문 데이터, B열은 분류, C열은 요약, D열은 핵심 키워드, E열은 처리 상태, F열은 검수 결과로 구성하세요. 결과 열을 미리 나누어 두면 입력과 결과를 쉽게 구분하고, AI 응답을 다시 편집하는 작업도 줄어듭니다.
시트에서 확장 프로그램의 Apps Script를 열고 아래처럼 처리 함수를 작성합니다. 코드는 OpenAI 호환 형식의 API를 예시로 하므로, 실제 서비스에 맞게 API 주소와 응답 구조를 확인해야 합니다. 요청 본문의 model은 사용할 모델을 지정하고, messages는 모델에 전달할 대화와 원문을 담으며, headers의 Authorization은 API 키를 전달하는 역할을 합니다.
function processRows() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('데이터');
const rows = sheet.getDataRange().getValues();
const apiKey = PropertiesService.getScriptProperties().getProperty('AI_API_KEY');
const endpoint = PropertiesService.getScriptProperties().getProperty('AI_API_ENDPOINT');
const model = PropertiesService.getScriptProperties().getProperty('AI_MODEL');
for (let i = 1; i < rows.length; i++) {
const source = rows[i][0];
const status = rows[i][4];
if (!source || status === '완료') continue;
const prompt = `다음 원문을 분석해 JSON 객체 하나만 반환하세요.
허용되는 키와 형식은 다음과 같습니다.
- category: 문자열
- summary: 2~3문장의 요약 문자열
- keywords: 최대 5개의 키워드를 담은 문자열 배열
JSON 외의 설명, 마크다운, 코드펜스는 출력하지 마세요.
원문: ${source}`;
try {
const response = UrlFetchApp.fetch(endpoint, {
method: 'post',
contentType: 'application/json',
headers: { Authorization: 'Bearer ' + apiKey },
payload: JSON.stringify({
model: model,
messages: [{ role: 'user', content: prompt }]
}),
muteHttpExceptions: true
});
const statusCode = response.getResponseCode();
if (statusCode < 200 || statusCode >= 300) {
throw new Error('API HTTP 오류: ' + statusCode);
}
const body = JSON.parse(response.getContentText());
const result = JSON.parse(body.choices[0].message.content);
const keywords = Array.isArray(result.keywords)
? result.keywords.join(', ')
: String(result.keywords || '');
sheet.getRange(i + 1, 2, 1, 4)
.setValues([[result.category, result.summary, keywords, '완료']]);
} catch (error) {
sheet.getRange(i + 1, 5).setValue('오류 확인 필요');
}
}
}
AI API 연동과 구조화 프롬프트
API 키는 코드에 직접 입력하지 말고 Apps Script의 프로젝트 설정에서 Script Properties로 저장합니다. 키 이름은 AI_API_KEY, API 주소는 AI_API_ENDPOINT, 사용할 모델 식별자는 AI_MODEL로 등록하면 코드와 비밀값을 분리할 수 있습니다.
구조화 프롬프트는 “요약해줘”처럼 짧게 끝내지 말고 출력 형식, 각 필드의 타입과 의미, 허용할 키, 금지할 문장을 함께 지정해야 합니다. 예를 들어 category는 문자열, summary는 2~3문장의 문자열, keywords는 최대 5개의 문자열 배열이라고 명시하세요. JSON만 반환하도록 요구해도 프롬프트만으로 형식을 완전히 보장할 수는 없으며, 서비스가 JSON Schema 같은 구조화 출력을 지원한다면 함께 사용하는 편이 안전합니다. 응답에 마크다운 코드펜스가 붙거나 형식이 어긋날 수 있으므로 오류 행을 별도로 기록해 두세요.
설치형 트리거 설정과 결과 확인
수동 실행 대신 Apps Script의 트리거 메뉴에서 processRows 함수를 선택하고 시간 기반 설치형 트리거를 추가합니다. 현재 processRows()는 실행할 때마다 시트 전체를 읽고 미처리 행을 처음부터 순회하므로, 일반적으로는 미처리 행을 일정 주기로 배치 처리하는 시간 기반 트리거가 적합합니다. 행 수정 직후 처리가 필요하다면 수정 트리거를 사용할 수 있지만, 새로 입력된 특정 행만 처리하도록 별도 조건을 두지 않으면 셀 하나를 수정할 때마다 전체 데이터를 다시 검사하게 됩니다. 데이터가 많아질 때는 한 번에 처리할 최대 행 수를 10~20개처럼 정해 두는 방식도 고려하세요.
처음에는 테스트 행 몇 개만 넣고 B~E열이 예상대로 채워지는지 확인하세요. API 응답이 늦거나 사용량 제한에 걸리면 상태 열에 오류를 남깁니다. 코드의 status === '완료' 조건은 이미 완료된 행을 건너뛰므로, 완료된 행을 다시 보내지 않아 중복 비용을 줄이는 흐름이 구현되어 있습니다.
운영 시 주의사항

개인정보나 외부 공개가 곤란한 내용은 API로 전송하기 전에 제거하거나 마스킹해야 합니다. 이름, 전화번호, 이메일, 주소, 주민등록번호, 계좌번호 등이 포함될 수 있는지 확인하세요. AI 결과는 항상 정확하지 않으므로 중요한 분류와 요약은 F열 같은 검수 열에서 사람이 확인하는 흐름으로 운영하세요. 데이터가 많아지면 한 번의 실행에서 모든 행을 처리하지 말고 일정 개수씩 나누어 처리해야 Apps Script 실행 시간과 API 사용량 제한에 대응할 수 있습니다.
결론
구글 시트와 AI 연동은 A~F열의 역할을 나눈 시트 설계, 출력 형식을 명시한 구조화 프롬프트, 오류를 기록하는 처리 상태, 설치형 트리거를 함께 구성할 때 실용적으로 운영할 수 있습니다. 먼저 소량의 데이터로 오류 처리와 결과 형식을 검증하고, 개인정보를 제거하거나 마스킹한 뒤 검수 열에서 결과를 확인하세요. 데이터가 늘어나면 미처리 행을 나누어 처리하는 방식으로 자동화 범위를 넓히는 편이 안전합니다.