[React]야구게임 & 리액트 라우트를 만들어보자

Kyle·2021년 5월 16일
3

project

목록 보기
11/13

야구게임 & 리액트 라우트를 만들어보자

깃허브 링크

개발기간: 05/03 ~ 05/14

실행화면

상태를 모든 화면에서 공유하는 형태의 프로젝트 상태관리가 힘들었지만 리액트가 아니었으면 더 난감했을 뻔했다.

이번 프로젝트에는 react-router를 사용했는데 기본적인 Link, BrowserRouter(Router), Route를 만들어보기도 했다.

먼저 react-router에 대해 작성하고 야구게임 프로젝트를 진행하면서 아쉬웠던 부분이나 마주쳤던 문제를 작성해보겠다.


react-router 만들어보기

react-router의 기본적인 원리는 window.history API와 react의 context를 이용해 구현했다. Router컴포넌트 하위에 있는 LinkRoute 컴포넌트들이 path에 관련된 정보를 context로 받아와서 사용한다.

(codesandbox의 new window에서는 history가 안 쌓여서 뒤로가기가 되지 않는다.)

Router

LinkRoute에서 사용할 주소값(상태)를 관리해주는 currentPath라는 state를 만들어 놓고 Context.Provider로 전해준다. 초기 셋팅을 useEffect를 이용해 2가지 작업을 해준다.

  1. 새로고침해도 값을 유지해야되기 때문에 window.location.pathnamewindow.location.search를 이용해서 url 경로를 설정하고 currentPath 상태를 setting 해준다.

  2. 뒤로가기를 위한 onpopstate 콜백함수를 설정해준다.

    뒤로가는 페이지가 있을 경우에는 뒤로가는 path로 설정을 해주고 아닐 경우 default_page(/)로 설정해준다.

const HistoryContext = createContext();

export const Router = ({ children }) => {
  const DEFAULT_PATH = window.location.pathname;
  const DEFAULT_QUERY = window.location.search;
  const [currentPath, setCurrentPath] = useState();
  useEffect(() => {
    setCurrentPath(DEFAULT_PATH + DEFAULT_QUERY);
    window.onpopstate = function (e) {
      e.state ? setCurrentPath(e.state?.page.to) : setCurrentPath(DEFAULT_PATH);
    };
  }, []);
  return (
    <HistoryContext.Provider value={{ currentPath, setCurrentPath }}>
      {children}
    </HistoryContext.Provider>
  );
};

Link 컴포넌트의 역할은 클릭했을 때 props.to의 path값으로 이동시켜 주는 것이다.

Link컴포넌트 클릭 콜백함수

  1. 이동시킬 때 setCurrentPath를 이용해 상태를 변경시켜준다.
  2. history API의 pushState를 해서 history에 push하면서 url path를 변경시켜준다.

(현재 a태그로 했지만 다른 태그를 사용해도 무관하다.)

export const Link = ({ to, children }) => {
  const { currentPath, setCurrentPath } = useContext(HistoryContext);

  const handleClick = (e) => {
    e.preventDefault();
    if (currentPath === to) return;
    setCurrentPath(to);
    window.history.pushState({ page: { to } }, to, to);
  };
  return (
    <a href="" onClick={handleClick}>
      {children}
    </a>
  );
};

Route

라우트의 역할은 currentPath값과 비교해 렌더링해주는 컴포넌트이다.

currentPath값에 prop.path가 포함된다면 렌더링한다.

  • exact[boolean]: true이면 path값이 일치할 때 만 렌더링한다.
export const Route = ({ children, exact, path }) => {
  const { currentPath } = useContext(HistoryContext);
  if (exact && currentPath !== path) return null;

  if (currentPath?.includes(path)) return children;
  else return null;
};

그냥 사용해도 너무 편하게 잘 만들어져 있지만 한번 구현해보는 과정도 재밌었다. 덕분에 history API에 대해서도 알게 됐고 어떤 방식으로 구현이 되는지 알 수 있었다.


