Type something to search...

06 Projects

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

이번 단계에서 할 일

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


피그마 디자인 분석

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

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

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

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

STEP 1 — Projects.jsx 작성

src/components/Projects.jsx
1
import SectionTitle from './SectionTitle'
2
3
/* ─── 프로젝트 데이터 (컴포넌트 밖에 위치) ─── */
4
// 나중에 프로젝트를 추가할 때 이 배열에만 항목을 추가하면 됩니다
5
const PROJECTS = [
6
{
7
id: 1,
8
number: 'Project 01',
9
title: '동대문구청',
10
stack: 'html, css, photoshop, figma',
11
deploy: 'desktop, mobile',
12
period: '2주',
13
contribution: '100%',
14
browsers: 'Chrome / Edge / Opera / Safari',
15
pages: '메인페이지 / 접근성 준수',
16
links: {
17
plan: '#',
18
github: '#',
19
live: '#',
20
},
21
},
22
// 프로젝트 추가 시 여기에 객체를 하나 더 작성하세요
23
]
24
25
/* ─── 프로젝트 한 항목을 보여주는 컴포넌트 ─── */
26
const ProjectItem = ({ project }) => {
27
return (
28
<div className="project-item">
29
30
{/* 왼쪽: 설명 */}
31
<div className="project-desc">
32
33
{/* 번호 (● Project 01) */}
34
<div className="project-number">
35
<span className="project-dot" />
36
<span className="project-number__text">{project.number}</span>
37
</div>
38
39
{/* 프로젝트 이름 */}
40
<h3 className="project-title">{project.title}</h3>
41
42
{/* 상세 정보 */}
43
<div className="project-info">
44
<div className="project-info__row">
45
<span className="project-info__label">기술스택 :</span>
46
<span>{project.stack}</span>
47
</div>
48
<div className="project-info__row">
49
<span className="project-info__label">배포매체 :</span>
50
<span>{project.deploy}</span>
51
</div>
52
<div className="project-info__row">
53
<span className="project-info__label">작업기간 :</span>
54
<span>{project.period}</span>
55
</div>
56
<div className="project-info__row">
57
<span className="project-info__label">본인기여도 :</span>
58
<span>{project.contribution}</span>
59
</div>
60
<div className="project-info__row">
61
<span className="project-info__label">브라우저 호환성 :</span>
62
<span>{project.browsers}</span>
63
</div>
64
<div className="project-info__row">
65
<span className="project-info__label">페이지수 / 특징 :</span>
66
<span>{project.pages}</span>
67
</div>
68
</div>
69
70
{/* 버튼 3개 */}
71
<div className="project-buttons">
72
<a href={project.links.plan} className="project-btn">기획서 보기</a>
73
<a href={project.links.github} className="project-btn">깃허브 보기</a>
74
<a href={project.links.live} className="project-btn">페이지 보기</a>
75
</div>
76
77
</div>
78
79
{/* 오른쪽: 이미지 자리 */}
80
<div className="project-image">
81
{/* 실제 이미지가 있으면: <img src="..." alt="..." /> */}
82
</div>
83
84
</div>
85
)
86
}
87
88
/* ─── Projects 메인 컴포넌트 ─── */
89
const Projects = () => {
90
return (
91
<section className="projects" id="projects">
92
93
<SectionTitle
94
title="Projects"
95
subtitle="끈기와 열정으로 성장하는 오성의입니다."
96
/>
97
98
{/* PROJECTS 배열을 반복해서 ProjectItem을 출력 */}
99
{PROJECTS.map((project) => (
100
<ProjectItem key={project.id} project={project} />
101
))}
102
103
</section>
104
)
105
}
106
107
export default Projects

코드 설명

객체 배열에서 map 사용

