🐨CoalaCoding
DocsExamplesTry itBoardB반B반
🐨CoalaCoding

개발자를 위한 한국어 웹 기술 문서

문서

  • JavaScript
  • Web Publishing
  • React
  • Python

커뮤니티

  • 게시판
  • 예제 모음
  • Try it 에디터

기타

  • GitHub
  • 관리자
© 2026 CoalaCoding. All rights reserved.
  • 시작하기
  • App
  • CSS
  • Nav
  • Hero
  • AboutMe
  • Projects
  • Contact
  • Footer
  • 완성_정리
  • 바이브코딩
  1. 홈
  2. 문서
  3. React
  4. 프로젝트: 이력서
  5. Projects

Projects

코드 블록의 Try it Yourself 버튼으로 직접 실행할 수 있다.

구문

06. Projects.jsx — 프로젝트 섹션

이번 단계에서 할 일

프로젝트 목록을 데이터 배열로 관리하고, map으로 화면에 출력하는 방법을 배웁니다.


피그마 디자인 분석

│ ─── Projects ──────────────────────────────────── │
│                                                   │
│  ┌──────────────────────┬───────────────────────┐ │
│  │ ● Project 01         │                       │ │
│  │                      │                       │ │
│  │ 동대문구청             │      이미지 영역        │ │
│  │                      │                       │ │
│  │ 기술스택 : html,css…  │                       │ │
│  │ 배포매체 : desktop…   │                       │ │
│  │ 작업기간 : 2주         │                       │ │
│  │ 기여도   : 100%        │                       │ │
│  │                      │                       │ │
│  │ [기획서] [깃허브] [페이지] │                   │ │
│  └──────────────────────┴───────────────────────┘ │
요소값
주황 점 색상#f26440
Project 번호 색#c7c7c7
프로젝트 타이틀32px
설명 텍스트18px, #555555
버튼 배경#000000

새로운 개념: 데이터와 화면 분리

데이터(배열)와 화면(JSX)을 분리하면:

  • 프로젝트가 늘어나도 배열에 항목만 추가하면 됩니다
  • 코드가 훨씬 깔끔해집니다
// 데이터만 따로 (내용)
const PROJECTS = [
  { id: 1, title: '동대문구청', ... },
  { id: 2, title: '두 번째 프로젝트', ... }, // 추가도 쉬움
]

// 화면만 따로 (형태)
{PROJECTS.map((project) => (
  <ProjectItem project={project} />
))}

STEP 1 — Projects.jsx 작성

// src/components/Projects.jsx
import SectionTitle from './SectionTitle'

/* ─── 프로젝트 데이터 (컴포넌트 밖에 위치) ─── */
// 나중에 프로젝트를 추가할 때 이 배열에만 항목을 추가하면 됩니다
const PROJECTS = [
  {
    id: 1,
    number: 'Project 01',
    title: '동대문구청',
    stack: 'html, css, photoshop, figma',
    deploy: 'desktop, mobile',
    period: '2주',
    contribution: '100%',
    browsers: 'Chrome / Edge / Opera / Safari',
    pages: '메인페이지 / 접근성 준수',
    links: {
      plan: '#',
      github: '#',
      live: '#',
    },
  },
  // 프로젝트 추가 시 여기에 객체를 하나 더 작성하세요
]

/* ─── 프로젝트 한 항목을 보여주는 컴포넌트 ─── */
const ProjectItem = ({ project }) => {
  return (
    <div className="project-item">

      {/* 왼쪽: 설명 */}
      <div className="project-desc">

        {/* 번호 (● Project 01) */}
        <div className="project-number">
          <span className="project-dot" />
          <span className="project-number__text">{project.number}</span>
        </div>

        {/* 프로젝트 이름 */}
        <h3 className="project-title">{project.title}</h3>

        {/* 상세 정보 */}
        <div className="project-info">
          <div className="project-info__row">
            <span className="project-info__label">기술스택 :</span>
            <span>{project.stack}</span>
          </div>
          <div className="project-info__row">
            <span className="project-info__label">배포매체 :</span>
            <span>{project.deploy}</span>
          </div>
          <div className="project-info__row">
            <span className="project-info__label">작업기간 :</span>
            <span>{project.period}</span>
          </div>
          <div className="project-info__row">
            <span className="project-info__label">본인기여도 :</span>
            <span>{project.contribution}</span>
          </div>
          <div className="project-info__row">
            <span className="project-info__label">브라우저 호환성 :</span>
            <span>{project.browsers}</span>
          </div>
          <div className="project-info__row">
            <span className="project-info__label">페이지수 / 특징 :</span>
            <span>{project.pages}</span>
          </div>
        </div>

        {/* 버튼 3개 */}
        <div className="project-buttons">
          <a href={project.links.plan}   className="project-btn">기획서 보기</a>
          <a href={project.links.github} className="project-btn">깃허브 보기</a>
          <a href={project.links.live}   className="project-btn">페이지 보기</a>
        </div>

      </div>

      {/* 오른쪽: 이미지 자리 */}
      <div className="project-image">
        {/* 실제 이미지가 있으면: <img src="..." alt="..." /> */}
      </div>

    </div>
  )
}