야구게임 회고

어려웠던 문제 & 해결하지 못한 문제

시간이 부족하기도 했고 잘 몰라서 해결하지 못한 문제들이 있다.

- 2루타, 3루타,홈런의 이어지는 애니메이션

2,3루타 와 홈런을 구현하기 위해서 base주자들이 한칸씩만 이동하도록 설계를 했다.

  • 첫시도 : for문에서 2루타면 한칸씩 2번 나눠서 setState를 해주려고했다. 하지만 for문에 setState는 하나씩 적용되는 것이 아닌 리액트에서 마지막 값을 알아서 계산해 한번만 리렌더링 된다.
  • 두번째 시도: transitionEnd 이벤트를 사용해 transitionEnd때 마다 한칸씩 이동하도록 했지만 이것 역시 맨처음만 애니메이션이 작동되고 그 후에 최종버전으로 setState가 됐다. (이부분은 아직 이해 불가능)

아직 시도는 안해봤지만 모든 경우를 keyframes로 설정해주면 가능할 것 같다는 생각이든다.

- 자동공격

setTimeout 혹은 setInterval을 이용해 pitch하는 함수를 반복적으로 실행해주려고 했지만 계속 중첩되는 문제가 발생함 아직 어떻게 해결해야될지 고민을 제대로 못해봐서 아쉬움이 남는다.

고민 및 아쉬운 점

  • useReducer를 사용하면서 연관되어있는 2가지 이상의 상태는 어떻게 컨트롤하지? 라는 생각을 했다.

    -> 나는 커스텀훅을 만들어서 그 훅을 이용했는데...

    -> 관련된 상태들을 객체형태로 관리하면 해결되는 문제였다.

  • 상태들이 워낙 많고 Context.Provider를 계속 사용하다 보니 코드가 보기 어려워 진것 같다. context에 관련된 몇가지 고민들이 있었다.

    • 어느 수준은 props로 내려주고 어떤 경우에 context를 사용할지에 대한 고민이 계속된다.

      나는 여러군데에서 동시에 다 사용하거나 너무 깊은 곳에서 사용하지 않으면 그냥 props로 내려줘도 괜찮다고 생각하는데 조금 더 큰 프로젝트를 다뤄보면서 배우게 될 것 같다.

    • context를 관련있는 상태별로 구별해야될까???

      이 부분에서는 리렌더링 문제도 있기 때문에 그 상태의 변화로 인해서 변경되는 단위?로 묶어주면 된다고 생각한다.

회고

2주 동안 제이슨과 프로젝트를 진행하면서 전체적으로는 여유로웠지만 진행할 때만큼은 집중해서 했다. 10시~6시까지만 집중해서 하는 것을 목표로 하루를 제외하고는 모두 그렇게 했던 것 같다.

일단 큰 장점은 프로젝트를 끝나고 내가 부족했던 부분이나 추가로 공부해보고 싶은 부분에 공부할 수 있는 시간을 얻을 수 있었다. 그 시간 동안 알고리즘이나 react에 관련된 것들을 공부할 수 있는 시간을 가졌다.

이번에 프로젝트를 진행하면서 백엔드분들과 많이 소통한 부분도 좋았다. 이번 프로젝트는 API에 대해 매일매일 소통하면서 수정이 필요한 부분을 계속 수정하면서 진행했다. 처음에는 당연히 완벽한 API 설계가 될 수 없으니 매일매일 조금씩 발전시키면서 완성시켰고 이 과정이 너무 재밌었다.


코딩테스트 2차에서 vanilla JS로 상태를 통한 렌더링을 하는 미션이 많이 주어지고 있는 것 같다. 그 부분을 학습해야겠다.

profile
Kyle 발전기

2개의 댓글

comment-user-thumbnail
2021년 5월 20일

크.. 카일 라우터 넘나 멋짐다! 👍👍

1개의 답글