2026년 9월 6일 일요일

[학급 경영] 학급 3D 가상 갤러리 - 친구 작품을 한 곳에 남기다



우리 반은 하루에도 몇 번이라도 갤러리가 됩니다 — 학급 3D 가상 전시관·작품 갤러리 완전 정복

🎨 미술 시간에 그린 그림과 조형물 사진이 사라지는 벽면이 아닌, 회전 가능한 3D 가상 갤러리 벽면에 1년 내내 걸립니다. 학생들은 화면 좌우로 갤러리를 돌아다니며 친구 작품에 감상평 노트를 붙입니다. 이름 없는 감상이 모이면 전시가 완성됩니다.

외부 3D 엔진 없이도 순수 캔버스 원근 투영으로 벽면 투어(tour)를 구현하고, 모든 작품 이미지는 Base64(베이스64) 텍스트로 파일 안에 심는 심기 모드(데이터 임베딩)로 외부 통신을 완전히 차단합니다.

📖 한 줄 정의

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

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

1. 3대 핵심 분석 비교표

무엇이 바뀌었나요? / 영역 초보자를 위한 쉬운 설명 이렇게 한번 써보세요!
3D 투어 원근 회전 좌우 화살표 키나 화면 좌우 드래그로 가상 전시관의 벽면을 걸어 다니는 체험. 3D 엔진 설치 없이 원근 투영 수식으로 완성됩니다. 전시관 좌우 스크롤 투어.
작품 이미지 심기 학생이 그린 작품 사진을 Base64 텍스트로 파일 안에 심는 심기 모드(데이터 임베딩) — 외부 서버 없이, 학내망 완결 안정 운영. 작품 사진 파일 심기 루틴.
익명 감상평 노트 학생이 붙이는 감상평은 이름 없이 칭찬 문구로 남기는 설계 — 다른 학생의 성명을 입력·저장하지 않아 개인정보 0 원칙을 지킵니다. 감상평 노트 붙이기.

2. 핵심 아키텍처 해설

① 작품 데이터 심기 (Base64 상수)

const ARTWORKS = [
  { title: "가을 산책로", artistNick: "3모둠-코알라", b64: "iVBORw0KGgo..." },
  { title: "우리 학교 벚꽃", artistNick: "5모둠-돌고래", b64: "iVBORw0KGgo..." }
];

실제 작품 이미지는 파일 안에 문자열로 심어져 있으므로 외부 이미지 링크가 아예 없습니다. 학생 개인 실명이 아닌 artistNick(닉네임)만 사용됩니다.

② 원근 투영 3D 벽면 투어

let tour = 0;   // 현재 보고 있는 벽면 위치 (0~1)

function renderTour() {
  const wall = document.getElementById("wall");
  wall.style.transform = "perspective(700px) rotateY(" + (tour * 60) + "deg)";
}
document.addEventListener("keydown", function (e) {
  if (e.key === "ArrowRight") tour = Math.min(tour + 0.02, 1);
  if (e.key === "ArrowLeft") tour = Math.max(tour - 0.02, 0);
  renderTour();
});

CSS 원근 변환으로 3D 벽면 회전을 구현하는 가장 가벼운 방법입니다. 웹 캔버스 렌더링 루프도 불필요해서 크롬북에서 매우 빠르게 돌아갑니다.

③ 감상평 노트 붙이기 (세션 메모리)

const NOTES = [];

function postNote(artId, text) {
  NOTES.push({ artId: artId, text: text, at: Date.now() });
  sound("pin");
  renderNotes(artId);
}

감상평은 누구의 것인지 저장하지 않고 순수 세션 메모리에만 존재합니다 — 종료하면 사라지는 존중의 안전망 설계.

④ Web Audio API 벽면 투어 효과음

