Google Apps Script의 웹 애플리케이션 공개 기능을 이용해, 스프레드시트를 데이터베이스처럼 다루는 간단한 앱이나 도구를 만들고 싶은 경우가 있었다.
S3 같은 별도 호스팅까지 갈 정도는 아니지만, 그렇다고 스프레드시트를 직접 만지는 것도 애매한 상황에서 이 방식이면 Svelte, React, Vue를 이용한 웹앱을 만들 수 있다.
저장소
svelte-with-tailwindcss-on-gas
GitHub의 템플릿 저장소 기능을 쓸 수 있게 해 두었다.
TailwindCSS가 필요 없다면 제거해도 문제 없다.
기술 스택
디렉터리 구조
client 디렉터리는 Svelte로 만든 프런트엔드 구현을 모아 둔 계층이다.
server 디렉터리는 GAS 쪽에서 실행되는 서버사이드 구현을 모아 둔 계층이다.
src/├── client/│ ├── api/│ │ ├── mocks│ │ └── index.ts│ ├── components│ ├── features│ ├── stores│ ├── types│ ├── utils│ ├── App.svelte│ └── main.ts├── server/│ ├── main.ts│ └── types.ts└── vite-env.d.ts서버사이드
GAS 웹앱 기능으로 HTML을 제공한다
server/main.ts에 doGet 함수를 추가한다.
프런트엔드에서 title 태그나 favicon을 바꿔도 반영되지 않으므로, 필요하다면 doGet 안에서 지정해야 한다.
const HTML_TITLE = "App name";const HTML_FAVICON_URL = "https://example.com/favicon.ico";
function doGet() { const html = HtmlService.createTemplateFromFile("index.html").evaluate(); html.setTitle(HTML_TITLE); html.setFaviconUrl(HTML_FAVICON_URL); return html;}API 엔드포인트 만들기
server/main.ts에서 엔드포인트로 노출하고 싶은 함수를 export하기만 하면 된다.
type APIResult<T> = | { ok: true; data: T; } | { ok: false; error: Error; };
const doSomething = (): APIResult<string> => { return { ok: true, data: "success", };};
export { doSomething };프런트엔드
src/client/api/index.ts에서 서버사이드 API와 연결한다.
내부적으로는 google.script.run이 실행된다.
import { GASClient } from "gas-client";import type * as Server from "../../server/main";
const { serverFunctions } = new GASClient<typeof Server>();
export const APIClient = serverFunctions;서버사이드 API 호출하기
<script lang="ts"> import { APIClient } from "./api";
const promise = APIClient.doSomething();</script>
{#await promise}<div>Loading...</div>{:then result}<p>{result}</p>{:catch error}<p>error</p>{/await}정리
Google Apps Script와 Svelte를 조합하면, 스프레드시트를 백엔드처럼 사용하는 고기능 웹앱을 만들 수 있다.
gas-client를 쓰면 GAS 함수를 타입 세이프하게 호출할 수 있어서 개발 경험도 꽤 좋다.
hsb.horse