코로 넘어져도 헤딩만 하면 그만

[MD]Next에서 useSearchParams 사용(Suspense) 본문

Project

[MD]Next에서 useSearchParams 사용(Suspense)

꼬드리 2024. 9. 13. 17:08

🤔 useSearchParams 쓰니까 빌드가 안 된다고?

- app 라우터, Next14 사용 중 -

백엔드에서 전달 받은 에러

 

소셜 로그인 기능을 구현하면서 useSearchParams를 쓸 일이 있었다. 

유저가 로그인 성공한 뒤 사전에 정한 페이지로 redirect 되면 해당 페이지의 url로 들어온 인가 코드를 받아올 수 있다. 해당 인가 코드를 다시 백엔드로 넘겨 우리 프로젝트에서만 사용하는 토큰을 만들어서 받는 흐름의 로직이다.

 

이때 useSearchParams를 쓰면 쿼리 스트링으로 들어온 데이터를 쉽게 추출해서 사용할 수 있었다. 해당 훅을 사용하면 현재 url의 쿼리 스트링을 가져오는데, code라는 키로 들어온 값을 세션 스토리지 쪽으로 넘겨서 저장하는 순서였다. 스토리지로 잘 들어오는 것까지 확인하고 다른 작업을 먼저 하고 있었다.

//page.tsx
"use client";
import { useEffect } from "react";
import { useSearchParams } from "next/navigation";

const AuthRedirectPage = () => {
  const searchParams = useSearchParams();
  
  useEffect(() => {
    const code = searchParams.get("code");
    if (code) {
      sessionStorage.setItem("oauth_code", code);
    }
  }, [searchParams]);

  return <div>로그인 성공</div>;
};

export default AuthRedirectPage;

 

문제는 빌드하면서 발생했다.

백엔드에서 빌드를 하다가 해당 훅 관련으로 빌드가 멈추는 현상이 발생했다고 연락이 왔다. 

 

Generating static pages (1/9) [== ] ⨯ useSearchParams() should be wrapped 
in a suspense boundary at page "/auth". Read more:
https://nextjs.org/docs/messages/missing-suspense-with-csr-bailou

 

에러 메세지를 보면 클라이언트 컴포넌트, 서버 컴포넌트를 next에서 엄격히 구분하기 때문에 발생하는 문제 같은데. (React만 쓰다가 Next로 넘어오면서 이 구분 문제로 고생을 좀 했다. Provider 분리라던가...)

suspense boundary에 주목한다. suspense로 영역이 감싸져야 한다고? 

 

 

 

🤔왜 suspense로 막아줘야 할까?

 

Next.js 13 App Router useSearchParams Hook Behaviors That We Should Aware of

How to solve client-side rendering issues in Next.js when using the useSearchParams hook in a statically-rendered page/route

blog.bitsrc.io

 

Reading search parameters through useSearchParams() without a Suspense boundary will opt the entire page into client-side rendering. This could cause your page to be blank until the client-side JavaScript has loaded.

 

공식 문서에 useSerachParams 훅 관련으로 위와 같이 적혀 있는 것을 확인할 수 있다.

Suspense는 React에서 비동기 처리를 하는 동안 로딩 중일 때 다른 컨텐츠를 표시할 경우 사용한다. useSearchParams는 사용할 때 CSR을 필요로 하기 때문에 해당 영역이 client 컴포넌트가 되는데, 이에 대한 대안책으로 보인다. 

 

결론: React는 useSearchParams를 쓰게 될 경우 자신과 가장 가까운 Suspense 경계까지 렌더링을 일시 중단한다. 빌드 과정에서 useSerachParams를 사용하는 페이지 전체는 클라이언트 측에서 JavaScript 파일을 다운하기 전까지 빈 페이지가 되어 버린다. 따라서 Next에서는 Suspense로 감싸서 적절한 데이터를 가져올 때까지 대기하도록 처리해주는 것이다. 

 

공식 문서에도 적혀 있는 내용이니 확인하도록 하자.  

 

//page.tsx
//페이지 생성하는 파일에서 client 컴포넌트인 AuthRedirectPage를 불러온 뒤 Suspense로 감싼다.
import { Suspense } from "react";
import AuthRedirectPage from "./AuthRedirectPage";

const AuthPageWrapper = () => (
  <Suspense fallback={<div>Loading...</div>}>
    <AuthRedirectPage />
  </Suspense>
);

export default AuthPageWrapper;

 

상위 컴포넌트인 page.tsx에서 따로 뺀 페이지 코드를 Suspense로 감싸두니 기능 자체는 원활하게 돌아가고 있다.

페이지가 지저분해지는 것 같은데 이 방법이 최선인지, 다른 방식으로 관리 가능한지 추후 다시 생각해보는 것으로...

 

일단은 빌드는 무사히 되었다. Next에서 해당 에러가 뜰 때는 Suspense를 한번 체크해 볼 것을 권고한다.

 

 

참고/

 

Missing Suspense boundary with useSearchParams

Using App Router Features available in /app

nextjs.org

 

 

useSearchParams() should be wrapped in a suspense boundary at page "/loginPage". Read more: https://nextjs.org/docs/messages/mis

Next.js에서 useSearchParams() 사용 시 주의사항문제 상황다음과 같은 에러 메시지를 보신 적 있나요?useSearchParams() should be wrapped in a suspense boundary at page "/loginPage". Read more: https://nextjs.org/docs/messages/missi

intelloper.tistory.com

 

Comments