포트폴리오 페이지의 핵심 콘텐츠를 구성하는 Hero, About, Projects, Skills, Contact 섹션을 개발합니다.
각 섹션은 src/sections/ 폴더에 파일 단위로 분리하여 개발하였으며, 필요한 경우 src/components/에서 UI 단위로 재사용 가능한 컴포넌트도 제작했습니다.
src/
├── app/
│ └── page.tsx // 모든 섹션을 불러오는 메인 페이지
├── sections/
│ ├── Hero.tsx
│ ├── About.tsx
│ ├── Projects.tsx
│ ├── Skills.tsx
│ └── Contact.tsx
├── components/
│ └── SkillBadge.tsx // Skills 섹션용 배지 컴포넌트
├── data/
│ ├── projects.ts // Projects 섹션용 데이터
│ └── skills.ts // Skills 섹션용 데이터
export default function Hero() {
return (
<section id="hero" className="text-center py-24 px-4 sm:px-6 md:px-12 lg:px-24">
<h1 className="text-4xl sm:text-5xl font-bold mb-4">안녕하세요! 👋</h1>
<p className="text-lg sm:text-xl text-zinc-600 dark:text-zinc-300">
사용자 경험을 생각하며 개발하는 프론트엔드 개발자입니다.
</p>
</section>
);
}
export default function About() {
return (
<section id="about" className="bg-zinc-100 dark:bg-zinc-800 py-20 px-4 sm:px-6 md:px-12 lg:px-24">
<h2 className="text-3xl sm:text-4xl font-bold text-center mb-8">👨💻 소개</h2>
<p className="max-w-3xl mx-auto text-zinc-700 dark:text-zinc-200 text-lg leading-relaxed">
Next.js 기반 SSR, 반응형 UI, 모던 JavaScript에 능숙하며, 꾸준히 사용자 경험 개선과 성능 최적화를 고민합니다.
</p>
</section>
);
}
📄 data/projects.ts
export const projects = [
{
title: "정보처리기사 실기 학습 플랫폼",
description: "비전공자를 위한 C 언어 학습 + 기출 해설 플랫폼",
github: "https://github.com/HTML-is-a-programming-language/study-info",
},
{
title: "포트폴리오 사이트",
description: "개인 프로젝트 및 기술 소개를 위한 정적 웹사이트",
github: "https://github.com/HTML-is-a-programming-language/frontend-portfolio",
},
];
📄 sections/Projects.tsx
import { projects } from "@/data/projects";
export default function Projects() {
return (
<section id="projects" className="py-20 px-4 sm:px-6 md:px-12 lg:px-24">
<h2 className="text-3xl sm:text-4xl font-bold text-center mb-12">🚀 프로젝트</h2>
<div className="grid gap-8 md:grid-cols-2">
{projects.map((project, index) => (
<div key={index} className="border border-zinc-300 dark:border-zinc-700 rounded-lg p-6">
<h3 className="text-xl font-semibold mb-2">{project.title}</h3>
<p className="text-zinc-600 dark:text-zinc-300 mb-4">{project.description}</p>
<a href={project.github} target="_blank" rel="noopener noreferrer" className="text-blue-600 dark:text-blue-400 underline">
GitHub 보기 →
</a>
</div>
))}
</div>
</section>
);
}
📄 data/skills.ts
export const skills = [
"JavaScript", "TypeScript", "React", "Next.js",
"Tailwind CSS", "HTML", "CSS", "Git", "GitHub"
];
📄 components/SkillBadge.tsx
interface SkillBadgeProps {
skill: string;
}
export default function SkillBadge({ skill }: SkillBadgeProps) {
return (
<li className="bg-zinc-100 dark:bg-zinc-700 text-zinc-800 dark:text-white px-4 py-2 rounded-full text-sm sm:text-base">
{skill}
</li>
);
}
📄 sections/Skills.tsx
import { skills } from "@/data/skills";
import SkillBadge from "@/components/SkillBadge";
export default function Skills() {
return (
<section id="skills" className="px-4 sm:px-6 md:px-12 lg:px-24 py-20">
<h2 className="text-3xl sm:text-4xl font-bold text-center mb-12">🛠 기술 스택</h2>
<ul className="flex flex-wrap justify-center gap-4">
{skills.map((skill) => (
<SkillBadge key={skill} skill={skill} />
))}
</ul>
</section>
);
}
export default function Contact() {
return (
<section id="contact" className="bg-zinc-100 dark:bg-zinc-900 py-20 px-4 sm:px-6 md:px-12 lg:px-24">
<h2 className="text-3xl sm:text-4xl font-bold text-center mb-8">📮 Contact</h2>
<p className="text-center text-lg text-zinc-700 dark:text-zinc-300">
포트폴리오에 관심이 있으시다면 언제든지 연락주세요.<br />
<strong>Email:</strong> your_email@example.com
</p>
</section>
);
}
import Hero from "@/sections/Hero";
import About from "@/sections/About";
import Projects from "@/sections/Projects";
import Skills from "@/sections/Skills";
import Contact from "@/sections/Contact";
export default function Home() {
return (
<>
<Hero />
<About />
<Projects />
<Skills />
<Contact />
</>
);
}
| 포인트 | 설명 |
|---|---|
| 📦 분리된 구조 | 각 섹션을 파일 단위로 관리하여 유지보수성과 확장성 향상 |
| 🔁 재사용 컴포넌트 | SkillBadge 등은 다른 곳에서도 쉽게 활용 가능 |
| 📊 데이터 분리 | 프로젝트 및 스킬 정보를 data/ 폴더에서 분리 관리 |
| 🧠 개발자 경험 | Tailwind로 빠르고 유연한 스타일 적용 |