9/4/2024
react router 뿐만 아니라 react를 사용하면서 조회 화면을 만들면 비동기로 fetch한 조회 결과나, 조회를 위한 조회 조건을 유지할 수 없는 문제가 있다.
예를 들면 페이지나 컴포넌트의 이동이 일어났을 때, 이전 페이지(컴포넌트)로 돌아가면 이전에 조회했던 내용이 전부 사라지고 초기화 된다.
이는 사용자에게 큰 불편함을 줄 수도 있는데, 목록 조회 페이지와 상세 페이지를 오가는 과정에서 목록 조회 페이지가 계속 초기화 된다면 매번 조회 조건을 설정하고 조회 버튼을 클릭 해주어야 하는 상황이 된다.
이를 방지하기 위해 페이지(컴포넌트)의 이동 직전에 마지막 상태를 저장해줄 필요가 있다.
React Router6를 사용한다고 가정하고 서술해본다.
React Router는 6부터 history 관련 객체 및 hook이 없어졌다. 대신 관련 기능들이 locaiton과 navigate로 옮겨갔는데,
본 문서에서 다룰 중요한 hook들은 useLocation
, useNavigate
, useSearchParams
이다.
먼저 살펴볼 것은 useSearchParams
hook이다.
해당 hook은 이름에도 나와 있듯 search param을 손쉽게 관리해주는 hook이다.
(설마 모르는 이를 위해 설명하자면 search param은 url에 명시되는 query string이다 "?param1=222¶m2=333" 이러한 형식)
const [searchParams, setSearchParams] = useSearchParams();
searchParams
는 URLSearchParams
가 주어진다.
searchParams
를 수정하려면 setSearchParams
를 호출하면 되는데, 간단하게 객체 형태를 넣어주면 된다.
setSearchParams({ key1 : value1, key2 : value2 })
이렇게 설정하면 자동으로 url에 ?key1=value1&key2=value2
가 붙게된다.
주의할 점은 setSearchParams
는 navigate
와 동일하게 동작한다는 점이다. 즉, setSearchParams
로 searchParams
를 변경하면 url만 바뀌는 것이 아니라, 실제로 페이지의 이동처럼 처리된다는 것이다.
실제로 setSearchParams
만 호출해도 history
에는 새로운 페이지가 push된다.
그렇기 때문에 setSearchParams
에는 두 번째 인자로 navigate
와 동일한 옵션 인자를 받는다. 만약 history
에 push되지 않고 현재 페이지의 history
를 덮어쓰고자 한다면 replace 옵션에 true를 주자.
자, 그렇다면 이제 이 useSearchParams
hook을 어떻게 사용할 것이냐. 간단하다. 조회 조건의 값들이 변경될 때 마다 searchParams
를 변경해주면 된다.
그러면 url에는 현재의 조회 조건들이 기록되어 남게되고, 새로고침이나 뒤로가기 등으로 다시 조회 페이지로 돌아오더라도 searchParams
를 통해 이전의 조회 조건들을 불러올 수 있게 된다.
react router를 사용한다면 useNavigate
hook은 익숙하게 사용할 것이다.
useNavigate
는 페이지를 이동하기 위해 사용하는 대표적인 hook인데, 첫 번째 인자로는 이동할 페이지의 라우터 path를 받고, 두 번째 인자로는 옵션 인자를 받는다.
옵션 인자에는 여러가지가 있는데, 본 문서에서 다루고자 하는 것은 state 옵션
이다.
state 옵션
은 이동한 페이지로 데이터를 전달하기 위한 방법으로 사용되는 옵션이다. useNavigate
hook에 전달된 state
는 이동된 페이지에서 location
을 통해 접근할 수 있다.
그렇다면 state 옵션
에 어떤 데이터를 전달해야 할까. 보통 이러한 방식을 사용하는 상황은 목록 조회 화면에서 상세 화면으로 이동할 때 나타난다.
즉, 상세 화면에서 다시 목록 화면으로 돌아갈 때 필요한 정보들을 state
로 전달해 주고 상세 화면에서 목록화면으로 돌아갈 땐 전달된 state
를 활용하여 돌아오도록 구현하는 것이다.
목록 화면에서 상세 화면으로 이동할 때 전달할 state
에는 조회 조건, 현재 조회된 목록 데이터 등이 있을 수 있다.
그리고 상세 화면에서 목록 화면으로 돌아갈 때 다시 그 state
를 전달함으로써 이전 목록 화면에서 과거의 목록 화면 상태를 유지할 수 있는 것이다.
그런데 상세 화면에서 목록 화면으로 돌아가는 것이 아니라 목록 화면에서 조회 후 다른 페이지를 갔다가 브라우저의 뒤로가기 기능을 이용해 다시 목록 화면으로 돌아올 경우엔 어떻게 될까?
위에서 서술한 방식은 상세 화면에서 특정 버튼을 통해, 즉 동일한 생애주기 안에서 이루어지는 컴포넌트간 이동에 적용되는 방식이다.
브라우저를 통해 새로고침을 하거나 뒤로가기를 통한 페이지 이동은 생애주기가 연결되지 않고 컴포넌트간 이동이 아니다.
따라서 별도의 처리가 필요한데, 본 필자는 이를 해결하기 위한 방법으로 목록을 조회할 때 마다 조회된 현재의 상태를 state
에 저장하여 history
를 replace하는 navigate
를 활용했다.
즉, 사용자는 느끼지 못하겠지만 조회 버튼을 클릭할 때 마다 history
는 매 번 새롭게 교체되는 것이다.
이렇게 교체된 history
에는 마지막으로 조회한 조회 결과 데이터 및 조회 조건들이 담겨져 있으니, 이제 브라우저에서 뒤로가기를 하여도 이전의 state
를 유지할 수 있게 된다.
이제 마지막으로 useNavigate
hook으로 전달된 state
를 활용하기 위한 useLocation
hook이다.
목록 조회 페이지에서는 useEffect
로 페이지 컴포넌트가 마운트 될 때, useLocation
으로 state
에 접근하여 존재하는 state
에 따라 조회 조건과 조회 결과를 초기에 설정해줄 수 있다.
결국 본 문서에서의 핵심은 바로 이 useLocation
이 되는 것이다.
useLocation
에 담긴 state
는 useNavigate
로 인해 전달된 값이 될 수도 있고, replace된 history
에 담겨있는 값이 될 수도 있다.
따라서 이를 사용하는 페이지(컴포넌트)에서는 어디서 담겨온 것이든 useLocation
의 state
를 통해 초기 상태를 이전의 상태로 설정할 수 있는 것이다.