1. ํ๋ก์ ํธ ์ฌ๋ผ์ด๋
- ๋ด๊ฐ ์ฐธ์ฌํ๋ ํ๋ก์ ํธ๋ค์ ์๋๋ aํ๊ทธ๋ง ๋ฌ์์ ํด๋น ํ์ด์ง๋ก ๋๊ธฐ๋ ค๊ณ ํ๋๋ฐ, ๊ฐ๋ตํ ์๊ฐ๊ฐ ์์ผ๋ฉด ์ข์ ๊ฒ ๊ฐ์์ ํ๋ก์ ํธ ์ฌ๋ผ์ด๋๋ฅผ ๋ง๋ค๊ธฐ๋ก ๊ฒฐ์ !
1) ํ๋ก์ ํธ ๋ด์ฉ ํ์ผ ์์ฑ
- ์ฐ์ , ํ๋ก์ ํธ ๋ด์ฉ๋ค์ ๊ฐ์ฒด ๋ฐฐ์ด ํํ๋ก ์ ๋ฆฌํด์ projectItems๋ผ๋ ์ด๋ฆ์ผ๋ก ์ ์ฅํจ.
projectItems.js
export const projectItems = [
{
title: "๐๋ฌผํ๋์ฌ์๋น์ค",
category: "๊ฐ์ธ ํ๋ก์ ํธ",
imageUrl: ``,
githubLink: "",
description:
"",
features:
"",
techStack: "",
},
{
title: "๐โ๏ธ๋๋ง์ ํฌํธํด๋ฆฌ์ค",
category: "๊ฐ์ธ ํ๋ก์ ํธ",
imageUrl: ``,
githubLink: "",
description:
"",
features:
"",
techStack: "",
},
];
- ์ดํ projectDetail์์ importํด ์ฌ์ฉ.
2) ํ๋ก์ ํธ ๋ด์ฉ ๋ฟ๋ฆฌ๊ธฐ
ProjectDetail.js
import { projectItems } from "./ProjectItems";
...
const [currentProjectIndex, setCurrentProjectIndex] = useState(0);
const handlePrevProject = () => {
setCurrentProjectIndex((prevIndex) =>
prevIndex === 0 ? projectItems.length - 1 : prevIndex - 1
);
};
const handleNextProject = () => {
setCurrentProjectIndex((prevIndex) =>
prevIndex === projectItems.length - 1 ? 0 : prevIndex + 1
);
};
- ํ๋ก์ ํธ๋ฅผ ๊ธฐ์ค์ผ๋ก ์์ <, > ๋ฒํผ์ ๋๋ฅด๋ฉด ํ๋ก์ ํธ๊ฐ ๋ณ๊ฒฝ๋๋ ์ฌ๋ผ์ด๋๋ก ๊ตฌํ ์์ ์ด๋ผ, ํ์ฌ ํ๋ฉด์ ๋ณด์ฌ์ค ํ๋ก์ ํธ ์ธ๋ฑ์ค๋ฅผ ์ ์ฅํ ๊ฐ์ฒด currentProjectIndex ์์ฑ.
- handlePrevProject() ํจ์์ handleNextProjext() ํจ์๋ ๋ฒํผ์ ๋๋ฅด๋ฉด ํ๋ฉด์ ๋ณด์ฌ์ค ํ๋ก์ ํธ์ ์ธ๋ฑ์ค๋ฅผ ๋ฐ๊ฟ์ฃผ๋ ํจ์์.
- ๋ ํจ์ ๋ชจ๋ setCurrentProjectIndex์ ์ธ์๋ก, ์๋ก์ด ์ํ๋ฅผ ๋ฐํํ๋ ์ฝ๋ฐฑ ํจ์๋ฅผ ์ ๋ฌํจ(์ด๋ prevIndex๋ ํ์ฌ์ ํ๋ก์ ํธ ์ธ๋ฑ์ค๋ฅผ ๋ํ๋).
- handlePrevProject() ํจ์์ ๊ฒฝ์ฐ ์ด ๊ฐ์ด 0์ด๋ฉด ๋ง์ง๋ง ํ๋ก์ ํธ๋ก ์ด๋ํ๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉด ์ด์ ํ๋ก์ ํธ๋ก ์ด๋.
- handleNextProjext() ํจ์์ ๊ฒฝ์ฐ prevIndex ๊ฐ์ด ๋ง์ง๋ง ํ๋ก์ ํธ์ ์ธ๋ฑ์ค๋ฅผ ๊ฐ๋ฆฌํค๊ณ ์๋ค๋ฉด 0๋ฒ์งธ ํ๋ก์ ํธ๋ก ์ด๋ํ๊ณ , ๊ทธ๋ ์ง ์๋ค๋ฉด ๋ค์ ํ๋ก์ ํธ๋ก ์ด๋.
return (
<div className="container project" ref={ref}>
<h1 className="project-title">
<a name="Project">Projects</a>
</h1>
<div className="project-card-wrapper">
<div className="slide">
<img
src={process.env.PUBLIC_URL + "/projectImgs/left.png"}
onClick={handlePrevProject}
/>
</div>
<Card className="project-card">
<div className="project-order">
{currentProjectIndex + 1} / {projectItems.length}
</div>
<h2 className="project-title">
{projectItems[currentProjectIndex].title}
</h2>
<h4 style={{ textAlign: "center", width: "100%" }}>
{projectItems[currentProjectIndex].category}
</h4>
<section>
<div className="project-img"></div>
</section>
<section>
<article className="info-article">
<p className="link-wrapper">
Github
<br />
</p>
<a href={projectItems[currentProjectIndex].githubLink}>
{projectItems[currentProjectIndex].title}
</a>
</article>
<article>
<h3>ํ๋ก์ ํธ ์๊ฐ</h3>
<p
dangerouslySetInnerHTML={{
__html: projectItems[currentProjectIndex].description,
}}
></p>
<h3>์ฃผ์ ๊ธฐ๋ฅ</h3>
<p
dangerouslySetInnerHTML={{
__html: projectItems[currentProjectIndex].features,
}}
></p>
<h3>๊ธฐ์ ์คํ</h3>
<p>{projectItems[currentProjectIndex].techStack}</p>
</article>
</section>
</Card>
<div className="slide">
<img
src={process.env.PUBLIC_URL + "/projectImgs/right.png"}
onClick={handleNextProject}
/>
</div>
</div>
</div>
);
});
- projectItems ๋ฐ์ดํฐ๋ฅผ ์ด์ฉํด ๋์ ์ผ๋ก ๋ฐ์ดํฐ ํ๋ฉด์ ๋ฟ๋ ค์ฃผ๊ธฐ.
- <Card className="project-card"></Card> ์ ์์ <div className="slide"></div> ๋ด๋ถ ํ์ดํ ์ด๋ฏธ์ง์ ๊ฐ๊ฐ ๋ฌ์์ค.
3) ์ด๋ฏธ์ง ์ฌ๋ผ์ด๋
- ์๋๋ ํ๋ก์ ํธ ๋ด์ ์ด๋ฏธ์ง๋ ์๋๋ ๋ํ ์ด๋ฏธ์ง ํ ์ฅ๋ง ๋ณด์ฌ์ฃผ๋ ค๊ณ ํ๋๋ฐ ์ด๋ฏธ์ง๋ก ์ฌ๋ผ์ด๋๋ก ๋ณด์ฌ์ฃผ๊ธฐ๋ก ๊ฒฐ์ ํจ.
projectItems.js
export const projectItems = [
{
title: "๐๋ฌผํ๋์ฌ์๋น์ค",
category: "๊ฐ์ธ ํ๋ก์ ํธ",
imageUrls: [
...
],
},
...
]
- ๋จผ์ imageUrl์ ๋ฐฐ์ด๋ก ์ ์ธ.
ProjectDetail.js
import { projectItems } from "./ProjectItems";
...
const [currentProjectIndex, setCurrentProjectIndex] = useState(0);
const [currentImageIndex, setCurrentImageIndex] = useState(0);
const imageUrls = projectItems[currentProjectIndex].imageUrls;
const hasMultipleImages = imageUrls.length > 1;
const handlePrevProject = () => {
setCurrentProjectIndex((prevIndex) =>
prevIndex === 0 ? projectItems.length - 1 : prevIndex - 1
);
setCurrentImageIndex(0); // ํ๋ก์ ํธ ๋ณ๊ฒฝ ์ ์ด๋ฏธ์ง ์ฌ๋ผ์ด๋ ์ด๊ธฐํ
};
const handleNextProject = () => {
setCurrentProjectIndex((prevIndex) =>
prevIndex === projectItems.length - 1 ? 0 : prevIndex + 1
);
setCurrentImageIndex(0);
};
const handlePrevImage = () => {
setCurrentImageIndex((prevIndex) =>
prevIndex === 0
? projectItems[currentProjectIndex].imageUrls.length - 1
: prevIndex - 1
);
};
const handleNextImage = () => {
setCurrentImageIndex((prevIndex) =>
prevIndex === projectItems[currentProjectIndex].imageUrls.length - 1
? 0
: prevIndex + 1
);
};
...
- currentImageIndex ์ํ ๋ณ์ ์์ฑํด์ ํ์ฌ ์ ํ๋ ํ๋ก์ ํธ ๋ด์์์ ์ด๋ฏธ์ง ์ธ๋ฑ์ค๋ฅผ ๊ด๋ฆฌ(์ด๊ธฐ๊ฐ 0).
- imageUrls ๋ฐฐ์ด ๋ณ์ ์ ์ธํด ํ์ฌ ํ๋ก์ ํธ์ ์ด๋ฏธ์ง๋ฅผ ๋ค๋ฃฐ ์ ์๊ฒ ํจ.
- ์ด๋ฏธ์ง๊ฐ ํ์ฅ ๋ฟ์ธ ํ๋ก์ ํธ๋ฅผ ๊ณ ๋ คํด, ์ด๋ฏธ์ง๊ฐ ์ฌ๋ฌ ์ฅ์ธ ํ๋ก์ ํธ๋ง ์ด๋ฏธ์ง ์์ ์์ผ๋ก ๊ฐ๊ธฐ ๋ฒํผ์ด ๋ณด์ด๋๋ก ์ค์ ํ๊ณ ์ถ์์.
- hasMultipleImages ๋ถ๋ฆฌ์ธ ๋ณ์๋ฅผ ์ ์ธํด ํ์ฌ ํ๋ก์ ํธ์ ์ด๋ฏธ์ง๊ฐ ๋ ์ฅ ์ด์์ธ์ง ์ฌ๋ถ๋ฅผ ํ์ธํจ.
- ๊ทธ๋์ ์ด๋ฏธ์ง๊ฐ ์ฌ๋ฌ ์ฅ์ผ ๊ฒฝ์ฐ์๋ง ์ฌ๋ผ์ด๋๊ฐ ์๋ํ๊ฒ๋ ์ฌ์ฉ.
return (
<div className="container project" ref={ref}>
<h1 className="project-title">
<a name="Project">Projects</a>
</h1>
...
<section>
<div className="project-img">
<div className="slider">
<img
src={
projectItems[currentProjectIndex].imageUrls[
currentImageIndex
]
}
alt={projectItems[currentProjectIndex].title}
/>
{hasMultipleImages && (
<div className="slider-controls">
<button onClick={handlePrevImage}>{"<"}</button>
<button onClick={handleNextImage}>{">"}</button>
</div>
)}
</div>
</div>
</section>
<section>
<article className="info-article">
...
</article>
</section>
</Card>
...
</div>
);
});
- {hasMultipleImages && (...)} ์ ๊ฒฝ์ฐ, ์กฐ๊ฑด๋ถ ๋ ๋๋ง์ ํตํด, ํ์ฌ ํ๋ก์ ํธ์ ์ด๋ฏธ์ง๊ฐ ์ฌ๋ฌ ์ฅ(hasMultipleImages) ์๋ ๊ฒฝ์ฐ์๋ง ์ฌ๋ผ์ด๋ ์ปจํธ๋กค์ ๋ ๋๋งํจ.
- hasMultipleImages๊ฐ true์ผ ๋, ์ฌ๋ผ์ด๋ ์ปจํธ๋กค(์ด๋ฏธ์ง ์ ํ ๋ฒํผ)์ด ํ๋ฉด์ ๋ํ๋จ.