Frontend 개발자 - hyo.loui

fanpick 프로젝트 셀프 코드 리뷰 - CRUD(in R) 본문

Javascript

fanpick 프로젝트 셀프 코드 리뷰 - CRUD(in R)

hyo.loui 2022. 11. 29. 20:52

Read API

게시글을 조회하고, 보여주는 함수이다

 

우선은 게시글을 클릭했을 때 우리가 가진

데이터를 보여주려면 id 가 필요했다 

id 안에 게시글이 객체형태로 데이터가 들어있기 때문이다

 

우선 게시글에 삽입 될 HTML 태그이다

<div class="content_card_container" id="${fanPickList.id}" onclick="sendId(this.id)">
/*
...innerHTML
*/
</div>

fanPickList 객체가 가지고있는 id 데이터를 태그 id에 넣어주고 onclick 으로 전달되도록 구현했다.

onclick="sendId(${fanPickList.id})"

처음에는 위 처럼 해당아이디를 바로 클릭하면 전달 할 수 있게 작성했으나,

레퍼런스 에러가 나서 수정했다

// 클릭한 카드의 id 받아적는 변수
let selectId = "";
// 함수가 실행 될 때마다, 해당게시글 id 를 update
export function sendId(showId) {
  selectId = "";
  selectId = showId;
}

내가 클릭한 카드(게시글)의 고유한 아이디를 받아놓을
변수(selectId)에 매번 업데이트 할 수 있는 코드를 미리 구현했다

 

왜냐하면, 우리는 게시글을 클릭하면 상세 내용을 띄워줄 모달을 구현해야 했기 때문이다!

 

메인 화면에 카드형식으로 보여줄 코드이다.

// 뉴스피드 업데이트 = 겟 리스트
export async function getList() {
  const cardList = [];
  // query 를 db에서 받아와 q로 선언
  const q = query(collection(dbService, "fan-pick"), orderBy("시간", "desc"));
  // query 조건에 맞는 documents 데이터를 배열로 받아오기
  const querySnapshot = await getDocs(q);
  // doc.id는 DB가 자체적으로 생성하는 값으로, id도 함께 포함시키기 위해 객체 재구성
  querySnapshot.forEach((doc) => {
    const fanPickList = {
      id: doc.id,
      ...doc.data(),
    };
    cardList.push(fanPickList);
  });
  const newsFeed = document.getElementById("newsFeed");
  newsFeed.innerHTML = ""; // append가 쌓이지 않도록 지워주는 코드

  cardList.forEach((fanPickList) => {
    const temp_html = `<div class="content_card_container" id="${
      fanPickList.id
    }" onclick="sendId(this.id)">
    <div onclick="modalOn(${fanPickList.id})">
        <!--카드이미지-->
        <div class="card_img">
            <img  src="${fanPickList.이미지 ?? no_img}"
                alt="게시글 이미지" />
            <!--글제목,내용 간단히-->
            <div class="card_content">
                <h4 id="title">${fanPickList.제목}</h4>
                <p id="content">${fanPickList.내용}</p>
            </div>
            <!--좋아요
            <div class="card_like">
                <span>162</span> <i class="fa-solid fa-heart"></i>
            </div>-->
            <div class="card_bottom">
                <div class="card_profile">
                <img src="${
                  fanPickList.프로필이미지 ?? no_img
                } " alt="기본이미지">
                </div>
                <div class="card_name"><span>${fanPickList.작성자}</span></div>
                <div class="card_date"><span>
                ${new Date(fanPickList.시간)
                  .toString()
                  .slice(0, 25)}</span></div>
            </div>
        </div>
        </div>
    </div>`;
    const div = document.createElement("div");
    div.classList.add("mycards");
    div.innerHTML = temp_html;

    newsFeed.appendChild(div);
  });
}

생소한 함수들 (addDoc, collection, ordBy, getDoc) 은

firebase API 이다 공식 문서에서 참고할 수 있다

 

https://firebase.google.com/docs/firestore/quickstart?authuser=0

 

Cloud Firestore 시작하기  |  Firebase

Firebase Summit에서 발표된 모든 내용을 살펴보고 Firebase로 앱을 빠르게 개발하고 안심하고 앱을 실행하는 방법을 알아보세요. 자세히 알아보기 이 페이지는 Cloud Translation API를 통해 번역되었습니

firebase.google.com

 

흔히 알고있는 게시글의 상세페이지를

모달창으로 구현했다