/* ─── Projects 메인 컴포넌트 ─── */
const Projects = () => {
  return (
    <section className="projects" id="projects">

      <SectionTitle
        title="Projects"
        subtitle="끈기와 열정으로 성장하는 오성의입니다."
      />

      {/* PROJECTS 배열을 반복해서 ProjectItem을 출력 */}
      {PROJECTS.map((project) => (
        <ProjectItem key={project.id} project={project} />
      ))}

    </section>
  )
}

export default Projects

코드 설명

객체 배열에서 map 사용

const PROJECTS = [
  { id: 1, title: '동대문구청', ... },
  { id: 2, title: '두 번째 프로젝트', ... },
]

{PROJECTS.map((project) => (
  <ProjectItem key={project.id} project={project} />
))}
  • project 는 배열의 각 객체 (예: { id: 1, title: '동대문구청' })
  • project.id, project.title 처럼 .으로 값에 접근
  • key={project.id} — 각 항목의 고유 번호를 key로 사용

props로 객체 전달

// 통째로 넘기기
<ProjectItem project={project} />

// 컴포넌트 안에서 꺼내 쓰기
const ProjectItem = ({ project }) => {
  return <h3>{project.title}</h3>
}

객체 전체를 project 라는 이름으로 전달하면 컴포넌트 안에서 project.title, project.stack 등으로 씁니다.

왜 PROJECTS 를 대문자로?

관례상 변하지 않는 상수 데이터는 대문자로 씁니다.

const PROJECTS = [...]  // 대문자: 변하지 않는 데이터
const [active, setActive] = useState('Home')  // 소문자: 변하는 상태

STEP 2 — CSS 추가

/* src/index.css 에 추가 */

/* ── Projects ────────────────────────────── */

.projects {
  padding: 80px 24px;
}

/* 프로젝트 한 항목: 2단 레이아웃 */
.project-item {
  display: grid;
  grid-template-columns: 1fr 1fr;  /* 설명 50% : 이미지 50% */
  margin-bottom: 40px;
  border: 1px solid #f0f0f0;
}

/* 왼쪽 설명 영역 */
.project-desc {
  padding: 40px;
  background-color: #ffffff;
}

/* ● 번호 부분 */
.project-number {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 16px;
}

/* 주황 점 */
.project-dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;  /* 원 모양 */
  background-color: #f26440;
}

/* "Project 01" 텍스트 */
.project-number__text {
  font-size: 12px;
  color: #c7c7c7;
}

/* 프로젝트 이름 */
.project-title {
  font-size: 32px;
  font-weight: 700;
  color: #000;
  margin-bottom: 24px;
}

/* 상세 정보 목록 */
.project-info {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 32px;
}

/* 정보 한 줄 */
.project-info__row {
  display: flex;
  gap: 8px;
  font-size: 18px;
  color: #555555;
}

/* 라벨 (기술스택 :) */
.project-info__label {
  min-width: 140px;
  flex-shrink: 0;  /* 라벨이 줄어들지 않게 */
}

/* 버튼 3개 묶음 */
.project-buttons {
  display: flex;
  gap: 16px;
}

/* 검정 버튼 */
.project-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 160px;
  height: 52px;
  background-color: #000;
  color: #fff;
  font-size: 18px;
  transition: background-color 0.2s;
}

.project-btn:hover {
  background-color: #333;
}

/* 오른쪽 이미지 영역 */
.project-image {
  background-color: #e8e8e8;
  min-height: 447px;
}

브라우저 확인

저장 후 브라우저에서:

  • "Projects" 큰 제목이 보입니다
  • 왼쪽에 프로젝트 설명, 오른쪽에 회색 이미지 자리가 있습니다
  • 3개의 검정 버튼이 보입니다

프로젝트 추가하는 방법

PROJECTS 배열에 객체 하나를 추가하면 자동으로 새 항목이 생깁니다.

const PROJECTS = [
  {
    id: 1,
    title: '동대문구청',
    // ...
  },
  // ↓ 이렇게 추가
  {
    id: 2,
    number: 'Project 02',
    title: '두 번째 프로젝트',
    stack: 'React, CSS',
    deploy: 'web',
    period: '1개월',
    contribution: '80%',
    browsers: 'Chrome / Edge',
    pages: '5페이지',
    links: { plan: '#', github: '#', live: '#' },
  },
]

목차

  • 구문