★에듀테크 인공지능 수업/인공지능 활용 수업

디지털스탬프 구글AI스튜디오와 깃허브를 이용하여 제작하기

SNACK SCIENCE 2025. 6. 22. 00:10

인트로

디지털 스탬프 챌린지에 오신 것을 환영합니다!
이 페이지에서는 구글 AI Studio와 깃허브를 활용해 누구나 쉽게 따라할 수 있는 디지털 스탬프 시스템 제작 방법을 안내합니다. 부스별로 스탬프를 모으고, 나만의 진행 상황을 저장하며, 재미있게 체험할 수 있는 과정을 지금 바로 시작해보세요.
생년월일로 로그인하고, 각 부스의 비밀번호를 입력해 스탬프를 획득하는 특별한 경험을 만나보실 수 있습니다.
지금부터 단계별 안내를 따라, 나만의 디지털 스탬프 챌린지를 완성해보세요!

 

이 글을 읽으면 다음을 할 수 있습니다

  • 구글 AI Studio와 깃허브를 활용한 디지털 스탬프 챌린지 시스템을 직접 만들어볼 수 있습니다.
  • 부스별로 스탬프를 수집하고, 나만의 진행 상황을 저장하는 방법을 익힐 수 있습니다.
  • 생년월일로 로그인하고, 각 부스의 비밀번호를 입력해 스탬프를 획득하는 과정을 따라할 수 있습니다.
  • 단계별 안내를 통해 디지털 스탬프 챌린지를 쉽고 재미있게 체험할 수 있습니다.

 

따라하기

1. 구글 AI Studio에 접속합니다.

 

2. 다음과 같이 프롬프트를 입력합니다.

디지털스탬프 만들고 싶어총 6개 스템프
스템프 안에 부스1, 부스2, 부스3, 부스4, 부스5, 부스6 써주고
스탬프는 아무나 클릭 못하고 비밀번호를 누르면 클릭할 수 있도록

비밀번호
부스1 0702
부스2 0703
부스3 0704
부스4 0705
부스5 0706
부스6 0707

배경은 밝고 재미있게 만들어줘.
웹사이트로 다른 선생님들 접근 쉽게

처음에 로그인할 때 생년월일을 입력하여 로그인할 수 있도록 해주고
도장 찍은 것을 저장 버튼을 눌러 저장할 수 있도록 해주고, 
초기화, 로그아웃 버튼도 제작해줘.
생년월일로 로그인하고 -> 스탬프를 클릭하면 -> 비밀번호를 물어보고 -> 맞으면 도장이 찍히는
구조야.

 

2. AI가 생성한 코드를 입력합니다.

