SPA
라우팅에 필요한 대부분의 기능을 브라우저의 자바스크립트에 의존하는 방식
- 최초 내려받은 HTML에서 모든 작업을 처리한다. (오직 하나의 HTML을 가진다.)
- 최초에 로딩해야 할 자바스크립트 리소스가 커지는 단점이 있다.
- 한번 로딩된 이후에는 서버를 거쳐 필요한 리소스를 받아올 일이 적어져 빠르게 쾌적한 페이지 전환이 가능하다.
웹서비스의 새로운 패러다임
- 많은 양의 자바스크립트가 리소스로 넘어오며 코드 규모가 점점 방대해진다.
- 모바일 환경에서는 웹 사이트의 로딩 속도가 느리다.
- 더 나은 웹 서비스 환경에 대해 고민해야 한다.
서버 사이드 렌더링 (SSR)
렌더링에 필요한 작업을 모두 서버에서 수행한다.
클라이언트 렌더링은 사용자 기기 성능의 영향을 받지만 서버 사이드 렌더링은 비교적 안정적인 렌더링이 가능하다.
서버 사이드 렌더링 장점
- 최초 페이지 렌더링이 빠르다.
- 검색 엔진 및 메타데이터 제공에 유리하다.
- 누적 레이아웃 이동이 적다.
- 사용자의 디바이스 성능에 비교적 자유롭다.
- 보안에 좀 더 안전하다.
서버 사이드 렌더링 단점
- 소스 코드 작성할 때 서버를 고려해야 한다.
- 서비스 지연에 따른 문제 (서버가 렌더링 하는데 오래걸리면 그 만큼 빈화면이 보여짐)
- 각 페이지 요청마다 서버에서 HTML을 새로 생성해야 하므로 서버 부하가 증가한다.
가장 뛰어난 SPA
최초 진입시 보여줘야할 정보만 최적화 시키고, 이미지와 같은 중요도가 떨어지는 리소스는 게으른 로딩으로 처리하며, 코드 분할 또한 완벽하다면 브라우저 API와 JS를 활용한 라우팅 기반의 SPA는 완벽하다.
최근 서버 사이드 렌더링
Next, Rmix와 같은 SSR 프레임 워크는 최초 웹 사이트 진입 시에는 서버에서 완성된 HTML을 제공받고, 이후 라우팅에서 서버에서 내려받은 자바스크립트를 바탕으로 SPA처럼 작동한다.
서버 사이드 렌더링을 위한 리액트 API 살펴보기
renderToString
인수로 넘겨받은 리액트 컴포넌트를 렌더링하여 HTML 문자열로 반환하는 함수
const result = ReactDOMServer.renderToString(
React.createElement('div', {id: 'root'}, <SampleComponent />)
)
// result
<div id="root" data-reactroot="">
<div>hello<div>
<ul>
<li>apple</li>
</ul>
</div>
SampleComponent를 렌더링하여 문자열로 변환한다.
여기서 주의할 점은 훅 이나 이벤트 핸들러는 결과물에 포함되지 않는다.
추후 자바스크립트 코드를 모두 다운로드, 파싱, 실행하는 과정을 거쳐야 한다.
renderToStaticMarkup
renderToStaticMarkup은 renderToString과 매우 유사한 함수이다. 두 함수 모두 리액트 컴포넌트를 기준으로 HTML 문자열을 만든다는 점에서 동일하다. 차이점은 리액트에서만 사용하는 추가적인 DOM 속성을 만들지 않는다.
즉 renderToStaticMarkup은 hydrate가 필요없는 정적인 HTML 용도로 사용해야 한다.
블로그 글이나 상품의 약관 정보와 같이 이벤트 핸들러가 필요 없는 정적 내용만 전달할 때 유용하다.
renderToNodeStream
renderToString과 결과물이 완전히 동일하지만 타입이 다르다.
renderToString은 String이지만 renderToNodeStream은 ReadableStream이다.
- ReadableStream은 큰 HTML을 작은 단위로 쪼개 작성함으로써 Node.js 부담을 덜 수 있다.
- 대부분 리액트 서버 사이드 렌더링 프레임워크는 renderToNodeStream을 채택한다.
renderToStaticNodeStream
renderToNodeStream에서 hydrate가 필요없는 HTML에 사용된다.
hydrate
정적으로 생성된 HTML에 이벤트와 핸들러를 붙여 완전한 웹페이지를 만든다.
renderToString과 renderToNodeStream으로 생성된 HTML 콘텐츠에 자바스크립트 핸들러나 이벤트를 붙이는 역할
render vs hydrate
render는 컴포넌트를 렌더링하며, 여기에 이벤트 핸들러를 붙이는 작업까지 모두 한 번에 수행한다.
hydrate는 이미 렌더링된 HTML을 기준으로 이벤트를 붙이는 작업만 실행한다.
hydration시 브라우저에서 한번 더 렌더링을 한다.
hydrate가 수행한 렌더링 결과물 HTML과 인수로 넘겨받은 hTML을 비교했을 때 불일치가 발생하면 에러가 생기고, 다시 웹 페이지를 그린다.
Page Router
pages 폴더를 기반으로 라우팅을 한다.
_app.tsx는 모든 page 컴포넌트의 부모 컴포넌트 역할을 한다.
또한 공통으로 설정해야 하는 것들을 여기에 실행한다.
- 에러바운더리
- 전역 css
- 모든 페이지에서 사용되는 데이터 제공
_document.tsx는 Layout의 역할을 하는 것으로 뼈대가 되는 HTML 설정과 관련된 코드를 추가하는 곳이다.
Next 프리패칭
Next Link로 연결되어 있는 모든 페이지들을 사전에 미리 다 불러와 놓는 그런 기능을 말한다.
즉 내부 링크를 클릭하기 전에 현재 페이지에서 이동이 가능한 모든 페이지들에 필요한 데이터를 미리 불러와 놓는다.
리액트에서 모든 JS Bundle을 다 불러왔는데 왜 프리패칭 같은 기능을 더 추가했나?
→ Next는 페이지별로 JS를 스플리팅해서 전달되기 때문이다.
→ /search 페이지로 접속하면 /search 페이지에 해당하는 JS 파일만 전달된다.
API Routes란
Next에서 API를 구축할 수 있게 해주는 기능이다.
API 주소는 pages 파일과 다르게 HTML 요청을 하는 것이 아니라 서버 요청을 주고 받는다.
리액트에서 데이터 패칭
리액트에서 데이터 패칭은 마운트 되고 나서 실제로 데이터 패칭 작업이 진행된다.
FCP 이후 데이터 로딩이 진행되기 때문에 더 늦어지게 된다.
Next에서 데이터 패칭
Next는 서버에서 렌더링 진행될 때 서버에서 데이터를 받아 진행한다.
만약 서버에서 서버 패칭하는 작업이 대용량이라 오래 걸릴 경우, 사용자는 빈화면을 보게 된다. Next는 이러한 문제를 해결하기 위해 빌드타입에 사전 렌더링을 진행하는 방법으로 지원한다.
SSR
SSR이란 요청이 들어올 때 마다 사전 렌더링을 진행 하는 방식이다. (build 타임 x)
SSR을 하기 위해서 page 최상단 경로에 getServerSideProps라는 함수를 정의하고 export 해야한다.
이 함수는 매 페이지를 호출할 때마다 실행되고, 이 실행이 끝나기 전까지는 사용자에게 어떠한 HTML도 보여줄 수 없다.
최초에 보여줘야 하는 데이터가 아니라면 getServerSideProps보다 클라이언트에서 호출하는 것이 더 유리하다.
getServerSideProps에서 데이터 패치 병렬
Promise.all 문법을 사용하게 되면 병렬적으로 데이터를 패치할 수 있다.
getServerSideProps에서 쿼리스트링 받는 법
'한입'이라는 쿼리 스트링을 파싱하고 싶다.
context를 이용하면 된다.
SSR 정리
항상 사용자가 요청할 때마다 백엔드에 API를 날려 최신 데이터를 받아올 수 있다는 장점이 있다.
반면 데이터 크기가 크다거나 서버가 좋지 않다거나 데이터 응답 속도가 느려지게 된다면 결국 늦게 렌더링 될 수 밖에 없다.
SSG
SSR의 단점을 해결하기 위해 빌드 타임에 사전 렌더링을 진행하는 방식이다.
SSG 특징
장점은 사전 렌더링에 많은 시간이 소요되는 페이지더라도 사용자의 요청에는 매우 빠른속도로 응답한다.
단점은 빌드 이후에는 새로운 데이터를 반영하기 힘들다. 매번 똑같은 페이지만 응답한다.
getStaticProps를 사용하면 된다.
SSR은 getServerSideProps인데 대신 getStaticProps로 변경하면 된다.
만약 쿼리스트링 사용하는 페이지에 SSG를 사용하면 어떻게 될까?
→ 에러가 발생한다. 빌드 타임에 사용자가 어떤 것을 입력했는지 쿼리스트링을 알아올 방법이 없기 때문에 context를 지원하지 않는다. 이럴 때에는 클라이언트 측에서 데이터를 패치하는 방법으로 가야한다.
동적 경로에 대한 SSG 설정하기
이러한 동적 경로에 SSG 설정하는 방법
먼저 경로를 먼저 설정한 후 사전 렌더링을 해야한다.
즉 모든 경로들을 직접 설정하는 작업을 먼저 진행해야한다.
그 메서드가 getStaticPaths이다.
getStaticPaths를 통해 경로들을 먼저 설정한 다음,
getStaticProps로 일일이 한 번씩 다 호출해서 사전에 여러 개의 페이지를 렌더링 한다.
여기서 getStaticPaths로 dynamic Routes에 들어갈 id값을 반드시 string값으로 정의한다.
fallback 3가지 옵션
- false → paths에 없는 값을 호출하게 될 경우 404가 된다.
- blocking → SSR으로 사전 렌더링 후 반환한다. 그리고 정적 페이지로 저장된다. (데이터 크면 단점)
- true → 빈화면이 아닌 데이터가 없는 화면을 먼저 보여주고 데이터 패칭이 완료되면 보일 수 있게 한다.
ISR
SSG 방식으로 생성된 정적 페이지를 일정 시간을 주기로 다시 생성하는 기술
주기 동안 기존 V1 반환하다가 유효기간 끝나면 첫 요청에는 V1 그 뒤에 V2 반환
매우 빠른 속도로 응답 가능 (SSG 방식의 장점)
최신 데이터 반영 가능 기존 (SSR 방식의 장점)
getStaticProps에 revalidate 옵션을 추가하면 ISR이 된다.
여기에서 3초마다 재생성된다는 것이다.
그리고 ISR은 시간이 지나면 알아서 바뀌는 것이 아니라 사용자가 접속할 때 바뀌게 된다.
ISR을 적용하기 어려운 페이지도 존재한다.
시간과 관계없이 사용자의 행동에 따라 데이터가 업데이트 되는 페이지 (만약 사용자가 글을 수정했다면?)
이 때 사용하는 것이 On-Demand ISR이다.
요청을 받을 때마다 페이지를 다시 생성하는 ISR이다.
API Routes 기능을 사용한다.
api 폴더에 revalidate.ts라는 파일에 해당 함수를 정의한다.
그러면 /api/revalidate api가 만들어진다.
만약 블로그나 제품 정보가 백엔드에서 변경되었으면 백엔드에서 이 API를 호출하여 다시 업데이트 시켜줄 수 있다.
주로 ISR / SSG를 주로 쓰되
SSR은 최신 데이터를 보여줘야 되는 페이지 (거래 내역, 주식 차트)나 개인화된 페이지등에 사용한다.
SEO 최적화
리액트와 달리 각 페이지 별로 메타 태그를 설정해 줄 수 있다.
Page Route 정리
장점
- 파일 시스템 기반 간편한 페이지 라우팅 제공
- 다양한 방식의 사전 렌더링
단점
- 페이지별 레이아웃 설정이 어렵다.
- 데이터 페칭이 Page 컴포넌트에 집중된다. (Props drilling 문제 발생)
- 불필요한 컴포넌트들도 JS 번들에 포함된다. (여기서 불필요한 컴포넌트들은 상호작용하지 않는 컴포넌트들을 말한다.)
그 결과 JS Bundle이 커진다는 큰 단점이 존재한다.
App Route
page router와는 다르게 app router는 폴더 경로에 page.tsx 파일이름을 해야 한다.
App Route에서 쿼리스트링 받는 법
'한입'이라는 쿼리 스트링을 파싱하고 싶다.
SearchParams라는 props로 전달된다.
동적 경로 id값 받는 법
/book/200에서 동적 경로 id값인 200을 받고 싶다.
마찬가지로 params라는 props로 전달된다.
그리고 쿼리스트링이나 URL 파라미터 값을 꺼낸 땐 Promise로 꺼낸다.
Layout 설정
레이아웃은 하위 경로도 포함된다.
중첩이 되는 것이다.
라우트 그룹
()을 사용해서 그룹을 설정할 수 있다.
React Server Component란?
React 18v 부터 새롭게 추가된, 새로운 유형의 컴포넌트
기존의 컴포넌트들과 달리 오직 서버 측에서만 실행 되는 컴포넌트를 말한다. (브라우저에서 실행 안됨)
기존 문제점
- 서버에서 미래 렌더링 된 HTML을 보낸다.
- 추후 하이드레이션을 위한 JS Bundle을 후속으로 전달한다.
- 브라우저에서는 하이드레이션을 위해 한번 더 렌더링된다.
여기서 JS Bundle에는 모든 컴포넌트들이 다 있을 필요가 없었다.
useEffect나 이벤트 핸들러들이 붙어있어 hydrate가 필요한 컴포넌트들이 있지만, React Hook이나 이벤트 핸들러가 없어서 hydrate가 필요없는 컴포넌트들도 존재한다.
→ 페이지 라우터는 이런 것들을 전부 다 내려보내준다.
→ JS Bundle이 커지고 오래 걸림
개선
상호작용 없는 컴포넌트들 (브라우저에서 hydrate 될 필요 없는 컴포넌트)를 빼면 된다.
페이지 대부분을 서버 컴포넌트로 만들고, 필요한 부분만 클라이언트 컴포넌트로 사용하자
주의점
- 클라이언트 컴포넌트에서 서버 컴포넌트를 import 할 수 없다.
- 서버 컴포넌트에서 브라우저에서 실행할 코드가 포함되면 안된다.
- 서버 컴포넌트에서 클라이언트 컴포넌트에게 직렬화 되지 않는 props는 전달 불가능하다.
- 클라이언트는 서버에서 사전 렌더링때 한번, 하이드레이션 때 한 번, 총 두 번 실행된다.
RSC Payload란?
서버 컴포넌트를 직렬화 한 결과
서버 컴포넌트를 직렬화 한 후 클라이언트 컴포넌트들도 마저 실행이 되면서 RSC Payload 합쳐져서 HTML을 만든다.
App router에서 Page Router와 다르게 JS Bundle과 RSC Payload를 전달받아 페이지 이동을 하게 된다.
클라이언트 컴포넌트 (JS Bundle), 서버 컴포넌트 (RSC Payload)를 통해 적절히 합쳐져 페이지 교체가 이루어진다.
Page Router 와 App Router 프리패칭 차이
Page Router 버전에서 프리페칭은 이동 가능한 페이지들의 JS Bundle(모든 컴포넌트) 미리 불러옴
App Router 버전에서는 JS Bundle(클라이언트 컴포넌트), RSC Payload(서버 컴포넌트 결과물)을 불러옴
App Router 데이터 패칭 방법
Page Router 데이터 패칭 방법
모든 컴포넌트들이 클라이언트 컴포넌트이기 때문에 서버 측에서만 실행할 수 있는 함수 3가지를 따로 Page 경로에 정의 해주어야 합니다.
Page Router 문제점
page 최상단에 props로 전달받아야 하기 때문에 props drilling 문제 발생
App Router 데이터 패칭 방법
서버 컴포넌트에서 데이터 패칭해서 props로 전달
App Router 데이터 캐시
Next에서 데이터 fetch를 캐시해 놓을 수 있다. 이 때 axios나 다른 것들은 적용안되고 오로지 fetch에만 적용된다.
풀라우트 캐시
풀 라우트 캐시는 정적 페이지와 동적 페이지로 나뉜다.
정적 페이지만 풀 라우트 캐시가 적용된다.
리퀘스트 메모이제이션이란?
하나의 페이지를 렌더링 하는 동안에 중복된 API 요청을 캐싱하기 위해 존재한다.
렌더링이 종료되면 모든 캐시가 소멸된다.
데이터 캐싱이란?
백엔드 서버로부터 불러온 데이터를 거의 영구적으로 보관하기 위해 사용된다.
서버 가동중에는 영구적으로 보관된다.
풀 라우트 캐시 조건
동적 함수를 사용하지 않고 데이터 캐시를 사용할 때 정적 페이지가 되고 풀 라우트 캐시가 된다.
여기서 동적 함수는
- 쿠키, 헤더, 쿼리 스트링을 사용하는 컴포넌트가 있을 때 동적 페이지로 설정된다.
- cookies() , headers(), searchParams()
- data-fetch가 no-store인 경우
동적 페이지는 풀 라우트 캐시만 적용 안될 뿐이지 리퀘스트 메모이제이션이나 데이터 캐시는 적용된다.
동적 함수 컴포넌트 Suspense 처리
Suspense를 사용하여 사전 렌더링 과정 배제한다.
클라이언트에서 만들어진다.
동적 경로 대한 정적 페이지 설정하기
동적 경로를 갖는 페이지를 정적 페이지로 만들려면 gnerateStaticParams를 사용하면 된다.
옵션은 dynamicParams가 있다.
false → 이 외에 id로 접근 시 404 페이지로 보내진다.
dynamic 옵션
특정 페이지에 존재하는 모든 컴포넌트들이 동적인 함수를 사용하고 있지 않은지, 캐싱되지 않는 데이터 패칭을 하고 있지 않은지 다 체크하면 힘들다.
이럴 때 dynamic을 사용한다.
- auto : 아무것도 강제하지 않음
- force-dynamic : 페이지를 강제로 Dynamic 페이지로 설정
- force-static : 페이지를 강제로 Static 페이지로 설정
- error : Static 페이지로 강제로 변환하려고 할 때 오류가 발생하면 빌드 오류
이 때 queryString은 원래라면 build 에러가 발생하지만, undefined가 반환하도록 설정한다.
그리고 데이터 패칭도 no-store라면 강제로 force-cache로 변경한다.
dynamic 옵션은 안쓰는게 좋다. 왜냐하면 위에 처럼 강제로 변경되고 부작용을 일으킬 수 있기 때문이다.
페이지 스트리밍
큰 용량의 동영상을 아주 빠른속도로 시청할 수 있게 해준다.
Netflix, disney, watcher 등이 있다.
Next는 HTML 페이지를 스트리밍하는 기능을 제공한다.
사용자가 특정 페이지 접속했을 때 일단 빠르게 렌더링이 오래 걸리지 않는 단순한 컴포넌트들부터 먼저 화면에 보여주고 데이터 패칭등으로 오래 걸릴 것으로 예상되는 컴포넌트들은 일단 로딩바 같은 이런 대체 UI를 화면에 보여주고 있다가 서버측에서 렌더링이 완료가 되면 뒤늦게 이런 컴포넌트들만 따로 전달해서 컨텐츠 제공
장점은 렌더링이 아무리 오래 걸리는 컴포넌트가 있더라도 사용자에게는 회색이나 로딩바로 대체 UI를 보여줄 수 있어 사용자 경험을 제공한다.
이 때 풀 라우트 캐시에 저장되어 있지 않기 때문에 데이터 패칭이 오래 걸리면 전체 페이지 응답이 느려지게 된다.
특정 페이지 컴포넌트를 스트리밍 하도록 설정하려면 page 컴포넌트와 동일한 위치에 loading.tsx라는 파일을 만들어대체 UI를 설정한다. 그래서 async인 페이지 컴포넌트가 로딩중일 떄에는 loading.tsx가 적용된다.
즉 페이지 컴포넌트를 제외한 레이아웃 등은 먼저 보여지게 된다.
주의점
- 동일한 경로에 있는 이 페이지 컴포넌트만 스트리밍 되도록 설정하는 것이 아니라 마치 레이아웃처럼 하위 페이지 컴포넌트들에도 적용이 된다. (여기서 해당 경로 아래에 있는 모든 비동기 페이지 컴포넌트)
- 페이지 컴포넌트에서 비동기 컴포넌트만 해당한다.
- 페이지 컴포넌트에만 스트리밍 적용할 수 있다.
- 다른 별도의 컴포넌트들에도 스트리밍을 사용하고 싶으면 loading.tsx가 아닌 React에 Suspense를 사용한다.
컴포넌트 스트리밍
이런식으로 Suspense를 사용하여 여러 컴포넌트들을 병렬로 여러 개의 컴포넌트들을 완료되는 순서대로 화면에 렌더링 시킬 수 있다.
그렇기 때문에 loading.tsx를 이용하는 거보다 Suspense를 이용한다.
Error 컴포넌트
Error 컴포넌트는 loading.tsx 파일을 만든 것처럼 error.tsx라는 에러 핸들링을 담당할 파일을 하나 만들어준다.
또한 'use client'를 사용하여 서버든 클라이언트든 오류가 발생할 수 있기 때문에 서버 측에서도 대응할 수 있도록 클라이언트 컴포넌트로 설정해주어야 한다.
Error 컴포넌트는 페이지 컴포넌트에 try catch 블록을 씌운 것과 동일한 방식이다.
만약 컴포넌트 단위에 사용하려면 ErrorBoundary를 사용하면 된다.
서버 액션
브라우저에서 호출할 수 있는 서버에서 실행되는 비동기 함수
실제로 form에 submit 버튼을 클릭하면 api request가 전송된다.
Next 서버 콘솔에 "Server action called"가 출력된다.
- "use server"라는 지시자를 통해서 서버 액션을 만든 다음에 해당하는 서버 액션을 호출하는 폼을 제출하게 되면 HTTP Request가 날라간다.
- 서버 액션들은 컴파일 결과 자동으로 특정한 해시 값을 갖는 API로 설정이된다.
- 브라우저 측에서 이 서버 액션을 호출할 때 이런식으로 request 헤더에 Next-Action이라는 이름으로 현재 호출하고자 하는 action의 해시값을 전달한다.
- 전달될 때, Action ID와 form Data들도 전송된다.
서버액션
서버에 데이터만 전달이 될 뿐 실행은 서버에서 하기 때문에 보안상 민감하거나 중요한 데이터를 다룰 때 유용하게 사용된다.
서버액션에서 DB 접근까지 가능하다.
재검증
revalidatePath를 사용하게 되면 해당 경로 페이지를 재검증한다.
revalidatePath는 서버에서만 호출할 수 있다.
이 때 데이터 캐싱이나 다른 데이터 캐싱도 삭제된다. 풀 라우트 캐시도 삭제된다.
다시 접속할 때 풀라우트 캐시된다.
여기서 revalidateTag가 좋다.
그 이유는 만약 페이지 단위로 재검증을 하게 되면 거기에 포함된 다른 데이터들도 재검증이 되기 때문에 캐시가 날라간다. 그래서 특정 데이터 캐시만 재검증하도록 태그를 설정하는 것이 좋다.
useActionState
form 관련할 때 useActionState를 사용하면 폼태그 상태를 굉장히 쉽게 핸들링할 수 있다.useActionState에 전달해야 하는 것으로는 액션함수, state 초기값 있다.그러면 state (폼의 상태), formAction(폼 action), isPending(로딩 상태)를 받는다.
궁금증
초기 화면에 진입 후 페이지 이동은 CSR 방식으로 렌더링된다. 그러면 초기화면 제외한 나머지 페이지에서 getServerSideProps를 이용하여 SSR방식을 채택해야 하나?
→ 모든 페이지 이동이 Link로 이동하는 상황이 아닌, url을 입력한다던가, reload를 할 때 해당 페이지들을 사전렌더링 하기 때문에 getServerSideProps함수가 필요해진다.
SSR 과 SSG + 클라이언트 사이드 패칭
→ SSR은 API 결과를 통해 페이지를 생성하기 전까지 브라우저에게 아무것도 응답하지 않기 때문에 사용자는 이 시간동안 빈 화면을 봐야한다. 반면 SSG로 설정하고 검색 부분만 따로 클라이언트 사이드에서 API를 직접 호출해 데이터를 불러오도록 설정하면, 브라우저에서는 API 응답이 완료되지 않더라도 우선 로딩바 정도는 보여줄 수 있기 때문에 더 좋은 로딩 경험을 제공할 수 있다.
왜 클라이언트 컴포넌트에서 서버 컴포넌트를 import 할 수 없나?
→ 서버 컴포넌트는 RSC Payload, 클라이언트 컴포넌트는 JS Bundle로 나뉘어 오기 때문이다. 브라우저에서 JS Bundle로 hydrate 작업을 할 때, 만약 서버 컴포넌트를 import 한다면 해당 서버 컴포넌트는 JS Bundle에 존재하지 않기 때문에 오류가 발생한다.
→ 서버 컴포넌트를 클라이언트에 children 구조로 넘겨주면 된다. 그러면 import를 사용하지 않기 때문이다.
Next에서 React-query 대체할 수 없나?
→ Next는 주로 첫 서버에서 api를 호출한 것을 dehydrate한 후 클라이언트에서 데이터를 hydrate 과정을 거쳐서 그 데이터를 react-query에 관리하고 사용자가 데이터 수정 삭제 추가 이러한 것들을 관리하기 위해서 사용될 수 있다.
스트리밍을 사용하면 SEO 어떻게 될까?
→ 스트리밍되는 초기에는 HTML에 포함되지 않는다. 하지만 Vercel 공식문서에 따르면 스트리밍은 SEO에 부정적인 영향을 미치지 않는다고 한다. 요새 크롤러들이 똑똑하게 동작해서 스트리밍 되는 컨텐츠가 있으면 특정 시간까지는 기다려준다고 한다.
'개인 학습' 카테고리의 다른 글
자료구조 원리 파헤치기 (0) | 2025.04.14 |
---|---|
React의 Suspense 동작 원리 (0) | 2025.04.09 |
전역 상태 관리 파헤치기 (0) | 2025.04.06 |
Debounce과 Throttle (0) | 2025.04.04 |
리액트 코드 분석하기 (0) | 2025.04.02 |