개발 이야기/React & Next

[React/Next.js] 특수한 조건의 라우팅 컴포넌트 제작(삽질)기

Heman 2023. 2. 18. 22:03

[React/Next.js] 특수한 조건의 라우팅 컴포넌트 제작(삽질)기

라우팅 컴포넌트 정도로 삽질을 한다고?

현업 개발자 맞나요?


사용자 입력값을 라우팅하는 컴포넌트를 개발하는 것은 사실 어렵지 않습니다. 하지만 다 이유가 있다구욧..!

어디 한번 들어나 봅시다ㅋ

프로젝트의 기획을 담당하신 분께서 뒤로가기를 위한 공통컴포넌트가 필요해요라는 요건을 주셨습니다. 그런데 이 컴포넌트는 항상 사용자가 설정한 이전 페이지로 돌아가야한다는 제약 사항이 있었습니다.

그냥 버튼에 history.back() 을 넣으면 되는거 아닌가? 라고 생각했지만, 이전 페이지라는 단어에서 고민해볼 점이 생기게 됩니다.

그래서 고민해봐야 할 점은 뭔가요?

문제를 하나씩 짚어가며 이야기 해보면 좋을 것 같군요.

첫번째 문제
: window.history.back() 이나 router.back() 사용하여 뒤로가기

window.history.back() 코드를 사용하거나 Next.js 의 router.back() 코드를 버튼의 onClick 함수에 넣어주면 뒤로가기는 가능합니다.
하지만 매번 사용자가 원하는 페이지로 되돌아 갈 수는 없습니다.

아래의 순서로 예시를 들어보겠습니다. 도메인은 [project] 로 명명하겠습니다.

  1. 사용자가 youtube.com 을 방문
  2. 유저 상세 페이지인 [project]/user/detail?id=123 URL을 직접 브라우저에 입력하여 접속
  3. 해당 페이지에서 유저 리스트 페이지로 돌아가기 위해 뒤로가기 컴포넌트 클릭
  4. [project]/user/list 가 아닌 youtube.com 으로 이동

이처럼 단순 뒤로가기 기능으로는 기획 요건을 만족하지 않습니다.

그렇다면 뒤로가기고 뭐고 그냥 버튼 onClick 이벤트에 사용자가 원하는 주소로 navigate 해주면 되는 것 아닌가?

그래서 나온 두번째 문제ㅋ



두번째 문제
: router.push("/user/list") <a href=“user/list” … /> 사용하여 지정된 주소로 라우팅

이 방법은 "뒤로가기"처럼 보이지만, 확정적으로 지정된 주소로 라우팅 할 수 있습니다.
요건에 완벽히 부합하는 것 같은 간단한 해결법처럼 보이지만, 치명적인 단점이 있습니다 ㄷㄷ

그것은 바로 쿼리스트링을 유지할 수 없다는점..!

주소가 "/user/list" 인 유저 목록 페이지에서 유저 정보를 필터링하는 조건을 쿼리스트링에 담고 있다면, 유저 상세페이지인 /user/detail?id=123 를 방문 후 "뒤로가기" 버튼 클릭 시 쿼리스트링을 휘발시킨채로 주소이동을 할 것입니다.

좀 더 자세히 예시를 들면 이렇습니다.

주소가 "/user/list?hair=red" 인 유저 목록 페이지는 쿼리스트링에 머리가 빨간 사람을 필터링하고 있습니다.
머리가 빨간 사람 중 한명의 상세정보를 조회 후 "뒤로가기" 버튼을 클릭한다면, "/user/list?hair=red" 가 아닌 "/user/list" 주소로 이동할 것입니다.

점점 헷갈리기 시작했어..!


이..이미지를 준비했습니다;;

위 이미지와 같이 "뒤로가기" 컴포넌트는 외부 주소나 쿼리스트링을 담고 있지 않는 주소에서 접근했을때는 "/user/list" 로 이동하고, 쿼리스트링을 담고있는 이전 주소에서 접근했을때는 진.짜. 뒤로가기를 해주어야합니다.