function sound(kind) {
  const ctx = new (window.AudioContext || window.webkitAudioContext)();
  const osc = ctx.createOscillator();
  osc.type = kind === "pin" ? "triangle" : "square";
  osc.frequency.value = kind === "pin" ? 660 : 220;
  const gain = ctx.createGain();
  gain.gain.value = 0.1;
  osc.connect(gain); gain.connect(ctx.destination);
  osc.start(); osc.stop(ctx.currentTime + 0.08);
}

⑤ 원칙·정합

단일 HTML 파일 완결. 외부 CDN·API·이미지 URL 완전 금지. 학생 실명·성별·얼굴 사진 금지, 표기는 모둠 번호와 닉네임만. 감상평은 세션 메모리(종료 시 소멸)로 관리되며 CSV 내보내기는 옵션(학급 자치 임원용)입니다.

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

  1. 프롬프트 복사 — 아래 '제미나이 전용 에러 제로 프롬프트' 전체를 복사해 Gemini에 붙여넣습니다.
  2. 역질문 답변 — Gemini의 질문 3가지(작품 데이터 구조, 투어 화면 톤, 감상평 초기 문구)에 답하면 단일 파일 코드가 확정됩니다.
  3. HTML 파일 실행 — 완성 코드를 '우리반갤러리.html'로 저장 후 더블클릭하면 곧바로 3D 벽면 투어가 시작됩니다.

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

[🚨 에러 방지 기본 안전장치]
1. 결과물은 Three.js 등 외부 라이브러리, 폰트, CDN, 외부 이미지 URL 없이 순수 바닐라 JS와 HTML5 Canvas/CSS 3D로만 단일 HTML 파일로 완성한다.
2. 파일 상단 ARTWORKS 상수에 학생 작품 데이터를 심어두고(심기 모드 — 데이터 임베딩), 실제 이미지는 Base64(베이스64) 텍스트로 파일 안에 심는다 (외부 URL 금지).
3. 작품은 최소 8개 이상 예시로 심고, 좌우 화살표 키와 터치 드래그로 벽면을 걸어 다니는 투어(tour)를 구현한다.
4. 감상평 노트 기능: 각 작품 카드에 클릭하여 짧은 칭찬 메모를 붙일 수 있게 하되, 붙이는 사람의 실명은 절대 저장하지 않고(개인정보 0), 세션 메모리에만 보관한다.
5. 사운드는 Web Audio API로 오실레이터를 합성하여 감상평 붙이기 '톡' 소리와 벽면 이동 '워우웅' 소리를 출력한다 (오디오 파일 금지).
6. 모바일 및 태블릿 터치 드래그 투어 완벽 지원 (Pointer Events 적용, 가로 스크롤 방지).
7. 학생 실명·얼굴 사진·성별은 일절 저장하지 않는다.
8. // TODO, /* 생략 */ 같은 미완성 코드는 절대 넣지 말고 끝까지 완성한다.

[❓ 역질문 유도]
코드를 바로 만들지 말고, 아래 3가지를 먼저 나에게 질문한 뒤 내 답변으로 설계를 확정한다.
Q1. 작품 카드 레이아웃은 어떻게 할까요? (좌우 벽면 정렬 / 그리드 배열)
Q2. 감상평 노트의 색과 모양은? (포스트잇 노랑 / 봉투 느낌)
Q3. 작품 심기 갱신 담당은? (미술 담당 교사 직접 / 학급 자치 임원)

🎯 에디터 한줄평

벽면 공간이 좁다고 눈물 삼키던 학급 미술 전시가 하나의 3D 가상 공간에서 매년 두꺼워집니다. 익명 감상평 노트가 훈육이 아니라 경험의 전시로 만들어준다는 점이 놀라웠습니다. Base64 이미지 심기 모드로 학내망 원칙까지 깔끔하게 지키는 정통 에듀테크 글입니다.

📚 기술·교육 참고 링크

  • MDN — Window.localStorage : 세션 메모리 외에 학기 전체 유지가 필요할 때 활용 가능한 로컬 저장소
  • 교육과정 연계: 초등 미술 '재미있는 재료로 나타내기', 창의적 체험활동(미술 동아리)과 직접 연계