Next.js _ Form 전송 및 저장
자체 기능으로 FormData를 전송할 수 있는데
next.js는 위 상단에 'use client' 와 'use server'를 설정하여
쓸 수 있으나 두개가 한번에 사용은 불가능하다.
그래서 useState 같은 거나 eventHandel 을 사용할때는 use client를 사용하게 될텐데
그럴경우에는 use server를 따로 컴포넌트를 분리해서 가져다가 써야한다.
아래와 같은 방법을 사용할 수 있을 거 같다.
"use server";
export async function shareMeal(formData) {
const meal = {
name: formData.get("name"),
email: formData.get("email"),
title: formData.get("title"),
summary: formData.get("summary"),
instructions: formData.get("instructions"),
image: formData.get("image"),
};
console.log(meal);
}
import 해 온 뒤
그리고 form을 action을 사용하여 사용할 수 있다.
import classes from "./page.module.css";
import ImagePicker from "@/components/meals/image-picker";
import { shareMeal } from "@/lib/meals";
export default function ShareMealPage() {
return (
<>
<header className={classes.header}>
<h1>
Share your <span className={classes.highlight}>favorite meal</span>
</h1>
<p>Or any other meal you feel needs sharing!</p>
</header>
<main className={classes.main}>
<form className={classes.form} action={shareMeal}>
<div className={classes.row}>
<p>
<label htmlFor="name">Your name</label>
<input type="text" id="name" name="name" required />
</p>
<p>
<label htmlFor="email">Your email</label>
<input type="email" id="email" name="email" required />
</p>
</div>
<p>
<label htmlFor="title">Title</label>
<input type="text" id="title" name="title" required />
</p>
<p>
<label htmlFor="summary">Short Summary</label>
<input type="text" id="summary" name="summary" required />
</p>
<p>
<label htmlFor="instructions">Instructions</label>
<textarea id="instructions" name="instructions" rows="10" required></textarea>
</p>
<ImagePicker label="Meal Image" name="image" />
<p className={classes.actions}>
<button type="submit">Share Meal</button>
</p>
</form>
</main>
</>
);
}
Next.js 데이터 관리, 상태 처리, 이미지 관리, 그리고 메타데이터 설정 방법
Next.js로 개발을 진행할 때 데이터 관리, 상태 처리, 이미지 저장, 그리고 메타데이터 설정은 중요한 구성 요소다. 이번 포스팅에서는 데이터를 안전하게 관리하고, 상태를 처리하며, 이미지를 효율적으로 저장하고, SEO를 위해 메타데이터를 설정하는 방법까지 알아보자.
1. 데이터 형태 관리: slugify와 xss 처리
A. slugify로 URL-friendly 문자열 생성
slugify는 문자열을 URL에 사용하기 적합한 형식으로 변환하는 도구다. 예를 들어, 제목을 기반으로 블로그 포스트의 슬러그를 생성할 때 유용하다.
import slugify from "slugify";
const title = "Next.js로 데이터 관리하기!";
const slug = slugify(title, {
lower: true, // 소문자로 변환
strict: true, // 특수 문자 제거
});
console.log(slug); // "next-js로-데이터-관리하기"
B. xss로 데이터 보안 강화
xss는 XSS(Cross-Site Scripting) 공격을 방지하기 위해 사용된다. 사용자 입력 데이터를 저장하거나 표시하기 전에 이를 처리해 잠재적인 보안 위협을 줄일 수 있다.
import xss from "xss";
const userInput = "<script>alert('XSS!')</script>";
const sanitizedInput = xss(userInput);
console.log(sanitizedInput); // "<script>alert('XSS!')</script>"
2. 상태 관리: useFormStatus와 useActionState
A. useFormStatus로 상태 추적
useFormStatus는 Next.js에서 Form 컴포넌트의 상태를 추적하는 데 사용된다. 이 훅은 클라이언트 측에서 동작해야 하므로, 반드시 'use client' 지시문과 함께 사용해야 한다.
- 사용 예제:
"use client";
import { useFormStatus } from "react";
const SubmitButton = () => {
const { pending } = useFormStatus();
return (
<button type="submit" disabled={pending}>
{pending ? "Submitting..." : "Submit"}
</button>
);
};
B. useActionState로 상태 관리와 오류 처리
Next.js의 업데이트로 useActionState가 추가되어 상태 관리를 더 직관적으로 처리할 수 있다. 이를 사용하면 페이지 이동 없이도 데이터 검증과 오류 메시지를 관리할 수 있다.
- 사용 예제:
"use client";
import { useActionState } from "react";
const FormComponent = () => {
const { error, success } = useActionState();
return (
<form>
{error && <p style={{ color: "red" }}>{error.message}</p>}
{success && <p style={{ color: "green" }}>Form submitted successfully!</p>}
<button type="submit">Submit</button>
</form>
);
};
3. Next.js에서 캐시 문제와 revalidatePath 활용
Next.js는 빌드 후 정적 데이터를 캐시하여 빠른 페이지 로드를 지원한다. 그러나 새로운 데이터가 로드되지 않는 문제가 발생할 수 있다. 이를 해결하기 위해 revalidatePath를 사용한다.
- 예제:
import { revalidatePath } from "next/cache";
export async function addData(newData) {
// 데이터 추가 로직
await fetch("/api/add-data", {
method: "POST",
body: JSON.stringify(newData),
});
// 데이터 변경 후 특정 경로 재검증
revalidatePath("/data-list");
}
4. 이미지 관리
A. 로컬 파일 시스템을 활용한 이미지 저장
Next.js의 fs 모듈을 사용하여 서버에서 이미지를 저장할 수 있다.
- 예제:
import fs from "fs";
import path from "path";
export async function saveImage(file) {
const filePath = path.join(process.cwd(), "public/images", file.name);
fs.writeFileSync(filePath, file.buffer);
}
B. Amazon S3로 이미지 저장
Amazon S3는 대규모 이미지 관리에 적합하다. Next.js에서 S3를 사용하려면 aws-sdk 또는 @aws-sdk/client-s3를 활용한다.
- 설정 및 사용 예제:
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
const s3 = new S3Client({
region: "your-region",
credentials: {
accessKeyId: "your-access-key",
secretAccessKey: "your-secret-key",
},
});
export async function uploadToS3(file) {
const params = {
Bucket: "your-bucket-name",
Key: file.name,
Body: file.buffer,
ContentType: file.type,
};
await s3.send(new PutObjectCommand(params));
}
이미지 저장시에는 secret key 값이 필요해서 key를 사용해야하고,
보안유지가 중요하기 때문에 .env.local 에 key를 적어주고
gitignore를 해줘서 보안을 유지해주자.
5. 메타데이터 설정
A. 정적 메타데이터
정적 메타데이터는 페이지가 고정된 정보를 표시할 때 유용하다.
- 예제:
export const metadata = {
title: "My Blog Post",
description: "Learn about Next.js metadata settings",
};
B. 동적 메타데이터
동적 메타데이터는 API에서 데이터를 가져와 페이지에 따라 다르게 설정한다.
- 예제:
export async function generateMetadata({ params }) {
const post = await fetchPost(params.id);
return {
title: post.title,
description: post.excerpt,
};
}
결론
Next.js는 강력한 데이터 관리와 상태 처리, 그리고 이미지 및 메타데이터 관리 기능을 제공한다.
- slugify와 xss를 활용해 데이터를 안전하고 URL-friendly하게 처리하자.
- useFormStatus와 useActionState로 사용자 입력 상태를 효율적으로 관리하자.
- revalidatePath를 활용해 정적 데이터 캐시 문제를 해결하자.
- Amazon S3를 사용해 이미지 저장을 확장 가능하게 만들자.
- 정적 및 동적 메타데이터 설정으로 SEO를 최적화하자.
이 모든 기능을 적절히 활용하면, 안정적이고 확장 가능한 Next.js 애플리케이션을 구축할 수 있다. 🚀
자세한 코드는 아래의 깃허브를 통해서 다시 살펴보자.