관리자 인증 확인 중...
B 또는 Space 로 복귀
LUNA CODE LAB · CLASS II Week 10 — Firebase Firestore · 방명록 · 댓글 · 폼 고1 · 성인 / 120분
1 / 9 📄 워크시트
WEEK 10 · 2026 · CLASS II

사이트가
살아 움직인다

지금까지 사이트는 — 박물관 안의 액자 같았어요. 사람이 와서 보고 그냥 갑니다. 오늘부터 다릅니다. Firestore 붙이면 — 방명록·댓글·문의 폼이 실시간으로 작동. 누가 글 남기면 즉시 사이트에 나타납니다.

Duration120 minutes
ToolFirebase Firestore
Output작동하는 방명록 페이지
Phase인터랙티브 (1/2)
02 / Learning Goals⏱ 5분

오늘의 학습 목표

1
Firestore 기본 개념
Collection · Document · Field — NoSQL의 3가지 구성. 폴더-파일-속성 비유로 직관 잡기.
2
데이터 모델 설계
방명록 컬렉션: name·message·createdAt 필드 3개. 단순해야 강하다.
3
실시간 표시
onSnapshot 한 줄로 새 글 즉시 화면에 등장. 새로고침 불필요.
4
보안 규칙
누구나 read·create OK / 삭제는 본인 또는 관리자만. firestore.rules 4줄.
03 / Concept⏱ 10분

정적 사이트 → 인터랙티브

지금까지 사이트는 HTML 파일에 박힌 글자. 누구한테도 똑같음. 데이터베이스가 붙는 순간 — 사이트가 '살아있는 공간'이 됩니다. 어제 친구가 쓴 글이 오늘 내가 새로고침할 때 떠 있어요. 그게 SNS·블로그·쇼핑몰의 본질.

📄
정적 사이트
HTML에 박힌 글자
모든 방문자 동일 화면
+
🗄
Firestore
실시간 NoSQL DB
JSON처럼 저장
=
💬
인터랙티브
방문자 → 글 입력
모두에게 실시간 표시
Firestore의 핵심 강점 = "실시간 동기화". 한 사람이 글을 쓰면 — 같은 페이지를 보고 있는 100명에게 0.5초 안에 자동으로 나타납니다. 새로고침 버튼 누를 필요 없음. 이게 옛날 PHP·MySQL과의 결정적 차이.
04 / Prompt Pattern⏱ 10분

DB 요청 — 막연 vs 정확

❌ 막연한 요청
"내 사이트에
DB 좀 만들어줘."
왜 안 되나? AI가 추측으로 SQL·MongoDB·Firestore 중 아무거나 골라서 만들어줌. 컬렉션 이름·필드 다 자기 마음대로. 나중에 못 고침.
✓ 컬렉션·필드 명시
DB: Firestore
컬렉션: guestbook
필드:
 · name (string, 50자 이하)
 · message (string, 500자 이하)
 · createdAt (timestamp, 자동)
정렬: createdAt 내림차순
규칙: 누구나 read·create, delete X
왜 좋나? AI가 정확히 그대로 만듦. 데이터 모델 직접 그려본 학생만 나중에 수정도 가능. "이름·메시지·시간" 단 3개로 충분.
💡 오늘의 비법: DB는 컬렉션 이름 · 필드 목록 · 보안 규칙 3가지를 글로 적은 후 Claude에 던지기. 머릿속에 그림이 안 그려지면 한 글자도 코딩 X.
05 / Live Build · Step 1⏱ 10분

Step 1 — Firestore 활성화

Firebase Console에서 클릭 3번. "Firestore Database" → "데이터베이스 만들기" → 리전 선택(asia-northeast3 = 서울). 코드 한 줄 없이 클라우드 DB 한 개 탄생.

1
Console UI 작업 — 함께 따라하기
// 브라우저 작업 (코드 X) 1. console.firebase.google.com 접속 2. 내 프로젝트 선택 (W3에서 만든 것) 3. 좌측 메뉴 → "Firestore Database" 4. "데이터베이스 만들기" 클릭 5. 모드: "테스트 모드로 시작" (30일간 모든 접근 허용) 6. 리전: asia-northeast3 (서울) 선택 ⚠️ 한 번 정하면 변경 불가 7. "사용 설정" → 1분 대기 → 완료 // 첫 컬렉션 만들기 (UI에서) 8. "컬렉션 시작" 클릭 9. 컬렉션 ID: guestbook 입력 10. 첫 문서 추가 (테스트용): · 필드 name(string) = "관리자" · 필드 message(string) = "첫 방문 환영합니다!" · 필드 createdAt(timestamp) = 지금 11. 저장 → 컬렉션 생성 완료 ✓
🎙
멘토 멘트 "DB라고 하면 SQL 외워야 할 것 같죠? Firestore는 UI 클릭만으로도 데이터 생성·수정·삭제 다 됩니다. 진짜 엑셀 다루는 느낌. 코드 없이 손으로 한번 만져봐야 감이 와요."
🗄
학생 액션 (7분) Firebase Console 들어가서 위 11단계 따라하기 → guestbook 컬렉션에 견본 문서 1개 박힘 → 옆 짝과 화면 비교하며 확인.
05 / Live Build · Step 2⏱ 15분

