logo hsb.horse
← 블로그 목록으로 돌아가기

블로그

Svelte로 Google Apps Script 기반 고기능 웹앱 만들기

Google Apps Script의 웹앱 공개 기능과 Svelte를 조합해, 스프레드시트를 데이터베이스처럼 사용하는 고기능 SPA를 만드는 방법.

게시일:

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.tsdoGet 함수를 추가한다.

프런트엔드에서 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 함수를 타입 세이프하게 호출할 수 있어서 개발 경험도 꽤 좋다.