// 모달 / 해당 게시글 누르면 모달창이 켜지게 하기
export async function modalOn(id) {
  let user = authService.currentUser;
  if (user) { // 로그인상태 감지
    const card = [];
    const q = query(collection(dbService, "fan-pick"));
    const querySnapshot = await getDocs(q);

    querySnapshot.forEach((doc) => {
      // doc.data() is never undefined for query doc snapshots
      // 해당 파이어베이스 문서에 존재하는 id값과 selectId와 동일한 게시글 데이터 가져오기
      if (doc.id === selectId) {
        const commentObj = {
          id: selectId, //게시글 클릭하여 모달창이 선택된 아이디값을 부른다
          ...doc.data(),
        };
        card.push(commentObj);
      }
    });
    //해당 페이지에 id값 부여
    const feedModal = document.getElementById("modal_area");
    const currentUid = authService.currentUser.uid;
    card.forEach((modalCard) => {
      const isOwner = currentUid === modalCard.creatorId;
      const temp_html = `<div class="ceo"  id = "${id.id}"> // 댓글 불러오기 위한 id 할당
      <div id="modal" class="modal-overlay">
          <div class="modal-window">
              <div class="headline1">
                  <div class="profile_wrap">
                  <div class="profile_img_box"><img src="${
                    modalCard.creatorImg ?? no_img
                  }"
                  alt="profileImg" /></div>
                  <div class="profile_name">${modalCard.nickname ?? "익명"}</div>
                  </div>
                  <button id="close-area" class="close-area" onclick="modalOff()">
                  <i class="fa-regular fa-x xBtn"></i>
                  </button>
              </div>
  
          <div class="headline2">
              <p class="title">${modalCard.title}</p>
          </div>
  
          <div class="headline3">
              <button onclick="edit_btn(event)" style="${
                isOwner ? "display:inline-block;" : "display:none"
              }" class="btn">수정</button>
              <button onclick="update_content(event)" id="save_edit" style="display:none"
              }" class="btn">완료</button>
              <button style="${
                isOwner ? "display:inline-block;" : "display:none"
              }" class="btn ml10" id="${
        modalCard.id
      }" onclick="delete_comment(event)">삭제</button>
          </div>
  
          <div class="contents_area">
              <div class="content_pic">
              <img
                  src="${modalCard.imgUpload}"
                  alt="게시글 이미지"
              />
              </div>
              <p class="content">${modalCard.content}</p>
          </div>
  
          <div class="comments_area">
              <div class="form-commentInfo">
                  <textarea class="comment-input" placeholder="comment" id="comment"></textarea>
                  <button class="submit" onclick="Post_comment(event)">댓글 저장</button>
              <!-- <div class="profile_img_box"></div> -->
              </div>
              <div class="comments_wrap" >
           </div>       
      </div>`;

      const div = document.createElement("div");
      div.classList.add("modal_inner");
      div.innerHTML = temp_html;
      feedModal.appendChild(div);
    });
  } else {
    window.location.replace("#changsun"); // 로그인페이지 유도
    alert("로그인을 해주세요."); 
  }
    getCommentList(); // 댓글 불러오기
    selectId = ""; // 게시글 아이디 저장변수 초기화
}

함수 도입부 부터 user를 조건문으로 하여, user 가 아니라면 로그인 페이지로 유도할 의도로 구현했다.

firebase api를 이해하고 나서는 api 를다루는 create 부분과 비슷했지만
코드를 작성할 당시에는 보이지 않았다...

하지만 getDoc으로 해당 데이터를 가져오는 api 만 다르고 크게 다른 부분은 별로 없었다.

 

프로젝트가 얼마 남지 않았을 때 선택기능으로 댓글 기능을 추가로 작업하여
getCommentList() 함수도 호출했다.

 


read api 구현 중 가장 어려웠던 부분은
(수정>완료), (삭제) 버튼이였다

 

게시글이 가지고있는 creatorId와 현재 접속한 user의 id와 동일 했을 때만

update가 가능하도록 삼항연산자를 활용하여 구현했다

 

머릿속에서 생각을 끄집어내고 구현하면서 느껴지는 도파민과 성취감은 이루 말할 수 없다ㅜㅜ

 

 

CRUD 부분에서 가장 시간을 오래 썼던 것 같다

모달창을 안에서 이루어지는 동적인 요소들을 어떻게 구현할지

오랜 시간동안 고민했고,

 

생각한 대로 잘 구현되어서 가장 만족스러운 코드였다

 

selectId 부분에서도 많이 고민하며 오래 참다가 처음으로 튜터님께 질문해서

얻었던 힌트(id를 가지고 와야하는데 id가 어디에 있을까요?)를 듣고

머릿속에 떠오른 생각을 바로 코드로 구현하는데 성공했다

 

또한 read API 를 구현하면서
update API 도 쉽지 않겠다는 생각이 들었다...😣