๐ผ Outline
Why - ๊ต๋ด์น๊ฐ๋ฐ๋์๋ฆฌ์์ ๊ฒจ์ธ๋ฐฉํ ํ ์ดํ๋ก์ ํธ๋ก ์งํ
What - ์ ํ๋ธ ์น์ฌ์ดํธ ํด๋ก ์ฝ๋ฉ
Who - spring์ ์ฌ์ฉํ์๋ ๋๋ช
์ ๋ฐฑ์๋ ๋ถ๋ค๊ณผ ํ์
ํ์์ผ๋ฉฐ ๋๋ ํ๋ก ํธ๋ฅผ ๋งก์๋ค
How - React ๊ธฐ๋ฐ
When - ์ฝ ํ ๋ฌ(2021๋
11์ 08์ผ ~ 2021๋
12์ 4์ผ)๊ฐ ์งํํ๋ค
โจ Main Features
1. ๋ฐ์ํ
2ํ๊ธฐ์ ์ง์ค์ ์ผ๋ก ๊ณต๋ถํ ๋ฐ์ํ์ ๋ณธ ํ๋ก์ ํธ ๊ณณ๊ณณ์์ ๊ตฌํํ๋ ค ๋ ธ๋ ฅํ๋ค.
๋น์ฐํ์ง๋ง? ๋ฏธ๋์ด ์ฟผ๋ฆฌ๋ฅผ ์ด์ฉํ์ฌ css ์คํ์ผ์ ์ ์ฉํ์๊ณ
const Wrapper = styled.div`
display: flex;
flex-direction: column;
gap: 20px;
width: 70vw;
@media (max-width: 1300px) {
width: 80vw;
}
@media (max-width: 800px) {
width: 80vw;
}
`;
์ฌ์ด๋๋ฉ๋ด๋ ํค๋ ๊ฐ์ ํ๋ฉด ๊ตฌ์ฑ๋ค์ ํฌ๊ฒ 3๋จ๊ณ(๋ชจ๋ฐ์ผ๋ทฐ, ์์ดํจ๋๋ฐํญ, pc๋ทฐ)๋ก ๋๋ ์ ๋ ์ด์์ ๊ตฌ์ฑ ๋ฐฉ์์ ๋ฐ๊ฟจ๋ค
ํ์ํญ ๋ฒํผ๋ค๊ณผ ๋ฉ์ธํญ ๋์์ ์ปดํฌ๋ํธ๋ค์ ๋ฐฐ์ด ๋ฐ ์ฌ์ด์ฆ๋ ํ๋ฉด ํฌ๊ธฐ์ ๋ฐ๋ผ ์ฐ์์ ์ผ๋ก ์กฐ์ ๋๋๋ก ์ค์ ํ์๋ค
2. ๋ง์ฐ์ค ์ฌ๋ ธ์ ๋ ๋์์ ์ฌ์
์ค์ ์ ํ๋ธ ์น์์๋ ๊ฐ ๋์์ ์ปดํฌ๋ํธ๋ค์ ์ธ๋ค์ผ์ด ์ ์ง๋์ด์๊ณ
๋ง์ฐ์ค๋ฅผ ๊ทธ ์์ ์ฌ๋ ธ์ ๋ ๋์์์ด ๋ฏธ๋ฆฌ๋ณด๊ธฐ ํ์์ผ๋ก ์๋์ผ๋ก ์ฌ์๋๋ค
์ด๋ฒ ์ ํ๋ธ ํด๋ก ์ฝ๋ฉ์์๋ ํด๋น ๊ธฐ๋ฅ์ ์ง์คํ๋ค.
์ฐ๋ฆฌ ํ์ ๋ฐฑ์๋ ๊ฐ๋ฐ์๋ถ๋ค์ด ๋์์๋ณ๋ก ์ธ๋ค์ผ๊ณผ ๋์์์ ๋งํฌํํ๋ก ์ ๋ฌํด์ฃผ์
จ๊ณ ,
๋๋ ์ด๋ฅผ ์ด์ฉํ์ฌ ๋ง์ฐ์ค๋ฅผ ์ฌ๋ ธ์๋๋ ๋์์์ด, ๋ง์ฐ์ค๋ฅผ ์ฌ๋ฆฌ์ง ์์์๋๋ ์ ์ง๋ ์ธ๋ค์ผ์ด ๋ณด์ด๊ฒ ๋ง๋ค์ด์ ๋ณธ ๊ธฐ๋ฅ์ ๊ตฌํํด์คฌ๋ค.
2-1. ์ฌ์๋๋ ๋์์ ์ปดํฌ๋ํธ
์ฐ์ ๋ณธ ๊ธฐ๋ฅ์ ๊ตฌํํ๊ธฐ ์ํด "์ฌ์๋๋" ๋์์ ์ปดํฌ๋ํธ๊ฐ ํ์ํ๋ค.
๊ฐ์ฌํ๊ฒ๋ url์ ๋ฃ์ผ๋ฉด ํด๋น ๋น๋์ค๋ฅผ ์ฌ์์์ผ์ฃผ๋ ์ปดํฌ๋ํธ๊ฐ ์คํ์์ค๋ก ์ ๋ง๋ค์ด์ ธ ์์ด ๊ฐ์ฌํ ์ฌ์ฉํ๋ค.
ReactPlayer Component
https://www.npmjs.com/package/react-player
๋ณด๋ฉด ์๊ฒ ์ง๋ง ์ ์ฉํ props๋ค๋ ๋ง์ด ์์๋๋ฐ,
playing="true"
๋ก ์ฌ์ ์ฌ๋ถ๋ ๊ฒฐ์ ํ ์ ์์๊ณ muted="true"
๋ก ๋์์์ ์กฐ์ฉํ ์ฌ์ ์ํฌ ์ ์๊ฒ ์ปค์คํ
ํ ์ ์์๋ค.
<ReactPlayer url={data.videoUrl} muted="true" playing="true" />
2-2. ๋ง์ฐ์ค ํธ๋ฒ๋ง react๋ก ๊ด๋ฆฌํ๊ธฐ
์ด์ ๋์์ ์ฌ์์ ์ค๋น ๋์์ผ๋ ๋ง์ฐ์ค๋ฅผ ์ฌ๋ ธ์๋ ํด๋น ์ปดํฌ๋ํธ๊ฐ ๋ณด์ด๊ฒ ๋ง๋ค๋ฉด ๋๋๋ฐ..
๋ฌธ์ ๋ ๋ฉ์ธํ์ด์ง ํญ๋ฐ ๋ฒํผ์ด๋ ์ฌ์ด๋๋ฐ ๋ฉ๋ด ๋ฒํผ๋ค์ ์์ ๋ณํ๋ฅผ ๊ตฌํํ ๋ ์ฌ์ฉํ๋
:hover
๊ธฐ๋ฅ์ css๋ก ํ ์ ์๋ ์คํ์ผ ๋ณํ๋ง ์ ์ฉ์ด ๊ฐ๋ฅํ๋ค๋ ๊ฒ์ด์๋ค.
์ฌ๊ธฐ์๋ ๋ง์ฐ์ค ํธ๋ฒ๋ง์ ๋ฐ๋ผ ์ปดํฌ๋ํธ๊ฐ ๋ณํํ๊ฒ ํ๋ ๊ฒ์ด ํ์ํ๋ค.
์ด์ useState()
๋ฅผ ์ด์ฉํ์ฌ ๋ง์ฐ์ค ํธ๋ฒ๋ง ์ฌ๋ถ๋ฅผ ์ํ๋ก์จ ๊ด๋ฆฌํ๊ธฐ๋ก ํ๋ค.
const [hover, setHover] = useState(false);
์ดํ onMouseOver
์ onMouseOut
์์ฑ์ ์ด์ฉํด
๋ง์ฐ์ค๊ฐ ํด๋น ์ปดํฌ๋ํธ์ ์ฌ๋ผ์์๋๊ฐ๋ฅผ ํ๋จํ์ฌ ์ํ๋ฅผ set ํด์คฌ๋ค
<VideoItem
onMouseOver={() => setHover(true)}
onMouseOut={() => setHover(false)}
>
{hover ? (
<ReactPlayer url={data.videoUrl} />
) : (
<Thumbnail src={data.videoThumbnail} />
)}
๊ฒฐ๋ก ์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ด ๋น๋์ค ์ปดํฌ๋ํธ ์ฝ๋ ์์ฑ!
<VideoItem
onMouseOver={() => setHover(true)}
onMouseOut={() => setHover(false)}
>
{hover ? (
<ReactPlayer
url={data.videoUrl}
muted="true"
width="100%"
height="auto"
playing="true"
style={{ marginBottom: "10px" }}
/>
) : (
<Thumbnail src={data.videoThumbnail} />
)}
<Profile src={youtubeData["data"][index + 28].channelThumbnail} />
<Info>
<Title>{data.videoTitle}</Title>
<Chanel>{data.videoChannel}</Chanel>
<Views>์กฐํ์ {data.videoCount}ํ·</Views>
<Date>{relativeDate()}</Date>
</Info>
</VideoItem>
3. ๋ก๋ฉํ๋ฉด ๊ตฌํ
ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉด์ ๋น๋ํ ๋๋ง๋ค ๋ณด์ด๋ ํฐ์ ํ๋ฉด์ด ๋๋ฌด ๊ฑฐ์ฌ๋ ธ๋ค.
์ด์ ์ผ๋งค์์ง๋ง ์ค์ ์ ํ๋ธ ๋ก๋ฉ ํ๋ฉด๊ณผ ์ ์ฌํด๋ณด์ด๊ฒ ๋์์์ฉ์ผ๋ก๋ผ๋ ๋ก๋ฉํ๋ฉด์ ๋ง๋ค์ด๋ณด๊ธฐ๋ก ํ๊ณ ,
๋ง์นจ 2ํ๊ธฐ๋ ๋ด๊ฐ ๋งก์ ์ธ๋ฏธ๋ ๋ถ๋ถ์ด ๊ณ ๊ธCSS ์ ๋๋ฉ์ด์ ๋ถ๋ถ์ด์๋๋ฐ,
๋ก๋ฉ ์ ๋๋ฉ์ด์ ์ ์ค์ต ์๋ฃ๋ฅผ ๋ง๋ค๋ฉฐ ๋ก๋ฉ์ฐฝ์ ๋์ถฉ ๋ค๋ฃฌ์ ์ด ์์๋ค
์ฐ์ ๋ก๋ฉํ๋ฉด์ ๋ฐ๋ณต์ ์ผ๋ก ๋์ฌ ํ์ ์ปดํฌ๋ํธ๋ฅผ ๋น ๋ฅด๊ฒ ๊ตฌํํ๊ณ
(์ ๊ธฐ ์ ๋ชฉ๋ถ๋ถ์ด๋ ์ปจํ
์ธ ๊ธธ์ด๊ฐ ๋ค๋ฅธ๊ฑฐ ์ผ๋ถ๋ฌ ๊ทธ๋ฐ๊ฑฐ๋ค.. ์ง์ง ์ ๋ผ..)
(์ด๋ฉด์ ๋ก๋ฉํ๋ฉด ์บก์ณํด๋๊ณ ์์ ์ถ์ถํ๊ณ ์ฌ์ด์ฆ ์ฌ๊ณ ๊ทธ๋ฐ๊ฑด ์ฒ์..)
์ดํ useState()
๋ก ๋ก๋ฉ ์ํ๋ฅผ ๊ด๋ฆฌ
const [loading, setLoading] = useState(false);
๊ทธ๋ฆฌ๊ณ useEffect()
๋ฅผ ์ด์ฉํ์ฌ ์๋ฒ๋ก ๋ถํฐ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๋ ๋์์ true,
๋ฐ์์ค๋๊ฑธ ์๋ฃํ ํ์๋ false ๋ก ๋ก๋ฉ์ํ๋ฅผ set ํด์ฃผ์๋ค
useEffect(() => {
const fetchData = async () => {
setLoading(true);
try {
const response = await axios.get(
`http://${baseurl}/video/get/${index}`
);
setData(response.data);
console.log(data);
} catch (e) {
console.log(e);
}
setLoading(false);
};
fetchData();
}, []);
if (loading) {
return <Loading />;
}
if (!data) {
return <Loading />;
}
๊ทธ๋ ๊ฒ ์์ฑ-!
๐ Structure
1. ํด๋ ๊ตฌ์กฐ
ํด๋ ๊ตฌ์กฐ๋ ์ฉ๋์ ๋ฐ๋ผ ํฌ๊ฒ ๋ค๊ฐ์ง๋ก ๋๋๊ณ ๊ฐ ํด๋ ๋ด๋ถ์ ํ์ด์ง๋ณ ํด๋๋ฅผ ๋ ๋ง๋ค์ด์ ํ์ผ๋ค์ ๊ด๋ฆฌํด์คฌ๋ค.
์ด๋ฒ์๋ ํผ์ ์์
ํ ๋๋ถ์ ์จ์ ํ ๋ด ์ทจํฅ๋๋ก ํด๋๋ฅผ ๊ตฌ๋ถํ๋๋ฐ ๋๋ ์ด๊ฒ ์ ๋ง ํธํ๋คใ
ใ
- assets
: ์ด๋ฏธ์ง ๋ฐ ์์ด์ฝ ์์ ๋ค - pages
: ํ์ด์ง๋ณ js ํ์ผ๋ค - component
: ๊ฐ ํ์ด์ง์ ์ฌ์ฉํ ์ปดํฌ๋ํธ๋ค - shared
: ๋ชจ๋ ํ์ด์ง์์ ๊ณตํต์ ์ผ๋ก ์ฌ์ฉํ๋ ์ปดํฌ๋ํธ๋ค
App.js
- App.css
- index.js
- assets
- assets_header - ํค๋์ ์ฌ์ฉํ ์ด๋ฏธ์ง ์์ด์ฝ ์์ ๋ชจ์
- card - ํ์ ํ์ด์ง ์นด๋ ์ด๋ฏธ์ง์์
- icon - ์ฌ์ด๋๋ฐ์ ์ฌ์ฉํ ์์ด์ฝ ์์
- pages
- Finder.js
- Main.js
- Subscribe.js
- component - ๊ฐ ํ์ด์ง์ ์ฌ์ฉํ ์ปดํฌ๋ํธ๋ค
- Finder
- LargeVideo.js
- Main
- Ad.js
- Filter.js
- Loading.js
- Video.js
- VideoList.js
- Subscribe
- LargeVIdeoWithChannel.js
- loading.png
- Finder
- shared - ๋ชจ๋ ํ์ด์ง์ ๊ณตํต์ ์ผ๋ก ์ฌ์ฉํ ์ปดํฌ๋ํธ
- Header.js
- Layout.js
- Sidebar.js
2. ๋ ์ด์์ ๊ตฌ์ฑ
๋ง์ง๋ง์ ์๋ shared ์์ Layout.js
๊ฐ ์ด๋ฒ ํ๋ก์ ํธ์์ ๋ฐ๋ณต์ ์ต์ํํ ์ ์๊ฒ ํด์ค ํ์ผ์ด๋ค.
function Layout({ active, content }) {
return (
<Wrapper>
<Header />
<Body>
<Sidebar active={active} />
<div className="contents">{content}</div>
</Body>
</Wrapper>
);
}
๋ค์๊ณผ ๊ฐ์ด ๊ณตํต๋ ์ปดํฌ๋ํธ์ธ ํค๋์ ์ฌ์ด๋๋ฐ์ ๋ ์ด์์์ ๋ณธ Layout.js
์์ ์ก์์ฃผ๊ณ
๋ด์ฉ์ ํด๋นํ๋ ๋ถ๋ถ์ content ์ปดํฌ๋ํธ๋ฅผ ๋ฐ์์์ ๋ณด์ฌ์ฃผ๊ฒ ํ๋ค.
์ฆ, ํํญ, ํ์ํญ, ๊ตฌ๋ ํญ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋ ๋ด์ฉ ๋ถ๋ถ์ content ์ปดํฌ๋ํธ๋ก ๋ฐ์์ค๋ ํ์
App.js
์์๋ ๊ฒฝ๋ก์ ๋ฐ๋ผ Layout ์ปดํฌ๋ํธ์ content ์ปดํฌ๋ํธ๋ง ๋ฐ๊ฟ์ ๋ณด์ฌ์ฃผ๊ธฐ๋ง ํ๋ฉด ๋๋ค.
function App() {
return (
<Router>
<Routes>
<Route
path="/"
exact={true}
element={<Layout active="main" content={<Main />} />}
/>
<Route
path="/Finder"
element={<Layout active="finder" content={<Finder />} />}
/>
<Route
path="/Subscribe"
element={<Layout active="subscribe" content={<Subscribe />} />}
/>
</Routes>
</Router>
);
}
๐ช Closing
์๋ฌดํผ ์ด๋ ๊ฒ ๊ธธ๋ฉด ๊ธธ๊ณ ์งง์ผ๋ฉด ์งง์ ํ๋ก์ ํธ๊ฐ ๋์ด ๋ฌ๋ค..!
Github
https://github.com/seondal/Clone-Youtube-Web
์ฌ์ค ํ์ ๋ฐฐ์ ๋ ํ๋ก ํธ ๋ด๋น์ด ๋๋ช ์ด์๋๋ฐ,
๊ฐ์ ํ์ด์ จ๋ ํ๋ก ํธ ์ ๋ฐฐ๋๊ป์ ์ง์ฅ ๋๋ฌธ์ ๋ฐ๋น ์ง์ ์ ํ๋ก ํธ๋ถ๋ถ์ ๋ ํ๋ก ์งํํ๊ฒ ๋์๋ค.
์ด๋ ๋ฐ์ํ ์ฐ์ตํ ๊ฑธ๋ก ์ดํ์ ์น์ฌ์ดํธ ์ธ์ฃผ๊น์ง ํ๊ฒ ๋์์ผ๋ ๊ฒฐ๊ณผ์ ์ผ๋ก๋ ์ ๋ง ์ข์ ๊ฒฝํ์ด์๋ ๊ฒ ๊ฐ๋ค :)
https://www.instagram.com/p/CXSYOIiBctm/?utm_source=ig_web_copy_link
'_ > Velog' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Github Readme ๊พธ๋ฏธ๊ธฐ ์ด์ ๋ฆฌ ๐จ (2) | 2023.10.01 |
---|---|
2023๋ ์๋ฐ๊ธฐ ICT ํ์ ์ฐ๊ณ ํ๋ก์ ํธ ์ธํด์ญ ํฉ๊ฒฉ ํ๊ธฐ ๐ (0) | 2023.09.07 |
[React] Hook (0) | 2021.06.03 |
๋์ด์ฐ๊ธฐ (0) | 2021.06.03 |
[ html / css ] h1 ํ๊ทธ์ h2 ํ๊ทธ๊ฐ ํ์ค์ ๋์ค๊ฒ ํ๊ธฐ = inline ์์ฑ (0) | 2021.06.03 |