1. 발단

  • 최근에 google-apps-script 프로젝트를 한 개 끝냈는데 …
    • pyscaffold 처럼 초기에 환경을 설정해주는 툴이 있을것 같아 찾아봤다.
  • 찾았는데 .. Google Apps Script Development 인 것 갈다.
    • 작성자는 Amit Agarwal이라는 인도사람이며 인도 최초의 전업 블로거라고 한다.
    • 블로그 내용에 Google Apps Script 관련내용이 많고 직접 개발한 add-on도 많아 왠지 믿음이 간다.
    • Google Apps Script for Developers 는 블로그에 관련글을 쓴내용이며 직접 설명한 유튜브 링크도 포함하고 있다.
  • 한번 유튜브 비디오를 따라해보면서 익혀보기로 했다.

2. 전개

Amit Agarwal 방식 (현재 사용하지 않음)

처음에 한 번 해봤지만 현재 사용하지 않는 방식이라 접어둠. 내용 보려면 Click !!

환경 설치

  • 일단 첨에 해당 git을 클론해온다. 비디오에서 하라는 대로 이름을 mailman으로 해본다.
  • git clone을 하면 .git 폴더가 생기는데, 일단 지운다
    • 신규 프로젝트를 하려고 클론을 하는거기 때문에, 필요없는 history를 지우기 위함이다.
    • 현재 폴더가 mailman인 상황에서 rm -rf .git
  • 아무것도 없는 상태로 시작하기 위해, 샘플 프로그램이 있는 src 폴더도 제거한다.
    • 현재 폴더가 mailman인 상황에서 rm -rf src
  • node가 깔려있는 상태에서 시작하는걸로 가정한다.
    • 노드 버전 확인 명령 : node -v
  • 다음에 개발하는데 필요한 모든 dependency를 설치한다
    • 명령 : npm install
    • 참조링크 npm-install
      • 참조하는 파일 - 해당 git에 미리 등록되어 있다.
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        
        $ npm install
        npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.11 (node_modules\fsevents):
        npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.11: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
        added 1048 packages from 451 contributors and audited 1119 packages in 166.52s
              
        43 packages are looking for funding
          run `npm fund` for details
                
        found 6 low severity vulnerabilities
          run `npm audit fix` to fix them, or `npm audit` for details
        
        • fsevents : MacOS의 FSEvents 관련 라이브러리
          • “os”:”darwin”을 원하는데.. 현재는 “os”:”win32”라고 나오고.. 현재 플랫폼이 지원되지 않는다고 나온다.
          • darwin은 MacOS의 기본 OS이다.
          • Windows 환경에서 필요없는 라이브러리이므로 무시한다
        • 취약점(vulnerabilities) 관련

코딩 시작전

  • clasp login후 clasp create로 프로젝트 만들기
    • 명령 : clasp create --type sheets --title "MailMan" --rootDir ./dist
    • 시트와 관련 script를 한꺼번에 만드는 명령
  • Cloud script editor 에서 안된다고 하는 명령이 일부 되는듯함.
  • root에 src 디렉토리를 새로 만듬 ( subfoloder로 html도 만듬)
  • 코딩 시작전에 ./webpack.config.js 편집
    1
    2
    3
    
    cons isProduction = process.env.NODE_ENV === 'production';
    // 위값을 'none' 으로 변경 , none 이 development mdoe라고 함.
    // production mode로 되어 있으면 코드가 최적화 되지만 읽기불편하고 debug하기가 어려움
    
  • 다음으로 appsscript.json을 편집
    • appsscript.json 편집시에 권한을 조정했는데 자세한 사항은 google developer playground를 참조하면 모든 권한이 나옴