<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>디지털 스탬프 챌린지! (Ver 4.1 - 최종 수정본)</title> <style> /* 기본 폰트 및 배경 설정 */ body { font-family: 'Pretendard', 'Malgun Gothic', sans-serif; margin: 0; padding: 20px; background: linear-gradient(135deg, #f5f7fa, #c3cfe2); display: flex; justify-content: center; align-items: center; min-height: 100vh; } .container { background-color: white; padding: 30px 40px; border-radius: 20px; box-shadow: 0 15px 30px rgba(0, 0, 0, 0.1); text-align: center; max-width: 800px; width: 90%; transition: all 0.5s ease-in-out; } h1 { color: #1a2c4e; font-size: 2.2em; margin-bottom: 15px; } p { color: #555; font-size: 1.1em; margin-bottom: 30px; line-height: 1.6; } /* 로그인 영역 */ #auth-container { /* 기본적으로 보임 */ } /* 메인 콘텐츠 영역 (초기에는 숨김) */ #main-container { display: none; } /* 입력 필드 및 버튼 스타일 */ .input-area { margin-bottom: 20px; display: flex; justify-content: center; gap: 10px; } .input-field { padding: 12px 15px; font-size: 1.2em; border-radius: 8px; border: 2px solid #ddd; width: 220px; text-align: center; transition: border-color 0.3s; } .input-field:focus { outline: none; border-color: #6a82fb; } .primary-button { padding: 12px 25px; font-size: 1.2em; font-weight: bold; color: white; background-image: linear-gradient(to right, #6a82fb 0%, #fc5c7d 100%); border: none; border-radius: 8px; cursor: pointer; transition: transform 0.2s; } .primary-button:hover { transform: scale(1.05); } /* 스탬프 보드 (데스크탑: 3열, 모바일: 2열) */ .stamp-board { display: grid; grid-template-columns: repeat(3, 1fr); gap: 25px; margin-bottom: 40px; } /* 개별 스탬프 */ .stamp { aspect-ratio: 1 / 1; border: 5px dashed #ccc; border-radius: 50%; display: flex; justify-content: center; align-items: center; cursor: pointer; transition: all 0.4s ease; background-color: #f0f0f0; color: #aaa; font-size: 1.6em; /* 부스 이름이 짧아져서 폰트를 조금 키움 */ font-weight: bold; padding: 10px; word-break: keep-all; } /* 획득한 스탬프 */ .stamp.stamped { border-style: solid; transform: rotate(-8deg) scale(1.05); } /* 하단 버튼 영역 */ .action-buttons { display: flex; flex-wrap: wrap; /* 모바일에서 버튼이 줄바꿈 되도록 */ justify-content: center; gap: 15px; } .action-button { padding: 10px 20px; font-size: 1em; font-weight: bold; border-radius: 8px; border: 2px solid; cursor: pointer; background-color: white; transition: all 0.3s; } #save-button { color: #27ae60; border-color: #27ae60; } #save-button:hover { background-color: #27ae60; color: white; } #reset-button { color: #e74c3c; border-color: #e74c3c; } #reset-button:hover { background-color: #e74c3c; color: white; } #logout-button { color: #8e44ad; border-color: #8e44ad; } #logout-button:hover { background-color: #8e44ad; color: white; } /* 축하 메시지 */ #congrats-message { display: none; margin-top: 40px; font-size: 1.8em; font-weight: bold; color: #fc5c7d; } /* 모바일 반응형 (화면 너비 600px 이하) */ @media (max-width: 600px) { .container { padding: 20px; } h1 { font-size: 1.8em; } .stamp-board { grid-template-columns: repeat(2, 1fr); /* 2열로 변경 */ } .stamp { font-size: 1.4em; } } </style> </head> <body> <div class="container"> <!-- 1. 로그인 영역 --> <div id="auth-container"> <h1>✨ 디지털 스탬프 챌린지! ✨</h1> <p>본인 확인을 위해 생년월일 6자리를 입력해주세요.<br>(예: 900101)</p> <div class="input-area"> <input type="password" id="birthdate-input" class="input-field" placeholder="생년월일 6자리" maxlength="6" pattern="[0-9]*"> <button id="login-button" class="primary-button">확인</button> </div> </div> <!-- 2. 메인 콘텐츠 영역 (로그인 후 보임) --> <div id="main-container"> <h1>나의 스탬프 현황</h1> <p>스탬프를 클릭하고 비밀번호를 입력하여 도장을 모아보세요!</p> <div class="stamp-board"> <!-- 스탬프가 동적으로 생성될 공간 --> </div> <div class="action-buttons"> <button id="save-button" class="action-button">💾 진행 상황 저장하기</button> <button id="reset-button" class="action-button">🔄 처음부터 다시하기</button> <button id="logout-button" class="action-button">🚪 로그아웃</button> </div> <h2 id="congrats-message">🎉 모든 스탬프를 모았습니다! 정말 대단해요! 🎉</h2> </div> </div> <script> // --- 요소 선택 --- const authContainer = document.getElementById('auth-container'); const mainContainer = document.getElementById('main-container'); const birthdateInput = document.getElementById('birthdate-input'); const loginButton = document.getElementById('login-button'); const logoutButton = document.getElementById('logout-button'); const stampBoard = document.querySelector('.stamp-board'); const saveButton = document.getElementById('save-button'); const resetButton = document.getElementById('reset-button'); const congratsMessage = document.getElementById('congrats-message'); // --- 데이터 및 상태 변수 (이름이 '부스'로 변경되었습니다) --- const stampData = [ { id: 'booth1', name: '부스1', password: '0702', color: { border: '#4a90e2', bg: '#d4e6ff', text: '#00408b' } }, { id: 'booth2', name: '부스2', password: '0703', color: { border: '#50e3c2', bg: '#d7fff7', text: '#00695c' } }, { id: 'booth3', name: '부스3', password: '0704', color: { border: '#bd10e0', bg: '#f2d1f7', text: '#6a0080' } }, { id: 'booth4', name: '부스4', password: '0705', color: { border: '#f5a623', bg: '#fff0d5', text: '#8c5d00' } }, { id: 'booth5', name: '부스5', password: '0706', color: { border: '#7ed321', bg: '#e9ffd1', text: '#387002' } }, { id: 'booth6', name: '부스6', password: '0707', color: { border: '#e55039', bg: '#ffddd8', text: '#8d230f' } }, ]; let stampedIds = new Set(); let currentUserKey = null; // --- 함수 정의 (이하 코드는 변경 없음) --- function renderStamps() { stampBoard.innerHTML = ''; stampData.forEach(data => { const stampElement = document.createElement('div'); stampElement.className = 'stamp'; stampElement.dataset.id = data.id; stampElement.innerHTML = data.name; if (stampedIds.has(data.id)) { stampElement.classList.add('stamped'); stampElement.style.borderColor = data.color.border; stampElement.style.backgroundColor = data.color.bg; stampElement.style.color = data.color.text; } stampBoard.appendChild(stampElement); }); checkAllStamped(); } function checkAllStamped() { congratsMessage.style.display = (stampedIds.size === stampData.length) ? 'block' : 'none'; } function handleLogin() { const birthdate = birthdateInput.value; if (birthdate.length !== 6 || !/^\d{6}$/.test(birthdate)) { alert('생년월일 6자리를 숫자로 정확히 입력해주세요.'); return; } currentUserKey = `stamp-progress-${birthdate}`; authContainer.style.display = 'none'; mainContainer.style.display = 'block'; loadProgress(); } function handleLogout() { if (confirm('로그아웃 하시겠습니까?')) { currentUserKey = null; stampedIds.clear(); birthdateInput.value = ''; mainContainer.style.display = 'none'; authContainer.style.display = 'block'; } } function handleStampClick(event) { const clickedStamp = event.target.closest('.stamp'); if (!clickedStamp) return; const stampId = clickedStamp.dataset.id; if (stampedIds.has(stampId)) { alert('이미 획득한 스탬프입니다.'); return; } const matchedStamp = stampData.find(s => s.id === stampId); if (!matchedStamp) return; const userInput = prompt(`'${matchedStamp.name}' 스탬프의 비밀번호를 입력하세요:`); if (userInput === null) { return; } if (userInput.trim() === matchedStamp.password) { alert('정답입니다! 스탬프를 획득했습니다! 쾅!'); stampedIds.add(stampId); renderStamps(); } else { alert('비밀번호가 틀렸습니다. 다시 시도해주세요.'); } } function saveProgress() { if (!currentUserKey) return; localStorage.setItem(currentUserKey, JSON.stringify(Array.from(stampedIds))); alert('현재 진행 상황이 이 브라우저에 저장되었습니다!'); } function loadProgress() { if (!currentUserKey) return; const savedData = localStorage.getItem(currentUserKey); stampedIds = savedData ? new Set(JSON.parse(savedData)) : new Set(); renderStamps(); } function resetProgress() { if (!currentUserKey) return; if (confirm('정말 모든 스탬프를 초기화하시겠습니까? 저장된 기록이 사라집니다.')) { stampedIds.clear(); localStorage.removeItem(currentUserKey); renderStamps(); alert('초기화되었습니다.'); } } // --- 이벤트 리스너 연결 --- loginButton.addEventListener('click', handleLogin); birthdateInput.addEventListener('keyup', e => e.key === 'Enter' && handleLogin()); logoutButton.addEventListener('click', handleLogout); stampBoard.addEventListener('click', handleStampClick); saveButton.addEventListener('click', saveProgress); resetButton.addEventListener('click', resetProgress); </script> </body> </html>

index.html
0.01MB

 

4. 위 코드를 복사하여 메모장에 붙여 넣습니다.

 

5. 파일 - 다른 이름으로 저장을 클릭합니다. 이 때 중요한 것은 index.html로 파일명을 저장해야합니다.

 

6. 깃허브에 접속하여 로그인합니다.

 

7. New repository를 클릭합니다.

 

8. Repository name을 입력하고, Public을 선택합니다.

 

9. Create repository를 클릭합니다.

 

10. Create a codesapce를 클릭합니다.

 

11. Create new codespace를 클릭합니다.

아래와 같은 화면이 보입니다.

 

12. 뒤로 가기를 클릭하면 다음과 같은 화면이 보입니다.

 

13. Add file에서 Upload files를 클릭합니다.

 

14. index.html 파일을 끌어다 놓습니다.  Commit change를 클릭합니다.

 

15. index 파일이 업로드된 모습입니다.

 

16. Settings - Pages를 순서대로 클릭합니다.

 

17. Branch에서 main을 선택하고 save를 클릭합니다.

 

18. 새로고침을 하면 생성된 주소를 확인할 수 있습니다.

 

최종 결과물

https://jinyeonja.github.io/booth/

 

디지털 스탬프 챌린지! (Ver 4.1 - 최종 수정본)

나의 스탬프 현황 스탬프를 클릭하고 비밀번호를 입력하여 도장을 모아보세요! 💾 진행 상황 저장하기 🔄 처음부터 다시하기 🚪 로그아웃 🎉 모든 스탬프를 모았습니다! 정말 대단해요! 🎉

jinyeonja.github.io

 

 

아웃트로

지금까지 구글 AI Studio와 깃허브를 활용해 디지털 스탬프 챌린지 시스템을 만드는 과정을 함께 살펴보았습니다.
직접 따라하며 부스별 스탬프를 수집하고, 나만의 진행 상황을 저장하는 경험을 통해 디지털 도장 시스템의 원리를 쉽게 이해할 수 있었길 바랍니다.
궁금한 점이나 추가로 시도해보고 싶은 내용이 있다면 언제든 댓글로 남겨주세요.
여러분만의 창의적인 스탬프 챌린지를 만들어보며, 즐거운 체험이 되시길 바랍니다! 감사합니다.

반응형