Next.js의 page 개념부터 시작한다.
pages 디렉토리에 리액트 컴포넌트 파일을 추가하면 따로 설정해 주지 않아도 해당 URL에 접근했을 때 자동 라우팅이 구현된다.즉
pages 폴더 안의 파일 이름이 해당 페이지의 주소가 된다는 것이다.
그 중 Link 컴포넌트를 사용하지 않고 함수나 로직 내에서 라우팅을 수행해야 할 때가 있다.
프로그래밍적으로 페이지 네비게이션을 하고자 하면 useRouter을 사용하면 된다.
라우팅이란 뭔데요?
라우팅이 중요한 이유는?
그럼 SPA(Single Page Appplication) 이 뭐에요?
이렇듯 Next.js의 라우터는 이러한 라우팅을 관리하고, 페이지 전환 시의 다양한 이벤트를 처리하는데 도움을 줍니다. 사용자가 URL을 변경하거나 링크를 클릭할 때마다 라우터가 적절한 페이지 컴포넌트를 렌더링하고, 필요에 따라 데이터를 미리 불러오는 등의 작업을 수행한다.
Next.js에서 useRouter 함수로 얻을 수 있는 객체들을 살펴보자
pathname (문자열): 현재 페이지의 경로명을 나타냅니다.
query (객체): 현재 페이지의 쿼리 매개변수를 나타냅니다.
asPath (문자열): 브라우저의 주소 표시줄에 표시되는 현재 경로를 나타냅니다. pathname과 query를 기반으로 생성됩니다.
route (문자열): 현재 라우팅에 대한 정보를 포함한 문자열입니다. 일반적으로 pathname에 해당합니다.
push(url, as, options) (함수): 새로운 페이지로 이동합니다. url은 이동할 페이지의 경로이고, as는 주소 표시줄에 표시될 경로입니다. options에는 다양한 설정이 가능합니다.
replace(url, as, options) (함수): 현재 페이지를 새로운 페이지로 교체합니다. url, as, options는 push와 동일한 역할을 합니다.
reload() (함수): 현재 페이지를 리로드합니다.
back() (함수): 뒤로가기 기능을 수행합니다.
beforePopState(cb) (함수): 브라우저의 뒤로가기/앞으로가기 버튼을 클릭할 때 실행될 콜백 함수를 등록합니다.
isFallback (부울): 현재 페이지가 fallback 모드인지 여부를 나타냅니다.
events (이벤트 에미터): 라우터 이벤트에 대한 이벤트 에미터 객체입니다. 여러 라우터 이벤트에 리스너를 추가할 수 있습니다.
isReady (부울): 라우터 객체가 클라이언트 측에서 업데이트되어 사용 가능한 상태인지 여부를 나타냅니다.
pathname (문자열): 라우팅된 페이지의 경로명을 나타냅니다.
route (문자열): 현재 라우팅에 대한 정보를 포함한 문자열입니다.
query (객체): 현재 페이지의 쿼리 매개변수를 나타냅니다.
이러한 속성과 메서드를 통해 개발자는 현재 페이지 및 라우팅 상태에 대한 정보를 읽고 조작할 수 있습니다.
라우터의 속성에는
pathname: String - /pages 이후의 현재 라우트 파일의 경로. 따라서 basePath, locale 및 trailing slash (trailingSlash: true)는 포함되지 않습니다.
query: Object - 동적 라우트 매개변수를 포함하여 객체로 파싱된 쿼리 문자열. 페이지가 서버 측 렌더링을 사용하지 않는 경우 프리렌더링 중에는 빈 객체입니다. 기본값은 {}
asPath: String - 브라우저에서 표시되는 경로, 검색 매개변수를 포함하며 trailingSlash 구성을 고려합니다. basePath와 locale은 포함되지 않습니다.
isFallback: boolean - 현재 페이지가 fallback 모드인지 여부.
basePath: String - 활성화된 basePath (활성화된 경우).
locale: String - 활성화된 로캘 (활성화된 경우).
locales: String[] - 모든 지원되는 로캘 (활성화된 경우).
defaultLocale: String - 현재 기본 로캘 (활성화된 경우).
domainLocales: Array<{domain, defaultLocale, locales}> - 구성된 도메인 로캘.
isReady: boolean - 클라이언트 측에서 라우터 필드가 업데이트되어 사용 가능한지 여부. useEffect 메서드 내에서만 사용하고 서버에서 조건적으로 렌더링하는 데는 사용하지 않아야 합니다. 자동으로 정적으로 최적화된 페이지에서의 사용 사례에 대한 관련 문서 참조.
isPreview: boolean - 현재 응용 프로그램이 미리보기 모드인지 여부.
주의: asPath 필드를 사용하면 페이지가 서버 측 렌더링이나 자동 정적 최적화를 사용하여 렌더링되는 경우에 클라이언트와 서버 간 불일치가 발생할 수 있습니다. isReady 필드가 true인 경우까지 asPath 사용을 피하십시오.
들이 있다.
속성과 메서드 차이.
- 메서드(Method):
정의: 객체가 수행할 수 있는 동작이나 행동을 나타냅니다.
호출: 메서드는 해당 객체에 대해 호출되어 실행됩니다.
예시: router.push('/new-page')에서 push는 메서드입니다. 객체에 대해 특정 동작을 수행하도록 지시합니다.
-속성(Property):
정의: 객체의 특징이나 속성을 나타냅니다. 객체의 상태나 특성을 표현합니다.
접근: 속성은 해당 객체에 대해 조회하거나 설정할 수 있습니다.
예시: router.isReady에서 isReady는 속성입니다. 객체의 특정 속성(상태)을 나타냅니다.
메서드는 어떤 동작을 실행하도록 하는 함수이고, 속성은 객체의 상태나 특성을 나타내는 변수라고 이해하면 된다. 메서드는 함수의 형태를 가지며 ()를 사용해 호출함. 속성은 값에 직접 접근할 수 있으며 괄호 없이 사용됨
라우터에는 여러가지 메서드들이 있는데 push, replace, prefetch, beforePopState, back 등이 있다.
먼저
새로운 페이지로 이동하고자 할 때 사용된다. 이 메서드를 호출하면 새로 고치지 않고 즉시 브라우저의 URL을 업데이트 할 수 있다. 클라이언트측에서 페이지 이동을 수행하므로 페이지가 서버에 렌더링 되지 않는다.
router.push(url, as, options)
url: UrlObject | String - 이동할 URL을 나타냅니다. (UrlObject 속성에 대한 Node.JS URL 모듈 문서 참조).
as: UrlObject | String - 브라우저 URL 표시줄에 나타날 경로의 선택적 장식자입니다. Next.js 9.5.3 이전에는 동적 라우트에 사용되었습니다.
options - 다음 구성 옵션을 포함하는 선택적 객체:
scroll - 선택적 부울 값으로, 내비게이션 후 페이지 상단으로 스크롤을 제어합니다. 기본값은 true입니다.
shallow - getStaticProps, getServerSideProps 또는 getInitialProps를 다시 실행하지 않고 현재 페이지의 경로를 업데이트합니다. 기본값은 false입니다.
locale - 선택적 문자열로, 새 페이지의 로케일을 나타냅니다.
그럼 언제언제 쓰나를 보면
미리 정의되어있는 경로에는(내부경로)
ex
import { useRouter } from 'next/router'
export default function Page() {
const router = useRouter()
return (
<button type="button" onClick={() => router.push('/about')}>
Click me
</button>
)
}
동적 라우트 경로에는
ex
import { useRouter } from 'next/router'
export default function Page() {
const router = useRouter()
return (
<button type="button" onClick={() => router.push('/post/abc')}>
Click me
</button>
)
}
-동적 라우팅 시 파일 명에 전개연산자를 붙여
catch all routes 기능을 사용하면 여러 개의 파라미터를 받을 수 있다
외부 URL로의 이동
ex
import { useRouter } from 'next/router';
function MyComponent() {
const router = useRouter();
const handleButtonClick = () => {
// 외부 URL로 이동
router.push('https://example.com');
};
return (
<button onClick={handleButtonClick}>외부 페이지로 이동</button>
);
}
push와 비슷하지만 살짝 차이가 있다. replace를 사용하는 경우에는 페이지의 이동이력에 새로운 항목이 추가되지 않는다. 대신 현재 페이지의 이력을 교체하게 된다.
예를 들어보자.
사용자가
홈페이지 (/)
뉴스 페이지 (/news)
기술 블로그 (/blog/tech)
검색 결과 페이지 (/search?q=web+development)
순서로 웹 페이지를 방문한다고 가정해보자.
이렇게 방문한 페이지들은 브라우저의 이력에 저장된다. 뒤로가기 버튼을 누르면 이런 이력들이 역순으로 따라가면서 이전 페이지로 이동할 수 있다. 이렇게 브라우저의 이력은 사용자가 방문한 웹 페이지의 흐름을 추적하는데 사용된다.
router.push를 사용하면 이력에 새로운 항목이 추가되어 뒤로가기 버튼을 눌렀을 때 이전 페이지로 이동할 수 있다. 반면 router.replace를 사용하면 새로운 항목이 추가되지 않고 현재 페이지의 이력이 교체되기 때문에 뒤로가기 버튼을 눌렀을 때 이전 페이지로 이동한다. 즉 브라우저 이력에 새로운 항목이 추가되냐 아니냐의 차이를 보인다.
router.beforePopState(cb)
router.beforePopState({url, as, option})
여기서 cb는 callback 함수를 나타낸다. 콜백 함수는 'popstate'이벤트가 발생할 때 실행되며 해당 이벤트의 상태를 나타내는 객체가 파라미터로 전달된다. 이 객체에는 새로운 상태의 경로(url), 브라우저에 표시될 URL(as), 그리고 router.push로 전송된 추가적인 옵션(option)이 포함됨
만약 콜백 함수가 false를 반환하면 Next.js 라우터는 'popstate'를 처리하지 않으며 이 경우에는 개발자가 직접 이벤트를 처리해야 한다. 이를 통해 라우터 동작을 커스터마이징하거나 특정 상황에서 페이지 전환을 막을 수 있다.
Next.js 라우터 객체('next/router'의 'useRouter'로 얻을 수 있는 객체)에서 제공하는 이벤트 핸들러이다. 뒤로가기 또는 앞으로 가기 버튼을 클릭 했을 때 페이지가 전환되기 전에 실행되는 함수를 등록할 수 있다. 이를 통해 페이지 이동을 막거나 조작할 수 있다.
주로 사용되는 경우는 사용자가 뒤로가기 버튼을 눌렀을 때 특정 조건에 따라 페이지 이동을 막아야 하는 경우이다.
예를들어 사용자가 특정 양식을 작성하고 있고 이 양식 작성중에 뒤로가기 버튼을 누르면 정보가 손실될 수 있다. 이떄 'router.beforePopState'를 사용해 사용자에게 경고를 표시하거나 페이지 이동을 막을 수 있다.
예시를 보자
import { useEffect } from 'react';
import { useRouter } from 'next/router';
function MyComponent() {
const router = useRouter();
useEffect(() => {
const handleBeforePopState = (event) => {
// 사용자에게 경고 표시
const userConfirmed = window.confirm('작성 중인 정보가 손실될 수 있습니다. 정말 떠나시겠습니까?');
// 사용자가 취소를 선택하면 페이지 이동 막기
if (!userConfirmed) {
event.preventDefault();
}
};
// beforePopState 이벤트에 핸들러 등록
router.beforePopState(handleBeforePopState);
// 컴포넌트가 언마운트될 때 이벤트 핸들러 제거
return () => {
router.events.off('beforePopState', handleBeforePopState);
};
}, []); // useEffect가 한 번만 실행되도록 빈 배열 전달
return (
// 컴포넌트의 JSX
);
}
export default MyComponent;
위의 코드에서 'handleBeforePopState'함수는 뒤로가기 버튼을 클릭했을 때 실행되는 콜백 함수이다. 사용자에게 경고를 표시하고 사용자가 취소를 선택하면 'event.preventDefault()'를 호출하여 페이지 이동을 막는다. 필요에 따라 핸들러에서 다양한 조건을 검사하여 페이지 이동을 제어할 수 있다.
브라우저의 뒤로가기 기능을 수행한다. 이 메서드를 호출하면 사용자를 이전 페이지로 이동시킨다.
import { useRouter } from 'next/router';
function MyComponent() {
const router = useRouter();
const handleGoBack = () => {
// 브라우저의 뒤로가기 기능 수행
router.back();
};
return (
<button onClick={handleGoBack}>뒤로가기</button>
);
}
export default MyComponent;
위의 예시에서 'router.back()'을 호출하면 브라우저는 이전에 방문한 페이지로 이동한다. 이 메서드를 통해 사용자는 뒤로가기 버튼을 누르거나 프로그램적으로 페이지를 이전 상태로 되돌릴 수 있다.
이 메서드는 뒤로가기의 역할을 하는 것이므로 페이지 이력에 이전 페이지가 없는 경우에는 아무 동작도 수행되지 않는다. 만약 뒤로 갈 수 있는 페이지가 없는 경우 'router.back()'은 오류가 발생하지 않거나 무시됩니다.
이 메서드를 사용하면 현재 페이지를 다시 불러오는 역할을 한다. 이 메서드를 호출하면 현재 페이지를 다시 로드하고 페이지를 갱신한다.
컴포넌트의 상태를 초기화하거나 최신 데이터를 다시 가져오는 등의 상황에서 유용하다
import { useRouter } from 'next/router';
function MyComponent() {
const router = useRouter();
// 현재 페이지를 다시 로드하는 함수
const handleReload = () => {
// 현재 페이지를 다시 로드
router.reload();
};
return (
// 버튼 클릭 시 현재 페이지를 다시 로드하는 함수 실행
<button onClick={handleReload}>페이지 다시 로드</button>
);
}
export default MyComponent;
라우팅과 관련된 상태 변화를 감지할 때 사용한다.
import { useEffect } from 'react';
import { useRouter } from 'next/router';
function Page() {
const router = useRouter();
useEffect(() => {
const handleRouteChangeStart = (url) => {
console.log(`페이지 전환 시작: ${url}`);
};
const handleRouteChangeComplete = (url) => {
console.log(`페이지 전환 완료: ${url}`);
};
// 이벤트 리스너 등록
router.events.on('routeChangeStart', handleRouteChangeStart);
router.events.on('routeChangeComplete', handleRouteChangeComplete);
// 컴포넌트 언마운트 시 이벤트 리스너 제거
return () => {
router.events.off('routeChangeStart', handleRouteChangeStart);
router.events.off('routeChangeComplete', handleRouteChangeComplete);
};
}, []); // 한 번만 등록/해제하도록 빈 배열을 의존성으로 전달
return <div>내용이 들어갈 부분</div>;
}
export default Page;
주로 로딩 표시, 로딩 숨김, 오류처리, 사용자 트래킹, 페이지 전환 전, 후처리 할 때 사용한다.
참고
https://velog.io/@gyumin_2/Next.js-%EB%9D%BC%EC%9A%B0%ED%8C%85
Next.js 공식문서 : https://nextjs.org/docs/pages/api-reference/functions/use-router