개발자일기/리액트 이야기

[React] URL을 이용한 검색 상태 관리: Hooks를 활용한 효율적인 방법

뫙뭉 2023. 5. 13. 09:54
반응형

우리가 흔히 사용하는 검색 플랫폼으로는 구글, 네이버 등이 대표적이다.

해당 플랫폼에서 검색을 해보면 단순히 화면만 바뀌는 것이 아니고 URL도 바뀌는 것을 확인할 수 있다.

검색 뿐만 아니라 여러 필터기능도 URL을 변경시키는 것을 확인할 수 있다.

해당 사항은 얼마전 검색 기능을 구현하면서 고민하게 되었던 부분이다.

화면만 바뀌어도 무방할 것 같은데 왜 URL도 바뀌게 한 걸까. 분명히 이에 따른 장점이 있어서 그런것일 텐데..

그래서 여러 고민과 검색 끝에 알아낸 것이 있다.


검색을 하면서 URL이 바뀌게 해야하는 이유 3가지

1. 사용자 경험 개선

URL에 검색어나 필터를 포함시키면 사용자가 현재 검색상태를 쉽게 이해할 수 있음. 그리고 URL을 통해 검색 결과를 북마크하거나 공유할 수 있게함. (URL 복사해서 카톡에 보내주기 같은 것)

2. 브라우저 히스토리

검색상태에 URL이 포함되면 뒤로가기, 앞으로 가기를 했을 경우, 이전 검색상태로 돌아가기가 쉬워짐

3. 웹 크롤러 최적화

검색 엔진 크롤러가 URL을 기반으로 콘텐츠를 수집하고 인덱싱함. 따라서 검색상태를 URL에 포함시키면 웹크롤러가 쉽게 해당 페이지를 인식하고 분석할 수 있음. -> SEO(검색 엔진 최적화)에 도움이 됨.

생각보다 많은 역할을 하고 있다는 것이었다는 것이었다... 역시 괜히 있는 것이 아닌 것.

이제 이렇게 하는 이유는 알게 되었으니 다음으로 구현을 어떻게 할 것인가가 관건이다.


URL을 통해 핸들링 가능한 검색기능을 구현해보자.

우선 해당 기능 구현에 있어 고려해야 할 사항 5가지를 정했다.

1. URL을 입력하면 검색 input창, 필터 체크박스가 이에 맞게 변경되어 있어야함.

2. 사용자가 URL을 직접 입력하는 것 만으로도 검색 기능이 작동되어야 함.

3. onChange로 변경된 state는 URL을 변경시켜야함.

4. url에 포함된 쿼리 파라미터를 파싱해서 가져와 API 요청을 보내야 함.

5. 공백 또는 특수문자가 포함된 검색어는 적절하게 변환시켜서 URL에 포함시켜야 함.

 

단순히 Input창에 의해 state가 바뀌어 API 요청을 보내는 상황이라면 굉장히 간단하다.

- onChange 이벤트에 setState를 넣고, 엔터 또는 검색 버튼을 눌렀을 때, 요청을 보냄.

- 요청을 통해 받은 데이터를 랜더링함

 

하지만 위와같은 상황을 고려해야 한다면 다음과 같이 로직이 바뀌어야 한다.

- 검색버튼을 누르면, 필터와 검색어 상황에 맞게 URL만 바뀌어야함.

- useEffect에 URL이 변경될 때마다 API 요청을 자동으로 보내도록 함. 쿼리 파라미터를 전달.

- 요청을 통해 받은 데이터를 랜더링함.

반응형

 

