항해99 6주차 WIL

코잼·2021년 4월 11일
0

이번 6주차에는 처음으로 백엔드와 같은 팀이 되어 홈페이지 하나를 클론코딩을 하게 되었다. 처음으로 백엔드와 하다 보니 생각이 많이 들었다. 백엔드와 어떻게 정보를 주고받지? 어떤 정보를 주고받지? 내가 어떤 작업을 하면 될까? 등 많은 고민이 있었다. 지금까지는 프론트엔드를 하면서 풀스택으로 정보와 데이터 저장 같은 모든 것들을 맡았기 때문에 어떤 부분이 백엔드고 프론트엔드 담당인지 헷갈렸기 때문이다.
처음 팀원들과 만난 후 어떤 홈페이지를 할지 고민을 많이 했다.

고민을 하면서 나온 홈페이지.

  • 벨로그
  • 인스타그램
  • 콜로소
  • 클래스101
  • 바이블

이 중에 인스타그램을 하기로 하였다.

고민을 하던 것 중 하나인 정보를 주고받는 방법에 대해서는 MOCK API로 해결되었다.
MOCK API에서 셋팅을 다하면 페이지에 띄워져 있는 주소를 사용해 데이터를 get post 등으로 주고 받으면 된다. 하지만 다음 고민이 생겼다.
fetch와 axios 중 어떤 것을 사용해야 할까.
fetch는 react native 사용할 때 좋다는 말이 많았다. 하지만 우리는 이번엔 react에서만 사용할 것이기 때문에 axios를 사용하기로 했다.

인스타그램 클론코딩


메인페이지 css 작업하는 데 고생 좀 했다. 클론코딩에 걸맞게 아주 똑같이 해보고 싶은 마음에 최대한 비슷하게 게시물 카드를 만들었다.

Post 가져오기

무한스크롤

useEffect(() => {
  dispatch(postActions.getPostDB(paging.start, paging.size, token));
}, []);

처음 메인을 접속하게 되면 getpostDB를 dispatch를 하는데 3가지 변수를 넣었다.

const initialState = {
is_loading: true,
list: [],
paging: { start: null, size: 4 },
likelist: [],
};


let result = docs.data.boardAll.slice(start, size)
let paging = {
        start: start + result.length + 1,
        size: size + 5,
      };

정보를 가져올 때 5개씩 가져올 것이다.
일단 initialState에 기본적으로 start는 null, size는 4를 넣어놨다.
4를 넣어논 이유는 리스트는 0부터 시작하기 때문에 0~4(5개)
api가 boardAll에 모든 포스트 정보들이 포함되어있다.
slice를 이용해 start번째 부터 size번째까지만 잘라서 result로 변수를 선언하고 그 정보들만 가져왔다.
이후 paging으로 start와 size를 그 다음 포스트 5개를 가져올 수 있게하여 객체로 넣어놓고 redux에 저장한다.
무한스크롤 라이브러리를 사용하여 스크롤이 맨 밑으로 이동 시
그 다음 5개 포스트를

draft.list.push(...action.payload.post_list);

를 사용하여 뒤에 5개씩 넣어주면 된다.

좋아요 애니메이션


이미지 더블클릭, 좋아요 클릭 시 나오는 하트 애니메이션도 완벽히 만들어봤다. 솔직히 애니메이션은 처음이다보니 많이 힘들었다.

          <Double
            actives={actives}
            onAnimationEnd={() => {
              setActives(false);
            }}
          />
          <Img img={props.img} onDoubleClick={imgpostLike} />

좋아요를 누를 시 imgpostlike가 실행한다.

const [actives, setActives] = useState(false);

const imgpostLike = () => {
  if (props.likeYn === "unLike") {
    dispatch(likeActions.sendLikeDB(props._id, token));
  }
  setActives(true);
};

인스타그램에서 이미지 더블클릭 시 좋아요가 이미 눌러져있다면 애니메이션만 보여진다.
if문을 사용해 좋아요가 안 눌러져있다면 dispatch를 이용해 좋아요를 눌렀다는 정보를 보내주면 된다.
setActives(true)는 좋아요 상관없이 실행되는데

const Double = styled.div`
  animation-timing-function: ease-in-out;
  background-image: url("${Doubleheart}");
  z-index: 99;
  ${(props) =>
    props.actives &&
    css`
      animation-name: ${DoublefadeIn};
    `}
`;

z-index를 이용해 맨 앞에 뜨게 만들고, 화살표 함수를 사용해 actives가 true 시 DoublefadeIn 애니메이션을 실행하게 된다. 애니메이션이 끝나면 컴포넌트 안에

onAnimationEnd={() => {
                setActives(false);
              }}

애니메이션이 끝날 때 실행하는 onAnimationEnd을 이용해 다시 false로 변경해주었다.

좋아요 정보 가져오기

처음 메인페이지에 접속할 때 로그인한 유저가 이미 좋아요를 누른 포스트가 있다면 포스트에 좋아요가 눌러져있어야 한다.

{
  "likeYn": [
    {
      "_id": "_id",
      "userId": "userId",
      "boardId": {
        "like": 1,
        "_id": "_id",
        "userId": "userId",
        "contents": "내용",
        "img": "이미지주소",
        "day": "2021-04-07T23:11:49.458Z",
        "__v": 0
      },
      "__v": 0
    },
  ]
}

원래 백엔드에서 가져올 때 이렇게 가져와져서 머리 아팠다.. 유저고유번호와 그 유저가 누른 post_id만 들어있으면 좋은데 백엔드 팀원이 3명이였다가 1명이 나가시면서 원래 계시던 한 분이 그 몫까지 해결하시느라 바쁘셨다. 그래서 이대로 진행하였다.

const likeYn_list = docs.data.likeYn.map((p, idx) => {
  return {
    post_id: p.boardId._id,
    user_id: p.userId,
  };

정리하여 likeYn_list를 만들었다.

result.forEach((doc) => {
        doc.day = moment(new Date(doc.day)).fromNow(); // 시간을 지정된 형식으로 변환 ex) n분 전, n시간 전
        const is_like = likeYn_list.find((a) => {
          if (a.post_id === doc._id && a.user_id === doc.userId._id) { // 두 가지 경우가 true면 is_like에 true를 선언, 아니면 false를 선언
            return true;
          } else {
            return false;
          }
        });

가져온 like 정보와 일치하는 것들만 true로 return을 하여 좋아요가 눌러져있게 만들었다.

끝마치며

좋아요 기능 때문에 머리 아팠지만 오기가 생겼었다. '누가 이기나 해보자'라는 마인드로 점심 먹을 때도 방법을 생각하고 저녁을 먹을 때도 생각하여 끝내 정보를 깔끔히 가져왔다. 원래대로라면 몇 시간 안 걸리는 작업이지만 처음 백엔드와 작업해서 그렇기도 하고 api가 복잡하게 정리되어 있었기도 하다. 하지만 이제 api가 복잡하게 되어 있어도 깔끔하게 처리할 수 있는 방법을 터득한 것 같아서 기분이 좋았다.

profile
cooooooding

0개의 댓글