2026년 9월 6일 일요일

[학급 경영] 학급 협동 성향 진단기 - 16문항 응답으로 모둠 자동 편성까지



협동 성향 4글자로 모둠이 완성된다 — 학급 협동 성향 진단기 & 자동 편성 보드

🤝 신학기 기초 조사 주간, 학생들이 협동 성향 진단 16문항(4축 × 4문항)에 응답하면 4글자 성향 코드와 보딩패스(boarding pass) 형태의 성향 카드가 발급됩니다. 담임교사는 균형 배분(round-robin)으로 4대 성향이 골고루 섞인 모둠을 자동 편성합니다.

진단은 학급 스마트패드에서 로컬 계산 — 이름 저장 없이 성향 코드만 다룹니다. 결과 카드를 캡처해 교실 환경판에 부착하면, 서로의 다른 성향을 존중하는 민주적 교실 분위기와 협동 학습 효과가 함께 올라옵니다.

📖 한 줄 정의

심기 모드(데이터 임베딩): API 데이터를 미리 받아 HTML 파일 안 상수로 박아두는 방식(앱 실행 중 외부 통신 0).

학내망 원칙: 학교 배포 웹앱은 개인정보 수집·저장·전송 없음(외부 CDN·API 호출 0, 단일 파일) — 학생은 학내망에서 교사 PC 서버에 접속.

1. 3대 핵심 분석 비교표

무엇이 바뀌었나요? / 영역 초보자를 위한 쉬운 설명 이렇게 한번 써보세요!
운영 시나리오 3월 신학기 기초 조사 주간 — 1차시 진단(16문항), 카드 캡처·환경판 부착, 2차시 모둠 편성 발표. 주간 일정표에 진단·편성 시간을 미리 배치.
4축 설계(예시) 발상(아이디어) vs 정리(계획), 발표 vs 기록, 응원 vs 도전, 꾸밈 vs 속도 — 실제 축과 문항은 학급 회의에서 확정합니다. "모둠 과제를 시작할 때 나는? 아이디어를 먼저 뿌린다 / 순서표부터 만든다"
균형 편성 성향 코드를 사전순으로 정렬한 뒤 모둠 수로 순환 배분(round-robin) — 같은 코드가 한 모둠에 뭉치지 않습니다. makeGroups 함수로 TOP 배치 미리보기.
개인정보 0 설계 이름 입력 칸이 아예 없습니다 — 진단 결과는 4글자 코드와 카드뿐. 코드와 사람을 잇는 것은 교실의 약속(교사 아날로그 매칭)입니다. 성향 코드 더미(코드만)로 편성 시연 → 배정은 환경판에서.
학내망 배포 대응 문항·축·카드 문구 전부 파일 안 상수 — 진단은 순수 로컬 계산이라 통신이 원래 없습니다. 심기 모드가 자연스럽게 전부입니다. 새 학기마다 문항 16개만 교체하는 갱신 루틴.

2. 핵심 아키텍처 해설 — 진단 엔진을 모둠 편성기로 확장

① 진단 엔진 재활용

가중치(weight) 연산 엔진(tally 8칸 + letterFor)을 그대로 가져옵니다. 바뀌는 것은 축과 문항뿐 — '엔진은 하나, 축은 주제마다 새로'가 이 설계의 철학입니다.

② 4축 문항 예시

  • 축1 발상 vs 정리: "모둠 과제 시작! 먼저 뿌릴 것은? 아이디어 / 순서표"
  • 축2 발표 vs 기록: "결과물 발표 방식? 말로 설명 / 글로 정리"
  • 축3 응원 vs 도전: "친구가 막혔을 때? 격려부터 도와주기 / 해결책 제시"
  • 축4 꾸밈 vs 속도: "완성된 결과물은? 멋지게 꾸민다 / 빠르게 제출한다"

문항 문구는 학급 회의에서 다듬습니다 — 진단 도구를 학생이 공동 설계하는 것 자체가 학급자치 활동입니다.

③ 균형 편성 코드: makeGroups

function makeGroups(students, size) {
  students.sort(function (a, b) {
    return a.code.localeCompare(b.code);   // 성향 코드 사전순 정렬
  });
  const n = Math.ceil(students.length / size);
  const groups = [];
  for (let i = 0; i < n; i++) groups.push([]);
  students.forEach(function (s, i) {
    groups[i % n].push(s);                 // 순환 배분(round-robin)
  });
  return groups;   // 사전순 정렬 덕분에 서로 다른 코드가 섞인다
}

원리는 간단합니다. '아아발발 → 아아발발꾸꾸'처럼 코드끼리 정렬하면 같은 코드가 이어지는데, 이 줄을 모둠 수만큼 순환하며 나누면 같은 코드가 한 모둠에 뭉치지 않습니다. 편성 후 '같은 코드가 모둠에 2개 이상'인지 검사해 경고만 띄워도 완성도가 올라갑니다.

④ 카드 캡처 → 환경판 부착 루틴

스마트패드에서 발급된 보딩패스 카드를 스크린샷 → 학급 프린터로 출력 → 환경판 부착. 카드 하단에 "나의 협동 한마디" 칸을 두면 환경판이 곧 자기소개 벽이 됩니다. 이름은 아날로그 방식(교사의 매칭표)으로만 연결 — 화면과 벽 모두 코드만 공개됩니다.

⑤ 심기 전략: 새 학기 갱신 루틴

축·문항·카드 문구는 모두 파일 안 상수(EMBED_DATA). 3월 문항을 6월 반성 회의용 문항으로 교체할 때 파일 상단 상수만 바꿔 저장하면 끝 — 심기 모드(데이터 임베딩) 갱신 루틴의 학급 경영 버전입니다.

3. 초보자를 위한 바이브 코딩 실전 사용 예시

  1. 프롬프트 복사 — 아래 '제미나이 전용 에러 제로 프롬프트' 전체를 복사해 Gemini에 붙여넣습니다.
  2. 역질문 답변 — 4축 확정, 모둠 크기, 카드 톤 세 질문에 답하면 설계가 고정됩니다.
  3. HTML 파일 실행 — 완성 코드를 '협동진단.html'로 저장 후 스마트패드에서 열기. 학급 단말 전부 통신 없이 동작합니다.

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

[🚨 에러 방지 기본 안전장치]
1. 결과물은 외부 라이브러리·프레임워크·웹폰트 없이 단일 HTML 파일로 완성한다.
2. 진단 엔진(4축 16문항 가중치 연산), 보딩패스 카드, 균형 편성 함수(makeGroups)를 한 파일에 완성한다.
3. 이름·번호 입력 칸을 만들지 않는다 — 화면은 4글자 성향 코드와 카드뿐이다(개인정보 수집·저장 0).
4. 사운드는 Web Audio API로 직접 합성한다: 문항 넘김 '똑', 카드 발급 '팡파르'.
5. 모바일·스마트패드 터치 대응: 뷰포트 메타 태그, 답 선택 버튼 최소 44×44px, 진행바 표시.
6. 편성 후 '같은 코드가 한 모둠에 2개 이상'이면 경고 문구를 보여주는 검사를 넣는다.
7. 도구명은 '성향 진단'으로 쓴다 — MBTI는 상표이므로 이름·로고에 사용 금지.
8. // TODO, /* 생략 */ 같은 미완성 코드는 절대 넣지 말고 끝까지 완성한다.

[❓ 역질문 유도]
코드를 바로 만들지 말고, 아래 3가지를 먼저 나에게 질문한 뒤 내 답변으로 설계를 확정한다.
Q1. 협동 성향 4축은 무엇으로 확정할까? (기본: 발상-정리 / 발표-기록 / 응원-도전 / 꾸밈-속도)
Q2. 모둠 크기와 개수는? (예: 4인 1조, 6개 모둠)
Q3. 성향 카드 톤은? (항공권 스타일 / 스티커 수집 체크리스트 스타일)

🎯 에디터 한줄평

'조 편성'이 '성향 합주'가 되는 순간입니다. 서로 다른 4글자가 한 모둠에 모이는 것 — 그것이 곧 협동의 정의입니다. 이름 칸을 두지 않은 설계는 화면이 아니라 마음을 지켜줍니다: 코드만 공개되니 성향 카드 앞에서 아이들은 비교당하는 대신 발견되는 경험을 합니다. 문항 16개를 학급 회의에서 직접 설계한다는 점은 학급자치 수업 그 자체이고요. 3월에 한 번, 6월에 문항만 갈아 끼우는 갱신 루틴까지 — 한 학기 내내 살아 있는 도구입니다.

📚 기술·교육 참고 링크

  • 교육과정 연계: 창의적 체험활동(학급자치), 협동학습(모둠 활동), 국어(문항 문장 다듬기)와 함께 활용

[바이브 코딩] Spaceflight News API - 하루에도 수십 편 쏟아지는 우주 뉴스를 한 화면에



우주 뉴스를 한 화면에 — Spaceflight News API 완전 정복

🛰 Spaceflight News API는 NASA를 비롯한 세계 우주 전문 언론의 뉴스를 자동으로 모아주는 무료 API입니다. API 키 없이 열리며, 오늘 실측으로 누적 기사 35,952편을 확인했습니다 — 어제(2026-09-04) 게시된 기사까지 신선하게 흘러나옵니다. 응답은 SWAPI와 같은 {count, next, previous, results} 표준 봉투(envelope) 구조에 offset 방식 페이지네이션입니다.

국어(뉴스 요약·제목 짓기)·과학·사회(우주 개발 경쟁)를 한 화면에서 묶는 수업 소재입니다. 기사마다 대표 이미지(image_url)도 함께 오는데, 학내망 배포본에서는 이미지 칸을 다루는 방식을 따로 설계해야 합니다 — 이번 글에서 해법까지 담았습니다.

📖 한 줄 정의

심기 모드(데이터 임베딩): API 데이터를 미리 받아 HTML 파일 안 상수로 박아두는 방식(앱 실행 중 외부 통신 0).

학내망 원칙: 학교 배포 웹앱은 개인정보 수집·저장·전송 없음(외부 CDN·API 호출 0, 단일 파일) — 학생은 학내망에서 교사 PC 서버에 접속.

1. 3대 핵심 분석 비교표

무엇이 바뀌었나요? / 영역 초보자를 위한 쉬운 설명 이렇게 한번 써보세요!
API 정체 우주 전문 언론(NASA·NASASpaceflight 등)의 뉴스를 모아두는 무료 창고. 키·등록 없이 브라우저에서 바로 열리고, 오늘 실측 기준 누적 35,952편입니다. /v4/articles/?limit=5 → 최신 기사 5편.
봉투(envelope) 구조 {count, next, previous, results} 봉투로 옵니다. next에는 offset이 붙은 다음 페이지 주소가 절대 URL로 들어 있어, 그대로 fetch하면 이어 보기가 됩니다. 받은 json.next 주소를 '더 보기' 버튼에 연결하기.
데이터 모양 기사 1편 = id·title·authors[]·url(원문 링크)·image_url·news_site(언론사)·summary(요약)·published_at(ISO8601)·launches[]·events[]. news_site(언론사)별로 묶어 '누가 가장 많이 쓰나' 세어보기.
검색·필터 ?search=Moon로 전체 검색(실측 성공), title/summary 조건, news_site 지정, published_at_gte(특정 시각 이후)까지. 정렬(ordering)도 지원합니다. ?published_at_gte=2026-09-01T00:00:00Z → 이번 주 뉴스만.
학내망 배포 대응 뉴스는 매일 바뀌므로 통째 심기는 부적합 — '주간 베스트 10편' 심기로 해결합니다. 교사가 아침에 한 번 받아 심으면 학생 단말은 통신 0. 대표 이미지(image_url)는 외부 주소이므로 학생 배포본에서는 텍스트 카드로 전환합니다. EMBED_DATA에 이번 주 뉴스 10편 요약 심기 + image 칸 제외.