코딩

  • 따라 하는 html path 설정관련해서 에러가 남
  • webpack.config.js에서 다음부분을 수정함
    1
    2
    3
    4
    5
    6
    7
    
    new CopyWebpackPlugin({
    patterns: [
      {
        from: `${src}/html/index.html`, // 원래는 `${src}/**/*.html`로 되어있었음
        flatten: true,
        to: destination,
      }
    
  • 이후에는 쭉 따라하면 별 문제없이 잘된다

소감

  • 체계적이긴 하나, 좀 예전에 작성된 느낌
  • webpack으로 빌드하는데 너무 오래 걸림 ( 느리면 50초 이상, 빠르면 20초 이상)
  • 일단 다른 방법을 좀 찾아보기로 함
  • 특수문자 복사하는 사이트

Clasp + Typescript로 GAS 프로젝트 시작하기 (현재 사용중인 방법)

개념정리

  • GAS 의 2가지 개발 시작 방법
    • 온라인 : 구글 문서(Sheets, Docs, Presentations, Forms,..)에서 스크립트 편집기를 열어 온라인으로 작업
    • 오프라인 : clasp을 다운로받아 로컬에서 작업후 온라인에 연동시키기
  • clasp을 쓸 때 유리한 점
    • 온라인이 아닌 상황에서도 개발할 수 있다. (실행할 때는 연결해야 겠지만)
    • git등을 사용하여 코드 버전 관리를 할 수 있다
    • 폴더를 사용해 구조적으로 코드를 분리할 수 있다
    • Typescript를 사용하여 개발할 수 있다
      • Typescript를 사용하면 유리한 점
        • Autocomplete을 지원하는 로컬 IDE 사용가능
        • classarrow function등을 지원하는 ES6 특징을 이용할 수 있다
      • 주의 : 일단 한 번 Typescript를 이용한 프로젝트는 계속 Typescript를 이용해야 한다 (서버에 올라가면서 transfile 되기 때문)
      • 주의 : GAS에서 허용되는 Typescript는 Node나 Web browser에서 허용되는 Typescript와 정확히 같지는 않다
        • exportrequire등의 용어를 사용할 수 없다.
        • window등의 용어를 사용할 수 없다.

환경 설정

  • 자세한 설명이 필요하면 개인 유튜브 영상(CLASP Tutorial)을 확인 한다
  • clasp 설치
  • clasp 초기기동
  • 오랜만에 돌아왔을 때는..
    • clasp -v 명령으로 clasp이 설치 되어있는지 확인하자

신규 TypeScript 프로젝트 생성 QuickStart

  1. 프로젝트를 저장할 폴더 생성
    • 이름을 잘 고민할 것
  2. git init 실행
    • git으로 관리할 필요가 있을 때
  3. npm init 실행
    • node package 배포용 환경을 만들기 위한것이지만 여기선 package.json을 만들기 위해 실행
      1
      2
      
        #아무것도 묻지 않고 실행완료
        npm init -y
      
  4. Apps Script 용 Type definition 설치
    1
    
      npm i -D @types/google-apps-script
    
  5. 프로젝트 루트에 tsconfig.json 파일을 다음과 같이 작성하여 TypeScript feature를 활성화 한다.
    • 만들기 전에 바로 윗 단계인 Type definition을 설치하면 tsconfig.json 편집시 auto completion이 지원된다.
    • .clasp.json 파일과 같은 곳에 위치시킨다.
    • "compilerOptions" 섹션만 의미 있고 다른 설정은 무시된다.
    • Apps Script Project가 V8 Engine을 사용하도록 설정되었다면, “target”: “ES2019”로 설정한다. (default: “ES3”)
      1
      2
      3
      4
      5
      6
      7
      
        {
         "comilerOptions": {
         "lib": ["esnext"],
         "target": "ES2019",
         "experimentalDecorators": true
         }
        }
      
  6. 다음은 생성한 폴더를 clasp project로 만들어야 하는데 …

Clasp 프로젝트로 만들기

  • script.google.com 사이트에 접속하기 전에 clasp create 방식으로 설정
1
prompt$ clasp create --title "Name of Project" --rootDir src 
  • 위와 같이 실행시 ? Create which script? 로 물어봄. 여기서 script 종류를 선택해도 되고…
  • 아래와 같이 처음부터 종류를 선택하고 들어갈수 도 있음.
1
  prompt$ clasp create --type sheets --title "sheet Project" --rootDir src
  • 이 방식 말고 script.google.com 사이트에 미리 프로젝트 만들어놓고 clone 하는 방식이 있는데 내 취향이 아님.
1
prompt$ clasp clone "<script_Id>" --rootDir src
  • 프로젝트 폴더밑에 src 디렉토리를 만들면 나중에 만들게 될 배포및 테스트 폴더와 구분 되어 좋음.

모듈, exports 와 imports

  • Google Apps Script는 ES 모듈은 현재 지원하지 않음. 일반적인 export/import 패턴은 실패함.
  • 실패하는 패턴은 다음과 같다.
1
2
3
  // module.ts
  // 'fool' is added to the 'exports' object in the global namespace
  export const foo = 'Hello form Module';
1
2
3
4
5
  // main.ts
  import { foo } from './module'; // this statement is ignored
  
  // the variable 'fool` does not exist in the global namespace
  cons bar = foo;

exports 선언 해결책

  • 이 해결책은 일반적인 모듈이 지원하는 code isolation조차 지원하지 않으므로, 찾기 어려운 버그를 낼수 있음을 주의
1
2
3
  declare const exports: typeof import('./module');
  
  exports.foo;  // address "imported" content as it will be visible when transpiled

namespace 실행문 해결책

  • 이전에 “internal module”로 알려졌던, TypeScript의 “namespaces”를 이용하며, 적절한 code isolation의 목적을 이룬다
  • Namespace definition은 중첩될수 있으며, 여러 파일에서 사용될수 있고, import/require 문장이 필요하지 않다.
1
2
3
4
5
 // module.ts
 namespace Module {
    export function foo() {}
    function bar() {}  // this function can only be addressed from within the 'Module' namespace
 }
1
2
3
4
5
 // anyFiles.ts
 Module.foo();   // address a namespace's exported content directly
 
 const nameIWantForMyImports = Module.foo;   // to simulate 'import' with renaming
 nameIWantForMyImports();

third party build-chain 해결책

  • webpack, rollup.js, gulp 등등의 써드 파티 도구를 이용한 방법
  • 다음 단계와 같이 수행한다
  1. 코드를 파싱해서 사용된 모듈을 확인한다. ( export 와 import 사용)
  2. (선택적) 사용하지 않는 코드를 제거하기 위해 나무 흔들기?를 한다.
  3. 결과를 한개의 javascript 패키지로 모은다.

설정

clasp github에서 건진 VSCode 설정

  • clasp github/docs/settings.md 에서 건진 VSCode 설정
  • 일단 써진대로 Code > Prefereces > Settings 로 들어간다
  • User > Extensions 메뉴에 JSON을 찾아 SchemasEdit in settings.json을 찾는다.
  • 들어 가서 추천하는 명령은 선택하면 일단 넣을수 있는 템플릿이 완성된다.

git repository에 있는 clasp_xxx 프로젝트의 구성

  • 요약 : 트리구조및 공통되는 파일쓰임새
  • 구글시트용 GAS 트리구조
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    # root
    ├── node_modules/  ( ignored )
    ├── src/
    │   ├─ appsscript.json - 필수 파일, timezone 설정, Library 설정 등등 (필수 파일)
    │   ├─ forms.ts - 옵션, 설문지를 사용한다면 있어야 함 
    │   ├─ sheets.ts - 거의 필수, 각 시트별로 직접적으로 조작하는 함수를 설정 ( 구글 시트라면 필수) 
    │   ├─ typealiases.ts - 거의 필수, .ts 파일에서 타입길이를 줄이기 위해 사용, .gs로 컴파일하면 내용이 사라지는 파일 (.ts일때만 내용이 존재) 
    │   ├─ util.ts - 모듈간에 공통적으를 쓸만한 유틸리티 함수. 2D공간에서 검색하는 함수등이 있음 
    │   └─ main.ts - entry point UI 설정, 최상위 함수 호출
    ├─ .clasp.json - Google Drive상에 연동되는 스크립트 파일 ID저장 
    ├─ .claspignore - clasp compiler시에 무시되는 함수 등록 
    ├─ .gitignore - git 관리 시에 무시되는 함수 등록 
    ├─ LICENSE - github 등록시 LICENSE 표시용