DURING | 뒤로가기로 오버레이 닫기

lynj·2023년 8월 11일
0
post-thumbnail

계기

어느 정도 가계부 앱의 구색을 갖추게 되니, 이젠 실제 유저들의 피드백을 받아야겠다고 생각했다.
빼곡히 약속을 잡고 지인들의 앱 사용 과정을 옆에서 직접 지켜보며 개선점을 찾았다.

그러던 중 까다로운 도전과제가 하나 생겼는데,
바로 '뒤로가기'버튼을 누를 때 현재 페이지를 유지하며 오버레이가 닫히도록 하는 것.

오버레이를 닫기 위해 뒤로가기 버튼을 누른 사용자가 있었다.
뒤로가기 동작은 이전 링크로 이동하는 것이고, 이전 링크는 서비스 화면 진입 이전의 링크이므로 아예 서비스 밖으로 튕겨나가버리게 되는 것이다.

'닫기' 버튼을 누르거나 백드롭을 눌러서 오버레이를 닫는 것으로 충분하다고 생각했었는데,
안드로이드 사용자들에게는 이전 버튼을 누르거나 제스처를 사용하는 것이 더 자연스러운 동작일 수 있었던 것이다.

해당 부분을 개선하려면 머리를 굴려야했다...

개발

해시를 사용했다.

해시만 변경되는 히스토리 간의 이동에서는 화면 전체가 리로드되지 않다.
이 점을 이용하여 히스토리 이동을 통한 오버레이 조작 구현에 성공했다.
이동은 react-router-v6의 useNavigate() 훅을 이용했다.

if (isOpen) {
  const url = `${location.pathname}${location.search}${location.hash}`;
  navigate(`${url}#${id}`);
} else if (location.hash.includes(id)) {
  navigate(-1);
}

오버레이를 열 때마다 현재 url 뒤에 해시를 붙여 navigate시켰다.
해당 해시는 오버레이 생성 시 props로 넘겨준 고유 id 값이다.
이렇게 하면 해시가 덧붙여진 히스토리가 쌓인다.

오버레이를 닫는 시점에 현재 id를 해시로 갖고 있다면,
뒤로 이동시켜 해당 해시가 붙기 이전 상태로 돌아가도록 한다.

개선

해당 기능 개발 이후...
한참 지난 시점에 리팩토링을 진행했다.

일단 제일 첫 랜딩화면과 인증과정부터 갈아엎기 시작했는데,
여기서 인증 처리 방식을 변경하며 문제가 생기기 시작했다.

모든 라우터의 부모가 되는 Root 라우트에서의 loader 사용이 문제였다...
navigate될 때마다 해당 loader가 동작하게 되어 컴포넌트가 리로드되는데,
이때 모든 상태가 초기화되어 오버레이가 애니메이션과 함께 부드럽게 내려가는 게 아니라 깜빡이며 사라지게 된다.

(사실 이전에도 Root에서 네트워크 체크를 위해 loader를 사용하고 있었긴 해서,
이게 리로드의 정확한 원인이 아닐 것 같긴 하다. 좀 더 연구해봐야하는 부분이다.)

  useEffect(() => {
    // NOTE: 오버레이를 닫아도 전체 페이지를 리로드하지 않도록 해시를 추가하여 해시 간의 이동으로 간주되도록 처리
    navigate('/landing#base', { replace: true });
  }, []);

해결 방법의 기본 원리는 이전과 같다.

베이스가 되는 모든 라우트에서 렌더링되는 컴포넌트, 즉 screen 디렉토리 이하의 컴포넌트가 로드될 때 #base 해시를 붙여놓는다.
이렇게 하면 오버레이를 닫을 때에도 #base#(오버레이id)의 상태에서 #base로 이동하는 해시 간 이동이 되어 리로드가 일어나지 않게 된다.

profile
Define, Design, Develop

2개의 댓글

comment-user-thumbnail
2023년 8월 11일

유익한 글이었습니다.

1개의 답글