회원가입, 글 작성하기, 댓글 달기 등등 기본적인 기능들은 이제 다 구현을 해보았으니 다크모드 기능을 한 번 구현해보려 한다.
state를 통해 다크모드인지 라이트모드인지를 관리하면 된다는 것은 누구나 쉽게 떠올릴 수 있을 것이다. 리액트 사용자였다면 특히 여기서 자연스럽게 useState를 생각하게 될텐데, useState 사용 시 새로고침 시 상태가 초기화되기 때문에 다크모드의 상태를 관리하기에는 적절하지 않다.
상태 데이터를 DB에 저장할 수도 있지만 간단하게 브라우저의 저장공간에 저장해보자.
1. localStorage에 저장하기
localStorage.setItem("저장할 이름", "값"); // 저장하기
localStorage.getItem("저장할 이름"); // 가져오기
localStorage.removeItem("저장할 이름"); // 삭제하기
export default function () {
useEffect(() => {
if (typeof window != "undefined") {
let res = localStorage.setItem("이름", "kim");
}
}, []);
return 생략;
}
이와 같이 간단하게 브라우저의 로컬 스토리지에서 데이터를 관리할 수 있다.
다만 useEffect 안에서 코드를 작성해주어야 하기 때문에 이 방식 또한 다크모드 기능을 구현하기에는 적절하지 않아보인다.
❓ useEffect 안의 코드는 HTML이 브라우저에 다 그려진 후에 실행되기 때문에, 로컬 스토리지에 다크모드인 상태가 저장되어 있어도 라이트모드가 먼저 보여지고 곧바로 다크모드로 바뀌게 될 것이다.
2. cookie에 저장하기 ✔
로컬 스토리지에 저장된 데이터는 클라이언트 컴포넌트에서만 사용이 가능한 것에 반해, 쿠키는 서버 컴포넌트에서도 쉽게 접근할 수 있다는 점에서 SSR에서 유용하다.
✅ 쿠키 사용 시 유의사항
- 단순 문자열만 저장 가능
- GET, POST 요청 시마다 서버에 전달되므로 네트워크 호스팅 비용 증가
쿠키를 생성할 때의 코드는 다음과 같다.
document.cookie = "쿠키이름=값; max-age=3600";
max-age
: 쿠키의 유효기간 (미설정 시 브라우저 종료와 함께 쿠키는 자동 삭제됨)
서버 컴포넌트에서 쿠키를 가져올 때는 다음과 같이 키값으로 값을 가져오면 된다.
const result = cookies().get('쿠키이름')
💻 전체 코드
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";
const ThemeBtn = () => {
const [theme, setTheme] = useState("light");
const router = useRouter();
useEffect(() => {
const mode = ("; " + document.cookie).split(`; mode=`).pop().split(";")[0];
if (mode == "") document.cookie = "mode=light; max-age=" + 60 * 60 * 30;
}, []);
const handleDarkMode = () => {
document.cookie = "mode=dark; max-age=" + 60 * 60 * 30;
setTheme("dark");
router.refresh();
};
const handleLightMode = () => {
document.cookie = "mode=light; max-age=" + 60 * 60 * 30;
setTheme("light");
router.refresh();
};
return (
<div>
{theme == "dark" ? (
<span onClick={handleLightMode}>🌞</span>
) : (
<span onClick={handleDarkMode}>🌛</span>
)}
</div>
);
};
export default ThemeBtn;
import { cookies } from "next/headers";
export default async function RootLayout({ children }) {
const mode = cookies().get("mode"); // 쿠키에 저장된 값 가져오기
console.log(mode, "mode");
return (
<html lang="en">
<body>
{/* 가져온 값(mode)이 'dark'이면 다크모드 css 입히기 */}
<div className={"p-[20px] " + `${mode.value == "dark" && "dark-mode"}`}>
<div className="navbar">
<Link
href="/"
className="pr-[20px] font-semibold text-black no-underline"
>
Home
</Link>
<Link href="/list" className="text-black no-underline">
List
</Link>
{session ? <LogoutBtn /> : <LoginBtn />}
<ThemeBtn />
</div>
</div>
{children}
</body>
</html>
);
}
.dark-mode .navbar {
background: #222;
}
.dark-mode .navbar a {
color: #fff;
}
'Next.js' 카테고리의 다른 글
[Next.js] Next.js Server Actions (0) | 2024.05.28 |
---|---|
[Next.js] Next.js Middleware / 미들웨어, 어떨 때 사용할까? (0) | 2024.05.28 |
[Next.js] Local Font 추가하여 전역 폰트 적용하기 (feat. TailwindCSS) (0) | 2024.05.24 |
Next.js로 웹서비스 만들기 4주차 - 게시판 만들기 (Dynamic Routes, 페이지 이동, MongoDB 데이터 수정) (0) | 2024.04.09 |
Next.js로 웹서비스 만들기 3주차 - Next.js에서 MongoDB 사용하기 (0) | 2024.04.02 |