2. 핵심 아키텍처 해설 — 뉴스 창고는 이렇게 생겼다

① URL 해부: 봉투와 offset 페이지네이션

https://api.spaceflightnewsapi.net/v4/articles/?limit=2

  • api.spaceflightnewsapi.net/v4 — 현재 버전 v4. 자원은 articles(뉴스)가 중심이고, blogs도 있습니다.
  • ?limit=&offset= — 한 번에 받을 건수와 건너뛸 건수. next/previous가 절대 URL로 오므로 주소 조립 없이 그대로 fetch하면 이어 보기가 됩니다(페이지네이션 표준 학습).
  • CORS — 실측 Access-Control-Allow-Origin: * — 브라우저에서 바로 fetch됩니다.
  • 탐색형 API 페이지 — 주소 뒤에 ?format=api를 붙이면 문서처럼 보이는 탐색 화면이 열립니다. 필터 목록을 읽는 연습에 좋습니다.

② 데이터 모양: 기사 한 편이 한 장의 카드

{
  "count": 35952,
  "next": "https://api.spaceflightnewsapi.net/v4/articles/?limit=2&offset=2",
  "previous": null,
  "results": [{
    "id": 39839,
    "title": "Blue Origin expands test and launch sites across the Cape",
    "url": "https://www.nasaspaceflight.com/2026/09/...",
    "image_url": "https://www.nasaspaceflight.com/wp-content/...jpg",
    "news_site": "NASASpaceflight",
    "summary": "Blue Origin is expanding its Kennedy Space Center ...",
    "published_at": "2026-09-04T20:37:43Z",
    "launches": [],
    "events": []
  }]
}

실측 데이터(2026-09-04 게시 기사)입니다. launches[]·events[]에는 이 기사가 관련된 발사·사건의 번호가 들어 있어, 발사 일정 데이터와도 연결할 수 있습니다.

③ 로딩 코드: 봉투를 그대로 돌려주기

const API = "https://api.spaceflightnewsapi.net/v4/articles";

async function loadNews(limit, offset) {
  const qs = new URLSearchParams({ limit: limit || 10, offset: offset || 0 });
  const res = await fetch(API + "?" + qs);
  const json = await res.json();
  return json;   // json.count, json.next, json.results
}

④ 날짜 표시: ISO8601을 사람 말로

function fmtDate(iso) {
  const d = new Date(iso);
  return d.getFullYear() + "-" + String(d.getMonth() + 1).padStart(2, "0")
       + "-" + String(d.getDate()).padStart(2, "0") + " "
       + String(d.getHours()).padStart(2, "0") + ":" + String(d.getMinutes()).padStart(2, "0");
}

published_at의 2026-09-04T20:37:43Z 같은 국제 표준 시각을 '2026-09-05 05:37'(한국 시각)처럼 바꿔주는 작은 함수 — 시차(Z=세계표준시, 한국은 +9시간)를 다루는 수학·사회 소재가 됩니다.

⑤ 학내망 전략: 주간 베스트 심기

교사가 아침에 최신 기사 10편을 받아 title·news_site·summary·url만 골라 EMBED_DATA로 심습니다. 심기 모드(데이터 임베딩)가 무엇인지는 앞의 '📖 한 줄 정의' 박스를 참고하세요. image_url은 외부 이미지 주소이므로 학생 배포본에서는 빼고, 대신 언론사 이름 배지로 카드를 꾸밉니다 — '데이터 API와 이미지 CDN은 별개'라는 개념이 여기서도 통합니다.

3. 초보자를 위한 바이브 코딩 실전 사용 예시

  1. 프롬프트 복사 — 아래 '제미나이 전용 에러 제로 프롬프트' 전체를 복사해 Gemini에 붙여넣습니다.
  2. 역질문 답변 — Gemini가 던지는 질문 3가지(화면 축, 데이터 모드, 톤)에 답하면 설계가 확정됩니다.
  3. HTML 파일 실행 — 완성 코드를 '우주뉴스.html'로 저장 후 더블클릭. 심기 모드 파일이면 곧 학내망 배포본입니다.

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

[🚨 에러 방지 기본 안전장치]
1. 결과물은 외부 라이브러리·프레임워크·웹폰트 없이 단일 HTML 파일로 완성한다. (Spaceflight News 데이터 fetch는 유일한 외부 통신 예외)
2. 사운드는 Web Audio API로 직접 합성한다: 새 기사 불러오기 성공 시 부드러운 '똑' 소리, 결과 0건·통신 실패 시 '삑' 경고음.
3. 모바일 터치 대응: 뷰포트 메타 태그 필수, 버튼 최소 44×44px, 입력 필드 font-size 16px 이상, 360px 화면 가로 스크롤 금지.
4. 응답 봉투(envelope)를 그대로 처리한다: count는 상단 배지로, next가 있으면 '더 보기' 버튼을 보여주고 누르면 next 주소를 그대로 fetch한다.
5. published_at은 국제표준시(Z)이므로 한국 시각(+9시간)으로 바꿔 보여주는 fmtDate 함수를 반드시 만든다.
6. 파일 상단 EMBED_DATA에 주간 뉴스 10편(제목·언론사·요약·원문 링크)이 심어져 있으면 fetch를 완전히 생략한다(학내망 배포용 외부 호출 0 모드).
7. image_url은 외부 이미지 주소이므로 심기 모드에서는 이미지 없는 텍스트 카드로 렌더링하고, fetch 모드에서만 이미지를 표시한다. 이미지 로딩 실패 시에도 카드가 깨지지 않게 한다.
8. // TODO, /* 생략 */ 같은 미완성 코드는 절대 넣지 말고 끝까지 완성한다.

[❓ 역질문 유도]
코드를 바로 만들지 말고, 아래 3가지를 먼저 나에게 질문한 뒤 내 답변으로 설계를 확정한다.
Q1. 화면의 기본 축은 무엇으로 할까? (최신순 카드 목록 / 언론사별 탭 / 검색창 중심)
Q2. 데이터 모드는 무엇으로 할까? (A: 실시간 fetch 모드 / B: 학내망용 주간 베스트 심기 모드)
Q3. 카드에 무엇을 강조할까? (제목 크게 / 언론사 배지 / 날짜)

🎯 에디터 한줄평

'뉴스를 검색하는 아이'와 '뉴스가 흘러오는 파이프를 만드는 아이'의 차이가 이 API 하나로 생깁니다. 봉투(envelope)의 next 주소를 그대로 fetch하는 '더 보기' 버튼은 페이지네이션의 본질을 손으로 익히는 최고의 예제이고, 언론사별 기사 수 세기는 데이터 리터러시의 첫 단계입니다. 주간 베스트 심기로 학내망 원칙까지 통과한 설계입니다.

📚 기술·교육 참고 링크

[행정/연구] 교직원 복무·청렴 연수 골든벨 출제기 - 공문서 PDF 원클릭 퀴즈



길고 딱딱한 공문이 10문항 골든벨이 되는 1초 — 골든벨 출제기 완전 정복

🏛️ 교직원 다모임·청렴·안전 연수. 길고 딱딱한 공문서 PDF를 제미나이 프롬프트에 주입하면 10문항 골든벨 문제 세트가 나오고, 퀴즈 플랫폼의 엑셀 서식에 붙여넣으면 1초 변환 — 교직원 스마트폰 접속 퀴즈로 수동적인 '읽는 연수'가 참여형 '맞히는 연수'로 바뀝니다.

복무·청렴 용어는 원문 그대로 — 조항 번호와 규정 문구를 바꿔 재해석하지 않는 정확성 가드레일이 생명입니다. 표기는 닉네임·부서만, 참여 확인은 로컬 문서·종이로 정리합니다.

📖 한 줄 정의

심기 모드(데이터 임베딩): API 데이터를 미리 받아 HTML 파일 안 상수로 박아두는 방식(앱 실행 중 외부 통신 0).

학내망 원칙: 학교 배포 웹앱은 개인정보 수집·저장·전송 없음(외부 CDN·API 호출 0, 단일 파일) — 학생은 학내망에서 교사 PC 서버에 접속.

1. 3대 핵심 분석 비교표

무엇이 바뀌었나요? / 영역 초보자를 위한 쉬운 설명 이렇게 한번 써보세요!
해결 문제 수동적 전달 위주 연수(읽고 지나가기) → 참여형 퀴즈 연수(맞히고 웃기기). 10문항이면 10분 — 회의 끝에 붙이는 미니 연수로 정착. 연수 리듬표(10분 문항 + 5분 정리)로 매월 정기화.
PDF → 10문항 공문서 PDF 텍스트를 제미나이에 넣고 프롬프트 규칙으로 객관식 10문항 생성 — 용어·조항 번호는 원문 그대로, 재해석 금지. 아래 제미나이 전용 프롬프트 복사 → PDF 텍스트 붙여넣기.
엑셀 서식 변환 문제은행 표를 퀴즈 플랫폼의 엑셀 서식 열에 맞춰 붙여넣어 파일로 저장 — 서식의 열 이름·순서는 사용하는 플랫폼의 공식 사이트에서 최신 양식을 반드시 확인합니다. 엑셀 붙여넣기 → 저장 → 플랫폼 업로드 → 1초 변환.
골든벨 운영 교직원 회의 10분 — 스마트폰 게임 코드 접속, '명예의 골든벨' 상징 연출, 클로징에 핵심 3줄 요약·서약. 진행 스크립트 3줄이면 충분. 오프닝(오늘의 공문 소개) → 문항 → 클로징(서약) 리듬.
원칙·정합 교직원 표기는 닉네임·부서만(인적 정보 최소), 참여 기록은 로컬 문서·종이(외부 플랫폼에 영구 보관 금지). 사용하는 공문은 학내망 공개 자료만. 운영 체크리스트 3줄(공개 자료 / 닉네임 / 로컬 기록) — 행정 안전장치.

2. 핵심 아키텍처 해설 — 공문이 문제은행이 되는 파이프라인

① 워크플로 4단

1단 공문 선택(학내망 공개 자료) → 2단 PDF 텍스트 확보 → 3단 제미나이 문제은행 생성 → 4단 엑셀 서식 변환·골든벨. 교과 도구든 행정 도구든 이 파이프라인 하나로 정리되는 점이 이 설계의 철학입니다.

② 정확성 가드레일

복무·청렴 문제은행의 실패 포인트는 '의미 왜곡'입니다. 프롬프트 규칙이 세 겹으로 방어합니다 — ① 용어·조항 번호는 원문 그대로 ② 해석이 필요한 문항은 출처 조항을 묻는 '본문 확인 문항'으로 전환 ③ 문장 안 쉼표는 가운뎃점으로(CSV 셀 보호). 연수 문항이 규정과 어긋나면 연수 자체의 신뢰가 흔들립니다.

