Next.js 는 프레임워크
개발자가 기능 구현에만 ‘딱’ 집중할 수 있도록 필요한 모든 프로그래밍적 재원을 지원하는 ‘기술의 조합’
React.js가 가지고 있는 기능을 확장, 웹 애플리케이션 개발에 필요한 다양한 기능과 구조를 제공한다.
💡 6가지 원칙
1. out-of-the-box functionality requiring no setup : 별도의 설정 없이 바로 사용할 수 있는 기능을 제공
2. JavaScript everywhere + all functions are written in JavaScript : JavaScript를 통해 모든 작업을 수행
3. automatic code-splitting and server-rendering : 서버에서 렌더링을 수행하여 초기 로딩 속도를 개선
4. configurable data-fetching : 개발자가 필요에 따라 다양한 방식으로 데이터를 패칭
5. anticipating requests : 사용자가 원하는 것이 무엇인지를 먼저 예측 = 요구사항 예측
6. simplifying deployment : 애플리케이션을 쉽게 배포
다양한 렌더링 기법
SSG(Static Site Generaton)
fetch한 데이터는 영원히 변치 않아요. 계속 컴포넌트를 갱신할 필요가 없어요.
- 서버에서 페이지를 렌더링하여 클라이언트에게 HTML을 전달하는 방식
- 최초 빌드시에만 생성
- 첫 페이지 로딩 시간이 매우 짧아(TTV) 사용자가 빠르게 페이지를 볼 수 있음
- 정적인 데이터에만 사용
- 마이페이지 처럼 데이터에 의존하여 화면을 그려주는 경우 사용 불가
이전에 SSG를 구현하기 위해서는 예전 getStaticPaths 가 필요했지만
13 버전에서는 generateStaticParams 함수로 바뀌었다. App Route 등장
// (1) 첫 번째 방법 : 아무 옵션도 부여 x
const SSG = async () => {
const response = await fetch(`https://randomuser.me/api`);
const { results } = await response.json();
const user: RandomUser = results[0];
}
// (2) 두 번째 방법 : force-cache
const SSG = async () => {
const response = await fetch(`https://randomuser.me/api`, {
cache: "force-cache",
});
const { results } = await response.json();
const user: RandomUser = results[0];
}
// 결과 : 아무리 새로고침을 하여도 동일한 페이지만 출력
ISR(Incremental Static Regeneration)
fetch한 데이터는 가끔 변해요. 일정 주기마다 가끔씩만 컴포넌트를 갱신해줘요.
- 정적 페이지를 먼저 보여주고, 필요에 따라 서버에서 페이지를 재생성하는 방식
- 설정한 주기만큼 페이지를 계속 생성
- 정적 페이지를 먼저 제공하므로 사용자 경험이 좋으며, 콘텐츠가 변경되었을 때 서버에서 페이지를 재생성하므로 최신 상태를 (그나마) 유지
- 동적인 콘텐츠를 다루기에 한계
- 마이페이지 처럼 데이터에 의존하여 화면을 그려주는 경우 사용 불가
// (1) 첫 번째 방법 : 옵션 추가
const ISR = async () => {
const response = await fetch(`https://randomuser.me/api`, {
next: {
revalidate: 5,
},
});
const { results } = await response.json();
const user: RandomUser = results[0];
}
// (2) 두 번째 방법 : page.tsx 컴포넌트에 revalidate 추가
// src>app>rendering>page.tsx
import ISR from "@/components/rendering/ISR";
import React from "react";
export const revalidate = 5;
const RenderingTestPage = () => {
return (
<div>
<h1>4가지 렌더링 방식을 테스트합니다.</h1>
<ISR />
</div>
);
};
export default RenderingTestPage;
// 결과 : 주어진 시간에 한 번씩 갱신
SSR(Server Side Rendering)
fetch한 데이터는 실시간으로 계속 바뀌어요. 컴포넌트 요청이 있을 때 마다 데이터를 갱신해서 최신 데이터만 제공해야 해요.
- 빌드 시점에 모든 페이지를 미리 생성하여 서버 부하를 줄이는 방식
- 빠른 로딩 속도(Time To View)와 높은 보안성을 제공
- SEO 최적화 좋음, 실시간 데이터 사용
- 마이페이지 구성 가능
- 요청할 때 마다 페이지를 만들어야 하며, 콘텐츠 변경 시 전체 사이트를 다시 빌드 해야하므로 서버 과부하 가능성
// (1) 첫 번째 방법 : no-cache 옵션
const SSR = async () => {
const response = await fetch(`https://randomuser.me/api`, {
cache: "no-cache",
});
const { results } = await response.json();
const user: RandomUser = results[0];
}
// 결과 : 요청이 있을 때 마다 지속해서 갱신
CSR(Client Side Rendering)
fetch한 데이터는 실시간으로 계속 바뀌어요. 컴포넌트 요청이 있을 때 마다 데이터를 갱신해서 최신 데이터만 제공해야 해요.
- 브라우저에서 JavaScript를 이용해 동적으로 페이지를 렌더링하는 방식
- 사용자와의 상호작용이 빠르고 부드러움
- 서버 부하가 적음
- 첫 페이지 로딩 시간(Time To View)이 김
- JavaScript가 로딩되고 실행될 때까지 페이지가 비어있어 검색 엔진 최적화(SEO)에 불리
// (1) 첫 번째 방법 : “use client” 옵션
“use client”
const SSG = () => {
const [user, setUser] = useState<RandomUser | null>(null);
useEffect(() => {
const fetchUser = async () => {
const response = await fetch(`https://randomuser.me/api`);
const { results } = await response.json();
setUser(results[0]);
};
fetchUser();
}, []);
if (!user) {
return <div>로딩중...</div>;
}
}
// 결과 : 요청이 있을 때 마다 지속해서 갱신
✍🏻 렌더링 기법 표 정리
구분 | 빌드 | SEO | 응답 시간 | 최신 데이터 |
SSG | 길다 | 좋음 | 짧다 | 아님 |
ISR | 길다 | 좋음 | 짧다 | 아닐 수 있음 |
SSR | 짧다 | 좋음 | 길다 | 맞음 |
CSR | 짧다 | 안좋음 | 보통 | 맞음 |
Next.js 프로젝트 생성
npx create-next-app@latest
Link
Next.js는 <Link>라는 리액트 컴포넌트를 제공합니다. <Link>태그는 기본 HTML의 <a>태그를 확장한 개념
1. prefetching을 지원
- 뷰포트(현재 보이는 부분)에 링크가 나타나는 순간 해당 페이지의 코드와 데이터를 미리 가져오는 프리페칭 기능을 지원
❓ 사용자의 마우스가 링크 위에 mouseover 되는 순간 네트워크 요청이 생긴다는 것일까?
💡 렌더링된 링크가 사용자의 뷰포트 내에 나타나는 순간,
Next.js는 해당 페이지의 데이터와 필요한 자원(예: JavaScript 파일)을 미리 가져오기 시작
2. client-side navigation 지원
- 브라우저가 새 페이지를 로드하기 위해 서버에 요청을 보내는 대신
클라이언트 측에서 페이지를 바꾸어 주기 때문에 페이지 전환 시 매우 빠른 사용자 경험(UX)을 제공
- 필요한 JSON 데이터만 서버로부터 가져와서 클라이언트에서 페이지를 재구성하여 렌더링
useRouter
사용 시 "use client"; 최상단에 기입
router.push, router.replace, router.back, router.reload
router.push
- 새로운 URL을 히스토리 스택에 추가
- 이동한 페이지의 URL이 히스토리 스택의 맨 위에 쌓임
router.replace
- 현재 URL을 히스토리 스택에서 새로운 URL로 대체
- 현재 페이지의 URL이 새로운 URL로 교체되며, '뒤로 가기'를 클릭했을 때 이전 페이지로 이동
router.back
- 히스토리 스택에서 한단계 뒤로 이동
- 브라우저의 뒤로가기 버튼과 같은 효과
router.reload
- 현재 페이지 새로고침
- 히스토리 스택에 영향X, 페이지의 데이터를 최신 상태로 업데이트하고 싶을 때 사용할 수 있음
Route Handlers
GET / POST / PATCH / PUT / DELETE 메서드로 웹 환경에서 요청과 응답 주고 받는 Restful API
export async function GET(request: Request) {
console.log("GET /api/test");
}
export async function POST(request: Request) {
console.log("POST /api/test");
}
export async function PUT(request: Request) {
console.log("PUT /api/test");
}
export async function DELETE(request: Request) {
console.log("DELETE /api/test");
}
export async function PATCH(request: Request) {
console.log("PATCH /api/test");
}
'Next.js' 카테고리의 다른 글
[Next.js] shadcn/ui와 Tailwind css 함께 사용해보기 (0) | 2024.07.16 |
---|---|
[Next.js] middleware.ts (0) | 2024.07.10 |
[Next.js] Next.js Local 폰트 적용, 동적라우팅, Image 세팅 (0) | 2024.07.03 |
[Next.js] CSR, SSR, SSG, ISR 정리 (0) | 2024.07.02 |