| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
- JavaScript
- AJAX
- api 라우트
- axios
- 차이점
- fetch pull 차이
- Mac
- 백준
- CSS
- 개발일지
- 클라이언트 컴포넌트
- js
- 서버 컴포넌트
- Next.js
- jQuery
- 끝까지 잘 마무리하기
- 공부할 거 넘많다~
- javascript30
- TS
- Main
- freecodecamp
- 바닐라JS
- git flow finish
- git
- 다시 홧팅
- 책으론 원리만
- HTML
- git flow start
- 힘들었던 한주
- 실무는 공식문서로
- Today
- Total
다다의 개발일지 6v6
[Next.js] Next.js에서 <a> 대신 <Link>를 사용하는 이유 ?! - SPA를 위해 본문
우리가 하고 싶은 건 페이지 전체 리로딩 없이 필요한 콘텐츠만 로딩하는 것인데
이를 위해 Next.js에서 <a> 대신 <Link>를 사용하면 SPA(Single Page Application)처럼 동작할 수 있다
우선 <a> 태그를 사용하면 발생하는 문제점!
페이지 전체가 새로고침됨
기본적으로 <a> 태그를 사용하면 브라우저가 새로운 요청을 보내서 페이지 전체를 다시 로드한다.
<a href="/about">About 페이지 이동</a>
- href="/about"을 클릭하면 서버에 요청을 보내고 페이지가 새로고침됨
- 방문했던 페이지라도 다시 다운로드하여 렌더링하기 때문에 비효율적
결과적으로
- 기존 상태(state)가 초기화됨 (예: 입력 폼 내용, 로그인 상태 등)
- 페이지 전환 속도가 느려짐
<Link> 태그를 사용하면? (Next.js 방식)
1️⃣ 클라이언트 사이드 내비게이션 (CSR) 적용
import Link from "next/link";
<Link href="/about">About 페이지 이동</Link>
- Next.js의 <Link> 컴포넌트는 페이지 전체 새로고침 없이 필요한 부분만 바꿔서 렌더링함
- 기존 상태(state)가 유지됨! (ex. 입력 폼 내용 유지)
- 빠른 페이지 이동 가능
2️⃣ 자동 캐싱으로 최적화됨
<Link>를 사용하면 Next.js는 이전에 방문한 페이지를 캐싱해서 다시 방문할 때 서버 요청 없이 즉시 렌더링 가능!
<Link href="/profile">프로필 페이지</Link>
- 사용자가 /profile을 한 번 방문하면 Next.js가 자동으로 캐싱
- 다시 /profile을 클릭하면 즉시 로드됨 (서버 요청 X)
- 네트워크 트래픽 감소 + 성능 최적화!
3️⃣ 미리 로드 (프리페치) 기능 지원
Next.js의 <Link>는 기본적으로 페이지를 미리 로드(Preload) 해서
사용자가 클릭하기 전에 이미 준비된 상태이다
<Link href="/dashboard">대시보드</Link>
- 사용자가 <Link>를 포함한 페이지를 보면, Next.js가 백그라운드에서 자동으로 /dashboard 페이지를 미리 로드함
- 사용자가 클릭하면 즉시 페이지 이동 -> 엄청 빠르게 느껴짐
프리페치 기능이 기본적으로 활성화되어 있음 (모바일 환경에서는 자동 비활성화)
- 미리 로드가 필요 없는 경우 → <Link prefetch={false}> 사용 가능
4️⃣ replace, scroll, shallow 같은 추가 기능 지원
✅ replace (기존 히스토리를 대체하고 뒤로 가기 불가능하게 하기)
<Link href="/dashboard" replace>대시보드</Link>
- 사용자가 뒤로 가기를 눌러도 이전 페이지로 돌아갈 수 없음
✅ scroll (페이지 이동 시 스크롤 위치 유지하기)
<Link href="/dashboard" scroll={false}>대시보드</Link>
- 페이지 이동 후에도 현재 스크롤 위치 유지
✅ shallow (데이터만 변경하고 getServerSideProps, getStaticProps 실행 방지)
<Link href="/profile" shallow>프로필</Link>
- 같은 페이지에서 URL만 변경하고 서버 요청을 보내지 않음
shallow 옵션을 언제 사용해야 할까?
shallow 옵션을 사용하면 URL만 변경하고 서버 요청을 보내지 않음.
즉, getServerSideProps, getStaticProps가 다시 실행되지 않음 → 불필요한 데이터 요청을 방지할 수 있음!
1️⃣ URL만 변경하고 데이터 요청을 방지하고 싶을 때
예를 들어, ?tab=profile 같은 URL 쿼리 파라미터를 변경할 때
굳이 서버에서 데이터를 다시 불러올 필요가 없으면 shallow를 사용하면 된다!
📌 예제: URL 쿼리 파라미터 변경 (탭 변경)
import { useRouter } from "next/router";
export default function ProfilePage() {
const router = useRouter();
return (
<div>
<h1>프로필 페이지</h1>
<button onClick={() => router.push("/profile?tab=posts", undefined, { shallow: true })}>
게시물 보기
</button>
<button onClick={() => router.push("/profile?tab=likes", undefined, { shallow: true })}>
좋아요 보기
</button>
</div>
);
}
✅ 동작 방식
- ?tab=posts 또는 ?tab=likes로 URL은 변경됨
- 하지만 서버에 새로운 데이터 요청을 보내지 않음!
- 클라이언트 측에서 상태(state)만 변경하여 즉시 UI 업데이트 가능
🚀 결과적으로
- shallow를 사용하면 서버 요청 없이 클라이언트 측에서 UI만 업데이트 가능
- 불필요한 서버 요청을 줄여 성능 최적화 가능
2️⃣ getServerSideProps 실행을 막고 싶을 때
서버에서 데이터를 가져오는 페이지에서 URL이 바뀔 때마다 불필요한 데이터 요청이 발생할 수 있음.
이때 shallow를 사용하면 서버 요청을 막고 클라이언트에서만 URL을 변경할 수 있다.
예제: getServerSideProps가 있는 페이지
export async function getServerSideProps(context) {
console.log("서버에서 데이터 가져오는 중...");
return {
props: { time: new Date().toISOString() },
};
}
export default function Page({ time }) {
const router = useRouter();
return (
<div>
<h1>서버에서 가져온 시간: {time}</h1>
<button onClick={() => router.push("/?page=2", undefined, { shallow: true })}>
다음 페이지 이동 (shallow)
</button>
</div>
);
}
✅ shallow을 사용하면?
- ?page=2로 이동해도 getServerSideProps가 실행되지 않음!
- 즉, 서버에서 데이터를 다시 불러오지 않고 클라이언트에서만 URL이 변경됨
- 따라서 페이지 내 클라이언트 상태(state)를 활용해서 UI를 즉시 업데이트 가능
3️⃣ URL 상태를 활용하는 SPA(Single Page Application)에서 사용
SPA에서는 URL을 상태(state)처럼 활용할 때가 많아.
예를 들어, 모달을 띄울 때 /profile?modal=true처럼 URL을 변경할 수 있음.
하지만 단순히 UI만 변경할 거라면, 서버에 불필요한 요청이 가지 않도록 shallow를 사용하면 좋다
📌 예제: 모달 열기/닫기
const router = useRouter();
function openModal() {
router.push("/profile?modal=true", undefined, { shallow: true });
}
function closeModal() {
router.push("/profile", undefined, { shallow: true });
}
return (
<>
<button onClick={openModal}>모달 열기</button>
{router.query.modal && (
<div className="modal">
<p>모달 창</p>
<button onClick={closeModal}>닫기</button>
</div>
)}
</>
);
✅ shallow을 사용하면?
- /profile?modal=true로 변경해도 서버 요청 없이 모달만 UI에서 렌더링됨
- 서버 부하를 줄이고, 즉각적인 UI 업데이트 가능!
| URL 쿼리 파라미터 변경 (예: ?tab=posts) | 서버 요청 없이 클라이언트에서 UI 변경 |
| getServerSideProps 실행 방지 | 서버 요청을 줄이고, 기존 데이터 유지 |
| SPA에서 모달/필터 적용 (예: ?modal=true) | UI만 즉시 변경하고 서버 요청 방지 |
❌ 과거 방법 (Next.js에서 비효율적인 방식)
<Link href="/about">
<a>About 페이지 이동</a>
</Link>
- 과거 Next.js에서는 <Link> 내부에 <a> 태그를 감싸는 방식을 사용했지만, 최신 Next.js에서는 필요 없음!
- <a> 태그를 <Link>로 교체하는 것만으로도 충분
✅ 올바른 방법
<Link href="/about">About 페이지 이동</Link>
Next.js 프로젝트에서는 반드시 <Link>를 사용해야 빠르고 최적화된 페이지 이동이 가능하다
'Frontend > Next.js' 카테고리의 다른 글
| [Next.js] 모던 리액트 Deep Dive _ next.js 톺아보기 ( 공식문서로 공부하자.. ㅎ ) (0) | 2025.03.22 |
|---|---|
| [Next.js] 서버 vs 클라이언트 컴포넌트에서 - fetch, axios로 API 호출 차이점 (4) | 2025.03.15 |
| [Next.js] 백엔드 설정하기, 서버 vs 클라이언트 컴포넌트 차이점 (0) | 2025.03.09 |
| [Next.js] App Router - 디렉토리 기반의 라우팅! 신기하다.. (0) | 2025.03.01 |
| [Next.js] - react 기반의 풀스택 프레임워크!! 배워봅시당 (2) | 2025.03.01 |