③ 엑셀 서식 변환

제미나이가 내준 표(문제,보기1~4,정답번호)를 플랫폼 엑셀 서식에 붙여넣습니다. 핵심은 열 이름·순서를 플랫폼 양식에 맞추는 일 — 양식은 언제든 바뀌므로, 도구 공식 사이트에서 최신 서식을 확인한 뒤 붙여넣는 순서가 안전합니다.

④ 골든벨 운영 리듬

오프닝 1분(오늘의 공문 소개 — '이 문서가 오늘 우리 회의의 주인공'), 문항 10분(스마트폰 접속, 정답마다 '명예의 골든벨' 상징 연출), 클로징 5분(핵심 3줄 요약 + 서약 한 줄). 총 16분 — 회의 끝에 붙이기 좋은 미니 연수 길이입니다. 연수 자료는 학내망 공개 자료만 사용합니다.

⑤ 원칙·정합

  • 인적 정보 최소 — 접속 표기는 닉네임·부서만. 참여 확인은 로컬 문서·종이 출석으로 정리하고 외부 플랫폼에 영구 보관하지 않습니다.
  • 공개 자료만 — 공문은 학내망에서 공개된 자료만 문제은행으로 씁니다.

3. 초보자를 위한 바이브 코딩 실전 사용 예시

  1. 프롬프트 복사 — 아래 제미나이 전용 에러 제로 프롬프트를 복사해 Gemini에 붙여넣습니다.
  2. 역질문 답변 — 공문 주제·문항 수·연수 시간에 답합니다.
  3. 엑셀 변환·연수 — 나온 표를 엑셀 서식에 붙여넣어 업로드하고, 회의 끝 16분 골든벨로 진행합니다.

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

[🚨 에러 방지 기본 안전장치]
1. 산출물은 표(문제,보기1,보기2,보기3,보기4,정답번호)로만 출력한다 — 객관식 10문항.
2. 용어·조항 번호·규정 문구는 원문 PDF의 표현을 그대로 인용한다 — 의미를 바꿔 재해석하지 않는다.
3. 정답이 스스로 드러나는 문항 금지, 보기 4개의 난이도 균형 유지, '모두/모두 아니다' 보기 금지.
4. 해석이 필요한 문항은 '본문 확인 문항'(출처 조항을 묻는 문항)으로 전환한다.
5. 문장 안의 쉼표는 가운뎃점(·)으로 바꾸어 엑셀 셀이 흩어지지 않게 한다.
6. // TODO, /* 생략 */ 금지 — 끝까지 완성한다.

[❓ 역질문 유도]
코드를 바로 만들지 말고, 아래 3가지를 먼저 나에게 질문한 뒤 내 답변으로 설계를 확정한다.
Q1. 사용할 공문 PDF는 학내망 공개 자료인가? (공개 자료만 사용한다)
Q2. 문항 수는? (기본 10)
Q3. 연수 시간 배분은? (10분 문항 + 5분 정리 권장)

🎯 에디터 한줄평

'읽는 연수'가 '맞히는 연수'가 되는 16분 — 청렴은 암기가 아니라 습관이고, 습관은 첫 문항에서 시작합니다. 이 출제기의 진짜 가치는 행정 전달력이 참여력으로 바뀌는 자리입니다. 공문이 무대장이 되는 순간, 골든벨 한 소리가 규정 문단 한 장보다 오래 남습니다. 물론 정확성 가드레일 — 원문 그대로 인용하는 규칙 — 이 있기에 가능한 설계입니다.

📚 기술·행정 참고 링크

  • 행정·교육 연계: 복무 규정·청렴·안전 연수 자료는 학내망 공개 자료 기준으로 사용

[바이브 코딩] 공정 청소 룰렛 - 이전 주 당번 자동 제외와 주간 히스토리 아카이빙



당번 뽑기 불만을 원천 없애는 공정 룰렛 — 청소 구역 추첨 & 주간 히스토리 아카이빙

🎡 청소 구역(칠판·복도·창틀·쓰레기통) 배정을 룰렛(roulette)으로 바꿉니다. 이전 주 당번은 자동 제외되고, 뽑힌 횟수가 적은 학생이 유리한 균등 추첨(draw)으로 매주 월요일 아침 자치 시간에 전교생이 보는 앞에서 돌아갑니다.

배정 결과는 아카이빙(archiving, 기록 보관) — '주간 기록 CSV 내보내기'로 당번 히스토리를 로컬 파일에 누적합니다(자동 외부 전송 없음). 교사가 학급 시트에 직접 옮겨 적으면 1년분 공평 보장이 완성됩니다. 실명 칸은 없습니다(번호·닉네임만).

📖 한 줄 정의

심기 모드(데이터 임베딩): API 데이터를 미리 받아 HTML 파일 안 상수로 박아두는 방식(앱 실행 중 외부 통신 0).

학내망 원칙: 학교 배포 웹앱은 개인정보 수집·저장·전송 없음(외부 CDN·API 호출 0, 단일 파일) — 학생은 학내망에서 교사 PC 서버에 접속.

1. 3대 핵심 분석 비교표

무엇이 바뀌었나요? / 영역 초보자를 위한 쉬운 설명 이렇게 한번 써보세요!
공정 규칙 3단 ① 이전 주 당번 자동 제외 ② 뽑힌 횟수가 적은 학생이 유리한 균등 추첨 ③ 전원 제외 시 전체 재등장. 규칙이 코드에 그대로 보입니다. pickPlayer 함수에서 제외·균등 로직 확인하기.
룰렛 애니메이션 CSS 회전(transform rotate)과 랜덤 각도로 돌다가 감속하며 멈춥니다. 도착 칸에서 '웅-딩' 사운드(Web Audio 합성)가 울립니다. 전자칠판에서 큰 회전 버튼(88px)을 눌러 구역별 추첨.
히스토리 아카이빙 '주간 기록 CSV 내보내기' 버튼이 주차·구역·번호·닉네임을 CSV 파일로 저장합니다. 자동 외부 전송은 없습니다 — 학급 시트로 옮겨 적는 것은 교사의 수동 관리입니다. 매주 금요일 내보내기 → 교사가 학급 시트에 붙여넣기.
개인정보 설계 실명 입력·저장 칸이 없습니다 — 번호·닉네임만. 참가자 목록은 파일 상단 상수로 심기되어 학내망 안에서만 완결됩니다. EMBED_PLAYERS 상수에 모둠 닉네임 목록 심기.

2. 핵심 아키텍처 해설

① 구역·참가자 데이터

const ZONES = ["칠판", "복도", "창틀", "쓰레기통"];
const PLAYERS = [
  { no: 1, nick: "코알라" },
  { no: 2, nick: "돌고래" }
];

참가자는 번호와 닉네임만 다룹니다 — 실명은 이 앱의 어디에도 들어가지 않습니다.

② 공정 추첨 로직

function pickPlayer(zoneIndex, history) {
  const last = history.filter(function (h) {
    return h.zone === ZONES[zoneIndex] && h.week === currentWeek - 1;
  });
  let pool = PLAYERS.filter(function (p) {
    return !last.some(function (h) { return h.no === p.no; });
  });
  if (pool.length === 0) pool = PLAYERS.slice();
  return pool[Math.floor(Math.random() * pool.length)];
}

이전 주 당번을 후보에서 빼고, 전원이 제외될 극단적인 경우에는 전체를 다시 후보로 세웁니다. '뽑힌 횟수 적은 학생 우선'은 히스토리의 누적 횟수로 후보를 정렬해 앞쪽에 비중을 주는 방식으로 확장할 수 있습니다.

③ 룰렛 스핀

let angle = 0;

function spin() {
  const target = angle + 1440 + Math.random() * 360;
  const timer = setInterval(function () {
    angle += 18;
    wheel.style.transform = "rotate(" + angle + "deg)";
    if (angle >= target) {
      clearInterval(timer);
      sound("ding");
    }
  }, 30);
}

④ 주간 기록 아카이빙

function archiveRow(zoneIndex, player) {
  return currentWeek + "," + ZONES[zoneIndex] + "," + player.no + "," + player.nick;
}
// CSV 내보내기 버튼으로 주간 기록을 로컬 파일로 저장 — 외부 전송 없음

⑤ 운영 체크리스트

  • 결락자(부재로 못 뽑힌 학생)는 다음 주 히스토리에서 자동으로 유리해집니다.
  • 학급 시트 관리는 교사 수동 — 앱은 자동 외부 전송을 하지 않습니다(학내망 원칙).
  • 새 모둠 닉네임이 생기면 EMBED_PLAYERS 상수를 갱신(심기 루틴)합니다.

3. 따라하기 3단계

  1. 제미나이 전용 에러 제로 프롬프트를 복사해 Gemini에 붙여넣습니다.
  2. AI가 던지는 역질문 3가지(구역 수, 당번 인원, CSV 서식)에 답하면 단일 HTML 코드가 완성됩니다.
  3. 코드를 roulette.html로 저장 후 더블클릭 — 월요일 아침 자치 시간에 전자칠판에서 구역별 추첨을 돌립니다.

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

[🚨 에러 방지 기본 안전장치]
1. 결과물은 외부 라이브러리·폰트·이미지 없이 단일 HTML 파일로 완성한다 — 더블클릭 즉시 실행(서버·설치·회원가입·외부 클라우드 금지).
2. 참가자 목록은 번호·닉네임만 다룬다(실명 입력·저장 금지) — 파일 상단 EMBED_PLAYERS 상수로 심기(학내망 배포용 외부 통신 0).
3. 공정 규칙: 이전 주 당번 자동 제외, 뽑힌 횟수가 적은 학생이 유리한 균등 추첨, 전원 제외 시 전체 재등장.
4. 룰렛 회전은 CSS transform(rotate)과 랜덤 각도 — 도착 사운드는 Web Audio API 합성('웅-딩').
5. 주간 기록(주차,구역,번호,닉네임)은 CSV 내보내기로 로컬 파일 저장 — 자동 외부 전송 없음(학급 시트 옮겨 적기는 교사 수동).
6. 전자칠판 대형 터치 대응: 회전 버튼 88px 이상, 결과 표기 큰 글씨.
7. // TODO, /* 생략 */ 금지 — 끝까지 완성한다.

[❓ 역질문 유도]
코드를 바로 만들지 말고, 아래 3가지를 먼저 질문한 뒤 내 답변으로 설계를 확정한다.
Q1. 청소 구역은 몇 개로 할까? (기본 4: 칠판·복도·창틀·쓰레기통)
Q2. 한 구역 당번은 몇 명? (2인 1조 권장)
Q3. 히스토리 CSV 서식은? (주차,구역,번호,닉네임 기본)

🎯 에디터 한줄평

'뽑기 불만'이 '공정 규칙 논의'로 바뀌는 것이 이 앱의 진짜 목표입니다. 규칙이 코드로 눈에 보이는 순간, 학생들은 불만 대신 제안을 하기 시작합니다 — "제외 기준을 2주로 늘리면 어때요?". 이력이 코드 안에서 쌓이는 것은 '공평은 믿음이 아니라 기록'이라는 자치 교육의 정수입니다. 전자칠판 앞에서 울리는 웅-딩 사운드 하나가 월요일 아침을 아이들 절반의 관심사로 만듭니다.

