달달 쇼핑은 모든 기능을 react로 만들고, 웹뷰를 통해 앱으로 서비스할 수 있도록 제작하였다.
웹뷰를 사용하면 고단한 점이 여럿 있지만, 그 중에서도 앱과 웹에서의 상이한 동작이 은근 구현하기 힘들다. (정확하게는 서치가 힘들다...)
오늘은 이 중 앱같은 화면 전환과 뒤로 가기 구현에 대해서 다뤄보도록 하겠다.
react native에서는 stack navigation
이라는 개념이 있다. 이는 데이터를 쌓는 자료구조의 stack처럼 화면을 stack에 쌓아 히스토리를 관리하는 navigation이다.
stack navigation을 사용하면 추가로 앱만의 화면 전환도 경험하게 된다.
이를 웹에서 구현하고 싶다면 어떻게 해야할까?
링크처럼 react native에서 navigation 관련된 기능은 모두 앱으로 빼는 방법이 있다.
위 예제는 단순히 exit, back 등의 기능을 하지만, 특정 페이지로 이동하는 navigation을 담당해야 한다면 앱으로 접근했다면 웹에서 페이지를 변경하지 말고, 앱과 웹 사이 bridge를 통한 통신을 사용하여 navigation을 하도록 설정할 수 있다.
하지만, 위와 같은 방법으로 웹으로 접근하는지, 앱으로 접근하는 지에 따라 다른 navigation을 제공하는 것은 번거롭다. 따라서, 애초에 웹과 앱 모두 앱처럼 navigation될 수 있도록 라이브러리나 프레임워크를 사용할 수 있다.
Stackflow는 모바일 디바이스(iOS/Android 등)에서 주로 활용되는 Stack Navigation UX를 JavaScript 환경에서 구현하고, 이를 통해 하이브리드 앱과 웹뷰 개발을 쉽게 할 수 있도록 돕는 프로젝트에요.
당근에서 stack navigation의 사용성을 제공하기 위해 만든 stackflow를 사용하여 구현할 수 있다.
stackflow는 history에 페이지를 push하거나 pop하는 방식으로 동작하고, 각 push 및 pop에 animate 옴션을 통해 페이지의 화면 전환을 적용할 수 있다.
Ionic is an open source UI toolkit for building performant, high-quality mobile apps using web technologies
또는, 웹 기술로 앱을 만드는 데에 사용되는 ionic framework를 사용해볼 수도 있다.
앱에서는 상황에 따라 왼쪽에서 오른쪽으로 슬라이딩되며 화면전환되기도 하고, 아래에서 위로 올라가며 화면 전환이 일어나기도 한다.
ionic에서는 개발자가 직접 원하는 화면 전환을 주입하여 사용할 수 있기 때문에 custom하기 좋다는 장점이 있지만, ionic router가 react-router-dom
의 구버전을 사용하고 있기 때문에 react 라우터 버전을 낮추어 사용해야 한다는 단점이 존재한다.
웹을 개발할 때에는 브라우저 자체의 뒤로 가기 기능을 제어할 일이 없었는데, 이번 프로젝트를 개발하면서 이전 페이지가 아닌 특정 페이지로 뒤로 가도록 해달라는 요구사항이 있었다.
위 내용을 상세한 예제로 살펴보자.
유저가 계좌 등록 페이지에서 뒤로 가기를 누르면 어디로 가야할까?
아무런 제어를 하지 않으면 다시 ARS를 인증하는 페이지로 넘어간다. 하지만, 이는 사용자 입장에서 정상적이지 않은 동작처럼 느껴지게 된다. 보다 자연스러운 흐름을 위해서는 해당 흐름이 시작하기 전으로 이동하는 것이 낫다.
토스에서는 flow
라는 모듈을 개발하여 위와 같은 기능을 구현한다.
모듈을 사용하면 여러 개의 페이지를 오가며 퍼널에서 해야 할 일을 수행하고, 할 일을 마치면 히스토리 스택을 비울 수 있어요.
아주 흥미로운 방법이지만, 토스에 비해서 flow가 단순한 우리 서비스에 적용하기에는 해당 방법이 공수가 크다는 생각이 들었다.
좀 더 단순한 방법으로 구현하기 위해 뒤로 가는 타이밍이 아닌, 화면을 전환하는 타이밍에 해결해보고자 하였다.
애초에 화면을 전환할 때 history에서 방금 지나온 페이지를 제거하면 뒤로 가기를 해도 이전 페이지로 가지 않겠다는 생각이 들었다.
이를 replace option으로 구현해보았다.
const navigate = useNavigate();
navigate('/주소 이름', { replace: true });
위 코드처럼 replace option을 true로 설정하면 페이지를 navigate할 때 페이지를 replace하면서 전환되기 때문에, history에 현 페이지가 남지 않아 원하는 대로 뒤로가기를 구현할 수 있다.
웹뷰는 고달프지만 오늘도...
웹뷰는 고려해야할 사항들이 많아서 힘들죠... 특히 히스토리는 대표적인 관리 포인트인데 잘 해결하셨네요. 멋집니다! :)