์ด๋ฒ ํฌ์คํ ์์๋ ๋ฐ์ํ ํค๋๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ๋ค๋ฃจ๊ฒ ์ต๋๋ค. ์ด ํค๋๋ ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธํ ์ํ์ ๋ฐ๋ผ ๋์ ์ผ๋ก ๋ก๊ทธ์ธ/๋ก๊ทธ์์ ๋ฒํผ์ ํ์ํ๊ณ , ๋ชจ๋ฐ์ผ ํ๋ฉด์์๋ ํ๋ฒ๊ฑฐ ๋ฉ๋ด๋ฅผ ํตํด ๋ฉ๋ด ํญ๋ชฉ์ ์กฐ์ํ ์ ์๋๋ก ๊ตฌ์ฑ๋์ด ์์ต๋๋ค.
1. ํ๋ก์ ํธ ๊ฐ์
์ด๋ฒ์ ๊ตฌํํ ํค๋๋ ๊ธฐ๋ณธ์ ์ผ๋ก 2๊ฐ์ง ์ค์ํ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค:
- ๋ฐ์ํ ๋์์ธ: ํ๋ฉด ํฌ๊ธฐ์ ๋ฐ๋ผ ๋ฉ๋ด๋ฅผ ํ๋ฒ๊ฑฐ ๋ฉ๋ด๋ก ์ ํํด ๋ชจ๋ฐ์ผ์์๋ ๊น๋ํ๊ฒ ํ์๋๋๋ก ํฉ๋๋ค.
- ๋ก๊ทธ์ธ ์ํ์ ๋ฐ๋ฅธ ๋์ ๋ฒํผ: ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธํ ์ํ์ ๋ฐ๋ผ ํค๋์ ๋ก๊ทธ์์ ๋ฒํผ์ ๋์ ์ผ๋ก ๋ณด์ฌ์ฃผ๋ฉฐ, ๋ก๊ทธ์ธํ์ง ์์ ๊ฒฝ์ฐ ๋ก๊ทธ์ธ์ด ํ์ํ๋ค๋ ๋ฉ์์ง๋ฅผ ์ ๋ํฉ๋๋ค.
2. ์ฃผ์ ๊ธฐ๋ฅ
2.1 ๋ฐ์ํ ๋์์ธ
ํค๋๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ฐ์คํฌํ ํ๋ฉด์์ ๋ชจ๋ ๋ฉ๋ด ํญ๋ชฉ์ ์ํ์ผ๋ก ๋ฐฐ์นํ๋ฉฐ, ํ๋ฉด ํฌ๊ธฐ๊ฐ ์ค์ด๋ค๋ฉด ํ๋ฒ๊ฑฐ ๋ฉ๋ด๋ฅผ ์ฌ์ฉํ์ฌ ๋ฉ๋ด ํญ๋ชฉ์ ๋๋กญ๋ค์ด ํ์์ผ๋ก ํ์ํฉ๋๋ค. ์ด๋ฅผ ํตํด ์์ ํ๋ฉด์์๋ ๋ฉ๋ด๊ฐ ์๋ฆฌ์ง ์๊ณ , ์ฌ์ฉ์๊ฐ ์ฝ๊ฒ ํ์ํ ์ ์๋๋ก ํฉ๋๋ค.
2.2 ๋ก๊ทธ์ธ ์ํ์ ๋ฐ๋ฅธ ๋ฒํผ ํ์
ํค๋์์๋ ๋ก๊ทธ์ธ ์ํ๋ฅผ ํ์ธํ์ฌ ๋ก๊ทธ์ธํ ๊ฒฝ์ฐ ๋ก๊ทธ์์ ๋ฒํผ์ ํ์ํ๊ณ , ๋ก๊ทธ์์ ๋ฒํผ์ ํด๋ฆญํ๋ฉด ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์์๋ฉ๋๋ค. ๋ก๊ทธ์ธํ์ง ์์ ๊ฒฝ์ฐ, ๋ก๊ทธ์ธ์ ์ ๋ํ๊ธฐ ์ํ ๋ก์ง์ ์ถ๊ฐํ ์ ์์ต๋๋ค.
2.3 ์คํฌ๋กค ์ ์คํ์ผ ๋ณ๊ฒฝ
ํค๋๋ ํ์ด์ง ์คํฌ๋กค ์ ์คํ์ผ์ ๋ณ๊ฒฝํ์ฌ ํ์ด์ง๊ฐ ์๋๋ก ์คํฌ๋กค๋ ๋ ํค๋์ ๋ฐฐ๊ฒฝ์ ์ด๋ก๊ฒ ์ฒ๋ฆฌํ์ฌ ์ฝํ ์ธ ๊ฐ ๋ ๋์ ๋๊ฒ ํฉ๋๋ค. ์ด๋ฅผ ํตํด ์ฌ์ฉ์๋ ํ์ฌ ํ์ด์ง์ ๊ตฌ๋ถ์ ๋ช ํํ ํ ์ ์์ต๋๋ค.
3. ์ฝ๋ ์ค๋ช
3.1 ์ํ ๊ด๋ฆฌ
ํค๋์์ ๊ด๋ฆฌํ๋ ๋ ๊ฐ์ง ์ฃผ์ ์ํ๋ isScrolled
์ isMenuOpen
์
๋๋ค.
isScrolled
: ํ์ด์ง๊ฐ ์คํฌ๋กค๋์ด ํค๋์ ๋ฐฐ๊ฒฝ์์ ๋ณ๊ฒฝํ ์ง ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํฉ๋๋ค.isMenuOpen
: ํ๋ฒ๊ฑฐ ๋ฉ๋ด์ ์ํ๋ฅผ ๊ด๋ฆฌํ์ฌ ๋ฉ๋ด๊ฐ ์ด๋ฆฌ๊ฑฐ๋ ๋ซํ๋ ๋์์ ์ฒ๋ฆฌํฉ๋๋ค.
const [isScrolled, setIsScrolled] = useState(false);
const [isMenuOpen, setIsMenuOpen] = useState(false);
3.2 ์คํฌ๋กค ์ด๋ฒคํธ ์ฒ๋ฆฌ
์ฌ์ฉ์๊ฐ ํ์ด์ง๋ฅผ ์คํฌ๋กคํ ๋, ํค๋์ ๋ฐฐ๊ฒฝ์์ ๋ณ๊ฒฝํ ์ ์๋๋ก handleScroll
ํจ์๋ฅผ ์ฌ์ฉํฉ๋๋ค. scrollY
๊ฐ์ ํ์ธํ์ฌ ์คํฌ๋กค์ด 50px ์ด์์ผ ๋ ํค๋์ scrolled
ํด๋์ค๋ฅผ ์ถ๊ฐํฉ๋๋ค.
const handleScroll = () => setIsScrolled(window.scrollY > 50);
useEffect(() => {
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
}, []);
3.3 ํ๋ฒ๊ฑฐ ๋ฉ๋ด ๋ฐ ๋ค๋น๊ฒ์ด์ ์ฒ๋ฆฌ
๋ชจ๋ฐ์ผ ํ๋ฉด์์ ๋ฉ๋ด๋ฅผ ์ด๊ฑฐ๋ ๋ซ์ ์ ์๋ ํ๋ฒ๊ฑฐ ๋ฉ๋ด๋ฅผ ๊ตฌํํฉ๋๋ค. ๋ฉ๋ด๊ฐ ์ด๋ฆด ๋ isMenuOpen
์ํ๋ฅผ true
๋ก ์ค์ ํ์ฌ ๋ฉ๋ด๋ฅผ ๋ณด์ฌ์ฃผ๊ณ , ๋ซ์ ๋๋ false
๋ก ์ค์ ํ์ฌ ๋ฉ๋ด๋ฅผ ์จ๊น๋๋ค.
const handleMenuToggle = () => {
setIsMenuOpen((prev) => !prev);
};
3.4 ๋ก๊ทธ์ธ ๋ฐ ๋ก๊ทธ์์ ์ฒ๋ฆฌ
ํค๋์๋ ๋ก๊ทธ์ธ ์ํ์ ๋ฐ๋ฅธ ๋์ ๋ฒํผ์ด ์์ต๋๋ค. ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธํ ๊ฒฝ์ฐ isLoggedIn
์ํ๋ฅผ ํ์ธํ์ฌ ๋ก๊ทธ์์ ๋ฒํผ์ ๋ณด์ฌ์ฃผ๊ณ , ํด๋ฆญ ์ ๋ก๊ทธ์์์ ์ฒ๋ฆฌํฉ๋๋ค. ๋ก๊ทธ์ธํ์ง ์์ ๊ฒฝ์ฐ, ๋ก๊ทธ์ธ์ด ํ์ํจ์ ์ ๋ํ๋ ๋์์ ์ถ๊ฐํ ์ ์์ต๋๋ค.
const handleLoginLogout = () => {
if (isLoggedIn) {
localStorage.removeItem("isLoggedIn");
onLogout();
setIsMenuOpen(false);
} else {
localStorage.setItem("isLoggedIn", true);
}
};
3.5 ๋ฉ๋ด ํญ๋ชฉ ํด๋ฆญ ์ฒ๋ฆฌ
๋ฉ๋ด ํญ๋ชฉ์ ํด๋ฆญํ๋ฉด, ๋ก๊ทธ์ธ ์ํ๋ฅผ ํ์ธํ์ฌ ๋ก๊ทธ์ธํ์ง ์์ ์ฌ์ฉ์๋ ํ์๊ฐ์ ํ์ด์ง๋ก ์ด๋ํ๊ณ , ๋ก๊ทธ์ธํ ์ฌ์ฉ์๋ ํด๋น ํ์ด์ง๋ก ์ด๋ํ ์ ์๋๋ก ํฉ๋๋ค.
const handleNavItemClick = (path) => {
if (!isLoggedIn) {
navigate("/signUp");
return;
}
setIsMenuOpen(false);
navigate(path);
};
3.6 ์คํ์ผ๋ง
CSS๋ฅผ ํ์ฉํ์ฌ ํค๋์ ์คํ์ผ์ ์ ์ํฉ๋๋ค. scrolled
ํด๋์ค๋ ์คํฌ๋กค ์ ๋ฐฐ๊ฒฝ์์ ๋ณ๊ฒฝํ๊ณ , ํ๋ฒ๊ฑฐ ๋ฉ๋ด์ ๋ก๊ทธ์ธ ์ํ์ ๋ฐ๋ฅธ ๋ฒํผ์ ์ ์ฒ๋ฆฌํฉ๋๋ค.
/* ๊ธฐ๋ณธ ์คํ์ผ */
.header {
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: transparent;
color: white;
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
z-index: 1000;
transition: background-color 0.3s ease, padding 0.3s ease;
}
/* ์คํฌ๋กค ํ ํค๋ ์คํ์ผ */
.header.scrolled {
background-color: rgba(0, 0, 0, 0.9);
padding: 10px 20px;
}
/* ๋ก๊ณ ์คํ์ผ */
.header .logo {
font-size: 1.8rem;
font-weight: bold;
text-transform: uppercase;
letter-spacing: 2px;
}
.header .logo a {
color: white;
text-decoration: none;
transition: color 0.3s ease;
}
.header .logo a:hover {
color: #e50914;
}
/* ๋ค๋น๊ฒ์ด์
๋ฉ๋ด */
.header nav {
display: flex;
gap: 20px;
align-items: center;
}
.header nav a {
color: white;
text-decoration: none;
font-size: 1.1rem;
transition: color 0.3s ease;
}
.header nav a:hover {
color: #e50914;
}
.header nav button {
background-color: #e50914;
color: white;
border: none;
padding: 10px 20px;
font-size: 1.1rem;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s ease;
}
.header nav button:hover {
background-color: #f40612;
}
/* ๋ฐ์ํ ๋์์ธ: ํ๋ฒ๊ฑฐ ๋ฉ๋ด */
@media (max-width: 768px) {
.header nav {
display: none; /* ๊ธฐ๋ณธ์ ์ผ๋ก ์จ๊ธฐ๊ธฐ */
flex-direction: column;
position: absolute;
top: 70px; /* ํค๋ ๋ฐ๋ก ์๋๋ก ์์น */
right: 0;
width: 100%; /* ์ ์ฒด ๋๋น๋ฅผ ์ฐจ์งํ๊ฒ */
background-color: rgba(0, 0, 0, 0.9);
padding: 20px;
box-sizing: border-box;
}
.header nav.open {
display: flex; /* ์ด๋ ธ์ ๋ ํ์ */
}
/* ํ๋ฒ๊ฑฐ ๋ฉ๋ด ์์ด์ฝ */
.header .hamburger {
display: block; /* ์์ ํ๋ฉด์์๋ง ๋ณด์ด๋๋ก ์ค์ */
cursor: pointer;
z-index: 1100;
}
.header .hamburger div {
width: 30px;
height: 3px;
background-color: white;
margin: 5px 0;
transition: 0.3s;
}
/* ํ๋ฒ๊ฑฐ ๋ฉ๋ด๊ฐ ์ด๋ฆด ๋ ์์ด์ฝ ์ ๋๋ฉ์ด์
*/
.header .hamburger.open div:nth-child(1) {
transform: rotate(45deg);
position: relative;
top: 8px;
}
.header .hamburger.open div:nth-child(2) {
opacity: 0;
}
.header .hamburger.open div:nth-child(3) {
transform: rotate(-45deg);
position: relative;
top: -8px;
}
}
/* ํฐ ํ๋ฉด์์ ๋ค๋น๊ฒ์ด์
๋ฉ๋ด ๋ ์ด์์ */
@media (min-width: 769px) {
.header .hamburger {
display: none; /* ํฐ ํ๋ฉด์์๋ ํ๋ฒ๊ฑฐ ๋ฉ๋ด ์จ๊ธฐ๊ธฐ */
}
}
๐ ๊ฒฐ๊ณผ ํ๋ฉด
- ๋ก๊ทธ์ธ ์ํ์์๋ง ๋ณด์ด๋ ๋ก๊ทธ์์ ๋ฒํผ


- ํ๋ฒ๊ฑฐ ๋ฉ๋ด


๐ก ์ ๋ฆฌ
์ด๋ฒ ํฌ์คํ ์์๋ ๋ฐ์ํ ํค๋๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ๋ค๋ค์ต๋๋ค. ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธํ ์ํ์ ๋ฐ๋ผ ๋ก๊ทธ์ธ/๋ก๊ทธ์์ ๋ฒํผ์ ๋์ ์ผ๋ก ํ์ํ๊ณ , ํ๋ฒ๊ฑฐ ๋ฉ๋ด๋ฅผ ํตํด ๋ชจ๋ฐ์ผ ํ๋ฉด์์๋ ์ฝ๊ฒ ๋ฉ๋ด๋ฅผ ํ์ํ ์ ์๊ฒ ํ์ต๋๋ค. ๋ํ, ํ์ด์ง ์คํฌ๋กค์ ๋ฐ๋ผ ํค๋์ ์คํ์ผ์ ๋ณ๊ฒฝํ์ฌ ์ฌ์ฉ์์๊ฒ ๋ ๋์ ๊ฒฝํ์ ์ ๊ณตํฉ๋๋ค.