그러기 위해서는 아래 이미지와 같이 컴포넌트에서 이전 페이지에 대한 정보를 갖고, 조건식에 따라 라우팅을 분기처리해야 한다고 생각했습니다.

 

그래서 어떻게 했는데?

이 문제를 해결해야했을 당시 4가지 정도의 해결방안을 생각해 보았는데요.

첫번째 해결방안.
: document.referrer

우선 기본적으로 document.referrer 를 사용하는 것이었는데, 이 api는 이전 페이지의 정보를 가져올 수 있지만 특정 링크를 통해서만 이동된 페이지의 정보만 알 수 있다는 제약사항이 있었습니다.

그래서 패스!



두번째 해결방안.
: 전역상태로 이전 페이지의 정보를 가지고 있기

너무 좋은 방법이죠. 하지만 새로고침 등 브라우저를 닫지 않았음에도, 특정 상황에서 휘발될 가능성이 있었습니다.
그래서 이 방법도 채택하지 않았습니다.

유저 상세페이지에서 새로고침을 했는데, 유저 목록에 존재해야할 쿼리스트링이 날아가는 것은 자연스럽지 않으니까요.



세번째 해결방안.
: window.history 에 쌓인 history 스택 정보 사용하기

사실 이 방법이 가장 좋다고 생각했습니다만, 이 부분은 웹 보안정책으로 현재가 몇번째 스택인지정도의 정보만 알수 있고, 스택에 쌓여있는 페이지들의 상세 정보는 알 수가 없었습니다 ㅠ

그리고 마지막 해결방안.  더..더이상은 NAVE..R....!



네번째 해결방안.
: 브라우저 내 스토리지에 이전 페이지 정보 저장

마지막으로 웹 브라우저 자체적으로 가지고 있는 로컬 스토리지나 세션 스토리지에 이전 페이지와 현재 페이지 정보를 수시로 저장하고,
교체를 하며 관리를 하면 좋겠다고 생각을 했습니다.

로컬스토리지에 데이터를 저장한다면 수동으로 삭제를 해줘야하기 때문에, 탭이나 브라우저 종료시에 자동으로 데이터를 소멸시켜주는 세션스토리지가 적합하다고 판단했습니다.



현재 세션 스토리지에 저장되어있는 최근 URL 정보를 가져와서 이전 URL로 등록을 한 후, 지금 사용자가 있는 페이지를 최근 URL로 등록하는 방식입니다.
이렇게 되면 다음페이지로 사용자가 넘어갔을때 지속적으로 이전페이지와 현재페이지 정보가 업데이트됩니다.

프로젝트 진행 당시 마지막 방안을 채택하여 적용을 했었는데, 요건대로 잘 동작했던 기억이 나네요 ㅎㅎ



사실 이후에 적용해보지는 않았지만 새로 생각해낸 방법이 하나 더 있습니다.

그런건 처음부터 말해..





마지막 해결방안.
간단하게 설명하면, 현재 페이지에서 다음 페이지로 넘어갈때 그냥 넘어가는 것이 아니라, 현재 URL 주소를 통으로 인코딩을 해서 쿼리스트링에 실어 다음 페이지에 기록을 하는 방식입니다.



이 방법의 장점이라고 생각되는 점은 특정 스토리지나 상태값으로 주소정보를 갖고 있지 않아도 되는 점입니다. 그렇기때문에 새로고침을 한다고 하더라도 쿼리스트링으로 이전주소를 갖고 있기 때문에 휘발되지 않습니다.

또한 쿼리스트링에 주소 자체를 기록 한것이기 때문에 탭이나 브라우저를 여러개 띄워놓고 사용을해도, 각각 다른 페이지 주소로 인식을 할 수 있는 장점이 있을 것 같습니다.



마무리하며

처음에는 간단하게 접근했던 요건이었는데, 여러가지 유저시나리오를 생각하다보니 개선점과 고민을 더 해볼 여지가 있었던 이슈였습니다.
역시 짱짱개발자의 길은 멀고도 험하군요..