최종 팀 프로젝트

Rock Kyun·2024년 1월 25일
1

오늘 했던 것

  • MVP에서 조금씩 기능을 추가하고 디버깅..
  • 모바일 대응
  • 뒤로가기 시 페이지 전환 없이 UI 제어

작은 회고

  • 많은 일들이 있었지만 MVP 일정에 쫓겨 TIL을 작성하지 못 했다..
    정말 많은 디버깅과 리팩터링 추가 기능 구현 등...... 많은 것을 했지만,
    힘든 날에 TIL을 쓰지 못 했던 것을 반성한다..

뒤로가기 시 페이지 전환 없이 UI 제어

개발 1010시간 중에 제일 힘들었다

navigate, history 등 여러 정보를 찾아보고
뒤로가기 이벤트를 감지할 수 있는 window의 이벤트 종류까지😫

(아니 근데 고민했던 것보다... 너무 간단한 거 아니오....)

1. 문제의 발단

  • 채팅 페이지는 처음 채팅방 목록과 채팅메세지가 뜨는 컴포넌트로 분리해놨었다.
    (반응형 디자인을 보고 이것이 신의 한 수였다는 것을 깨달았다..)

  • 분리가 잘 되어있던 컴포넌트의 스타일을 변경하여
    768px 이하에서는 메인에 채팅방 목록이, 채팅방을 클릭하면 채팅창이 열리는 구조인데

😫 UI에 만들어놓은 뒤로가기를 누르지 않으면, 완전히 이전 페이지로 간다..😫

2. 문제 접근

"클릭 이벤트처럼 이벤트를 감지하고 막는 뭔가가 있겠지..."

근데 그런 건 없었다 엉-엉-🥺

하지만 window 이벤트 리스너의 popstate를 찾게 되었는데
window.history.pushState()를 통해 쌓은 스택을
뒤로가기 버튼 클릭 시 popState 하는 것이다.
배열의 push, pop과 같았다. 여기서 콧구멍이 조금 드릉드릉 했던 거 같다.

간단하게 pushState, popState를 설명해보자면
어떤 요소를 클릭하면 pushState를 하여 스택을 쌓도록 해놓은
페이지에 방문을 했다 가정을 해보자

[클라이언트의 활동]           [스택]

   페이지 방문       =>        0
  pushState작동     =>        1
  또 pushState      =>        2
뒤로가기 (popstate)  =>        1
뒤로가기 (popstate)  =>        0
뒤로가기 (popstate)  =>  이전 페이지로 전환

이런 느낌이다.
원래는 뒤로가기를 누르면 해당 페이지에 어떤 것이 떠있든
스택이 0일 때는 뒤로가기는 기본 작동을 막을 수가 없다.
다만, 스택이 하나라도 있다면 뒤로가기를
내가 제어할 수 있다는 것!

하지만 위의 그림(?)처럼 어떤 요소를 클릭해서 스택을 쌓았다면
뒤로가기 시 페이지 전환은 없이 스택이 하나 제거되고 끝이나는 것이다.

3. 해결

  • 이제 내가 뭘 해야 되는지 확실히 알았다🥹

1. 스택 쌓기

먼저 채팅방을 눌렀을 때 채팅창 컴포넌트가 등장하도록 하는
함수에 pushState(null, '', '') 이렇게 빈 스택을 쌓도록 하였다.
이제 채팅방을 하나 누를 때마다 빈 스택이 하나씩 쌓인다.

 // 채팅방을 누르면 채팅창 styled-components를 조작해
 // 우측에서 채팅창이 쇽- 등장하게 하는 함수
 const handleBoardPosition = () => {
   // 채팅방을 하나씩 들어갈 때마다 스택하나 추가
   window.history.pushState(null, '', '');
   setboardPosition(0);
 };

2. 뒤로가기 시 스택 제거, 채팅창 원위치

useEffect(() => {
  const handlePopState = () => {
    // 뒤로가기 누르면 스택이 하나 빠지고
    if (boardPosition === 0) {
      // 만약 채팅창이 나와있으면 원위치로 돌려주고
      handleHideBoardPosition();
    } else {
      // 스택이 없으면 바로 이전 페이지로
      navi(-1);
    }
  };

  // 뒤로가기 이벤트를 감지하기 위한 리스너
  window.addEventListener('popstate', handleClickBrowserBackBtn);

  // 언마운트 시 리스너 제거
  return () => {
    window.removeEventListener('popstate', handleClickBrowserBackBtn);
  };
}, [boardPosition]);

결과

느낀점

해결하면서 정말 힘들었고
어떻게 하면 될 거 같다! 라는 생각이 막혀서 더 힘들었다.
정말 유용하고 좋은 것을 배웠고
해결한 후에는 감동적이었다.. 광광 우럭따...

0개의 댓글