어느 평화로운 오후,, 이슈카드가 올라왔다..!
잘못봤나 싶었다.
어떤 이슈냐하면🤔
검색 필터에서 검색 후, 상세 페이지에 들어간다. 다시 이전 페이지에 돌아왔을 때도, 검색어와 검색 결과가 일치하도록 원했다. (모든 검색 필터가 동일한 기능을 하도록 => 공통 컴포넌트 만든 후 갈아끼워야겠다고 생각했다.)
그 당시, 팀에는 혼자 밖에 없었다. 이게 가능할 지, 불가능할 지 몰랐다.
그냥 냅다 하겠다고 했다. 굉장히 단순하게 생각했다. swr에서 캐싱하니깐, 마지막 데이터 값을 가지고 유지하면 되지 않을까? (필자는 그냥 뭐든 Ready버튼이 눌러져 있는 거 같다.)
심지어 아주, 맹랑하게 4h으로 시간을 잡아놨다. (정확히 아는 선에서 EST하기를 바란다...)
(ㅠㅠ..)
계속 캐싱에 집착해서, 의미 없는 삽질을 굉장히 많이 했다..
방법을 찾기 위해서 react방에도 물어봤다.
이 글을 읽는 분도 구글링을 많이 하면서 보라색으로 물든 페이지가 익숙할 거라 생각한다.
결국에는 혼자 해결할 수 없는 문제라 판단했다. 그리고 팀원들이 충원 되었을 때 같이 고민하기로 하였다.
그러던 중, 새로운 팀장님이 입사 하셨다.
시간이 지나고 이야기를 꺼내자, search Params 써보는 걸 권했다.
그렇다. 페이지가 전환이 되고, 리렌더링을 하게 되면 상태값은 내부 컨텍스트에서 다시 초기값으로 할당되기 때문에 값이 휘발 된다.
그래서
검색 필터 부분은 useState로 관리 되고 있다. 그래서, 리렌더링 때는 쿼리스트링으로 써보려한다.
이유는 아래와 같다.
- 새로고침을 하더라도 필터가 그대로 유지된다.
- URL을 공유했을 때 서로 같은 데이터를 볼 수 있다.
- 단점도 따져보았을때, 데이터가 쉽게 노출 되기 때문에 보안 유지하는 데이터는 절대로 이 방식으로 넘기면 안된다.
이슈 카드에서 올라온 내용을 충분히 충족 시키기 때문에 결정하기로 했다.
query-string 쿼리스트링 라이브러리를 설치 해주자.
import queryString from 'query-string';
오늘의 주인공 설치 해주자.
import { useSearchParams } from 'next/navigation';
useSearchParams를 선언해준 뒤 const searchParams = useSearchParams(); 상수로 할당해서 써주자.
const query = useMemo(() => {
return {
...queryString.parse((searchParams && searchParams.toString()) || ''),
searchType: searchType ? searchType : undefined,
searchText: searchText ? searchText : undefined,
order: order ? order : undefined,
limit: limit ? limit : undefined,
};
}, [limit, order, searchParams, searchText, searchType]);
여기서 잠깐, searchParams.toString()는 쿼리 스트링의 값을 그대로 string 형태로 리턴해주는 메서드이다,
나는 필터 내부에 있는 값이 바뀔 때마다, 들고 있는 값을 바꿔주고, 지속되는 값은 연산하지 않도록 useMemo를 썼다.
해당 값을 setState로 뽑아온 후(useState 사용), 검색 버튼에서 쿼리스트링을 붙여주기로 하였다.
router.push(
queryString.stringifyUrl({
url: '/channels/category-mapping/list',
query: { ...query },
})
);
}, [confirmActions, query, router, searchText, searchType]);
onClickSearchButton을 누르면 해당 값 자체를 쿼리로 만들어서 넣는다.
useEffect(() => {
if (searchParams && searchParams.toString()) {
const { searchText, searchType, order, limit } = queryString.parse(
searchParams.toString()
);
setSearchText(searchText as string);
setSearchType(searchType as string);
setOrder((order as string) ?? 'id');
setLimit((limit as string) ?? '20');
}
}, [searchParams]);
useEffect를 통해서 searchParams값을 기억하게 한다.
사실 검색 필터 부분에 까다로운 요구사항이 있는데, 이번 화에 담지 못할 것 같다. 그 부분도 블로그에 따로 남기겠다!
현재 프로젝트에 전역상태를 사용하고 있지 않다보니, 로컬스토리지에 담아야하나 별 생각을 다 했다. 근데 결국엔 쿼리스트링을 알게되고 search Params도 알게 되면서 쿼리스트링이라는 객체 프로퍼티를 쓴다는 점이, 원하는 값을 편리하게 가져와서 좋았다. GET으로 보내는 데이터는 이렇게 쿼리스트링으로 해도 좋을 거같다. 해당 검색 부분은 독립적인 컴포넌트로 빼고, 자주 쓰는 selectbox는 훅으로 빼도 될 거 같다고 생각했다. 쿼리스트링의 값을 바뀌어도 데이터가 남아있다는게 참 신기했다. 데이터가 남아있게 하도록 useEffect 훅도 활용하고 등등 뿌듯했다. 역시 개발엔 안될 건 없다 그냥 시간이 더 필요할 뿐! 한층 더 성장 했다 !