Step 2 — SDK 연결 + 첫 쓰기

사이트에서 Firestore에 접근하려면 — SDK 두 줄 + config 한 덩어리. 그 후 addDoc() 한 줄로 데이터 쓰기 가능.

2
guestbook.html <head>에 SDK 추가
// Firebase compat SDK (전통 방식, 학습용 추천) <script src="https://www.gstatic.com/firebasejs/10.7.1/firebase-app-compat.js"></script> <script src="https://www.gstatic.com/firebasejs/10.7.1/firebase-firestore-compat.js"></script> // firebase-config.js (W3에서 받은 그대로) <script> const firebaseConfig = { apiKey: "AIzaSy...", projectId: "my-site-2026", ... }; firebase.initializeApp(firebaseConfig); const db = firebase.firestore(); </script>
💡
콘솔 테스트 — 첫 쓰기
// 브라우저 DevTools 콘솔(F12)에 붙여넣기 db.collection('guestbook').add({ name: '테스트', message: '콘솔에서 직접 추가!', createdAt: firebase.firestore.FieldValue.serverTimestamp() }).then(docRef => { console.log('추가됨!', docRef.id); }); // 즉시 Firebase Console 가서 guestbook 컬렉션 새로고침 → 방금 추가한 문서가 보이면 SDK 연결 성공 ✓
🎙
멘토 멘트 "코드 5줄로 클라우드 DB에 데이터가 들어가는 이 순간 — 12개월 전엔 서버 셋업·인증·라이브러리 설치만 2시간 걸리던 거예요. Firebase가 그걸 5분으로 줄여놨어요."
학생 액션 (12분) guestbook.html 만들고 SDK 두 줄 + config 박기 → F12 콘솔에 위 add() 코드 실행 → Firebase Console에서 문서 늘어난 것 확인.
05 / Live Build · Step 3⏱ 15분

Step 3 — 방명록 폼 만들기

콘솔이 아니라 — 일반 방문자가 쓰는 폼. 입력 칸 2개(이름·메시지) + 보내기 버튼. 클릭하면 Firestore에 즉시 저장.

3
guestbook.html 본문 + JS
// HTML <form id="gbForm"> <input name="name" placeholder="이름" maxlength="30" required> <textarea name="message" placeholder="한 줄 남기기" maxlength="300" required></textarea> <button type="submit">방명록 남기기</button> </form> <ul id="gbList"></ul> // JS — 폼 제출 처리 document.getElementById('gbForm').addEventListener('submit', async (e) => { e.preventDefault(); const fd = new FormData(e.target); await db.collection('guestbook').add({ name: fd.get('name').trim(), message: fd.get('message').trim(), createdAt: firebase.firestore.FieldValue.serverTimestamp() }); e.target.reset(); });
🎙
멘토 강조 "required · maxlength · trim() — 이 3가지가 빠지면 빈 줄 도배·이상한 입력으로 DB 망가져요. 클라이언트 검증은 신뢰 X지만, 90%의 실수는 막아줘요."
📝
학생 액션 (12분) 폼 HTML + JS 위 코드 그대로 박기 → 브라우저에서 이름·메시지 입력 → "남기기" 클릭 → Firebase Console 가서 새 문서 추가됐는지 확인.
05 / Live Build · Step 4⏱ 15분

Step 4 — 실시간 표시 (onSnapshot)

DB에 저장된 글 — 사이트에 자동으로 표시. onSnapshot()이 핵심. 누군가 새 글 쓰면 0.5초 안에 모든 사용자 화면에 등장.

4
실시간 구독 + 정렬
// guestbook.html <script> 추가 const listEl = document.getElementById('gbList'); db.collection('guestbook') .orderBy('createdAt', 'desc') // 최신순 .limit(50) // 최근 50개만 .onSnapshot((snap) => { listEl.innerHTML = ''; snap.forEach(doc => { const d = doc.data(); const time = d.createdAt?.toDate().toLocaleString('ko-KR') || '방금'; listEl.insertAdjacentHTML('beforeend', `<li><strong>${escapeHtml(d.name)}</strong> <p>${escapeHtml(d.message)}</p> <time>${time}</time></li>`); }); }); // XSS 방지 — 사용자 입력은 항상 이스케이프 필수! function escapeHtml(s) { return s.replace(/[<>&"]/g, c => ({'<':'&lt;','>':'&gt;','&':'&amp;','"':'&quot;'}[c])); }
💡
실시간 효과 — 짝과 함께 테스트
// 멘토 시연: 두 브라우저 창 동시에 열기 1. 본인 노트북 → guestbook.html 열기 2. 옆 짝 노트북 → 같은 URL 열기 (배포된 사이트면 더 좋음) 3. 짝이 "안녕!" 글 남김 4. 본인 화면이 자동으로 새 글 추가 — 새로고침 X 5. 본인이 글 남김 → 짝 화면에 즉시 등장 ✓ // 이게 실시간 동기화의 마법
🎙
멘토 멘트 "Firestore의 onSnapshot은 — 옛날에 WebSocket·polling·서버 동기화 코드를 직접 짜야 했던 걸 1줄로 압축한 거예요. 카톡·인스타·디스코드 다 이 원리. 실시간 SNS의 핵심을 5분 안에 손에 넣음."
학생 액션 (12분) onSnapshot 코드 박기 → 같은 페이지를 짝과 동시에 열기 → 글 주고받기 → 새로고침 없이 자동 갱신 확인. 안 되면 orderBy 인덱스 에러 확인.
05 / Live Build · Step 5⏱ 10분

