Next.js

[NextJS] 넥스트JS 정리하기

ejunyang 2024. 12. 16. 14:45

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");
}