[Next.js] 나만의 학습 블로그 만들기 #1 - 프로젝트 구조 잡기(Header, Footer, 다크모드)


이번에 모던 Modern-React-Deep-Dive
를 읽고 정리를 하려던 중에 아예 블로그를 만들어서 제작하는게 어떨까?!라는 생각을 갖고 시작한 미니 프로젝트(?)
👉🏻 예시 블로그
이런식으로 굉장히 간단하고 가독성 좋게(?) + 깔끔하게 만들려고 한다.
기술 스택 + 구성 방식
항목 | 추천 |
프레임워크 | Next.js |
스타일 | Tailwind CSS / MDX |
블로그 엔진 | 자체 마크다운 렌더링 or Contentlayer |
배포 | Vercel |
기능 추가 | 다크모드, 영문모드 지원(도전,,!) |
⚙️ 설치
npx create-next-app@latest react-deep-dive-site
컴포넌트
헤더
푸터
다크모드
를 먼저 만들어보려고 한다! 🌱
✏️ Header.js
import Image from "next/image";
export default function Header() {
return (
<header className="py-4 px-6 flex justify-between">
<h1 className="text-xl font-bold text-gray-800">모던 리액트 Deep Dive</h1>
<a
href="내 깃허브 블로그"
target="_blank"
rel="noopener noreferrer"
className="text-md font-bold text-sky-500 hover:underline flex items-center gap-2"
>
<div className="w-8 h-8 rounded-full overflow-hidden">
<Image
src="/profile.jpeg"
alt="Profile"
width={32}
height={32}
className="object-cover"
/>
</div>
수빈
</a>
</header>
);
}
굉장히 심플하게 만들어 줬다.
제목 + 이미지, 이름(클릭하면 깃허브로 갈 수 있도록 !)
🎖️ Next.js 장점 확인하기
여기서 Next 장점을 확인할 수 있었다..!! 바로 Image 부분인데
React와 달리 Next.js는 <img>
태그 대신 내장된 <Image>
컴포넌트를 사용한다는 것!!!
🧐 why?
저 Image에는 굉장히 장점이 있다
자동 최적화 (최적 크기, WebP 변환)
지연 로딩(lazy loading) 기본 지원
반응형 이미지 쉽게 구현 가능
빠른 페이지 로딩과 SEO 개선
import Image from "next/image";
<Image
src="/profile.jpeg" // public 폴더 기준 경로
alt="Profile"
width={32}
height={32}
/>
이런식으로 작성해주면된다. 또한 width
랑 height
를 줘야지 레이아웃 안정성이 좋아진다!(필수로 써주자)
✏️ Footer.js
export default function Footer() {
return (
<footer className="bg-gray-100 text-center py-4 text-sm text-gray-600">
© 2025 수빈 |
<a href="mailto:haely97@naver.com" className="underline mx-1">
Email
</a>{" "}
|
<a
href="https://github.com/subinsong01"
target="_blank"
rel="noopener noreferrer"
className="underline mx-1"
>
GitHub
</a>
<p className="mt-2">
이 사이트는 <em>『모던 리액트 Deep Dive』</em> 책 내용을 참고하여
제작되었습니다.
</p>
</footer>
);
}
푸터도 무난하게 구성해봤다 ! 👍🏻
✏️ 다크모드
Tailwind 다크모드(class 기반 다크모드) 내장 기능을 사용했다(강추)
/** @type {import('tailwindcss').Config} */
module.exports = {
darkMode: "class",
content: [
"./src/pages/**/*.{js,ts,jsx,tsx}",
"./src/components/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
};
darkMode: “class”를 추가해준다
glabal.css
body {
@apply bg-white text-black;
}
.dark body {
@apply bg-black text-white;
}
다크모드인 경우에는 bg-black
을 적용해줬다.
Header.jsx
<button
onClick={toggleDarkMode}
className="relative w-14 h-8 rounded-full bg-gray-300 dark:bg-gray-700 transition-colors duration-300 cursor-pointer"
aria-label="Toggle Dark Mode"
>
<span
className={`absolute top-1 left-1 w-6 h-6 bg-white rounded-full shadow-md transform transition-transform duration-300 ${
isDark ? "translate-x-6" : "translate-x-0"
}`}
/>
</button>
헤더에 다크모드랑 라이트모드를 체크할 수 있는 토글 버튼을 만들어줬다.
Subscribe to my newsletter
Read articles from 송수빈 directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
