기존 페이지 라우터에서는 아래 그림처럼 초기 접속이 완료된 이후 페이지 이동이 이루어지면
브라우저는 서버로부터 이동할 페이지에 필요한 모든 컴포넌트들이 포함된
JS Bundle파일을 받아 직접 브라우저 차원에서 실행하여 현재 페이지에 맞도록 컴포넌트를 교체한다.

앱라우터 또한 페이지 라우터의 방식과 거의 유사하게 이루어 지는데,
서버 컴포넌트의 추가로 작지만 중요한 차이점이 하나 발생하게 된다.
위 그림에서 이동할 페이지의 JS Bundle을 프리패칭할 때 RSC Payload를 받는 과정이 하나 추가되는 것이다.
RSC Payload
React Server Components(RSC)가 클라이언트로 전송하는 데이터 페이로드를 의미한다.
- 서버 컴포넌트는 서버에서 렌더링되며, 클라이언트로 HTML이 아니라 JSON 형태의 페이로드를 보낸다.
- 이 JSON에는 서버 컴포넌트의 렌더링 결과(데이터, 구조 등)가 포함되어 있으며, 클라이언트에서 React가 이를 해석해 UI를 조합한다.
- 페이지 이동(Navigation) 시, 서버에서 해당 페이지의 RSC Payload를 새로 요청하여 UI를 업데이트한다.
이렇게 되는 이유는 JS Bundle에는 클라이언트 컴포넌트들만 포함되며, 서버 컴포넌트는 JS 코드가 아니라 JSON(RSC Payload)으로 전달된다.
따라서 페이지 이동 시 서버 컴포넌트의 데이터가 브라우저에서 정상적으로 렌더링되기 위해서는 JS Bundle뿐만 아니라 RSC Payload도 함께 요청되어야 한다.

앱 라우터에서 Programmatic한 페이지 이동을 구현할 때는 페이지 라우터와 동일하게 useRouter를 import하여 사용한다.
단, 'next/router'는 페이지 라우터 버전의 라우터이기 때문에 'next/navigation'에서 import해야한다.
'use client';
import { useRouter } from 'next/navigation'; // 'next/navigation'에서 import
import { ChangeEvent, useState } from 'react';
export default function Searchbar() {
const router = useRouter();
const [search, setSearch] = useState('');
const onChangeSearch = (e: ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value);
};
const onSubmit = () => {
router.push(`/search?q=${search}`);
};
return (
<div>
<input type="text" value={search} onChange={onChangeSearch} />
<button onClick={onSubmit}>검색</button>
</div>
);
}