메인 프로젝트 회고

ddimi·2023년 2월 9일
0

프로젝트

담당한 기능

  • 회원가입 시의 이름, 닉네임,이메일, 비밀번호 유효성 검사 및 자체 회원가입 기능 구현
  • 회원정보 수정 기능, 회원 이미지 업로드(AWS S3)
  • 게시판 코멘트 작성 및 수정 기능
  • 디테일 페이지 코멘트 관련 수정, 삭제
  • 로그인 유지
  • 실시간 채팅 UI제작
  • 리액트 쿼리로 리팩토링

좋았던 점

리액트 쿼리 도입

상태관리와 데이터 캐싱을 위해

처음에는 상태관리 라이브러리로 리덕스를 사용했었다. 그 당시에 현재 팀이 직면하고 있던 문제에 대해서 스터디원분들에게 논의를 했더니 react-query를 도입하면 상태관리는 물론 데이터 캐싱이 가능하다는 것을 알게 되었다.

추천이나 비추천, 찜하기, 인생작품 등의 버튼을 클릭하면 api 통신은 되지만 실질적으로 화면에 보이는 데이터에서는 변화를 감지할 수 없어서 모든 api 통신 후에는 페이지를 리로드 하는 방식으로 구현을 했었다.

const handleRecommend = async () => {
    if (!isLogin) return navigate("/login");
    await axios
      .post(
        `http://whatu1.kro.kr:8080/contents/${contentId}/recommend`,
        {
          headers: {
            Authorization: localStorage.getItem("accessToken"),
          },
        }
      )
      .then(() => {
        if (deprecate) {
          setDeprecate(!deprecate);
        }
        setRecommend(!recommend);
        window.location.reload();
      })
      .catch((err) => {
        console.log(err);
      });
  };

리액트 쿼리를 도입한 후에는 refetch를 호출해서 쿼리키의 데이터와 상태를 업데이트 해준다.

  const handleRecommend = async () => {
    if (!isLogin) return navigate("/login");
    await axios
      .post(
        `http://whatu1.kro.kr:8080/contents/${contentId}/recommend`,
        JSON.stringify({}),
        {
          headers: {
            Authorization: localStorage.getItem("accessToken"),
          },
        }
      )
      .then(() => {
        if (deprecate) {
          setDeprecate(!deprecate);
        }
        setRecommend(!recommend);
        refetch();
      })
      .catch((err) => {
        console.log(err);
      });
  };

코멘트의 경우에도 post를 보낸 후 reload 하던 방식에서

	axios
      .post(
        `http://whatu1.kro.kr:8080/contents/${contentId}/comments`,
        bodyJSON,
        {
          headers: {
            "Content-Type": "application/json",
            Authorization: localStorage.getItem("accessToken"),
          },
        }
      )
      .then(() => {
        window.location.reload();
      })
      .catch((err) => {
        console.log(err);
      });

mutate를 사용해서 submit을 하면 바로 input창에 입력한 것들을 초기화 시키고 refetch를 하도록 수정했다.

 const submitcommit = () => {
    if (comment === "") return toast.info("한줄평 내용을 입력하세요");
    mutate({commentBody: comment})
    toast.success("한줄평 내용이 입력되었습니다");
    setComment("")
    refetch();
 };

매일 오전 9시 팀 미팅

매일 오전 9시에 팀 전체가 모여서 백엔드와 프론트엔드 각각의 전날까지 이슈를 쉐어, 변경해야할 것들을 요청하고, 피드백을 주고 받았다.
그 후에는 프론트엔드 팀원들과 모여서 프론트엔드 미팅을 했다. 간략하게 어제를 기준으로 분담한 업무의 진행정도와 이슈들을 공유하고 오늘 새롭게 업무를 배정하는 식으로 진행했다. 디스코드에 9-6동안은 점심시간을 제외하고 항상 상주를 하고 있어서 팀원들간에 기능을 구현하면서 생기는 에러들도 함께 잡고 구현하기 어려웠던 것들은 서로 공유하면서 함께 기능을 구현했다.
그래서 어느 분야할 것 없이 내 손이 닫지 않은 곳이 없다. 다른 팀원들도 마찬가지이다. 서로 맡지 않은 기능이라 할지라고 팀 전체를 위한 프로젝트이다 보니 누구랄 것 없이 다들 먼저 나서서 도움을 주었다.


아쉬웠던 점

토큰 관리

보안 이슈에 대응하지 못함

개인적으로 가장 아쉬웠던 점은 제출기한이 얼마 남지 않은 시점에서 refresh token을 이용해서 토큰을 재발행하는 로직을 추가하게 되면서 보안이슈에 제대로 대응하지 못한 것 이다.
access token으로만 유저인증을 하다가 마감기한이 일주일도 남지 않은 시점에 access token의 시간을 30분으로 축소시키면서 유저가 새로 로그인 할 수 있게끔 만들어야 했었다. 유저가 30분 마다 로그인하도록 하는 것은 사실 유저 경험 측면에서 좋지는 않다.
그래서 refresh token을 이용해서 토큰을 재발행해서 자동적으로 로그인을 연장시켜주는 기능을 구현하고자 했었다.
access token의 경우 localStorage에 보관을 하고 있었으나 토큰 재발급 기능을 구현하면서 access token은 변수로 선언을 해서 클라이언트측에서 따로 저장을 하지 않아 탈취의 위험을 없애고자 했다.

// 헤더에 바로 authoriztion 넣으면 로컬 스토리지에 저장할 필요 없어짐
   axios.defaults.headers.common["Authorization"] = `${res.headers.authorization}`;

refreshToken의 경우에는 만료기간이 길기 때문에 탈취 가능성이 적은 곳에 저장을 하고자 했으므로 쿠키에 저장하게끔 계획을 했다.
하지만 물리적인 시간의 한계에 부딪혀 실제로 보안보다는 현재 구현한 기능들에서 데이터 캐싱을 통해서 페이지 리로드 없이 refetch 해오도록 코드를 리팩토링하는 것이 팀이 설정한 우선순위에 해당한다고 결정을 내려서 아쉽게도 계획에만 그치게 되었다.

api에 대한 논의

api call 횟수를 늘릴 것인가 vs 불러오는 데이터 양을 쪼갤 것인가

사실 이번 프로젝트를 진행하면서 api 관련해서 논의를 제대로 하지 못했던 점들이 프로젝트 마무리까지 부작용(?)처럼 작용했다.
get 요청을 보낼 때 각각의 영화마다 달리는 comment들이 한 api에 통채로 불러와져서 contentid에 따라서 filter를 해서 뿌려주었다. 이게 infinite scroll을 구현하는데도 있어서 데이터를 10개씩 불러온다면 그 안(전체 comment 데이터)에 현재의 영화에 대한 comment가 없으면 스크롤이 작동하지 않는 것 처럼 보이는 문제점들이 있었다.
메인 프로젝트 멤버 전체가 다시 프로젝트를 기획한 만큼 이번에는 api에 대해서도 조금 더 적극적으로 커뮤니케이션 하도록 노력해야겠다.

0개의 댓글