📚 기술·교육 참고 링크

  • MDN — CSS transform : 룰렛 회전 애니메이션의 원리
  • MDN — Web Audio API : '웅-딩' 도착 사운드 합성
  • 교육과정 연계: 창의적 체험활동(학급자치·역할 분담), 모둠 활동과 학급 회의 안건으로 확장

[행정/연구] 교원 당직·감독 자동 추첨 배포기 - 균등 배분과 원클릭 배치표



당직·시험 감독·청소 구역 배정이 눈금으로 정해진다 — 균등 배분 추첨 배포기 완전 정복

🏫 학기 초·학기말의 반복 업무 — 전 교직원 당직 근무, 지필평가 고사실 감독관 배치, 교내 환경정리 구역 배정. 기피 요일과 선호를 체크로 취합하면 균등 배분(fair allocation) 알고리즘이 배치표(roster)를 몇 초 만에 만들고, 파일 하나를 공유 폴더에 올려 전 교직원에게 배포합니다.

핵심은 투명성입니다 — 배분 규칙(누적 횟수 최소 우선, 기피 요일 제외)이 화면에 보이므로 수기 배정의 불공정 시비가 원천 차단됩니다. 서버·Apps Script 배포 없이 단일 HTML 더블클릭 완결이며, 배포본은 번호·닉네임만 다룹니다.

📖 한 줄 정의

심기 모드(데이터 임베딩): API 데이터를 미리 받아 HTML 파일 안 상수로 박아두는 방식(앱 실행 중 외부 통신 0).

학내망 원칙: 학교 배포 웹앱은 개인정보 수집·저장·전송 없음(외부 CDN·API 호출 0, 단일 파일) — 학생은 학내망에서 교사 PC 서버에 접속.

1. 3대 핵심 분석 비교표

무엇이 바뀌었나요? / 영역 초보자를 위한 쉬운 설명 이렇게 한번 써보세요!
해결 문제 수기 배정의 불공정 시비 → 규칙이 코드로 보이는 균등 배분으로 전환. 당직·감독·청소 3가지 모드를 한 파일에서 전환합니다. 모드 3종 중 하나로 시작.
취합 기피 요일·선호 요일을 체크 입력으로 취합(2분) → 배분 계산은 몇 초. 사유까지 묻지 않습니다(정보의 최소 수집). 취합 표에서 요일만 체크.
균등 배분 알고리즘 누적 횟수 최소 우선 + 기피 요일 제외 + 직전 배정 제외 — 배분 규칙이 화면에 표시되어 투명합니다. allocate 함수로 배분 원리 이해.
배치표·배포 배치표(roster)를 화면에 크게 띄우고 CSV 내보내기로 로컬 저장 — 파일을 공유 폴더에 올려 전교직원 배포(자동 외부 전송 없음). downloadCSV → 공유 폴더 업로드.
개인정보 설계 배포본 화면은 번호·닉네임만 — 실명 배치표 CSV는 교무부가 로컬에서 관리합니다. 학내망 안에서 완결됩니다. EMBED 명단 상수 심기(외부 통신 0).

2. 핵심 아키텍처 해설

① 데이터: 명단과 요일 조건

const STAFF = [
  { no: 1, nick: "미리내", avoid: ["월"], pref: ["금"] },
  { no: 2, nick: "샛별",   avoid: [],     pref: ["화"] }
];

avoid는 기피 요일, pref는 선호 요일입니다. 사유는 저장하지 않습니다 — '월요일이 힘들다'는 사정까지 코드가 알 필요는 없습니다(정보의 최소 수집).

② 균등 배분: allocate

function allocate(pool, slots, history) {
  const sorted = shuffle(pool).sort(function (a, b) {
    return count(history, a.no) - count(history, b.no);
  });
  const roster = [];
  for (const s of slots) {
    const pick = sorted.find(function (p) {
      return !used(p) && s.avoid.indexOf(p.avoid) === -1;
    });
    if (pick) roster.push({ slot: s, who: pick });
  }
  return roster;
}

누적 횟수가 가장 적은 사람부터 슬롯을 채웁니다. 기피 요일이 겹치면 다음 후보로 넘어가고, 선호 요일이면 후보 순서에서 앞당겨집니다 — 배분 규칙이 화면에 그대로 표시됩니다.

③ 배치표(roster) 렌더

roster.forEach(function (r) {
  addRow(r.slot.day + " " + r.slot.task + " → " + r.who.no + " " + r.who.nick);
});

배치표는 회의 화면에 큰 글씨로 표기 — 모두가 같은 표를 보는 순간, 배정은 결론이 아니라 확인 절차가 됩니다.

④ CSV 기록과 배포

function rosterCSV(roster) {
  return roster.map(function (r) {
    return r.slot.day + "," + r.slot.task + "," + r.who.no + "," + r.who.nick;
  }).join("\n");
}
// CSV 내보내기로 로컬 파일 저장 — 자동 외부 전송 없음

배치표 CSV를 로컬 파일로 내보내면, 교무부는 그 파일을 학내망 공유 폴더에 올려 전 교직원에게 배포합니다(외부 클라우드·Apps Script 배포 없음). 실명이 필요한 공문용 배치표는 교무부가 로컬에서 관리합니다.

⑤ 운영 체크리스트

  • 배분 규칙(누적 최소 우선·기피 제외·직전 배정 제외)을 화면 하단에 상시 표시 — 투명성이 최고의 안전장치입니다.
  • '다시 배분'은 회의 안건으로 — 배분의 재현은 규칙 논의의 시작점입니다.
  • 신규 교원·신설 업무가 생기면 파일 상단 상수를 갱신(심기 루틴)합니다.

3. 따라하기 3단계

  1. 제미나이 전용 에러 제로 프롬프트를 복사해 Gemini에 붙여넣습니다.
  2. AI가 던지는 역질문 3가지(배분 대상, 요일 구조, CSV 서식)에 답하면 단일 HTML 코드가 완성됩니다.
  3. 코드를 배분배포기.html로 저장 후 더블클릭 — 취합 2분 → 배분 몇 초 → CSV 저장 → 공유 폴더 배포로 마무리됩니다.

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

[🚨 에러 방지 기본 안전장치]
1. 결과물은 외부 라이브러리·폰트·이미지 없이 단일 HTML 파일로 완성한다 — 더블클릭 즉시 실행(서버·설치·회원가입·구글 시트 API·Apps Script 금지).
2. 배포본 화면은 번호·닉네임만 다룬다(실명 저장 금지) — 기피 정보는 '기피 요일'만 취합(사유·건강 정보 저장 금지 — 정보의 최소 수집).
3. 균등 배분: 누적 횟수 최소 우선, 기피 요일 제외, 직전 배정 제외 — 배분 규칙을 화면에 표시해 투명하게.
4. 당직·시험 감독·청소 구역 3가지 모드를 한 파일에서 전환한다.
5. 배치표(roster)는 CSV 내보내기로 로컬 파일 저장 — 자동 외부 전송 없음(시트·공유는 교무부 수동).
6. 회의 화면 대응: 배치표 큰 글씨, 버튼 88px 이상. 배정 확정 사운드는 Web Audio 합성('똑').
7. 명단·요일 조건은 파일 상단 상수로 심기(학내망 배포용 외부 통신 0).
8. // TODO, /* 생략 */ 금지 — 끝까지 완성한다.

[❓ 역질문 유도]
코드를 바로 만들지 말고, 아래 3가지를 먼저 질문한 뒤 내 답변으로 설계를 확정한다.
Q1. 배분 대상은? (당직 / 시험 감독 / 청소 구역 / 3종 모드)
Q2. 요일 구조는? (월~금 / 주말 포함)
Q3. 배치표 CSV 서식은? (요일,업무,번호,닉네임 기본)

🎯 에디터 한줄평

수기 배정의 '누가 자꾸 나가?'라는 시비가 누적 횟수라는 한 칸의 눈금으로 끝납니다 — 공정은 감(感)이 아니라 눈금입니다. 그리고 이 도구의 진짜 우아함은 기피 사유까지 묻지 않는 설계에 있습니다. 요일만 묻는 배려는 동료를 존중하는 정보의 최소 수집이자, 배분 알고리즘보다 먼저 지켜야 할 원칙입니다.

📚 기술·교육 참고 링크

  • MDN — Array.sort() : 균등 배분의 정렬 원리
  • 교육·행정 연계: 교무 기획 업무(당직·시험 감독·환경정리), 연수·회의 운영으로 확장

[행정/연구] 교육청 공지·일정 스크래핑 대시보드 - 매일 아침 무인 수집



교육청 공지가 아침마다 교무실 대시보드로 — 웹 명세서 기반 스크래핑 완전 정복

📋 교육청 공지사항과 직속기관 연수 일정 웹사이트를 웹 명세서(specification) 기반 파이썬 스크립트가 매일 아침 자동 수집해, 단일 HTML 대시보드로 만들어 교무실 PC에서 공유합니다. Windows 작업 스케줄러(Task Scheduler)에 등록하면 무인 실행 — 연수·마감 일정을 더는 놓치지 않습니다.

대시보드는 매일 아침 코드가 새로 만들어 줍니다 — 지난 연재에서 정리한 심기 모드(데이터 임베딩)의 자동화 버전입니다. 데이터는 공개 정보를 '받아오기만' 합니다 — 외부 전송 0, 학생 개인정보 0.

📖 한 줄 정의

심기 모드(데이터 임베딩): API 데이터를 미리 받아 HTML 파일 안 상수로 박아두는 방식(앱 실행 중 외부 통신 0).

학내망 원칙: 학교 배포 웹앱은 개인정보 수집·저장·전송 없음(외부 CDN·API 호출 0, 단일 파일) — 학생은 학내망에서 교사 PC 서버에 접속.

1. 3대 핵심 분석 비교표

무엇이 바뀌었나요? / 영역 초보자를 위한 쉬운 설명 이렇게 한번 써보세요!
해결 문제 연수·마감 일정이 사이트마다 흩어져 놓치는 문제 → 매일 아침 자동 수집·한 화면 정리. 아침 대시보드에서 오늘 일정 확인.
웹 명세서 우선 명세서 방법 그대로 — 페이지·칸·셀렉터(selector)·주기를 지도로 남깁니다. 사이트 구조가 바뀌면 명세서만 고칩니다. 교육청 공지 페이지 명세서 2행 작성.
대시보드 생성 파이썬이 수집 결과를 단일 HTML 파일로 자동 생성 — 심기 모드의 자동 갱신 버전. 외부 라이브러리 없이 열립니다. 교무실대시보드.html 더블클릭.
무인 실행 Windows 작업 스케줄러(Task Scheduler)에 매일 07:30 등록 — 맥·리눅스는 크론(cron)으로 같은 원리. schtasks 등록 명령 한 줄.
원칙·안전 공개 정보 수신만 — 외부 전송 0, 학생 개인정보 0, 교무실 PC(학내망) 실행. 수집 결과는 학교 내부 공유용. 대시보드 하단에 '출처·수집 시각' 표기.

2. 핵심 아키텍처 해설 — 수집하고, 만들고, 등록한다

① 수집: 명세서에서 온 셀렉터

import requests
from bs4 import BeautifulSoup

SELECTORS = {
    "공지": ".board-list li",        # 명세서에서 온 값(예시 — 수업 시점에 확인)
    "제목": "b.tit",
    "날짜": "span.date"
}

