ํญ์ฃฝ์ ํฐํธ๋ ค๋ณด์ (์ต์ ํ๋ฅผ ๊ณ๋ค์ฌ์!!)
๊ฐ๋ฐ ๋์ค Interview๋ฅผ ์งํํ๋ ํ์ด์ง์์ ์ ์ ์ ๋ง์ง๋ง ๋ฉด์ ์ด ์ข ๋ฃ๊ฐ ๋์์๋, ์ ์ ์๊ฒ ์ถํ(?)์ ์๋ฏธ๋ฅผ ๋ด์ ์ด๋ฒคํธ๋ฅผ ์ ๊ณตํ๊ธฐ ์ํด์ ๋์ ๋์์ต๋๋ค!
์ด๋ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํด๋ณผ๊น ํ๋ค๊ฐ react-confetti๋ฅผ ๋ฐ๊ฒฌํ๊ฒ ๋์์ต๋๋ค.
ํด๋น ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๊ต์ฅํ ๊ฐ๋ณ๊ณ ๋ฌด์๋ณด๋ค ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ ์์ฒด๊ฐ ์ด๋ ต์ง ์์์ต๋๋ค.
import React from "react";
import Confetti from "react-confetti";
export default () => {
return <Confetti />;
};
๊ทธ์ react ํ๋ก์ ํธ ๋ด๋ถ์์ ์ฌ์ฉํด์ฃผ๊ธฐ๋ง ํ๋ฉด ๋๋ ์ด๋ ต์ง ์์ ๊ธฐ๋ฅ์ด์์ต๋๋ค! ํ์ง๋ง ์์ํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์๋๋ฐ!
Interview ํ์ด์ง ๋ ๋๋ง์ด ๋๋์ดํ ํด๋น Confetti๋ฅผ ํธ์ถํ๋ค์ ํ๋ฉด์ ํฌ๊ธฐ๋ฅผ ๋ณ๋ํ๊ฒ ๋๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ด์๊ฐ ๋ฐ์ํ๊ฒ ๋ฉ๋๋ค.
ํด๋น ์ด์๋ canvas๊ธฐ๋ฐ์ confetti๊ฐ ์ ์ธ๊ณผ ๋์์ ํ์ฌ view ์ฌ์ด์ฆ๋ฅผ ๋ฐํ์ผ๋ก ์ปดํฌ๋ํธ ํฌ๊ธฐ๋ฅผ ๊ฒฐ์ ํ๊ธฐ ๋๋ฌธ์ ์ดํ view์ ์ฌ์ด์ฆ๊ฐ ๋ณํ๊ฐ ์๊ฒผ์ ์ ๋ฐ์ํ์ง ๋ชปํ๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค.
๋ฐ๋ผ์ window resize๊ฐ ๋จ์ ๋ฐ๋ผ ๋ค์ confetti์ ํฌ๊ธฐ๋ฅผ ๋ณ๋ํด์ผํ ํ์๊ฐ ์์์ต๋๋ค.
๊ทธ๋์ ๊ฐ๋จํ useEffect๋ฅผ ๊ธฐ๋ฐ์ผ๋ก window resize์ด๋ฒคํธ๋ฅผ ํตํด์ ๋ค์ confetti๋ฅผ ๋ ๋๋งํด ์ฃผ์์ต๋๋ค. ๊ทธ๋ฌ๋๋ ๋ค์๊ณผ ๊ฐ์ ์ด์๊ฐ ๋ฐ์ํ์ต๋๋ค.
๋ฌด์ํ ๋ง์ ๋ ๋๋ง... ๋น์ฐํ๋ค...!
๋น์ฐํ๊ฒ๋ window.resize ์ด๋ฒคํธ๋ฅผ ํตํด์ ๋ฆฌ๋ ๋๋ง์ ์์ผ์ฃผ๋๊ฒฝ์ฐ window size์ ๋ณํ๊ฐ ์กฐ๊ธ์ด๋ผ๋ ์๊ธด๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋งค ์๊ฐ๋ง๋ค ๋ฆฌ๋ ๋๋ง์ ์งํํ๊ธฐ ๋๋ฌธ์ ๋ ๋๋ง ์ฑ๋ฅ์ ํฐ ์ ํ๊ฐ ์๊ธฐ๊ฒ ๋ฉ๋๋ค. ์ ๋ ๊ทธ๋์ ์ด๋ฅผ Debounce๋ก ํด๊ฒฐํ์ต๋๋ค.
๋๋ฐ์ด์ค(debounce)๋ ํ๋ก๊ทธ๋๋ฐ์์ ์ฌ์ฉ๋๋ ๊ธฐ์ ๋ก, ํนํ ์ฌ์ฉ์ ์ธํฐํ์ด์ค์ ๊ด๋ จ๋ ์ด๋ฒคํธ ์ฒ๋ฆฌ์ ์์ฃผ ์ฌ์ฉ๋ฉ๋๋ค. ๋๋ฐ์ด์ค๋ ์ฐ์์ ์ผ๋ก ๋ฐ์ํ๋ ์ด๋ฒคํธ๋ค ์ค์์ ๋จ ํ๋์ ์ด๋ฒคํธ๋ง์ ์ฒ๋ฆฌํ์ฌ, ๋ถํ์ํ ํจ์ ํธ์ถ์ ํ์๋ฅผ ์ค์ด๋ ๋ฐ ๋ชฉ์ ์ด ์์ต๋๋ค. ์ด๋ ์ฑ๋ฅ ์ต์ ํ์ ์ฌ์ฉ์ ๊ฒฝํ ํฅ์์ ์ค์ํ ์ญํ ์ ์ํํฉ๋๋ค!
๋๋ฐ์ด์ค์ ๋์ ์๋ฆฌ ๋๋ฐ์ด์ค์ ๊ธฐ๋ณธ ์๋ฆฌ๋ "์ผ์ ์๊ฐ ๋์ ์ถ๊ฐ์ ์ธ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์ง ์์ผ๋ฉด, ๋ง์ง๋ง์ ๋ฐ์ํ ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ๋ค"์ ๋๋ค. ์๋ฅผ ๋ค์ด, ์ฌ์ฉ์๊ฐ ์ ๋ ฅ ํ๋์ ๊ธ์ ํ์ดํํ๋ ๊ฒฝ์ฐ๋ฅผ ์๊ฐํด๋ณผ ์ ์์ต๋๋ค. ์ฌ์ฉ์๊ฐ ํ์ดํ์ ๋ฉ์ถ ๋๊น์ง ๊ธฐ๋ค๋ ธ๋ค๊ฐ, ์ผ์ ์๊ฐ(์: 300ms)์ด ์ง๋ ํ์๋ง ์ ๋ ฅ๊ฐ์ ๋ํ ์ฒ๋ฆฌ(์: ๊ฒ์, ์ ํจ์ฑ ๊ฒ์ฌ)๋ฅผ ์ํํฉ๋๋ค.
import { useState, useEffect } from "react";
const useWindowSize = () => {
const [windowSize, setWindowSize] = useState({
width: window.innerWidth,
height: window.innerHeight,
});
useEffect(() => {
let timeoutId: number;
const handleResize = () => {
window.clearTimeout(timeoutId); // ๋งค๋ฒ ์ด๋ฒคํธ๋ฅผ ์ ๊ฑฐ ํฉ๋๋ค. ์ฆ resize event๊ฐ ๋ฑ๋ก๋ ๋ ๋ง๋ค ์ด์ ์ ์ด๋ฒคํธ๋ฅผ ์ ๊ฑฐํฉ๋๋ค.
timeoutId = window.setTimeout(() => {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
}, 250);
};
window.addEventListener("resize", handleResize); // ์ด๋ฒคํธ ์ถ๊ฐ
return () => {
window.removeEventListener("resize", handleResize); // ํด๋น ์ปดํฌ๋ํธ๊ฐ unmount ๋ ๋ ์ ๊ฑฐ ๋ฉ๋๋ค.
window.clearTimeout(timeoutId);
};
}, []);
return windowSize;
};
export default useWindowSize;
ํด๋น ์ฝ๋๋ฅผ ํตํด์ windowSize๋ฅผ ๋ฐ์, confetti ์ปดํฌ๋ํธ์ ์ธ์๋ก ๋ฃ์ด์ฃผ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๋ฌผ์ ํ์ธํ ์ ์์ต๋๋ค.
์กฐ์ฌ์ค๋ฝ๊ฒ ๋จ์ด์ง๋ ์์ข ์ด๊ฐ ์ด์๊ตฐ์!