본문 바로가기

[Dev] 🎯Self Study

[리액트에서 Next로] Next.js 기초 : 캐싱부터 정적-동적 렌더링

 

Caching


캐싱은 데이터나 결과를 저장하고 재사용하여 성능 향상과 리소스 절약을 목적으로 하는 기술로,
이전에 검색한 정보를 다시 계산하지 않고 빠르게 액세스할 수 있다. 

 



캐싱은 찾고자 하는 데이터에 더 빠르게 접근할 수 있도록 데이터를 저장하는 행위 

 

 

데이터는 크게 메모리, 파일 시스템, 그리고 네트워크 이렇게 3개의 장소에서 가져올 수 있다.

가져오는 속도는 메모리에서 파일 시스템 순으로 빠름
즉, 메모리를 통해 데이터를 가져오는 것이 가장 빠르고 네트워크를 통해 데이터를 가져오는 것이 가장 느림

 

 

넥스트JS는 내장 데이터 캐시를 제공 


1. 패칭을 통해 데이터를 가져오면 가져온 결과를 파일 시스템 기반의 캐시에 저장
2. 결과적으로 동일한 URL의 재요청을 보내는 경우 다시 데이터를 요청하는 대신에 캐시에서 빠르게 가져올 수 있다.

자주 변경되는 데이터의 경우 캐싱을 비활성화함으로써 최신의 데이터를 렌더링 할 수 있다.

 


앞서 작성한 패치 함수의 두 번째 인자 값의 캐시 속성을 정의함으로써 캐시 사용 유무를 결정 

import React from 'react'

// User 인터페이스를 정의
interface User {
  id : number;
  name : string;
} 

const UsersPage = async () => {
  const res = await fetch("https://jsonplaceholder.typicode.com/users")
  const users : User[] = await res.json();

  return (
    <div>
      <h1>this is user.</h1>
      <ul>
        {users.map((user)=><li key={user.id}>{user.name}</li>)}
      </ul>
    </div>
  )
}

export default UsersPage

 

 

Next.js는 기본 동작을 캐싱을 제공 

fetch 함수의 두 번째 인자 값으로 전달한 객체를 
통해 캐싱 여부를 설정할 수 있습니다.
아무것도 적지 않는 경우 기본값인 캐싱 활성화 
방식으로 동작합니다.

 


 캐싱 비활성화

캐싱을 비활성화할 때는 두 번째 인자로 다음 객체를 전달 
{ cache: "no-store" };
데이터가 자주 변경되는 경우 유용하게 사용할 수 있습니다.

