알아볼내용 nextjs 15 서버컴포넌트 서스펜스
React18
을 사용하며 코딩을 시작했다. 그땐 CSR이 대세였다. 그래서 주야장천 Javascript와 react만 공부했다. 그냥 그런가보다. 하면서 공부했다. 뭐가 좋고 뭐가 안 좋고 뭐가 나은지 생각할 겨를이 없었다. 그때의 나를 예로 들자면 아랍어를 사용하는 두바이 아부다비에 아무런 언어적 능력없이 내던저져 생존해야 되는 상황이었기 때문이다.
2년 전 한창 SEO를 등에 업은 SSR 프레임워크가 급부상하고 있었다. 프론트엔드 만 하기엔 풀스택을 지원하는 NEXT.js나 sveltekit이 버거웠다. 하지만 진짜 개발자가 되려면 당연히 습득해야 하는 스킬이었다. 근데 nextjs
가 아니라 sveltekit
으로 풀스택을 연마했다. 그래야 하는 상황이었기 때문에 나의 풀스택 프레임워크는 sveltekit에 맞춰져있었다. (지금 생각해봐도 sveltekit은 정말 잘 만들어진 프레임워크 같다.) nextjs도 사용하는데는 크게 문제가 없었지만, 세부적인 기능들을 적절히 사용하기엔 공부가 필요했다.
한국에선 react & nextjs를 원한다. 그게 이유다. Javascript를 잘하면 된다고 생각했는데, 결국 nextjs라는 프레임워크의 기술도 익혀야 한다. 2년 새에 많은 것이 바뀌어 있었다. 내가 제일 헷갈렸던 부분은 sveltekit의 경우 서버 컴포넌트와 클라이언트 컴포넌트 자체는 아예 다른 파일로 구성되어 있어서 헷갈일 일이 없었다. 하지만 오랜만에 nextjs를 사용해보니 여기가 서버야 클라이언트야 중구난방 도때기 시장 같았다. 그러면서 버전을 올라가면서 nextjs와 sveltekit이 서로의 장점을 닮아가고 있다는 것을 알 수 있었다.
둘 다 서버 사이드 렌더링과 클라이언트 분리를 지향하며, 최신 웹 개발 트렌드를 반영하고 있다. 정답은 없다.
nextjs는 컴포넌트 단위로 서버와 클라이언트를 명시한다. 기본적으로는 server로 구성되어 있고, 'use client'를 명시하면 기본 react처럼 작동한다.
서버에서만 렌더링되는 React 컴포넌트 초기 렌더링 결과만 클라이언트에 전달되며, 클라이언트 번들에는 포함되지 않는다. 데이터 패칭, 보안이 필요한 연산, 무거운 비동기 연산 등에 적합하다.
초기렌더링 성능 및 SEO가 강화된다.
SEO 가 강화되는 이유는 SSR의 장점을 알면 되는데 쉽게 설명하자면 클라이언트가 javascript로 화면의 변화를 조작하는 것이 아니라 server에서 html을 그려서 주기 때문에 검색엔진에 잘 걸릴 확률이 높다. 크롤러가 내용을 쉽게 볼 수 있다.
// 서버 컴포넌트
// app/page.js (서버 컴포넌트)
import UserList from './UserList';
export default function HomePage() {
return (
<main>
<h1>유저 목록</h1>
<UserList />
</main>
);
}
// app/UserList.js (서버 컴포넌트)
export default async function UserList() {
// 서버에서만 데이터를 가져옵니다.
const res = await fetch('https://jsonplaceholder.typicode.com/users', {
// 서버 전용 옵션 사용 가능
cache: 'no-store', // 항상 최신 데이터
});
const users = await res.json();
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
// 클라이언트 컴포넌트
// app/page.js
'use client';
export default function Page() {
// 브라우저 상호작용, React 훅 사용 가능
return <button onClick={() => alert("클릭!")}>클릭</button>;
}
초기 렌더링이 늦어진다. 모든 비동기 작업(데이터 패칭 등) 이 완료 될 때까지 전체 HTML이 클라이언트로 전달되지 않아 초기 렌더링 속도가 늦어 질 수도 있다. 그냥 하얀 화면만 떠 있을 수 있는 것이다.
이는 UX(유저 경험) 가 엄청나게 망가진다. 왜 안떠? 새로고침 새로고침! 이러면 내 폰이나 인터넷에 문제가 있다고 판단할 수 있다. 그래서 nextjs팀은 suspense를 제공한다.
사용자가 빈 화면을 오래 보는 불편함을 줄이기 위해, 필요한 부분만 먼저 렌더하고, 느린 부분은 나중에 점진적으로 보여줄 수 있도록 도와주는 기능을 제공
import { Suspense } from 'react';
import Comments from './Comments'; // 서버 컴포넌트, 비동기 데이터 패칭 포함
export default function Page() {
return (
<div>
<ArticleContent /> {/* 주요 콘텐츠는 바로 렌더링 */}
<Suspense fallback={<div>댓글 불러오는 중...</div>}>
<Comments /> {/* 느릴 수 있는 부분 */}
</Suspense>
</div>
);
}
서버 컴포넌트는 SSR로 SEO에 탁월한 이점을 가지지만, 오히려 비동기 작업이 많으면 초기 렌더링이 지연될 수 있다. Suspense는 이를 보완하여 필요한 부분만 fallback UI로 대체하며 점진적으로 렌더링 하는 현대적인 방법이다.