개발일지/tweet/ rt, heart 여부 확인

바다·2021년 11월 15일
0

project

목록 보기
2/6

이 글은 tweet 프로젝트를 구현하면서 발생했던 문제와 이를 해결한 방법과 그 과정에서 배운 점을 적은 글입니다.


1. 구현하고자 한 기능

해당 tweet을 사용자가 rt나 heart했는지 확인하는 기능을 구현하고 싶었다.

rt, heart를 누른 tweet들은 사용자의 tweet 저장소에 저장되도록 코딩하였기 때문에 해당 tweet이 사용자의 저장소에 있는지 확인하는 방향으로 작성하기로 했고 이를 위해서는 fireBase에서 다중조건을 가져오는 방식과 다중 조건에 맞는 문서의 존재 여부를 확인하는 방법, 존재 여부에 따라 rt, heart 각각에 boolean값으로 설정해야 했다.

2. 문제점과 해결

1)

문제점: 다중조건 적용과 조건에 맞는 문서 여부 확인

firebase 에서 다중조건을 적용하고, 조건에 맞는 문서의 여부 확인해야 했다.

해결 :

collection().where().where().get().then().catch()을 통해 다중조건을 적용했고 doc.empty의 속성을 활용하여 조건에 만족하는 문서의 존재여부를 확인할 수 있었다.

const checkAlarm = async()=>{
    const rt_vlaue = await userObjCollection
    .where("creatorId" , "==" , `${tweetObj.creatorId}` )
    .where("createdAt" , "==" , `${tweetObj.createdAt}`)
    .where("value" , "==" , "rt")
    .get()
    .then(doc => setRt({
			empty : doc.empty, //문서 존재여부 확인
			id :doc.docs.map(d=>d.id)[0] // 추후에 삭제기능을 위해 문서의  id 를 함께 저장함 
		)
    )
    .catch(error => console.log("Error" , error))
    ;

    ...... 
  };

😀 tip!!

firebase에서 비동기 방식을 데이터 베이스에서 문서를 가져와서 해당 문서를 전역변수로 이용하고 싶다면
useSate 를 이용하여 then에서 setState로 promise의 결과값을 가져와 사용할 수 있다.


2)

문제점 : where()에서 숫자인 조건은 쓸 수 없다는 것

tweet을 작성할 때 작성된 날짜를 뜻하는 createdAt은 숫자로 저장되는데 다중 조건을 가져오면 숫자인 createdAt은 읽히지 못하는 상황이 발생한다.

해결:

createdAt을 문자형식으로 전환했다.

3)

문제점 : 비동기 함수 실행 시 데이터를 가져오는데 시간이 오래 걸리는 점

rt,heart 여부는 서버로 부터 정보를 얻어야 하는 하기 때문에 서버로 부터 정보를 알아보는 데 시간이 걸린다. 따라서 useEffect를 통해 마운트 시에만 rt, heart 여부를 알아보는 checkAlarm함수 실행하면 서버에서 정보를 알아보기 전에 rt,heart의 상태가 원하는 결과가 아닌 초기 상태로 실현된다는 문제점이 있었고 필요할 때만 checkAlarm 함수를 실행하면 서버로부터 정보를 알아보는데 시간이 오래 걸려 유저 경험에 좋지 못했다.

해결 :

cheackAlarm()을 계속 실행하는 방식으로 전환했다. rt,heart 여부는 버튼의 스타일에도 영향을 주며 자주 필요한 기능이기 때문에 계속 실행하는 방식을 전환했으나 해당 기능이 필요한 때에만 작성하도록 하는 방식이 아니기 때문에 서버에 부하를 주는 효율적인 방식은 아니므로 이는 개선이 필요하다고 생각한다.

수정 : 필요할 때만 checkAlarm 실행시키기 (21.11.16)

useEffect(()=>{
  checkAlarm();
},[]);

const Rt =()=> {
(async()=> await checkAlarm())(); 
.....}

Rt 함수를 실행 시킬 때 선제적으로 checkAlarm 함수의 결과값이 필요했다. 이에 async와 await를 이용한 비동기 방식으로 Rt 함수에 async를 거는데 아니라 따로 무기명 함수를 만들어 cheakAlarm을 실행시켰다.
무기명 함수만으로 실행시에는 서버의 결과값을 받아오는데 시간이 걸려서 마운트시에 cheakAlarm을 실행시키는 것을 추가했더니 서버의 결과값을 받아오는 시간이 많이 단축되었다.

4)

문제점: 다중 조건으로 배열 필터링하기

rt, heart를 해제할 때 해당 tweet의 원래 작성자(타 이용자가 nweet을 rt,heart한 nweet의 해제한 경우에는 타 이용자도 포함)의 알림에서 이용자의 rt,heart의 알림 소식을 제거하는 기능을 구현하고자 했다.
그래서 알림은 [{userId: 이용자의 아이디, createdAt: 문서의 작성일자,..},,,{...}] 의 형식으로 저장되고 해당 알림 배열에서 이용자에게 해당하는 알림의 객체를 삭제해야 했고 다중 조건으로 배열을 필터링해야 했다.

해결 : 필터링 조건을 함수로 구현하여 array.filter에 적용

const deleteAlarm = (what) => {
    const ownerAlarm = ownerProfile.alarm;
    const filterAlarm =(a)=> {
      if (a.creatorId === newAlarm(what).creatorId &&
      a.createdAt === newAlarm(what).createdAt &&
      a.userId === newAlarm(what).userId &&
      a.value === newAlarm(what).value) {
        return false
      }
      return true ;  
    };
    const newOwnerAlarm = ownerAlarm.filter(a=>filterAlarm(a));
    getProfileDoc(nweetObj.creatorId).set({alarm :newOwnerAlarm} ,{merge:true});

! 주의 ☝ !
array.filter는 array.push 나 array.concat과 달리 해당 array에 바로 적용되지 않으므로 필터링한 배열을 사용하고자 한다면

 const newOwnerAlarm = ownerAlarm.filter(a=>filterAlarm(a));

위와 같이 따로 객체로 정의하여 사용해야 한다.


그러나....
이렇게 열심히 고민했으나...

twitter 클론 코딩 프로젝트를 다 끝내고 보니,
A 라는 트윗에 해당 트윗에 대해 일어나는 모든 알림들(rt,heart,인용 트윗,답변)을 모아놓는 notification에서 현재 로드인한 유저의 uid와 알림의 유형을 확인하는 방식으로 수정했다.
그래서 위의 코드들을 깃허브에 가면 없어요.

그래도 열심히 고민한 나 칭찬해.

어찌되었든 또 다른 해답을 찾은 나 칭찬해.

profile
🐣프론트 개발 공부 중 (우테코 6기)

0개의 댓글