const UsersPage = async () => {
  const res = await fetch("https://jsonplaceholder.typicode.com/users", {cache : "no-store"})
  const users : User[] = await res.json();



캐싱을 특정 시간 동안만 유지하고, 그 이후에는 다시 요청을 보내 최신 버전을 캐싱하고 싶은 경우

캐싱을 특정 시간만큼만 유지하고 특정 시간이 지나면 저장한 캐싱을 삭제하고
재요청을 보내는 방법

{ next: { revalidate: 10 }}

 

- 앞서 작성한 캐시 속성을 지우고 next라는 키 값을 작성하고 프로퍼티로 validate를 작성 

const UsersPage = async () => {
  const res = await fetch("https://jsonplaceholder.typicode.com/users", {next : {revalidate : 20}})
  const users : User[] = await res.json();

 

- 이렇게 되면 Next.js 내부 로직에 의해 특정 시간이 지난 이후에 요청이 오는 경우 다시 서버에 데이터를 요청 

 

 

 

Next.js에서 캐싱 속성을 변경하고 싶은 경우 반드시 패치 함수를 사용해야 한다.

 

1. Next.js의 캐싱 기본값은 캐싱 활성화
2. 캐싱 활성화 여부는 개발자에게 달려있음
3. 캐싱 활성화 여부는 fetch 함수에서만 사용할 수 있다.
(axios 등 3rd-party 라이브러리에서는 사용이 불가)

 

 




Static Rendering (정적 렌더링)


Static rendering은 웹 페이지를 서버 측에서 미리 생성하여 정적 HTML 파일로 저장하는 방식으로, 
동적 생성이나 클라이언트 측 렌더링과는 다르다.


정적 렌더링(Static Rendering)은 프로덕션 빌드 시점에 변하지 않는 데이터가 포함된 컴포넌트를 미리 생성하고, 
요청이 들어올 때마다 재생성하는 대신, 미리 생성한 것을 클라이언트에 전달하는 방식을 의미
(파일 시스템 기반으로 캐싱)

 



Production Build (빌드)


Next.js에서 Production Build(프로덕션 빌드)는 개발자가 작성한 애플리케이션 코드와 리소스를 최적화된 형태로 번들링하고, 
불필요한 정보를 제거하여 웹 애플리케이션을 실제 사용을 위한 최종 제품으로 만드는 프로세스를 의미
Production Build(프로덕션 빌드)를 통해 애플리케이션의 성능을 최적화하고,
사용자에게 빠르고 안정적인 웹 경험을 제공할 수 있게 된다.

 

 

Dynamic Rendering (동적렌더링, 요청시점)


Dynamic rendering은 웹 페이지가 클라이언트 측에서 요청 시에 동적으로 생성되며,
JavaScript를 사용하여 페이지 상태 및 내용을 동적으로 조작하는 방식을 나타낸다.

 


 

코드로 실습하기

app/users/page.tsx

1. 사용자 목록에 타임스탬프 추가

Timestamp: 특정 이벤트 또는 데이터 기록이 발생한 시간을 나타내는 정보

 

1. p 태그 생성
2. new Date 인스턴스 생성
3. 생성한 인스턴스에서 toLocalTimeString 메소드 호출

 

import React from 'react'

// User 인터페이스를 정의
interface User {
  id : number;
  name : string;
} 

const UsersPage = async () => {
  const res = await fetch("https://jsonplaceholder.typicode.com/users", {next : {revalidate : 20}})
  const users : User[] = await res.json();

  return (
    <div>
      <h1>this is user.</h1>
      <p>{new Date().toLocaleTimeString()}</p>
      <ul>
        {users.map((user)=><li key={user.id}>{user.name}</li>)}
      </ul>
    </div>
  )
}

export default UsersPage

 



시간이 계속 변경되는 이유는 현재 개발 모드(Development mode)로 설정되어 있어, 
테스트 목적으로 페이지를 새로고침할 때 마다 새로운 요청으로 동적 렌더링이 발생하기 때문  

 

 

BUT 프로덕션 모드로 빌드할 시, 새로고침을 눌러도 타임스탬프 변화가 X

- Next.js가 이 페이지를 변경되지 않는 정적 데이터로 취급하므로 최초 렌더링한 데이터를 캐싱에 저장, 재사용

 


캐싱을 비활성화하는 경우, 정적 렌더링 대신 동적 렌더링 방식으로 동작!

 

 

2. Production Build(프로덕션 빌드) 하기

npm run build

-> 현재 생성한 애플리케이션이 어떤 경로에 어떤 컴포넌트가 매핑되는지 모두 확인 가능

 

그러나 지금은 캐싱 허용상태이므로  

빌드 결과를 살펴보면 홈페이지, users 페이지 등의 경로가 출력, 각 경로 앞에는 원 모양의 형태가 붙어 있음.

빌드되는 경로들이 어떤 방식으로 렌더링되는지 확인 가, 경로 앞에 붙은 원 기호는 해당 경로의 컴포넌트가
정적으로 렌더링되었음을 나타낸다.

 


3. 이제 빌드된 애플리케이션(결)을 실행시키는 명령어를 통해 앱을 실행

npm run start


브라우저로 돌아가 새로고침을 여러번 눌러도 타임스탬프가 변경되지 않는다. 
- 해당 페이지가 빌드 시점에 정적 렌더링 방식 으로 빌드되었기 때문이다. 

 

4. 데이터 패칭 부분의 캐싱을 노스토어로 설정해 캐싱되지 않도록 수정 

  const res = await fetch("https://jsonplaceholder.typicode.com/users", {cache: "no-store"})


다시 화면에 빌드 명령어를 실행하면 사용자 경로 앞에 있는 아이콘이 원 -> Lambda로 변경

프로덕션 모드 빌드
npm run build
(람다는 동적 렌더링 방식으로 렌더링 되는 컴포넌트를 가리키는 기호)

 

 

한장요약