2026년 9월 8일 화요일

[행정/교무] 특별실·기자재 교사 간 예약 시스템 - GAS + 구글 시트로 무료 서버 없이 만들기

교사끼리만 쓰는 특별실 예약 시스템 — GAS + 구글 시트 백엔드로 무료 서버 없이 만들기

📅 교내 특별실(과학실·컴퓨터실·음악실·체육관) 및 기자재(노트북 카트, 3D 프린터 등) 예약 — 교사들이 스마트폰이나 PC에서 원하는 날짜·교시·특별실을 선택하면 구글 스프레드시트에 실시간 기록되고, 이미 예약된 시간은 자동으로 마감(중복 방지)되는 교사 전용 행정 도구입니다. Apps Script(GAS)를 웹앱으로 배포하므로 서버 비용이 완전 무료입니다.

📖 한 줄 정의

Google Apps Script(GAS): 구글 스프레드시트 안에서 실행되는 서버리스 백엔드 스크립트 — 별도 서버 없이 무료로 웹앱을 배포할 수 있습니다.

구글 스프레드시트 = 무료 데이터베이스(DB): 예약 데이터가 시트 행으로 자동 누적되어 교사가 엑셀처럼 확인·수정·통계를 낼 수 있습니다.

⚠️ 개인정보·보안 안내 (필독)

이 웹앱은 Google Apps Script(GAS)와 구글 스프레드시트를 활용하여 데이터를 구글 클라우드에 저장합니다.

• 학교 소속 교육청의 개인정보 처리 방침·정보보호 정책에 따라 허용 범위가 다를 수 있습니다.

구현 전 반드시 소속 교육청 정보보호 담당과에 사전 문의하세요.

• 이 도구는 교사 전용입니다 — 학생 개인정보(실명·의견·성적·상담 기록)를 일절 다루지 않습니다.

1. 3대 핵심 분석 비교표

무엇이 바뀌었나요? / 영역 초보자를 위한 쉬운 설명 이렇게 한번 써보세요!
서버 비용 0원 Apps Script를 웹앱으로 배포하면 구글이 서버를 무료로 제공합니다. 별도 호스팅 계약이나 결제가 필요 없습니다. 구글 시트 ➔ 확장 ➔ Apps Script ➔ 배포 ➔ 웹앱 — 클릭 5번!
중복 예약 원천 차단 같은 날짜·교시·특별실의 조합이 이미 시트에 있으면 자동으로 거부하고 "이미 예약된 시간입니다" 경고를 표시합니다. 다른 교사가 먼저 예약한 과학실 3교시를 다시 누르면 "🔴 이미 예약됨" 경고.
구글 시트 = 교사 친화적 DB 예약 데이터가 구글 시트 행으로 자동 누적되므로, 교무부장이 시트에서 그대로 열람·수정·필터링할 수 있습니다. 시트 열: 날짜 / 교시 / 특별실 / 예약자 / 상태(예약·완료·취소)

2. 초보자를 위한 GAS 실전 구축 가이드

이 시리즈는 단일 HTML 파일과 달리 2개 파일 세트로 구성됩니다:

파일 1: Code.gs (구글 시트 안의 Apps Script 백엔드)

function doGet(e) {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("예약목록");
  var data = sheet.getDataRange().getValues();
  var rows = [];
  for (var i = 1; i < data.length; i++) {
    rows.push({
      date: data[i][0], period: data[i][1],
      room: data[i][2], teacher: data[i][3],
      status: data[i][4]
    });
  }
  return ContentService
    .createTextOutput(JSON.stringify({ reservations: rows }))
    .setMimeType(ContentService.MimeType.JSON);
}

function doPost(e) {
  var params = JSON.parse(e.postData.contents);
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("예약목록");

  // 중복 예약 검사
  var data = sheet.getDataRange().getValues();
  for (var i = 1; i < data.length; i++) {
    if (data[i][0] === params.date && data[i][1] === params.period && data[i][2] === params.room) {
      return ContentService
        .createTextOutput(JSON.stringify({ ok: false, message: "이미 예약된 시간입니다." }))
        .setMimeType(ContentService.MimeType.JSON);
    }
  }

  sheet.appendRow([params.date, params.period, params.room, params.teacher, "예약"]);
  return ContentService
    .createTextOutput(JSON.stringify({ ok: true }))
    .setMimeType(ContentService.MimeType.JSON);
}