res = requests.get(URL, timeout=10)
soup = BeautifulSoup(res.text, "html.parser")
notices = []
for li in soup.select(SELECTORS["공지"]):
    notices.append({
        "title": li.select_one(SELECTORS["제목"]).get_text(strip=True),
        "date": li.select_one(SELECTORS["날짜"]).get_text(strip=True)
    })

URL·셀렉터 모두 명세서에서 옵니다 — 코드에는 '명세서 몇 행' 주석이 함께 갑니다.

② 대시보드 생성: 파이썬이 HTML을 심는다

html = '<html><head><meta charset="utf-8">'
html = html + '<style>body{font-family:"맑은 고딕";max-width:720px;margin:40px auto;}</style>'
html = html + '</head><body><h1>오늘의 교육청 공지·일정</h1>'

for item in notices:
    html = html + '<p>' + item["date"] + ' · ' + item["title"] + '</p>'

html = html + '</body></html>'
open("교무실대시보드.html", "w", encoding="utf-8").write(html)

이 파일이 곧 '어제의 심기 모드가 자동으로 갱신되는 버전'입니다 — 매일 아침, 코드가 데이터를 파일 안에 심어줍니다.

③ 무인 실행: 작업 스케줄러 등록

schtasks /create /tn "교육청공지수집" /tr "python 수집기.py" /sc daily /st 07:30
  • /sc daily /st 07:30 — 매일 아침 7시 30분 자동 실행.
  • 맥·리눅스라면 크론(cron)으로 30 7 * * * 한 줄 — 원리는 같습니다.
  • 실행 결과(성공·건수)는 로그 파일로 남겨 '조용한 실패'를 막습니다.

④ 운영 원칙

  • 출처 표기: 대시보드 하단에 '수집 시각·원문 링크'를 항상 남깁니다.
  • 공개 정보만: 학생 개인정보는 수집 대상이 아니며, 외부 전송도 없습니다(학내망 원칙 정합).
  • 명세서 갱신 루틴: 사이트 개편이 감지되면(빈 목록·'확인 필요') 명세서를 고치고 셀렉터를 교체합니다.

3. 초보자를 위한 바이브 코딩 실전 사용 예시

  1. 프롬프트 복사 — 아래 '제미나이 전용 에러 제로 프롬프트' 전체를 Gemini에 붙여넣습니다.
  2. 역질문 답변 — 수집 대상 페이지, 실행 시각, 대시보드 서식에 답합니다.
  3. 스케줄러 등록 — 스크립트 실행 확인 후 schtasks 명령 한 줄로 무인화.

제미나이 전용 에러 제로 프롬프트 (파이썬판)

[🚨 에러 방지 기본 안전장치]
1. 라이브러리는 requests, beautifulsoup4만 사용한다.
2. 웹 명세서(페이지·칸·셀렉터·주기)를 먼저 마크다운 표로 만들어 달라고 요청한 뒤, 셀렉터를 상수로 옮긴다.
3. 수집 결과가 0건이면 대시보드에 '오늘 수집 결과 없음 — 명세서 확인 필요'를 남긴다(조용한 실패 금지).
4. 대시보드는 외부 CSS·JS 없는 단일 HTML로 만들고, 하단에 수집 시각·출처를 표기한다.
5. 로그 파일에 실행 시각·건수·오류를 기록한다.
6. 이 스크립트는 공개 정보를 받아오기만 한다 — 데이터를 외부로 전송하는 기능을 만들지 않는다(학내망 원칙).
7. // TODO, pass 등 미완성 코드 금지 — 끝까지 완성한다.

[❓ 역질문 유도]
코드를 바로 만들지 말고, 아래 3가지를 먼저 나에게 질문한 뒤 내 답변으로 설계를 확정한다.
Q1. 어느 사이트의 무엇을 수집할까? (교육청 공지 / 직속기관 연수 일정 등 — URL을 함께 알려준다)
Q2. 실행 시각은? (매일 07:30 기본)
Q3. 대시보드 서식은? (최신순 목록 + 날짜·제목 기본)

🎯 에디터 한줄평

'놓치는 일정'이 '아침마다 도착하는 대시보드'로 — 행정 안전망이 코드로 완성됩니다. 명세서와 셀렉터 상수를 분리한 설계가 유지보수의 핵심이고, '수집 결과 0건'을 조용히 넘기지 않는 습관이 자동화의 신뢰를 만듭니다. 심기 모드가 '자동으로 갱신되는 심기'로 진화하는 순간이기도 합니다.

📚 기술·교육 참고 링크

[바이브 코딩] SWAPI - 스타워즈 6편의 우주를 데이터로 탐사하는 은하수 도감



스타워즈 6편의 우주를 데이터로 탐사하는 은하수 도감 — SWAPI 완전 정복

🌌 SWAPI(swapi.dev)는 스타워즈 세계관 데이터(영화 6편·인물·행성·스타십·종·탈것)를 무료로 제공하는 팬메이드 API입니다. API 키 없이 열리며, 오늘 실측으로 search=skywalker 한 번에 루크·아나킨·쉬미 3대가 나란히 검색되는 것, 응답이 {count, next, previous, results} 표준 봉투(envelope) 구조로 오는 것, format=wookiee로 우키어(웨이스의 언어) 번역 응답까지 가능한 것을 확인했습니다.

이 API의 진짜 교육적 보물은 관계 데이터가 '숫자'가 아니라 '주소(URL) 목록'으로 온다는 하이퍼미디어 구조입니다 — 웹의 본질을 만지는 첫 경험. 학내망 '외부 호출 0' 원칙은 관심 카드(에피소드 IV + 주요 인물) 심기로 통과합니다.

📖 한 줄 정의

심기 모드(데이터 임베딩): API 데이터를 미리 받아 HTML 파일 안 상수로 박아두는 방식(앱 실행 중 외부 통신 0).

학내망 원칙: 학교 배포 웹앱은 개인정보 수집·저장·전송 없음(외부 CDN·API 호출 0, 단일 파일) — 학생은 학내망에서 교사 PC 서버에 접속.

1. 3대 핵심 분석 비교표

무엇이 바뀌었나요? / 영역 초보자를 위한 쉬운 설명 이렇게 한번 써보세요!
API 정체 스타워즈 공식이 아니라 팬메이드 무료 API. 자원 6개(people 인물·planets 행성·films 영화·species 종·vehicles 탈것·starships 스타십), 키 없이 열립니다. 영화는 6편(에피소드 I~VI) 실측. https://swapi.dev/api/ → 자원 6개 목록 확인.
응답 봉투(envelope) 목록 응답은 {count, next, previous, results} 봉투에 담겨 옵니다 — count는 전체 건수, next·previous는 다음·이전 페이지 주소. API의 페이지네이션 표준 구조를 그대로 배울 수 있습니다. people/?search=skywalker → count 3(실측) 확인.
데이터 모양 height '172', birth_year '19BBY' — 숫자도 문자열, 연대는 BBY(야빈 전투 기준 세계관 연도). opening_crawl에는 줄바꿈 문자(\r\n)가 그대로 들어옵니다. 인물이 인간이면 species는 빈 배열(실측 함정). Number(height)로 변환 후 표기, species 빈 배열엔 'Human(인간)' 기본값.
관계는 주소로 characters[]가 이름이 아니라 URL 목록으로 옵니다(에피소드 IV는 등장인물 18개 주소 — 실측). 주소를 따라가며 데이터를 연결하는 하이퍼미디어 구조, 웹의 본질입니다. 인물 카드 → homeworld 주소 따라가 행성 카드 열기.
학내망 배포 대응 관심 카드(에피소드 IV + 주요 인물 8명 등)를 미리 받아 슬림화해 심으면 학생 단말은 통신 0. 수치가 흥미로운 행성 카드(타투인: 하루 23시간·1년 304일 — 실측)도 심기 소재로 좋습니다. EMBED_DATA에 카드 목록 심기 → 학내망 배포본 완성.

2. 핵심 아키텍처 해설 — 은하수 창고는 이렇게 생겼다

① URL 해부: 루트가 안내판이다

https://swapi.dev/api/ 를 열면 자원 6개의 주소가 안내됩니다(실측): people, planets, films, species, vehicles, starships. 조건은 ?search=(검색), ?page=(페이지), ?format=wookiee(우키어 번역 — 재미용, 실측 200 OK). CORS는 Access-Control-Allow-Origin: * 로 열려 있습니다(실측).

② 봉투(envelope) 데이터 모양: search=skywalker 실측 예시

{
  "count": 3,
  "next": null,
  "previous": null,
  "results": [{
    "name": "Luke Skywalker",
    "height": "172",
    "birth_year": "19BBY",
    "gender": "male",
    "homeworld": "https://swapi.dev/api/planets/1/",
    "films": ["https://swapi.dev/api/films/1/", "..."],
    "species": []
  }]
}

실측 응답(간추림)입니다. count 3 = 루크·아나킨·쉬미, 스카이워커 3대가 한 번에 나옵니다. homeworld는 주소 — 타투인 행성 카드로 연결됩니다. species가 비어 있는 이유는 '인간은 종 목록에 등재되지 않은 기본값'이기 때문(실측) — 빈 배열 처리는 좋은 코딩 연습입니다.

③ 영화 자원: opening_crawl과 관계 목록

films/1(에피소드 IV)의 실측 구조: title "A New Hope", episode_id 4, opening_crawl(오프닝 크롤 텍스트, 줄바꿈 문자 포함), director "George Lucas", producer "Gary Kurtz, Rick McCallum", release_date "1977-05-25", 그리고 characters(18개 주소)·planets(3)·starships(8)·vehicles(4)·species(5)의 URL 목록. API는 결과를 에피소드 IV부터 나열합니다 — '번호 1번 = 에피소드 IV'라는 정렬 함정도 실측.

④ 행성 자원: 세계관 수치로 하는 진짜 단위 수업

planets/1 타투인(실측): rotation_period "23"(하루 길이), orbital_period "304"(1년 길이), diameter "10465", terrain "desert", population "200000". 지구의 하루·1년과 비교하는 활동이 곧 단위·비율 수업이 됩니다 — 모든 수치가 문자열이라 Number() 변환 연습도 함께.

⑤ 검색 코드와 관계 따라가기

const API = "https://swapi.dev/api";

async function searchPeople(word) {
  const res = await fetch(API + "/people/?search=" + encodeURIComponent(word));
  const json = await res.json();
  return json;   // json.count, json.next, json.results
}
async function follow(url) {
  const res = await fetch(url);
  return await res.json();   // characters[]의 주소를 하나씩 방문
}

학내망 배포용은 에피소드 IV 카드와 주요 인물 목록을 미리 받아 슬림화한 뒤 EMBED_DATA로 심습니다. 심기 모드(데이터 임베딩)가 무엇인지는 앞의 '📖 한 줄 정의' 박스를 참고하세요 — 상태가 절대 바뀌지 않는 세계관 데이터는 심기와 궁합이 좋습니다.

3. 초보자를 위한 바이브 코딩 실전 사용 예시

  1. 프롬프트 복사 — 아래 '제미나이 전용 에러 제로 프롬프트' 전체를 복사해 Gemini에 붙여넣습니다.
  2. 역질문 답변 — Gemini가 던지는 질문 3가지(자원 중심, 데이터 모드, 화면 톤)에 답하면 설계가 확정됩니다.
  3. HTML 파일 실행 — 완성 코드를 '은하수도감.html'로 저장 후 더블클릭. 심기 모드 파일이면 곧 학내망 배포본입니다.

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