1
const PROJECTS = [
2
{ id: 1, title: '동대문구청', ... },
3
{ id: 2, title: '두 번째 프로젝트', ... },
4
]
5
6
{PROJECTS.map((project) => (
7
<ProjectItem key={project.id} project={project} />
8
))}
  • project 는 배열의 각 객체 (예: { id: 1, title: '동대문구청' })
  • project.id, project.title 처럼 .으로 값에 접근
  • key={project.id} — 각 항목의 고유 번호를 key로 사용

props로 객체 전달

1
// 통째로 넘기기
2
<ProjectItem project={project} />
3
4
// 컴포넌트 안에서 꺼내 쓰기
5
const ProjectItem = ({ project }) => {
6
return <h3>{project.title}</h3>
7
}

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

PROJECTS 를 대문자로?

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

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

STEP 2 — CSS 추가

1
/* src/index.css 에 추가 */
2
3
/* ── Projects ────────────────────────────── */
4
5
.projects {
6
padding: 80px 24px;
7
}
8
9
/* 프로젝트 한 항목: 2단 레이아웃 */
10
.project-item {
11
display: grid;
12
grid-template-columns: 1fr 1fr; /* 설명 50% : 이미지 50% */
13
margin-bottom: 40px;
14
border: 1px solid #f0f0f0;
15
}
16
17
/* 왼쪽 설명 영역 */
18
.project-desc {
19
padding: 40px;
20
background-color: #ffffff;
21
}
22
23
/* ● 번호 부분 */
24
.project-number {
25
display: flex;
26
align-items: center;
27
gap: 8px;
28
margin-bottom: 16px;
29
}
30
31
/* 주황 점 */
32
.project-dot {
33
display: inline-block;
34
width: 7px;
35
height: 7px;
36
border-radius: 50%; /* 원 모양 */
37
background-color: #f26440;
38
}
39
40
/* "Project 01" 텍스트 */
41
.project-number__text {
42
font-size: 12px;
43
color: #c7c7c7;
44
}
45
46
/* 프로젝트 이름 */
47
.project-title {
48
font-size: 32px;
49
font-weight: 700;
50
color: #000;
51
margin-bottom: 24px;
52
}
53
54
/* 상세 정보 목록 */
55
.project-info {
56
display: flex;
57
flex-direction: column;
58
gap: 8px;
59
margin-bottom: 32px;
60
}
61
62
/* 정보 한 줄 */
63
.project-info__row {
64
display: flex;
65
gap: 8px;
66
font-size: 18px;
67
color: #555555;
68
}
69
70
/* 라벨 (기술스택 :) */
71
.project-info__label {
72
min-width: 140px;
73
flex-shrink: 0; /* 라벨이 줄어들지 않게 */
74
}
75
76
/* 버튼 3개 묶음 */
77
.project-buttons {
78
display: flex;
79
gap: 16px;
80
}
81
82
/* 검정 버튼 */
83
.project-btn {
84
display: inline-flex;
85
align-items: center;
86
justify-content: center;
87
width: 160px;
88
height: 52px;
89
background-color: #000;
90
color: #fff;
91
font-size: 18px;
92
transition: background-color 0.2s;
93
}
94
95
.project-btn:hover {
96
background-color: #333;
97
}
98
99
/* 오른쪽 이미지 영역 */
100
.project-image {
101
background-color: #e8e8e8;
102
min-height: 447px;
103
}

브라우저 확인

저장 후 브라우저에서:

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

프로젝트 추가하는 방법

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

1
const PROJECTS = [
2
{
3
id: 1,
4
title: '동대문구청',
5
// ...
6
},
7
// ↓ 이렇게 추가
8
{
9
id: 2,
10
number: 'Project 02',
11
title: '두 번째 프로젝트',
12
stack: 'React, CSS',
13
deploy: 'web',
14
period: '1개월',
15
contribution: '80%',
16
browsers: 'Chrome / Edge',
17
pages: '5페이지',
18
links: { plan: '#', github: '#', live: '#' },
19
},
20
]