간단한 기능 때문에 별도 서버와 데이터베이스를 준비하는 것은 부담스럽고 Google Apps Script를 작은 서버처럼 사용할 수 있다. doGet()과 doPost()로 간단하게 HTTP 요청을 받고, 구글 시트에 데이터를 쌓는 것. 서버 인스턴스나 배포 파이프라인을 직접 관리하지 않아도 웹 앱 URL 하나를 API 엔드포인트로 사용할 수 있다.
Apps Script 웹 앱이 서버 역할을 하는 방식
Apps Script 프로젝트를 웹 앱으로 배포하려면 루트에 doGet(e) 또는 doPost(e) 함수가 있어야 한다. 클라이언트가 배포 URL로 GET 요청을 보내면 doGet()이, POST 요청을 보내면 doPost()가 실행된다.
각 함수는 HtmlOutput 또는 TextOutput을 반환해야 한다. JSON API를 만들 때는 ContentService.createTextOutput()으로 문자열을 만들고 MIME 타입을 JSON으로 지정하면 된다.
function jsonResponse(body) {
return ContentService
.createTextOutput(JSON.stringify(body))
.setMimeType(ContentService.MimeType.JSON);
}
function doGet() {
return jsonResponse({
ok: true,
service: 'feedback-api',
});
}
이 코드만 배포해도 URL을 열어 서비스 상태를 확인하는 간단한 GET 엔드포인트가 된다. Express의 라우터처럼 경로별 기능이 자동으로 분리되지는 않으므로 기능이 늘어나면 e.parameter.action 같은 요청 값을 기준으로 직접 분기해야 한다.
Google Sheets에서 Apps Script 프로젝트 열기
시트를 데이터 저장소로 사용할 때는 Google Sheets의 확장 프로그램 > Apps Script 메뉴에서 시트에 연결된 프로젝트를 만들 수 있다.

독립 실행형 Apps Script 프로젝트도 같은 기능을 구현할 수 있다. 시트에 연결된 프로젝트는 대상 문서와 코드를 함께 찾기 쉽고, 독립 실행형 프로젝트는 여러 문서나 서비스를 다루는 기능을 분리하기 좋다.
POST 요청을 받아 한 행으로 저장하기
const SHEET_ID = 'YOUR_SPREADSHEET_ID';
const SHEET_NAME = 'responses';
function doPost(e) {
try {
const data = parseRequestBody(e);
const feedback = validateFeedback(data);
appendFeedback(feedback);
return jsonResponse({
ok: true,
message: 'saved',
});
} catch (error) {
console.error(error);
return jsonResponse({
ok: false,
message: error.message,
});
}
}
function parseRequestBody(e) {
if (!e || !e.postData || !e.postData.contents) {
throw new Error('request body is required');
}
return JSON.parse(e.postData.contents);
}
function validateFeedback(data) {
const rating = Number(data.rating);
if (!Number.isInteger(rating) || rating < 1 || rating > 5) {
throw new Error('rating must be an integer from 1 to 5');
}
return {
name: String(data.name || '').trim().slice(0, 50),
rating,
description: String(data.description || '').trim().slice(0, 500),
};
}
doPost, doGet 같은 함수는 루트 레벨에 작성해야 인식할 수 있다.
e.postData.contents에는 POST body 문자열이 들어온다. JSON 파싱에서 끝내지 않고 필수 값, 숫자 범위, 문자열 길이를 검증해야 잘못된 행이 시트에 계속 쌓이는 것을 막을 수 있다.
검증이 끝난 데이터는 SpreadsheetApp으로 저장한다.
function appendFeedback(feedback) {
const lock = LockService.getScriptLock();
lock.waitLock(5000);
try {
const spreadsheet = SpreadsheetApp.openById(SHEET_ID);
const sheet = spreadsheet.getSheetByName(SHEET_NAME);
if (!sheet) {
throw new Error(`sheet not found: ${SHEET_NAME}`);
}
sheet.appendRow([
new Date(),
escapeFormula(feedback.name),
feedback.rating,
escapeFormula(feedback.description),
]);
} finally {
lock.releaseLock();
}
}
function escapeFormula(value) {
return /^[=+\-@]/.test(value) ? `'${value}` : value;
}
여러 요청이 같은 시트를 동시에 수정할 수 있어 LockService의 스크립트 잠금을 사용한다. lock은 finally에서 반드시 해제한다.
문자열이 =, +, -, @로 시작하면 시트에서 수식으로 해석될 수 있다. 외부 입력을 그대로 저장하지 않고 앞에 작은따옴표를 붙여 일반 문자열로 처리한다.
요청을 보내 동작 확인하기
웹 앱을 배포한 뒤에는 생성된 /exec URL로 POST 요청을 보낼 수 있다. 아래 URL은 실제 배포 URL로 교체한다.
curl -L \
-H 'Content-Type: application/json' \
-d '{"name":"sample","rating":5,"description":"easy to use"}' \
'https://script.google.com/macros/s/DEPLOYMENT_ID/exec'
정상적으로 처리되면 다음 JSON이 반환되고 responses 시트에 새 행이 추가된다.
{
"ok": true,
"message": "saved"
}
curl에 -L을 넣은 이유는 Content Service 응답이 일회성 URL로 리디렉션될 수 있기 때문이다. HTTP 클라이언트가 리디렉션을 자동으로 따라가지 않는다면 응답 본문 대신 302 응답만 볼 수 있다.
웹 앱으로 배포

Apps Script 편집기에서 배포 > 새 배포 > 웹 앱을 선택하면 실행 사용자와 접근 사용자를 정할 수 있다.
웹 앱을 배포자 권한으로 실행하면 요청한 사람이 누구든 배포자가 허용한 Google Sheets에 접근한다. 클라이언트마다 Google OAuth를 구현하지 않아도 되는 대신, 공개 URL을 얻은 사람이 배포자 권한으로 준비된 기능을 호출할 수 있다는 뜻이다.
접근 권한은 데이터 성격에 맞춰 최소 범위로 설정해야 한다.
- 개인 도구라면 배포자만 접근하도록 제한한다.
- 조직 내부 도구라면 같은 Google Workspace 도메인으로 제한한다.
- 익명 접근이 필요하다면 저장 가능한 데이터와 작업을 강하게 제한하고 남용 가능성을 전제로 한다.
!warning 웹 앱 URL은 인증 정보가 아니다. 프론트엔드 코드에 공유 비밀을 넣는 방식도 사용자가 값을 확인할 수 있으므로 인증이 되지 않는다. 민감한 데이터, 결제, 개인정보, 관리자 기능처럼 강한 인증과 세밀한 권한이 필요한 API라면 전용 백엔드를 쓸것.
코드를 수정한 뒤에는 기존 배포를 새 버전으로 업데이트해야 /exec URL에 변경 사항이 반영된다. 편집 권한이 있는 사용자만 접근 가능한 /dev URL은 최신 저장 코드를 테스트하는 용도이며 운영 URL로 사용하면 안 된다.
참고한 페이지
developers.google.com
Web Apps | Apps Script
doGet과 doPost의 요청 처리, 웹 앱 배포와 실행 권한을 설명하는 공식 문서
developers.google.com
Content Service | Apps Script
Apps Script 웹 앱에서 TextOutput으로 JSON과 텍스트를 반환하는 공식 API 문서
developers.google.com
Lock Service | Apps Script
공유 자원을 동시에 수정할 때 실행 충돌을 막는 LockService 공식 문서
developers.google.com
Quotas for Google Services | Apps Script
Apps Script 실행 시간과 Google 서비스별 할당량을 정리한 공식 문서
댓글 0개