# 출처 장부 — 학부모 문의, 매번 처음처럼 답하지 않기

이 튜토리얼의 도구 사용법·한도는 아래 1차 출처에서 확인했다. 확인일은 모두 2026-10-11.
구글 로그인이 필요해 직접 실행하지 못한 단계는 `실행 확인: 사용자`, 문서에서 답을 찾지 못한 것은 `확인 필요`로 남겼다.
이전 편들과 같은 페이지(#1·#2·#3·#5·#6·#7)는 이번에 다시 열어 확인했다.

## 확인한 사실

| # | 확인한 사실 | 쓰인 곳 | 출처 | 문서 갱신일 |
|:-:|---|---|---|---|
| 1 | 사용자 메뉴는 문서에 묶인(bound) 스크립트만 만들 수 있다. `onOpen` → `getUi().createMenu().addItem().addSeparator().addToUi()` | 가이드 2, 카드 7 | https://developers.google.com/apps-script/guides/menus | 2026-09-03 |
| 2 | 단순 트리거(`onOpen`)는 권한이 필요한 서비스를 쓸 수 없고 30초 안에 끝나야 하며, 보기 전용으로 연 파일에서는 실행되지 않는다 | 가이드 2, 막히는 곳 | https://developers.google.com/apps-script/guides/triggers | 2026-09-03 |
| 3 | 설치형 트리거는 **만든 사람의 계정으로** 실행된다. 다른 계정이 설치한 트리거는 보이지 않는다. 스프레드시트의 폼 제출 트리거는 "폼이 스프레드시트로 제출될 때" 실행된다. `ScriptApp.getProjectTriggers()`로 나열, `ScriptApp.deleteTrigger(t)`로 삭제 | 가이드 4, 카드 9, Code.gs `enableFormTrigger`·`deleteOurTriggers_` | https://developers.google.com/apps-script/guides/triggers/installable | 2026-09-03 |
| 4 | 폼 제출 이벤트 객체: `namedValues`는 질문 제목 → 값 **배열**, `values`는 시트 열 순서의 배열(첫 값은 타임스탬프), `range`는 쓰인 범위, `triggerUid`, `authMode` | Code.gs `classifySubmission`, `firstValue` | https://developers.google.com/apps-script/guides/triggers/events | 2026-09-03 |
| 5 | 한도: 트리거 20개/사용자/스크립트, 트리거 총 실행 90분/일(개인) · 6시간/일(Workspace), 실행당 6분 | 가이드 한도 | https://developers.google.com/apps-script/guides/services/quotas | 2026-09-03 |
| 6 | `ScriptApp.newTrigger(fn).forSpreadsheet(ss)` → `SpreadsheetTriggerBuilder.onFormSubmit().create()` — 메서드 앵커로 확인 | Code.gs `enableFormTrigger` | https://developers.google.com/apps-script/reference/script/trigger-builder · …/script/spreadsheet-trigger-builder | 2026-04-13 |
| 7 | `Range`: `setBackground`, `setBackgrounds`, `setValues`, `getValues`, `getRow()`. `Sheet`: `appendRow`, `getLastRow`, `getRange`, `setFrozenRows`, `getName()`. `Spreadsheet`: `getSheets()`, `getSheetByName`, `insertSheet`. `Trigger.getHandlerFunction()`, `Session.getScriptTimeZone()`, `Utilities.formatDate()` — 모두 메서드 앵커로 확인 | Code.gs | https://developers.google.com/apps-script/reference/spreadsheet/range (2026-08-19) · …/spreadsheet/sheet · …/spreadsheet/spreadsheet · …/script/trigger · …/base/session · …/utilities/utilities | 2026-04-13 (Range 2026-08-19) |

## 열려 있는 항목

| 항목 | 상태 | 닫는 방법 |
|---|---|---|
| 폼 응답 탭에서 스프레드시트를 연결하는 한국어 버튼 이름 | 확인 필요 | 실제 폼 편집기 화면과 대조 |
| 폼이 만든 응답 시트의 기본 이름 | 확인 필요 — 코드는 이름이 아니라 질문 제목 다섯 개로 찾으므로 동작에는 영향 없음 | 실제 시트 확인 |
| 폼 제출 트리거의 권한 승인 창 문구 | 확인 필요 | 새 시트에서 ②를 처음 누를 때 화면을 기록 |
| `e.values[0]`이 타임스탬프 `Date`인지 문자열인지 | 확인 필요 — 코드는 둘 다 받음 | 시험 제출 뒤 문의함의 접수시각 칸 확인 |
| 폼 만들기 → ① → ② → 시험 제출 → ③ 전체 흐름 | 실행 확인: 사용자 | 가이드의 "혼자 다시 해 보기" 목록을 그대로 수행 |

## 문서 확인 없이 검증한 것

서비스에 의존하지 않는 함수(`headerMap`, `missingHeaders`, `firstValue`, `parseRules`, `classify`, `statusColor`)는 `source/check.mjs`로 Node에서 실행해 확인했다.

```bash
node source/check.mjs
```

확인 내용: 기본 유형표 여섯 줄이 깨끗이 읽힌다 / 키워드는 쉼표·슬래시로 나누고 공백·대소문자를 무시한다 / 폼의 유형 선택이 실제 유형이면 그대로 믿는다 / 기타·공백이면 키워드가 가장 많이 맞는 유형, 동점이면 위 행 / 기타인데 키워드가 없으면 기타 초안, 공백인데 없으면 확인 필요(초안 없음) / "직접 통화" 키워드가 본문에 있으면 유형 선택과 무관하게 초안 없이 직접 통화 / 상태별 색.

## 이 튜토리얼이 기대고 있지 않은 것

주제 선정 단계에서 국내 교육 사이트의 업무 자동화 유형 목록을 **주제 지도로만** 참고했다. 제목, 등장인물, 수치, 글의 전개는 가져오지 않았다. 자동 회신을 넣지 않은 것, 규칙을 시트에 둔 것, 민원 키워드를 유형보다 앞에 둔 것, 연락처를 선택으로 받는 것은 작성자의 학원 운영 경험에서 나온 설계다.
