[React] 웹뷰 모달창 안드로이드 뒤로가기 버튼 제어하기

앤지·2022년 12월 21일
0

문제 발생

공통모달창을 만들고 나는 ios환경 다른개발자분이 안드로이드환경에서 테스트를 했는데 안드로이드 뒤로가기 버튼을 눌렀을때 모달창만 꺼지는게 아니라 페이지 자체가 이동한다는 버그를 말씀해주셨다.

뒤로 가기 버튼이요...??

참고로 필자는 ios만 사용하고 있기 때문에 안드로이드 버튼들의 존재자체를 몰랐었다.

그리고 ios에서 뒤로가기 위해서는 앱내에 버튼을 눌러서 이동해야했기 때문에 생각치도 못했었다. (이렇게 또 배워갑니다...)

고민의 흔적

문제가 발생하는 원인에 대해서 먼저 생각하였다.

페이지 이동시 뒤로가기 버튼 터치시 정상동작
모달창을 띄우고 뒤로가기 버튼 터치시 이상하게 동작

둘의 차이점이 뭔가 하니 모달창은 display속성을 바꿔주는거라 페이지이동이라 할 수 없다. 따라서 이 문제를 해결하기 위해서는 모달창을 띄움과 동시에 페이지 이동을 하는것 처럼 동작을 해야한다는 것이다. 그래야 안드로이드 환경에서 뒤로가기 버튼을 눌렀을때 모달창만 닫히는 기능을 구현할 수 있다.

리액트는 SPA방식을 이용하고 있기 때문에 리액트를 사용하고 있는 많은 개발자들이 페이지 이동을 위해 react-router-dom이라는 패키지를 다운받아 사용하고 있는데 react-router-dom 내부에서는 페이지를 이동할때 스택을 사용해서 페이지 이동시 마다 스택을 쌓고 뒤로갈수 있도록 하게한다.

그리고 그 기능을 구현하기 위해 브라우저 내장함수인 Browser history api를 사용하고 있는데 나도 그 api를 사용해서 문제를 해결해 보려 한다.

해결

해야 될것

  • 모달창을 열때 새로운 history stack 쌓아주기
  • 모달창 닫기 버튼이 아닌 뒤로가기 버튼이 눌렸을때의 이벤트 감지 후 모달창 닫기

모달창을 열때 새로운 history stack 쌓아주기

window.history.pushState(null, "", window.location.href);

history.pushState(state, title[, url]);

  • state : 상태 객체. 모달창을 위해 임시로 쓰일거라 null로 지정하였다.
  • title : 상태에 대한 짧은 제목. MDN에서는 빈문자열이라도 지정해 놓는게 좋다고 말함.
  • url : 새로운 상태의 url. 여기서는 window.location.href를 사용하여 현재 페이지와 같은 이름인 새로운 페이지로 이동시키고 히스토리에 기록을 남긴다.

모달창 닫기 버튼이 아닌 뒤로가기 버튼이 눌렸을때의 이벤트 감지 후 모달창 닫기

react-router-dom v6에서 사라진 history

v5까지 있었던 history객체가 v6로 업그레이드 되면서 사라졌다. (하...ㅠ)

따라서 history package를 설치하여 직접 구현하기로 햇다.

npm i history

// modal.js

useEffect(() => {
    const event = history.listen((listener) => {
      if (listener.action === "POP") {
        history.back();
        toggleModal();
      }
    });
    return event;
  }, [history]);
  • history 객체에 있는 listen method를 사용하여 현재 history에 일어나는 이벤트를 감지할 수 있다.
  • 만약 listener.action이 "POP"과 같다면 뒤로가기 버튼이 눌렸다는 뜻임으로 그 안에 우리가 원하는 동작을 하도록 코드를 짠다.
    나는 여기서 toggleModal을 함으로서 모달창을 닫아줬다.

결과는 정상적으로 동작한다 ! 웹뷰작업은 처음이라 고려해야될 사항도 많고 놓치는 부분도 굉장히 많지만 덕분에 배워가는것도 많다!

window.onpopstate를 사용하지 않은 이유

구글링을 하다보면 onpopstate 함수를 통해 스택을 pop해주는 방식도 있다.
물론 그것을 사용해서 기능을 구현해도 되지만 나같은 경우 두가지 경우
1. 모달창 닫기 버튼을 눌렀을때
2. 뒤로가기 버튼을 눌렀을때
를 고려해야 했는데 window.onpopstate를 사용하면 두가지 경우를 한군데에서 모두 처리해야했다.
history객체를 사용했을때는 두가지 별개로 처리가 가능해서 구현상 쉽게 그리고 버그가 생기지 않을것 같아서 사용하였다.

0개의 댓글