on
[Clone Coding] 6. Firebase와 Javascript로 To do list 만들기
[Clone Coding] 6. Firebase와 Javascript로 To do list 만들기
PROJECT
바닐라 JS를 이용한 Chrome 앱 Momentum 클론 코딩
Github: https://github.com/chchaeun/Momentum-clone
Momentum
들어가기
이전에 이 프로젝트를 진행했을 때는 localStorage를 사용해서 To do list를 구현했는데, 단국대부속소프트웨어고등학교 자율동아리 친구들의 수업을 준비하면서, 이 프로젝트를 통해 Firebase를 사용해보면 좋은 경험이 될 것 같아서 리팩토링 해보았다.
Firebase의 firestore에 To do list를 저장하고, javascript를 통해 웹과 연동하여 불러온다.
Firebase와 Javascript 연동
바닐라 js에서 firebase를 사용하려면 script에 주소를 추가해주어야 한다. require 등 다양한 방법을 써봤지만 버전 문제 때문에 제대로 작동하지 않았다.
todo.js 파일을 만들어 index.html과 연결하고 다음과 같이 프로젝트를 불러왔다. firebase에서 프로젝트를 생성하고 config를 가져오는 부분은 생략했다.
const firebaseConfig = { apiKey: "apiKey", authDomain: "authDomain", projectId: "momentum-todo", storageBucket: "storageBucket", messagingSenderId: "messagingSenderId", appId: "appId", };
Firebase를 초기화하고 firestore를 불러온다.
// Firebase 초기화 // 인자로 위의 key들을 넣어주면 해당 프로젝트와 연결됨 firebase.initializeApp(firebaseConfig); // firestore를 불러와서 dbService에 넣어줌 // dbService를 통해 firestore를 동작(수정/추가/삭제)할 수 있음 const dbService = firebase.firestore();
Firebase에 데이터 추가
html에 to do를 입력하는 form과 input 요소를 넣는다. 불러온 to do list를 출력할 div 요소도 생성했다.
to do를 입력하고 submit했을 때 연결된 firestore에 데이터를 넣어주는 코드이다.
// html의 todo-form, todo, todos 불러오기 const todoForm = document.querySelector("#todo-form"); const todoInput = document.querySelector("#todo"); const todos = document.querySelector("#todos"); // todo가 새로 추가됐을 때 호출되는 함수 const onSubmit = async (e) => { // 새로고침 방지 e.preventDefault(); // 현재 시각을 아이디로 사용하기 위해서 Date 객체를 불러옴 const date = new Date(); // todo 생성 시각 불러옴 const createdAt = date.getTime(); // dbService에서 todos 컬렉션에 createdAt이라는 아이디를 가진 문서를 생성한다. // 내용은 todo: todo 내용으로 한다. todo 내용은 input에 입력돼있는 내용이다. // set함수를 통해서 생성하고, 내용을 넣어줄 수 있다. // set함수는 같은 id의 문서가 있을 때는 문서의 내용을 덮어쓰기하고, // 없을 때는 새로 추가해준다. await dbService.collection("todos").doc(`${createdAt}`).set({ todo: todoInput.value, }); // todoInput은 비워준다. todoInput.value = ""; }; // todo form에 submit을 감지하는 이벤트리스너를 추가한다. // submit되면 onSubmit 함수가 호출된다. todoForm.addEventListener("submit", onSubmit);
firestore의 실시간 데이터 감지
onSnapshot을 통해 데이터가 변경될 때마다 함수를 실행할 수 있다.
// 빈 배열 생성 let todoArr = []; // dbService(firestore)의 'todos' collection이 바뀔 때마다 감지 dbService.collection("todos").onSnapshot((snapshot) => { // 변경되었을 때 코드 실행 // map 함수는 배열의 요소들을 하나하나 돌면서 코드를 실행한다. // snapshot.docs.map은 documents를 배열로 받아온 것 // doc은 반복하고 있는 배열의 요소를 의미한다. // 예를 들어 python에서 for a in arr: 라는 코드가 있을 때 // map == for // snapshot.docs == arr // doc == a // todoArr에 문서의 데이터들과 id를 저장한다. todoArr = snapshot.docs.map((doc) => ({ ...doc.data(), id: doc.id, })); // console.log(todoArr) // to do list를 표시하는 함수 호출 paintingTodos(); });
화면에 To do list 출력하기
todoArr에 넣어준 to do 데이터들을 화면에 띄운다.
// to do list를 표시하는 함수 const paintingTodos = () => { // 밑의 내용을 먼저 보고 올라오도록 // preUl은 todos에 있는 ul을 불러온다. const preUl = document.querySelector("#todos ul"); // 이미 한 번 todo가 그려져서 todos 안에 ul이 존재하는 상황이라면 // 해당 ul을 지워준다. 그래야 새로 ul이 추가됐을 때 또 불러와지지 않는다. if (preUl) { preUl.remove(); } // ul(점으로 찍히는 리스트) 요소 생성 const ul = document.createElement("ul"); // map 함수를 이용해서 todoArr의 모든 요소를 반복해서 가져온다. // 반복할 때마다 하나의 요소씩 t에 들어가게 된다. todoArr.map((t) => { // li(ul 안에 들어가는 리스트 요소)와 button 요소 생성(삭제 버튼) const li = document.createElement("li"); const btn = document.createElement("button"); // li 태그의 안에는 todo의 내용이 들어간다. li.innerText = `${t.todo}`; // button 태그 안에는 delete라고 들어간다. btn.innerText = "delete"; // btn이 클릭됐을 경우 함수를 발생시키기 위해 이벤트 리스너를 추가해주었다. // btn이 클릭되면 onDeleteClick이 호출된다. btn.addEventListener("click", onDeleteClick); // btn의 아이디를 todo의 id로 설정해주었다. // 삭제 작업을 하기 위해선 아이디가 필요하기 때문에 // 버튼의 아이디에 todo 아이디를 넣어주었다. btn.id = `${t.id}`; // li에 btn을 넣고, ul에 li를 넣어준다. li.appendChild(btn); ul.appendChild(li); // 이 작업을 todoArr의 모든 요소에 반복한다. }); // li 요소가 모두 추가된 ul을 todos에 추가한다. // 이 때 최종적으로 화면에 todo가 표시되게 된다. todos.appendChild(ul); // 위에서 ul 삭제를 안한 경우 paintingTodos가 호출될 때마다 // 새로 todo를 그리기 때문에, // 맨 앞쪽에 기존에 있던 것을 지워주는 코드를 추가한다. };
Firestore에서 데이터 지우기
Firestore에서 아이디를 통해 데이터를 지운다.
// 위에서 btn에 추가해주었던 click 이벤트 리스너가 호출하는 함수이다. const onDeleteClick = (e) => { // 클릭된 타겟이 가지고 있는 아이디를 불러온다. const targetId = e.target.id; // dbService의 todos 컬렉션에서 해당 아이디의 문서를 지운다. dbService.collection("todos").doc(`${targetId}`).delete(); // 문서를 지웠으므로 다시 todo를 화면에 그린다. paintingTodos(); };
Reference
노마드코더: 바닐라 JS로 크롬 앱 만들기 https://nomadcoders.co/javascript-for-beginners/lobby
from http://chaennie.tistory.com/60 by ccl(A) rewrite - 2021-12-05 19:27:08