위의 고려사항은 다음과 같은 해결법으로 처리해야 겠다고 생각했다.

  1. URLSearchParams와 React Router의 useLocation 훅 사용
    • const query = new URLSearchParams(useLocation().search)
    • useLocation을 통해 현재 URL의 search 부분의 parameter를 가져오고 그것을 **URLSearchParams**에 넣어 조건, 검색어 등을 get을 통해 가져올 수 있음.
    • query.get("query")를 하면 내가 query로 설정해 놓은 부분을 가져올 수 있음.
  2. 사용자가 직접 URL에 검색어 및 조건을 입력하였을 경우, 잘못된 형식일 시 적절한 처리가 필요함.
    • 사용자가 잘못된 쿼리 파라미터를 입력한 경우, 애플리케이션은 이를 무시하거나 사용자에게 경고 메시지를 표시할 수 있게 처리.
  3. 검색 조건 및 검색어를 URLSearchParams 와 history 관련 메서드를 사용해 URL 변경
    const handleSearch = () => {
        const params = new URLSearchParams();
        params.append("query", searchInput);
    
    	// 여기에 추가적인 검색 조건을 추가할 수 있습니다.
        // 예: params.append("category", category);
    
        if (latest) {
            params.append("latest", "true");
        }
    	history.push(/search?${params.toString()});
    };

    • history.push는 사용자가 뒤로가기를 하였을 때, 기존의 검색 상태로 돌아갈 수 있게 할 경우 
      •  push는 새로운 기록을 만들어 추가하는 것으로, 뒤로가기 시 이전의 상태로 돌아갈 수 있음.
    • history.replace는 사용자가 뒤로가기를 하였을 때, 기존의 검색 상태로 돌아가지 못하게 할 경우
      • replace는 새로운 기록을 만들지 않고 현재의 기록을 변경만 하므로 뒤로가기 버튼을 사용해도 이전 상태로 돌아가지 않음
      • 예를 들어 로그인 후에 뒤로가기를 눌러도 로그인 페이지로 가지 못하게 처리하는 것이 자연스러운데 이럴 경우 사용함.
      • 특정 페이지로 가지 못하게 하는 경우는 위와 같이 replace를 사용하는 방법도 있지만 PrivateRoute를 사용하는 방법도 있음.  다만 사용처가 다름
        •  replace: 뒤로가기 버튼을 눌렀을 때 이전 경로 대신 특정 경로로 이동하게 만듦
        •  PrivateRoute: 특정 조건이 충족되지 않을 때, 강제로 다른 경로로 이동하게 만듦
    • 검색하기 기능이 실행되면, 검색어와 검색 조건으로 API 요청을 하는 것이 아닌, URL을 변경시켜야함
    • 검색어와 검색 조건을 url이 변경되었을 시 가져옴
      • useEffect를 통해 url이 변경되었을 때를 캐치하고 1번 코드와 마찬가지로 검색어와 검색 조건을 가져옴.
      const location = useLocation();
      
      useEffect(() => {
      //...
      }, [location])
      • 가져온 후에 API 요청을 보냄
  4. 1번의 코드와 마찬가지로 검색어 및 검색 조건을 가져와서 API 요청을 보냄
  5. 검색어에 띄어쓰기나 특수문자가 포함되어 있을 경우를 대비해 encodeURIComponent 메서드를 사용하여 검색어를 변경함
// 'React tutorial'을 검색할 경우

const searchTerm = 'React Tutorial';
const encodedSearchTerm = encodeURIComponent(searchTerm);
console.log(encodedSearchTerm);  // 'React%20Tutorial'

 

마무우리

뭔가 새로운 고민을 스스로 찾아보고 해결해 본다는 것이 참 재밌다. 이게 개발자를 하는 이유가 아닐까.

가끔 어떤 사이트를 보면, 페이지는 바뀌는데 URL이 그대로여서 당황스러울 때가 있다. 그리고 그런 사이트는 대부분 뒤로가기를 누르면 이전 상태를 보여주는게 아니라 사이트를 빠져나오게 된다는 것.

URL을 핸들링 하는 것이 중요하다는 것을 깨달으며 잘 다뤄줘야겠다는 생각을 하며 마치겠다.

 
 
반응형