안녕하세요. 제로초입니다.
곧 리액트 19, Next 15가 나올 것 같은데 12월 안에 정식 버전이 나온다면 강의 정책대로 영상 추가 제작해서 올리겠습니다. 기존에 헷갈려하셨던 부분도 대거 재촬영 예정입니다(next-auth, Streaming 같은 것).
Streaming, Suspense 관련해서 문의가 많아서(보통은 SSR, SEO를 위해서 도입하곤 하시죠?) 아래에 정리해보았습니다. 더 궁금하신 점 있으면 질문 남겨주시면 됩니다.
감사합니다.
조현영 드림.
서론: 일단 강의를 위해 SSR을 적용한 걸 보여줬지만 추천게시글 목록 같은 것은 SSR할 필요도, 목록에 대한 SEO도 필요 없음. 매번 게시글이 바뀌기 때문. 개별 게시글 페이지(/post/[id]) 같은 것만 SEO 적용할 것.
loading.tsx 없고 prefetch 있는 경우
유일하게 컨텐츠 SSR 되는 케이스(다만 handlers.ts에서 delay를 걸어둔 경우 첫 로딩이 오래걸림)
SSR이 되나 prefetch가 끝나야 화면이 보이므로 사용자가 답답해할 수 있음
loading.tsx 없고 useSuspenseQuery만 있는 경우
fallback 부분이 없어서 그런지 무한 요청 보내짐(사용X)
https://github.com/TanStack/query/issues/6116#issuecomment-1904051005 로 해결 가능
loading.tsx 있고 prefetch 있는 경우는
loading.tsx가 뜨고 3초 뒤에 게시글이 뜸. 따라서 SSR 안 됨
metadata나 generateMetadata로 SEO 정보 넣어줘야 함
loading.tsx 있는데 Suspense도 하나 더 있고 prefetch는 있는 경우
Suspense fallback이 뜨고 3초 뒤에 게시글이 뜸. 따라서 SSR안 됨
컨텐츠 SSR 안 됨. metadata나 generateMetadata로 SEO 정보 넣어줘야 함
loading.tsx 있는데 prefetch는 없는 경우
컨텐츠 SSR 안 됨. metadata나 generateMetadata로 SEO 정보 넣어줘야 함
isPending: true일 때 로딩 보여주게 직접 코딩해야 함
여기까지 알 수 있는 점: loading.tsx도 Suspense의 일종이고, Suspense는 prefetchQuery나 useSuspenseQuery가 있는 경우 작동한다.
loading.tsx와 prefetchQuery 중간에 Suspense가 있으면 중간 것이 작동한다. 그 이유는 loading.tsx도 Suspense라서 Suspense구조가 loading.tsx->중간 Suspense->prefetchQuery이면 prefetchQuery는 중간 Suspense에 걸림.
loading.tsx 있고 Suspense + useQuery 있고 prefetch 없는 경우
Loading.tsx 작동 안하고 Suspense 작동 안 함. isPending: true의 로딩이 보여짐
loading.tsx 있고 Suspense + useSuspenseQuery 있고 prefetch 없는 경우
Loading.tsx 작동 안하고 Suspense fallback의 로딩이 보여짐
서버에서 한번, 프론트에서 한 번 총 두 번 요청하므로 비효율
loading.tsx 있고 Suspense 없이 useSuspenseQuery 쓰는 경우
loading.tsx 씀.
서버에서 한번, 프론트에서 한 번 총 두 번 요청하므로 비효율
결론:
SSR이 전체적으로 완벽하게 되길 원하면, loading.tsx & 별도 Suspense 없이 prefetchQuery만 사용
useSuspense 시리즈 문제 있으므로 쓰지 말 것
SEO를 metadata로 대신 할 수 있다면 Suspense를 두고 prefetchQuery하거나 Suspense 없이 useQuery + isPending 로더 쓰면 됨. 전자는 서버에서 가져오는 것이고, 후자는 클라이언트에서 가져오는 것. SSR도 안 하는데 전자로 할 이유 없으므로 후자 추천
loading.tsx를 쓸지 별도의 Suspense를 둘지 선택하는 기준: Loading.tsx는 페이지 전체를 로딩하므로 부분만 로딩하고 싶다면 별도의 Suspense 사용
layout.tsx에서는 Suspense 안 먹음