Firebase와 Javascript로 To do list 만들기

김채은·2022년 1월 14일
0

 PROJECT

 들어가기

이전에 이 프로젝트를 진행했을 때는 localStorage를 사용해서 To do list를 구현했는데, 단국대부속소프트웨어고등학교 자율동아리 친구들의 수업을 준비하면서, 이 프로젝트를 통해 Firebase를 사용해보면 좋은 경험이 될 것 같아서 리팩토링 해보았다.

Firebase의 firestore에 To do list를 저장하고, javascript를 통해 웹과 연동하여 불러온다.

 Firebase와 Javascript 연동

바닐라 js에서 firebase를 사용하려면 script에 주소를 추가해주어야 한다. require 등 다양한 방법을 써봤지만 버전 문제 때문에 제대로 작동하지 않았다.

<script src="https://www.gstatic.com/firebasejs/8.8.1/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.8.1/firebase-firestore.js"></script>
<script src="todo.js"></script>

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 요소도 생성했다.

    <form id="todo-form">
      <input type="text" id="todo" />
      <input type="submit" value="ADD" />
    </form>
    <div id="todos"></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로 크롭 앱 만들기

profile
배워서 남주는 개발자 김채은입니다 ( •̀ .̫ •́ )✧

4개의 댓글

comment-user-thumbnail
2022년 1월 19일

좋은글 감사합니다!! 다음 내용도 기대되네요!

1개의 답글
comment-user-thumbnail
2022년 11월 1일

혹시 firebase로 바꾼 코드 볼 수 있을까요? 저도 바닐라 자바스크립트에서 firebase 사용하고 싶은데 자꾸 오류가 뜨네요

1개의 답글