Step 5 — 보안 규칙 (firestore.rules)

"테스트 모드"는 30일 후 자동 차단. 그 전에 보안 규칙 작성. "누구나 read·create, 삭제는 관리자만" — 4줄로 끝.

5
Firebase Console → Firestore → 규칙 탭
// firestore.rules rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { // 방명록 — 누구나 읽고 쓰기 OK, 삭제 X match /guestbook/{docId} { allow read, create: if true; allow update, delete: if request.auth.token.email == 'admin@example.com'; } // 그 외 모든 컬렉션 — 기본 차단 match /{document=**} { allow read, write: if false; } } } // 게시 → 1분 대기 → 즉시 적용
🛡
보안 검증 — 일부러 깨보기
// DevTools 콘솔에서 시도 1. 읽기 시도: db.collection('guestbook').get() → ✓ OK 2. 쓰기 시도: db.collection('guestbook').add({...}) → ✓ OK 3. 삭제 시도: db.collection('guestbook').doc('xxx').delete() → ❌ FirebaseError: Missing or insufficient permissions // 4번이 차단되면 보안 규칙 정상 작동
🎙
왜 보안이 중요한가 "테스트 모드로 30일 두면 — 한국 어디선가 봇이 발견하고 욕설·광고 1만 건 박아넣어요. 실제 사고 자주 일어나요. 오늘 규칙 안 박으면 다음 주 사이트 망가집니다."
🔒
학생 액션 (8분) Firebase Console → Firestore → 규칙 탭 → 위 코드 붙여넣기 → 본인 이메일로 admin 부분 교체 → 게시 → DevTools에서 삭제 시도해서 차단 확인.
10 / Checkpoint⏱ 5분

DB 점검 6가지

오늘 잘 됐다면
  • Firestore 활성화 완료 + asia-northeast3 리전
  • guestbook 컬렉션 생성 + 견본 문서 1개
  • 방명록 폼 입력 → DB에 저장 작동
  • onSnapshot 실시간 표시 — 짝과 함께 검증
  • 보안 규칙 게시 + 삭제 시도 차단 확인
  • XSS 이스케이프 — escapeHtml 적용
⚠️자주 막히는 부분
  • "Missing or insufficient permissions" → 보안 규칙 너무 엄격 / "테스트 모드" 만료
  • orderBy + where 동시 사용 시 인덱스 에러 → 에러 메시지 안의 링크 클릭하면 자동 생성
  • 실시간 표시 안 됨onSnapshot 콜백이 호출되는지 console.log로 확인
  • 같은 글 두 번 등장 → innerHTML을 비우기 전에 추가했을 가능성
  • createdAt이 null → 서버 timestamp는 한 박자 늦게 도착, 첫 화면엔 "방금"으로 표시
  • script 태그가 본문에 그대로 노출 → escapeHtml 빠짐 (XSS 위험!)
11 / Challenge⏱ 10분

DB 깊이 도전

❤️
좋아요 카운터 — 각 방명록 카드에 하트 버튼. 클릭마다 likes 필드 +1. FieldValue.increment(1) 사용.
난이도 ★
👤
익명 인증 — Firebase Authentication 익명 로그인. 글마다 자동 uid 저장, 본인 글만 삭제 가능하게 규칙 수정.
난이도 ★★
🛠
관리자 모드 — 댓글 삭제 — admin@example.com으로 로그인 시 각 글 우측에 "삭제" 버튼 노출. 비관리자에겐 숨김.
난이도 ★★★
12 / Student Gallery⏱ 5분

작년 친구들 방명록 페이지

13 / Next Week⏱ 5분

다음 시간 예고

WEEK 11 · COMING UP

SEO + Analytics —
구글이 내 사이트를 찾게

사이트 다 만들었는데 — 방문자 0명이면 빈 가게. W11에선 SEO(검색 최적화) + Google Analytics(방문자 추적) 적용. 구글이 내 사이트를 찾아서 보여주고, 누가 언제 어디서 들어왔는지 통계도 볼 수 있게.

PREPARE · 다음 주 준비물
  • 오늘 완성한 방명록 페이지 (배포된 URL)
  • 구글 계정 — Search Console·Analytics용
  • "내 사이트 구글에서 검색했을 때 떴으면 좋겠는 키워드" 3-5개
  • 사이트 메타: 제목·설명·키워드 한 줄씩 준비 (W9 OG와 통합)
  • W11 끝나면 → 구글에서 내 이름·작품명 검색 시 사이트 노출 가능!