파일 2: index.html (교사용 예약 화면 — 프런트엔드)

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>특별실 예약</title>
</head>
<body>
  <h2>🏫 특별실 예약</h2>
  <select id="room">
    <option>과학실</option><option>컴퓨터실</option>
    <option>음악실</option><option>체육관</option>
  </select>
  <input type="date" id="date">
  <select id="period">
    <option>1교시</option><option>2교시</option>
    <option>3교시</option><option>4교시</option>
  </select>
  <input type="text" id="teacher" placeholder="예약자">
  <button onclick="reserve()">예약</button>
  <div id="result"></div>

  <script>
    var GAS_URL = "여기에_배포_URL_붙여넣기";

    function reserve() {
      fetch(GAS_URL, {
        method: "POST",
        body: JSON.stringify({
          date: document.getElementById("date").value,
          period: document.getElementById("period").value,
          room: document.getElementById("room").value,
          teacher: document.getElementById("teacher").value
        })
      })
      .then(function(r) { return r.json(); })
      .then(function(d) {
        document.getElementById("result").textContent = d.ok ? "✅ 예약 완료!" : "🔴 " + d.message;
      });
    }
  </script>
</body>
</html>

배포 3단계 (구글 시트에서)

  1. Code.gs 붙여넣기 — 구글 시트 ➔ 확장 ➔ Apps Script ➔ Code.gs에 위 코드 붙여넣기.
  2. 배포 설정 — 배포 ➔ 새 배포 ➔ 웹앱 ➔ "나" 실행, "모든 사용자" 접근 ➔ 배포 URL 복사.
  3. index.html에 URL 붙여넣기 — 복사한 배포 URL을 index.html의 GAS_URL에 붙여넣고 파일 저장.

제미나이 전용 에러 제로 프롬프트

[🚨 에러 방지 기본 안전장치]
1. 2개 파일 완결성: Code.gs(백엔드)와 index.html(프런트엔드)을 각각 완성한다. 어느 쪽도 // TODO나 /* 생략 */이 없어야 한다.
2. doGet: 시트에서 예약 목록을 읽어 JSON으로 반환한다.
3. doPost: 중복 검사(같은 날짜+교시+특별실) 후, 중복이면 ok:false 반환, 아니면 시트에 appendRow한다.
4. index.html은 fetch(GAS_URL)로 doPost를 호출하고, 결과를 화면에 표시한다.
5. 학생 개인정보 0: 교사 이름만 입력하며, 학생 데이터는 일절 다루지 않는다.
6. // TODO, /* 생략 */ 등의 미완성 코드는 절대 넣지 말고 끝까지 완성한다.

[❓ 역질문 유도]
코드를 즉시 작성하지 말고, 아래 3가지를 먼저 나에게 질문한 뒤 내 답변으로 설계를 확정한다.
1. 예약 대상 특별실은 몇 개인가요? (기본: 과학실·컴퓨터실·음악실·체육관 4개)
2. 예약 가능 교시는 몇 교시까지인가요? (기본: 1~7교시)
3. 승인 절차가 필요한가요? (기본: 교사가 예약하면 즉시 확정)

🎯 에디터 한줄평

"메신저로 '과학실 3교시 비었나요?'를 물어보던 시대가 끝났습니다. 교사들끼리 예약 현황을 실시간으로 공유하면 특별실이 비는 낭비와 충돌하는 스트레스가 동시에 사라집니다. 구글 시트 한 장이 서버 역할까지 겸한다는 것 — 이것이 공교육의 진짜 기술적 혁신입니다."

📚 기술·교육 참고 링크

  • Google Apps Script 공식 문서: https://developers.google.com/apps-script
  • 교육과정 연계: 교무 행정(특별실·기자재 예약), 교사 업무 자동화