[🚨 에러 방지 기본 안전장치]
1. 결과물은 외부 라이브러리·프레임워크·웹폰트 없이 단일 HTML 파일로 완성한다. (SWAPI 데이터 fetch는 유일한 외부 통신 예외)
2. 사운드는 Web Audio API로 직접 합성한다: 검색 성공 시 부드러운 '똑' 소리, 결과 0건·통신 실패 시 '삑' 경고음. 오디오 파일·CDN 사운드 사용 금지.
3. 모바일 터치 대응: 뷰포트 메타 태그 필수, 버튼 최소 44×44px, 입력 필드 font-size 16px 이상, 360px 화면에서 가로 스크롤 금지.
4. 응답 봉투 {count, next, previous, results} 구조를 그대로 처리한다: count는 항상 화면에 표시하고, next가 null이 아닐 때 '더 보기' 버튼으로 다음 페이지를 이어서 불러온다.
5. height·mass·diameter 같은 수치 칸은 문자열로 오므로 Number()로 변환하고 천 단위 콤마로 표기한다. 'unknown' 같은 특수 값도 그대로 보여준다.
6. opening_crawl의 줄바꿈 문자(\r\n)는 화면용으로 정리해서 보여주고, 인물의 species가 빈 배열이면 'Human(인간)' 기본값을 보여준다.
7. 파일 상단 EMBED_DATA에 카드 목록이 심어져 있으면 fetch를 완전히 생략한다(학내망 배포용 외부 호출 0 모드). // TODO, /* 생략 */ 같은 미완성 코드는 절대 넣지 말고 끝까지 완성한다.

[❓ 역질문 유도]
코드를 바로 만들지 말고, 아래 3가지를 먼저 나에게 질문한 뒤 내 답변으로 설계를 확정한다.
Q1. 어떤 자원을 중심으로 만들까? (인물 / 행성 / 스타십)
Q2. 데이터 모드는 무엇으로 할까? (A: 실시간 fetch 모드 / B: 학내망용 관심 카드 심기 모드)
Q3. 화면 톤은? (검색 카드 목록 / 영화·인물 연결 탐사 지도)

🎯 에디터 한줄평

'172'와 172의 차이, '19BBY'라는 세계관 연대, 타투인의 304일 — 가짜 수치로 하는 진짜 데이터 다루기의 완벽한 안전한 실험실입니다. 관계가 URL 목록으로 온다는 하이퍼미디어 개념은 웹의 본질을 아이에게 처음 열어주는 문이고, '더 보기' 버튼은 페이지네이션의 첫 실습입니다. 스카이워커 3대가 검색 한 번에 나란히 나오는 순간, 도감이 아니라 우주 가계도 앱으로 확장할 수 있다는 것도 알게 되죠. 심기 모드로 학내망까지 통과한 설계 — 세계관 데이터 특유의 '절대 안 바뀜'이 이 설계를 쉽게 만들어줍니다.

📚 기술·교육 참고 링크

  • SWAPI : 이번 글의 은하수 데이터 창고(팬메이드)
  • SWAPI 공식 문서 : 자원·검색·페이지네이션·wookiee 포맷 설명
  • 교육과정 연계: 수학(단위·비율 — 행성 하루/1년 비교), 과학(우주·행성), 국어(세계관 설정문 읽기)와 함께 활용

[바이브 코딩] Launch Library 2 - 세계 로켓 발사 일정표 앱과 15회/시간 제한 실측 대응법



세계 로켓 발사 일정표를 교실로 — Launch Library 2 완전 정복

🚀 Launch Library 2는 전 세계 로켓 발사 기록과 예정 일정을 모아둔 국제 공유 데이터베이스입니다(The Space Devs 커뮤니티 운영, 무료·API 키 없음). 오늘 실측으로 다가오는 발사 360건을 확인했고, 심지어 오늘(2026-09-05) 발사 예정인 Isar Aerospace의 Spectrum 로켓('Go for Launch' 상태)까지 읽었습니다. mode=list 옵션으로 발사 1건을 3.3KB 슬림 응답으로 받을 수 있습니다.

이 API에는 결정적인 특징이 있습니다 — 익명 호출은 시간당 15회(실측). 대신 /api-throttle/ 엔드포인트가 남은 횟수를 직접 알려줍니다. 이 제한을 어떻게 우아하게 다루는지가 이번 글의 백미이자, 교실 배포에서는 심기 모드(데이터 임베딩)가 필수인 이유이기도 합니다.

📖 한 줄 정의

심기 모드(데이터 임베딩): API 데이터를 미리 받아 HTML 파일 안 상수로 박아두는 방식(앱 실행 중 외부 통신 0).

학내망 원칙: 학교 배포 웹앱은 개인정보 수집·저장·전송 없음(외부 CDN·API 호출 0, 단일 파일) — 학생은 학내망에서 교사 PC 서버에 접속.

1. 3대 핵심 분석 비교표

무엇이 바뀌었나요? / 영역 초보자를 위한 쉬운 설명 이렇게 한번 써보세요!
API 정체 세계 모든 로켓 발사의 과거 기록과 미래 일정을 담은 국제 DB. 키 없이 무료이며, 오늘 실측 기준 미래 발사 360건이 준비되어 있습니다. (현재 버전 2.2.0, 2.3.0도 열려 있습니다.) /2.2.0/launch/upcoming/?limit=3&mode=list → 다음 발사 3건.
자원명 함정 자원 이름이 launch(단수형)입니다. launches(복수)로 쓰면 404가 납니다 — 실측으로 직접 겪었습니다. launch(전체)·launch/upcoming(다가올 발사)·launch/previous(지난 발사)로 구성됩니다. 막히면 루트 주소(/2.2.0/)에서 자원 목록을 다시 읽는 습관.
mode=list 다이어트 기본 응답은 로켓 상세까지 싹 다 주늑 몇십 KB입니다. ?mode=list를 붙이면 발사 1건이 3.3KB짜리 슬림 카드로 줄어듭니다(실측) — 15회/시간 제한을 지키는 첫 번째 예의입니다. ?mode=list를 항상 기본값으로 쓰기.
데이터 모양 발사 1건 = name(로켓 | 임무)·status.name('Go for Launch')·net(발사 시각, ISO8601)·lsp_name(발사 기관)·pad·location(발사장)·mission·image. net을 한국 시각으로 바꿔 '우리 나라 시간 몇 시에 발사?' 계산.
15회/시간 대응 익명 호출 제한이 시간당 15회입니다(실측). /api-throttle/이 남은 횟수와 재충전 시각을 알려줍니다. 교실 배포는 반드시 심기 모드 — 교사가 아침에 한 번 받아 심으면 학생 단말은 통신 0입니다. EMBED_DATA에 이번 주 발사 일정 + '기준 시각' 표시.

2. 핵심 아키텍처 해설 — 발사 일정 창고는 이렇게 생겼다

① URL 해부: launch는 단수형, 2.3.0도 있다

https://ll.thespacedevs.com/2.2.0/launch/upcoming/?limit=3&mode=list

  • ll.thespacedevs.com/2.2.0 — 현재 표준 버전. 루트 주소가 자원 목록을 JSON으로 안내합니다(astronaut·pad·spacestation 등 40여 개 자원).
  • launch (단수형) — launches로 쓰면 404. 하위 경로: upcoming(미래+최근 24시간), previous(지난 발사).
  • mode=list — normal/list/detailed 세 모드. list가 슬림 카드 모드입니다.
  • search= — 발사명·로켓·기관·임무명 통합 검색(?search=SpaceX 같은 형태).

② 15회/시간: api-throttle이 직접 말해준다

{
  "your_request_limit": 15,
  "limit_frequency_secs": 3600,
  "current_use": 15,
  "next_use_secs": 291
}

오늘 실측 응답 그대로입니다 — our 검증 호출 15회를 다 써서 current_use가 15, 291초 뒤 1회가 재충전된다는 뜻입니다. '남은 횟수'를 API가 스스로 공개한다는 점은 기업형 API에서도 드문 친절함입니다. 교실에서는 '남은 횟수 읽기' 자체를 API 소양 수업으로 다룰 수 있습니다.

③ mode=list 데이터 모양: 발사 한 건이 한 장의 티켓

{
  "count": 360,
  "next": "https://ll.thespacedevs.com/2.2.0/launch/upcoming/?limit=1&mode=list&offset=1",
  "results": [{
    "name": "Spectrum | Onward and Upward",
    "status": { "name": "Go for Launch", "abbrev": "Go" },
    "net": "2026-09-05T20:00:00Z",
    "lsp_name": "Isar Aerospace",
    "mission": "Onward and Upward",
    "mission_type": "Test Flight",
    "pad": "Orbital Launch Pad",
    "location": "Andøya Spaceport",
    "image": "https://thespacedevs-prod...jpeg"
  }]
}

실측 데이터(2026-09-05 기준)입니다. net은 '발사 예정 시각'의 국제 표준 표기이고, 상태 약어(Go, Success, Failure)는 세계 발사 커뮤니티의 공용어입니다.

④ 발사 시각 다루기: 한국 시각 변환과 카운트다운

const t = new Date(launch.net);
const local = t.toLocaleString("ko-KR", { dateStyle: "short", timeStyle: "short" });

function countdown(net) {
  const diff = new Date(net) - new Date();
  const s = Math.floor(diff / 1000);
  const d = Math.floor(s / 86400);
  const h = Math.floor((s % 86400) / 3600);
  const m = Math.floor((s % 3600) / 60);
  return "T-" + d + "일 " + h + "시간 " + m + "분";
}

T-3일 14시간 22분 — 아이들이 가장 좋아하는 숫자 놀이가 그대로 수업이 됩니다.

⑤ 학내망 전략: 아침 1회 심기

교사가 매일 아침(또는 발사 주간 전) 한 번 upcoming 10건을 mode=list로 받아 name·status·net·lsp_name·location만 골라 EMBED_DATA로 심습니다. 심기 모드(데이터 임베딩)가 무엇인지는 앞의 '📖 한 줄 정의' 박스를 참고하세요. 파일 하단에 '기준 시각: 2026-09-05 아침'을 표시해 발사 시각이 흘렀으면 '발사 완료 여부는 launch/previous에서 확인' 안내를 붙입니다. 발사 이미지(image)는 외부 스토리지 주소이므로 학생 배포본에서는 로켓 아이콘 텍스트 카드로 대체합니다.

3. 초보자를 위한 바이브 코딩 실전 사용 예시

  1. 프롬프트 복사 — 아래 '제미나이 전용 에러 제로 프롬프트' 전체를 복사해 Gemini에 붙여넣습니다.
  2. 역질문 답변 — Gemini가 던지는 질문 3가지(일정 축, 데이터 모드, 카운트다운 여부)에 답하면 설계가 확정됩니다.
  3. HTML 파일 실행 — 완성 코드를 '발사일정표.html'로 저장 후 더블클릭. 심기 모드 파일이면 곧 학내망 배포본입니다.

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

