728x90
반응형
목차
중복된 요청에 대한 NextJs의 처리
아래와 같이 api를 요청하면 api의 헤더 값이 달라 각 요청을 모두 받는다.
export default async function MessagesLayout({ children }) {
const response = await fetch('http://localhost:8080/messages', {
headers: {
'X-ID': 'layout',
},
});
const messages = await response.json();
const totalMessages = messages.length;
return (
<>
<h1>Important Messages</h1>
<p>{totalMessages} messages found</p>
<hr />
{children}
</>
);
}
import Messages from '@/components/messages';
export default async function MessagesPage() {
const response = await fetch('http://localhost:8080/messages', {
headers: {
'X-ID': 'page',
},
});
const messages = await response.json();
if (!messages || messages.length === 0) {
return <p>No messages found</p>;
}
return <Messages messages={messages} />;
}
이런식으로 두 url을 수정해주면 중복된 요청이므로 next가 알아서 한번만 가져오게 된다.
const response = await fetch("http://localhost:8080/messages");
캐싱 설정하기
next15 버전은 캐싱 설정을 해줘야 캐싱이 된다. 따라서 아래와 같이 설정하게 되면 10초마다 캐싱을 최신화 시킨다.
이때 개발환경에서는 적용이 되지 않으므로 주의하자
import Messages from "@/components/messages";
export default async function MessagesPage() {
const response = await fetch("http://localhost:8080/messages",{next:{revalidate: 10}});
const messages = await response.json();
if (!messages || messages.length === 0) {
return <p>No messages found</p>;
}
return <Messages messages={messages} />;
}
그외에도 cache: 'no-store', cache: 'force-cache' 등 여러 옵션이 있다.
캐싱 제어의 다른 방법들
unsable_noStore() 함수 사용하기
import { unstable_noStore } from "next/cache";
import Messages from "@/components/messages";
export default async function MessagesPage() {
//확실하게 캐싱을 안하고자 하는 컴포넌트에 호출
unstable_noStore();
const response = await fetch("http://localhost:8080/messages");
const messages = await response.json();
if (!messages || messages.length === 0) {
return <p>No messages found</p>;
}
return <Messages messages={messages} />;
}
export const revalidate 사용
{next:{revalidate: 5}} 옵션과 같은 기능을 한다. (똑같은데 왜 여러개 있는지 모르겠음)
import Messages from "@/components/messages";
export const revalidate =5;
export default async function MessagesPage() {
const response = await fetch("http://localhost:8080/messages");
const messages = await response.json();
if (!messages || messages.length === 0) {
return <p>No messages found</p>;
}
return <Messages messages={messages} />;
}
export const dynamic 사용
파일 내 데이터를 항상 가져오게 만들 때 사용한다. (= 'no-cache')
import Messages from "@/components/messages";
//파일 내 데이터를 항상 가져오게
export const dynamic = "force-dynamic";
export default async function MessagesPage() {
const response = await fetch("http://localhost:8080/messages");
const messages = await response.json();
if (!messages || messages.length === 0) {
return <p>No messages found</p>;
}
return <Messages messages={messages} />;
}
이때 빌드 시에는 동적 페이지를 제외한 페이지들은 미리 생성된 상태로 만들어지게 된다.
아래에서 force-dynamic 설정을 한message를 보게 되면 동적으로 바뀐 것을 볼 수 있다.
revalidateTag 사용하기
import Messages from "@/components/messages";
export default async function MessagesPage() {
const response = await fetch("http://localhost:8080/messages",{
next: {tags: ['msg']}
});
const messages = await response.json();
if (!messages || messages.length === 0) {
return <p>No messages found</p>;
}
return <Messages messages={messages} />;
}
import { redirect } from "next/navigation";
import { addMessage } from "@/lib/messages";
import { revalidateTag } from "next/cache";
export default function NewMessagePage() {
async function createMessage(formData) {
"use server";
const message = formData.get("message");
addMessage(message);
revalidateTag("msg");
redirect("/messages");
}
return (
<>
<h2>New Message</h2>
<form action={createMessage}>
<p className="form-control">
<label htmlFor="message">Your Message</label>
<textarea id="message" name="message" required rows="5" />
</p>
<p className="form-actions">
<button type="submit">Send</button>
</p>
</form>
</>
);
}
api를 사용하지 않고 db 접근 코드만 사용했을 때 중복 요청 막기
cache 사용
import sql from "better-sqlite3";
import { cache } from "react";
export const getMessages = cache(function getMessages() {
console.log("Fetching messages from db");
return db.prepare("SELECT * FROM messages").all();
});
아래의 두 코드에서 중복 요청이 사라지게 된다.
import Messages from "@/components/messages";
import { getMessages } from "@/lib/messages";
export const dynamic = "force-dynamic";
export default function MessagesPage() {
const messages = getMessages();
if (!messages || messages.length === 0) {
return <p>No messages found</p>;
}
return <Messages messages={messages} />;
}
import { getMessages } from "@/lib/messages";
export default function MessagesLayout({ children }) {
const messages = getMessages();
const totalMessages = messages.length;
return (
<>
<h1>Important Messages</h1>
<p>{totalMessages} messages found</p>
<hr />
{children}
</>
);
}
api를 사용하지 않고 db 접근 코드만 사용했을 때 캐싱하기
import sql from "better-sqlite3";
import { cache } from "react";
import { unstable_cache } from "next/cache";
export const getMessages = unstable_cache(
cache(function getMessages() {
console.log("Fetching messages from db");
return db.prepare("SELECT * FROM messages").all();
}),
["messages"] //캐싱 식별을 위한 배열
);
프로미스를 반환하므로 다음과 같이 await를 추가하고 async로 수정해 주어야 한다.
import { getMessages } from "@/lib/messages";
export default async function MessagesLayout({ children }) {
const messages = await getMessages();
const totalMessages = messages.length;
return (
<>
<h1>Important Messages</h1>
<p>{totalMessages} messages found</p>
<hr />
{children}
</>
);
}
import Messages from "@/components/messages";
import { getMessages } from "@/lib/messages";
export const dynamic = "force-dynamic";
export default async function MessagesPage() {
const messages = await getMessages();
if (!messages || messages.length === 0) {
return <p>No messages found</p>;
}
return <Messages messages={messages} />;
}
반응형
'코딩 정보 > NextJs' 카테고리의 다른 글
[NextJs] 이미지 최적화에 대해 알아보자 (0) | 2025.04.16 |
---|---|
[NextJs] 서버 액션과 관련하여 더 자세히 알아보자 (1) | 2025.04.13 |
[NextJs] 서버 컴포넌트를 통한 데이터 가져오기 (0) | 2025.04.05 |
[NextJs] 라우터 기능에 대해 빠르게 알아보자 (0) | 2025.04.03 |
[NextJs] 핵심 기능 정리 (1) | 2025.03.12 |