포트폴리오 섹션별 컴포넌트 개발

Alchemist·2025년 8월 5일

포트폴리오 페이지의 핵심 콘텐츠를 구성하는 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 섹션용 데이터

1️⃣ Hero.tsx - 인트로 섹션

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>
  );
}

2️⃣ About.tsx - 자기소개 섹션

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>
  );
}

3️⃣ Projects.tsx - 프로젝트 목록 섹션

📄 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>
  );
}

4️⃣ Skills.tsx - 기술 스택 섹션

📄 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>
  );
}

5️⃣ Contact.tsx - 연락처 섹션

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>
  );
}

✅ 메인 페이지 연결 (page.tsx)

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로 빠르고 유연한 스타일 적용
profile
html_programming_language

0개의 댓글