[🚨 에러 방지 기본 안전장치]
1. 결과물은 외부 라이브러리·프레임워크·웹폰트 없이 단일 HTML 파일로 완성한다. (Launch Library 2 데이터 fetch는 유일한 외부 통신 예외)
2. 사운드는 Web Audio API로 직접 합성한다: 카운트다운 마지막 10초에 틱 소리, 발사 예정 시각 도달 시 '똑' 알림음, 통신 실패 시 '삑'.
3. 모바일 터치 대응: 뷰포트 메타 태그 필수, 버튼 최소 44×44px, 360px 화면 가로 스크롤 금지.
4. 데이터 주소는 https://ll.thespacedevs.com/2.2.0/launch/upcoming/?mode=list 이며, 자원명은 launch(단수형)로 정확히 쓴다(launches는 404).
5. 익명 호출은 시간당 15회 제한이므로 요청을 최소화하고, 429·제한 안내 시 '잠시 후 다시 시도' 화면을 보여준다.
6. net(발사 시각)은 국제표준시이므로 toLocaleString으로 한국 시각을 표시하고, T-카운트다운 타이머를 1초 간격으로 갱신한다.
7. 파일 상단 EMBED_DATA에 이번 주 발사 일정이 심어져 있으면 fetch를 완전히 생략한다(학내망 배포용 외부 호출 0 모드). 파일 하단에 '기준 시각'을 표시한다.
8. // TODO, /* 생략 */ 같은 미완성 코드는 절대 넣지 말고 끝까지 완성한다.

[❓ 역질문 유도]
코드를 바로 만들지 말고, 아래 3가지를 먼저 나에게 질문한 뒤 내 답변으로 설계를 확정한다.
Q1. 일정 축은 무엇으로 할까? (다가올 발사 upcoming / 지난 발사 previous)
Q2. 데이터 모드는 무엇으로 할까? (A: 실시간 fetch — 호출 15회/시간 주의 / B: 학내망용 심기 모드 — 권장)
Q3. 카운트다운 타이머를 넣을까? (가장 임박한 발사 1건만 크게 / 목록마다 표시)

🎯 에디터 한줄평

시간당 15회라는 제한이 문제가 아니라 최고의 교재입니다. '제한 있는 자원을 어떻게 나눠 쓰게 설계할까'는 세상 모든 API 사용의 본질이고, api-throttle로 남은 횟수를 읽는 습관은 데이터 소양 그 자체입니다. T-카운트다운 타이머는 수학(시간 계산)·과학(우주 개발)·국어(발사 기사 읽기)를 한 화면에 모으는 앱으로 완성됩니다. 아침 1회 심기 전략까지 — 설계가 가장 단단한 앱입니다.

📚 기술·교육 참고 링크

  • Launch Library 2 공식 문서 : 자원·필터·속도 제한 전체 정리
  • API 루트(자원 목록) : 자원명을 헷갈릴 때마다 다시 읽는 지도
  • The Space Devs : 운영 커뮤니티 소개
  • 교육과정 연계: 과학(우주 개발·인공위성), 수학(시각·시차·카운트다운), 사회(국제 협력과 우주 경쟁)와 함께 활용

[교과 연계] 모둠 PMI 토의 벽 - 입력 즉시 붙는 실시간 토의 웹앱 (단일 파일)



우리 모둠의 의견이 전자칠판 벽에 붙는다 — PMI 실시간 토의 벽 완전 정복

🗂️ PMI(Plus·Minus·Interesting — 장점·단점·흥미로운 점)는 에드워드 드 보노(Edward de Bono)가 제안한 사고 기법입니다. 학생들이 파스텔 색 붙임노트(post-it 스타일)로 의견을 쓰면 — 장점은 노랑, 단점은 분홍, 흥미는 하늘 — 전자칠판 벽에 입력 즉시 붙습니다. 설치도, 서버도, 회원가입도 없는 단일 HTML 파일 하나로 완성되어 더블클릭으로 바로 실행됩니다.

국어(토의·토론)·도덕(민주적 의사 결정)·사회 융합 교구입니다. '실시간'은 입력 즉시 반영으로 정직하게 실현하고, 태블릿 확장은 공유 코드 복사·붙여넣기로 전달합니다. 화면 표기는 모둠 번호·닉네임뿐(이름 저장 0), 수업 종료 후 CSV 저장 — 학내망 원칙(개인정보 수집·저장·전송 없음)을 그대로 지킵니다. Post-it®는 상표이므로 도구명은 '붙임노트·토의 벽'으로 부릅니다.

📖 한 줄 정의

심기 모드(데이터 임베딩): API 데이터를 미리 받아 HTML 파일 안 상수로 박아두는 방식(앱 실행 중 외부 통신 0).

학내망 원칙: 학교 배포 웹앱은 개인정보 수집·저장·전송 없음(외부 CDN·API 호출 0, 단일 파일) — 학생은 학내망에서 교사 PC 서버에 접속.

1. 3대 핵심 분석 비교표

무엇이 바뀌었나요? / 영역 초보자를 위한 쉬운 설명 이렇게 한번 써보세요!
수업 시나리오 토론 주제 하나를 놓고 모둠 대표가 차례로 전자칠판에 입력합니다 — '3모둠 차례!' 순환 리듬. 벽에 쌓인 색 노트가 곧 토론의 공유 자료가 됩니다. 주제: '초등학생 스마트폰 하루 1시간 제한' — 모둠마다 노랑·분홍·하늘 한 장씩.
PMI 3범주와 색 토큰 장점(Plus)·단점(Minus)·흥미(Interesting) 3범주를 파스텔 색으로 구분합니다 — 노랑·분홍·하늘은 디자인 토큰(design token) 방식으로 CSS 변수에 담아 어느 기기에서도 같은 색. --note-plus(노랑) / --note-minus(분홍) / --note-interesting(하늘) 토큰 3줄.
실시간 = 입력 즉시 반영 서버 없이도 '실시간'은 실현됩니다 — 입력하면 그 자리에서 즉시 벽에 렌더링. 한 화면을 같이 보니 발언이 곧 화면입니다. (여러 기기의 동시 편집은 서버가 없으면 불가 — 이 한계는 정직하게 알리고, 아래 공유 코드가 대안입니다.) addNote() 한 번 호출로 벽 갱신.
태블릿 확장(공유 코드) 각 태블릿에서 같은 파일을 열어 '모둠 메모 모드'로 의견을 쓰고, 공유 코드(한 줄 텍스트)로 복사 → 전자칠판 벽의 '코드 불러오기'로 일괄 등록. 서버 없이도 여러 기기의 의견이 한 벽에 모입니다 — 데이터 전달은 복사·붙여넣기뿐. shareCode() → 복사 → loadCode() 붙여넣기.
터치 드래그의 함정 웹의 HTML5 드래그 앤 드롭(drag and drop)은 데스크톱 마우스에만 편하고 전자칠판·태블릿 터치에서는 동작하지 않는 유명한 함정입니다. 해법은 포인터 이벤트(pointer events) — 터치와 마우스를 하나의 문법으로 다룹니다. pointerdown → pointermove → pointerup 3단 코드.
정리와 원칙 화면 표기는 모둠 번호·닉네임뿐(이름 저장 0), 데이터는 세션 메모리(새로고침하면 사라짐 — 세션 메모리 원칙), 수업 종료 후 CSV 내보내기로 장부를 로컬 저장. Post-it®는 상표이므로 도구명은 '붙임노트·토의 벽'으로. downloadCSV 함수 + 상표 안전장치.

2. 핵심 아키텍처 해설 — 서버 없는 벽은 이렇게 생겼다

① PMI 3범주와 색 토큰

PMI는 토론의 안전장치입니다 — '반대 의견(분홍)'도 정해진 자리와 색을 가지므로, 아이는 단점 말하기가 공격이 아니라 역할임을 배웁니다. 색은 디자인 토큰 방식으로 CSS 변수에 정의합니다.

:root {
  --note-plus: #fef9c3;        /* 장점 — 파스텔 노랑 */
  --note-minus: #fce7f3;       /* 단점 — 파스텔 분홍 */
  --note-interesting: #e0f2fe; /* 흥미 — 파스텔 하늘 */
}

② 입력 즉시 벽에: 세션 메모리

const notes = [];   // 세션 메모리 — 새로고침하면 사라짐(세션 메모리 원칙)

function addNote(category, text, who) {
  notes.push({ id: notes.length + 1, category: category, text: text, who: who });
  drawWall();
  sound("ding");   // Web Audio 합성음
}

③ 터치 드래그 재분류: 포인터 이벤트

note.addEventListener("pointerdown", function (e) {
  dragging = note;
  dx = e.clientX - note.offsetLeft;
  dy = e.clientY - note.offsetTop;
});
document.addEventListener("pointermove", function (e) {
  if (!dragging) return;
  dragging.style.left = (e.clientX - dx) + "px";
  dragging.style.top = (e.clientY - dy) + "px";
});
document.addEventListener("pointerup", function () { dragging = null; });

④ 태블릿 확장: 공유 코드 전달

여러 기기의 의견을 한 벽에 모으는 서버 없는 방법 — 의견 목록을 한 줄 텍스트 코드로 만들어 전달합니다. 태블릿에서 '공유 코드' 복사 → 전자칠판 벽의 '코드 불러오기'로 붙여넣기. 전송이 아니라 복사·붙여넣기라 외부 통신 0입니다.

function shareCode() {
  return notes.map(function (n) {
    return n.category + "|" + n.text + "|" + n.who;
  }).join("::");
}

function loadCode(code) {
  code.split("::").forEach(function (row) {
    const p = row.split("|");
    if (p[0]) addNote(p[0], p[1], p[2]);
  });
  sound("chime");
}

⑤ 수업 종료: CSV 장부 저장

세션 메모리는 새로고침에 사라지므로, 수업이 끝나면 downloadCSV로 누적 장부를 로컬 파일에 저장합니다(전송 아님). 저장한 CSV가 다음 수업의 토론 복기 자료가 됩니다.

3. 초보자를 위한 바이브 코딩 실전 사용 예시

  1. 프롬프트 복사 — 아래 '제미나이 전용 에러 제로 프롬프트' 전체를 복사해 Gemini에 붙여넣습니다.
  2. 역질문 답변 — Gemini의 질문 3가지(토론 주제, 벽 레이아웃, 태블릿 확장 여부)에 답하면 설계가 확정됩니다.
  3. HTML 파일 실행 — 완성 코드를 '토의벽.html'로 저장 후 더블클릭. 전자칠판 브라우저에 띄우고, 태블릿에는 같은 파일을 열어 모둠 메모 모드로 씁니다.

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

[🚨 에러 방지 기본 안전장치]
1. 결과물은 단일 HTML 파일 — 더블클릭으로 바로 실행되어야 한다. 서버 실행·프로그램 설치·회원가입·외부 클라우드(구글 시트 등)는 일절 사용하지 않는다.
2. 외부 라이브러리·웹폰트·이미지 금지. 사운드는 Web Audio API로 직접 합성한다: 등록 '똑', 재분류 '틱', CSV 저장 '팡파르'.
3. 색은 :root 토큰 변수(--note-plus/--note-minus/--note-interesting)로 정의하고 CSS에 하드코딩하지 않는다.
4. 드래그 재분류는 HTML5 drag and drop 대신 pointer events(pointerdown/move/up)로 구현해 전자칠판·태블릿 터치에서도 동작하게 만든다.
5. 이름·성별·학번 입력 칸은 만들지 않는다 — 표기는 모둠 번호·닉네임만, 데이터는 세션 메모리(새로고침 시 사라짐)를 기본값으로 한다.
6. 'CSV 내보내기' 버튼으로 수업 종료 시 누적 장부를 로컬 파일로 저장한다(외부 전송 아님). '공유 코드' 복사·불러오기 버튼도 함께 넣는다.
7. 도구명·UI 문구에 Post-it® 상표를 직접 사용하지 않는다('붙임노트', '토의 벽'으로).
8. // TODO, /* 생략 */ 금지 — 끝까지 완성한다.

