클론 코딩을 하면서 어느 주제로 할까하다가 처음에
싸이월드을 클론코딩하자고 했지만 미니홈피 기능을 구현하기 어려울것같고 미니홈피 기능이 없다면 클론코딩의미가 없는것 같아.
프론트엔드와 백엔드 둘다 적절한기술이 쓰인 트위터 코딩을 하면 좋겠다고 결정이 되었다.
이번 주차 팀원들은 아주 맘에드는 팀원을 만나서 서로에게 배울것도 많았고 좋은 시간이였다.
프로젝트 기간이 끝나고 다른팀원분이 아쉬워하면서 나머지부분을 업데이트를 해주셨다.
트위터 클론 코딩 파일 구조이다.
이번 프로젝트에서 사용된 라이브러리이다
"axios": "^0.27.2", "moment": "^2.29.4", "react": "^18.2.0", "react-cookie": "^4.1.1", "react-dom": "^18.2.0", "react-icons": "^4.4.0", "react-intersection-observer": "^9.4.0", "react-query": "^3.39.2", "react-router-dom": "^6.3.0", "react-scripts": "5.0.1", "styled-components": "^5.3.5", "web-vitals": "^2.1.0"
이번 프로젝트는 리액트쿼리를 사용하여 상태관리를 해주었다.
로그인과 다른부분도 있었지만 무한스크롤을 처음부터 다시 구현하고 싶었고 저번 프로젝트와는 다른부분을 시작하고 싶어
프로젝트에 내가 맡은 부분은 홈페이지와 트윗작성페이지, 디테일페이지이다.
이번 프로젝트도 일주일이라는 기간안에 만들어야 했기에 트위터에서 스코프 범위를 정했는데, 로그인, 메인, 트윗, 리트윗, 좋아요, 트윗작성,팔로우,언팔로우 기능 까지 하기로 했다.
홈페이지의 경우 구현했던것은 무한스크롤인데
리액트쿼리와 Scroll Event를 이용하여 구현을 하였다.
아직 리액트쿼리를 배우는중이였기에 infiniteQuery가 있음에도 미숙하여 사용하지 못하였고 다음프로젝트에서 사용했다.
Scroll Event로 구현한것도 기초적으로 라이브러리 없이 만들어 보고 싶어서 진행을 하였고 이후에는 라이브러리를 활용하여 만들었다.
const getTweets = async page => {
const res = await tweetAPI.getAllTwit(page);
let reslist = res?.data.data;
for (let i = 0; i < reslist?.length; i++) {
reslist[i] = { ...reslist[i], page: page };
}
setListTweet([...listTweet, ...reslist]);
return res;
};
const { data, isLoading } = useQuery(
["getTweets", page],
() => getTweets(page),
{
staleTime: 0,
retry: 1,
keepPreviousData: true,
}
);
infiniteQuery를 사용하지않고 만든 모습이다 api요청에서 respose값을 return 하기전에 useState에 값을 추가적으로 저장을 하여 구현을 하였고
이점에서 문제점은 useMutaion을 통한 invalidateQueries를 통해 데이터가 변경된점을 재렌더링 할수 없는 점이였다.
그래서 삭제같은 기능을 구현할때 일일이 특정 데이터를 찾아 지워 재렌더링을 하는방법으로 구현을 했다.
const deleteMutation = useMutation(tweetAPI.deleteTwit, {
onSuccess: () => {
const deletedTweets = listTweet.filter((x) => {
return x?.id !== tweet?.id;
});
setListTweet(deletedTweets);
},
});
이런식으로 서버로 데이터를 지우는 api를 요청하고 성공시 State안의 내용을 변경하는 식으로 했다.
이런방식으로하면 더욱 복잡해지기 때문에 추후에는 infiniteQuery를 사용하여 구현하였다.
Scroll Event 부분이다
const handleScroll = () => {
const scrollHeight = document.documentElement.scrollHeight;
const scrollTop = document.documentElement.scrollTop;
const clientHeight = document.documentElement.clientHeight;
// console.log(scrollHeight, scrollTop, clientHeight);
if (scrollTop + 0.4 + clientHeight >= scrollHeight && fetching === false) {
fetchMoreData();
}
};
useEffect(() => {
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
});
원래는 ClientHeight +ScrollTop >= ScrollHeight 이와 같은 식이었는데 위 조건에 둘의 합에서 >= 조건을 만족할려면 항상 소수점자리의 수가 조금씩 부족하여 0.4를 더해주었다. 어느값을 더해주도 상관없지만 1이상의 정수를 더할경우 스크롤을 아래로 내렸다가 올리는경우에도 이벤트가 실행이 되는경우가 있어 소수점의자리로만 더해야 이런 버그가 생기지 않았다.
이것은 1을 더할경우 >=의 조건을 미리 충족시키고 1px의 여유가 남아서 위로 스크롤을 올릴때 이벤트가 발생하고 1px를 충족시키지 못하는 소수점이 남았을때는 이벤트가 발생하지 않은것으로 보인다.
여기에 throttle을 추가 해주면 더욱 좋았겠지만 프로젝트 남은시간상 다른것도 구현해야해서 다음에 보완하기로 했다.
하지만 이후에는 react=intersection-observer을 이용하여 쉽게 구현을 하였다.
나머지는 다음포스트에서 이어가겠다