[❓ 역질문 유도]
코드를 바로 만들지 말고, 아래 3가지를 먼저 나에게 질문한 뒤 내 답변으로 설계를 확정한다.
Q1. 첫 토론 주제는 무엇으로 할까? (교사가 시작 노트 1장을 미리 심는 것을 권장)
Q2. 벽 레이아웃은? (3열 고정 / 자유 벽 + 드래그 재분류)
Q3. 태블릿 확장(공유 코드) 모드도 넣을까? (기본: 넣음 — 복사·붙여넣기 전달)

🎯 에디터 한줄평

'조용히 듣던 아이'가 '벽에 붙는 색'이 되는 순간이 이 도구의 마법입니다. 모든 의견이 보이는 벽은 민주적 토의의 물리적 조건이고, 분홍(단점) 노트에도 정해진 자리가 있다는 설계가 '반대 말하기는 공격이 아니라 역할'임을 가르칩니다. 특히 '서버 없이 실시간은 불가능한가'라는 고민을 '입력 즉시 반영 + 공유 코드 전달'로 풀어낸 점이 아름답습니다 — 실시간은 거창한 인프라가 아니라, 우리 수업의 리듬이 만들어 내는 것임을 보여준 설계입니다.

📚 기술·교육 참고 링크

  • PMI 사고 기법 — 에드워드 드 보노(Edward de Bono)의 Plus·Minus·Interesting 3단 사고 도구 (국어 토의·토론 단원 소개 자료로 활용)
  • 교육과정 연계: 국어(토의·토론의 규칙과 예절), 도덕(민주적 의사 결정과 존중), 사회(공동체 문제 해결)와 함께 활용

[행정/연구] 방과후·돌봄 신청 안내 & 만족도 설문 - 종이 취합을 없애는 단일 파일 포털



종이 설문지를 은퇴시키는 신청·설문 폼 — 방과후·돌봄 포털 완전 정복

🏫 방과후학교 수강 신청과 학기말 만족도 조사를 단일 HTML 앱 하나로 전산화합니다. 모바일 최적화 반응형(responsive) 폼, 문항 상수 심기(심기 모드(데이터 임베딩)), 입력 즉시 누적, 공유 코드 전달, CSV 내보내기까지 — 제미나이 프롬프트 한 번으로 생성되고 더블클릭으로 바로 실행됩니다.

'배포'라는 단어는 정직하게 다룹니다 — 가정 접속을 위한 외부 호스팅(Vercel 등)은 git·CLI 단계가 필요한 관리자 확장이고, 학부모 응답이 외부에 저장되는 문제도 함께 생깁니다. 이 글의 기본 설계는 학내망 안에서 100% 완결되는 원칙 준수형입니다.

📖 한 줄 정의

심기 모드(데이터 임베딩): API 데이터를 미리 받아 HTML 파일 안 상수로 박아두는 방식(앱 실행 중 외부 통신 0).

학내망 원칙: 학교 배포 웹앱은 개인정보 수집·저장·전송 없음(외부 CDN·API 호출 0, 단일 파일) — 학생은 학내망에서 교사 PC 서버에 접속.

1. 3대 핵심 분석 비교표

무엇이 바뀌었나요? / 영역 초보자를 위한 쉬운 설명 이렇게 한번 써보세요!
운영 시나리오 신청 기간(수강 12과목)에는 학생이 학내망 단말에서 신청하고, 학기말에는 같은 파일을 설문 모드로 전환해 만족도를 수집합니다. 파일 하나가 두 무대를 번갈아 맡습니다. 주간 리듬표: 신청 3일 → 취합 1일 → 안내
반응형 폼 설계 휴대폰 360px부터 전자칠판까지 화면이 흐트러지지 않는 반응형(responsive) 폼. 필수 미응답 검사(유효성 검사(validation)), 진행바, Web Audio 안내음까지 내장. renderForm 함수로 문항을 자동 배치
두 가지 전달 방식 ① 교실 단말에서 직접 입력(즉시 누적) ② 기기별 작성 후 '공유 코드' 복사 → 교탁 화면 '코드 불러오기'로 누적 — 서버 없이 여러 기기의 응답을 모읍니다. shareCode 함수
운영 방식 정직 비교 학내망 배포(원칙 완전 준수 — 권장) / 구글 폼 등 학교가 검토·계약한 서비스(원격 접속 최단 — 학교 절차 따름) / Vercel·Netlify 등 외부 호스팅(git·CLI 단계가 필요한 관리자 확장 + 응답 데이터가 외부에 저장됨) / 종이 설문(원점). 어떤 방식이든 응답 데이터가 어디에 남는지부터 확인하는 것이 행정의 첫 절차입니다. 비교표를 학무 회의 자료로
원칙·정합 단일 HTML·외부 통신 0, 표기는 번호·닉네임·학급만(개인정보 최소), 설문 문항은 파일 상단 상수로 심기 — 학기마다 문항만 교체하는 갱신 루틴 포함. 응답 CSV는 로컬 파일로 저장. EMBED_SURVEY 상수

2. 핵심 아키텍처 해설

① 문항 상수: EMBED_SURVEY

const SURVEY = [
  { q: "가장 만족한 방과후 수업은?", type: "choice",
    options: ["체험", "독서", "스포츠", "코딩"] },
  { q: "또 듣고 싶은 수업을 한 줄로", type: "text" }
];

문항은 이 상수 하나로 관리됩니다 — 신청 모드와 설문 모드가 각자의 문항 세트를 읽습니다.

② 반응형 폼 렌더링

function renderForm() {
  const wrap = document.getElementById("form");
  SURVEY.forEach(function (s, i) {
    const label = document.createElement("label");
    label.textContent = (i + 1) + ". " + s.q;
    wrap.append(label);
    if (s.type === "choice") {
      s.options.forEach(function (o) {
        const b = document.createElement("button");
        b.textContent = o;
        b.className = "opt";
        b.addEventListener("click", function () { pick(i, o); });
        wrap.append(b);
      });
    } else {
      const t = document.createElement("textarea");
      t.addEventListener("change", function () { pick(i, t.value); });
      wrap.append(t);
    }
  });
}

③ 유효성 검사와 진행바

function validate() {
  return SURVEY.every(function (s, i) {
    return ANSWERS[i] !== undefined && ANSWERS[i] !== "";
  });
}
progress.style.width = answered() / SURVEY.length * 100 + "%";

미응답 문항이 있으면 제출 버튼이 조용히 막히지 않고, '2번 문항에 답해 주세요'처럼 친절하게 안내합니다.

④ 공유 코드 전달

function shareCode() {
  return ANSWERS.map(function (a, i) {
    return i + "~" + (a || "-");
  }).join("::");
}

기기별로 작성한 응답을 한 줄 텍스트 코드로 복사해, 교탁 화면의 '코드 불러오기'에 붙여넣으면 누적됩니다 — 서버 없이 여러 기기의 응답이 모입니다.

⑤ CSV 취합과 운영 루틴

function csvRow() {
  return [no, nick, klass].concat(ANSWERS).join(",");
}
// 'CSV 내보내기'로 로컬 파일 저장 — 자동 외부 전송 없음

운영 루틴은 세 단계 — 파일을 학급 공유 폼더에 두거나 USB로 배포 → 학생·방문자 단말에서 작성·공유 코드 전달 → 교탁 화면 누적 후 CSV 저장. 학급 시트로 옮기는 것은 교사의 수동 관리입니다.

3. 따라하기 3단계

  1. 제미나이 전용 에러 제로 프롬프트를 복사해 Gemini에 붙여넣습니다.
  2. AI가 던지는 역질문 3가지(문항 구성, 응답자 표기, 화면 톤)에 답하면 단일 HTML 코드가 완성됩니다.
  3. 코드를 portal.html로 저장 후 더블클릭 — 신청 모드와 설문 모드를 전환하며 사용합니다.

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

[🚨 에러 방지 기본 안전장치]
1. 결과물은 외부 라이브러리·폰트·이미지 없이 단일 HTML 파일로 완성한다 — 더블클릭 즉시 실행(서버·설치·회원가입·외부 클라우드·Next.js 빌드 금지).
2. 설문·신청 문항은 파일 상단 EMBED_SURVEY 상수로 심기(학내망 배포용 외부 통신 0) — 학기마다 문항만 교체하는 갱신 루틴(상수 출력 버튼) 포함.
3. 모바일 최적화 반응형: 뷰포트 메타 태그, 360px 가로 스크롤 금지, 터치 영역 44px 이상, 입력 필드 font-size 16px 이상.
4. 유효성 검사: 필수 미응답 시 진행하지 못하게 하고 친절한 한국어 안내를 보여준다. 진행바 표시.
5. 개인정보 최소화: 이름·연락처 칸 만들지 않기 — 표기는 번호·닉네임·학급만. 응답은 세션 메모리(새로고침 시 사라짐) 기본값.
6. '공유 코드' 복사·불러오기 버튼으로 기기별 응답을 교탁 화면에 누적하고, 'CSV 내보내기'로 로컬 파일 저장 — 자동 외부 전송 없음.
7. 사운드는 Web Audio API 합성(문항 완료 '똑', 제출 완료 '팡파르').
8. // TODO, /* 생략 */ 금지 — 끝까지 완성한다.

[❓ 역질문 유도]
코드를 바로 만들지 말고, 아래 3가지를 먼저 질문한 뒤 내 답변으로 설계를 확정한다.
Q1. 문항 구성은? (수강 신청 12과목 목록 / 만족도 5점 척도 / 자유 서술)
Q2. 응답자 표기는? (번호·닉네임·학급 기본)
Q3. 화면 톤은? (가정통신문 느낌 파스텔 / 학교 대표 색 토큰)

🎯 에디터 한줄평

'종이 인쇄·수기 취합'이 '버튼 누적'으로 바뀌는 것 — 행정 전산화의 출발점은 인쇄기가 아니라 문항 상수입니다. 이 글이 진짜 다른 점은 '배포'를 광고 문구처럼 다루지 않고 정직하게 짚었다는 것 — 어디에 데이터가 남는지를 먼저 묻는 습관이 학교 디지털 도구의 첫 안전벨트입니다. 원격 접속이 꼭 필요해지는 날에는, 학교가 검토·계약한 서비스를 연결하는 절차를 밟으면 됩니다.

📚 기술·교육 참고 링크

  • MDN — HTML 폼(Form) : 입력·선택·유효성 검사의 공식 학습 문서
  • 교육·행정 연계: 방과후학교·돌봄교실 운영 안내 자료는 학내망 공개 자료 기준으로 사용, 원격 접속이 필요한 설문은 학교가 검토·계약한 서비스 절차를 따름