๋ก๊ทธ์ธ ๋ฐ ํ์๊ฐ์ ํ์ ๊ตฌํ
์ด ํฌ์คํ ์์๋ ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธํ ์ ์๋๋ก ๋ก๊ทธ์ธ ํ์ ์ ๊ตฌํํ์ต๋๋ค. ํ์ ์์์ ๋ก๊ทธ์ธ๊ณผ ํ์๊ฐ์ ๊ธฐ๋ฅ์ ๋ชจ๋ ์ง์ํ๋ฉฐ, ๋ก๊ทธ์ธ ์ ์ง ๊ธฐ๋ฅ๋ ์ถ๊ฐํ์ฌ ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ ์ํ๋ฅผ ์ ์งํ ์ ์์ต๋๋ค. ๋ํ, ๋ก์ปฌ ์คํ ๋ฆฌ์ง๋ฅผ ํ์ฉํ์ฌ ์ฌ์ฉ์์ ์ธ์ฆ ์ ๋ณด๋ฅผ ์ ์ฅํ๊ณ ๊ด๋ฆฌํฉ๋๋ค.
1. ์ฃผ์ ๊ธฐ๋ฅ
1.1 ๋ก๊ทธ์ธ
๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ ์ฌ์ฉ์๊ฐ ์
๋ ฅํ ์ด๋ฉ์ผ๊ณผ ๋น๋ฐ๋ฒํธ๋ฅผ ๋ก์ปฌ ์คํ ๋ฆฌ์ง์ ์ ์ฅ๋ ์ฌ์ฉ์ ๋ชฉ๋ก๊ณผ ๋น๊ตํ์ฌ ์ธ์ฆํฉ๋๋ค. ์ธ์ฆ์ ์ฑ๊ณตํ๋ฉด isLoggedIn
๊ฐ์ ๋ก์ปฌ ์คํ ๋ฆฌ์ง์ ์ ์ฅํ์ฌ ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ๋ ์ํ๋ก ์ฑ์ ์ด์ฉํ ์ ์๊ฒ ํฉ๋๋ค.
1.2 ํ์๊ฐ์
ํ์๊ฐ์ ์ ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ์ด๋ฉ์ผ๊ณผ ๋น๋ฐ๋ฒํธ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์๋ก์ด ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๋ก์ปฌ ์คํ ๋ฆฌ์ง์ ์ ์ฅํฉ๋๋ค. ๋ํ, ๋น๋ฐ๋ฒํธ ํ์ธ ํ๋๋ฅผ ์ ๊ณตํ์ฌ ์ฌ์ฉ์๊ฐ ๋น๋ฐ๋ฒํธ๋ฅผ ์ ํํ ์ ๋ ฅํ๋์ง ํ์ธํ ์ ์์ต๋๋ค.
1.3 ๋ก๊ทธ์ธ ์ ์ง ๊ธฐ๋ฅ
๋ก๊ทธ์ธ ์ ์ง ์ฒดํฌ๋ฐ์ค๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ ์ํ๋ฅผ ์ ์งํ ์ ์๋๋ก ํ์ต๋๋ค. ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ ์ keepLogin
๊ฐ์ ๋ก์ปฌ ์คํ ๋ฆฌ์ง์ ์ ์ฅํ๋ฉด, ์ดํ์ ์ฌ์ฉ์๊ฐ ์๋ก ๊ณ ์นจ์ ํ๊ฑฐ๋ ํ์ด์ง๋ฅผ ๋ฒ์ด๋ฌ๋ค๊ฐ ๋์์๋ ๋ก๊ทธ์ธ ์ํ๋ฅผ ์ ์งํ ์ ์์ต๋๋ค.
2. ์ฌ์ฉ์ ์ธ์ฆ ๊ด๋ฆฌ
์ฌ์ฉ์ ์ธ์ฆ์ ์น ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ค์ํ ๊ธฐ๋ฅ ์ค ํ๋์ ๋๋ค. ์ด๋ฒ ํ๋ก์ ํธ์์๋ ์ฌ์ฉ์์ ๋ก๊ทธ์ธ ์ํ๋ฅผ sessionStorage๋ฅผ ์ฌ์ฉํ์ฌ ๊ด๋ฆฌํ๊ณ , ๋ก๊ทธ์ธ ์ฌ๋ถ์ ๋ฐ๋ผ ํ๋ฉด์ ๋ค๋ฅด๊ฒ ํ์ํ๋ ๋ฐฉ์์ผ๋ก ๊ตฌํํ์ต๋๋ค.
2.1 ๋ก๊ทธ์ธ ์ํ ๊ด๋ฆฌ
์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธํ๋ฉด sessionStorage์ ๋ก๊ทธ์ธ ์ ๋ณด๋ฅผ ์ ์ฅํ๊ณ , ๋ก๊ทธ์์ ์ ํด๋น ์ ๋ณด๋ฅผ ์ ๊ฑฐํฉ๋๋ค. ์ด๋ฅผ ํตํด ์ฌ์ฉ์๊ฐ ์ฌ์ดํธ๋ฅผ ๋ ๋๋ ๋ก๊ทธ์ธ ์ํ๋ฅผ ์ ์งํ ์ ์์ต๋๋ค.
// App.js
useEffect(() => {
const loggedIn = sessionStorage.getItem("isLoggedIn") === "true";
setIsLoggedIn(loggedIn);
setIsPopupVisible(!loggedIn); // ๋ก๊ทธ์์ ์ํ๋ฉด ํ์
ํ์
}, []);
2.2 ๋ก๊ทธ์ธ ๋ฐ ๋ก๊ทธ์์ ์ฒ๋ฆฌ
๋ก๊ทธ์ธ ์ sessionStorage์ ๋ก๊ทธ์ธ ์ ๋ณด๋ฅผ ์ ์ฅํ๊ณ , ๋ก๊ทธ์์ ์ ํด๋น ์ ๋ณด๋ฅผ ์ ๊ฑฐํฉ๋๋ค. ๋ก๊ทธ์์ ํ ํ์ ์ ๋ค์ ํ์ํ์ฌ ์ฌ์ฉ์๊ฐ ๋ค์ ๋ก๊ทธ์ธํ ์ ์๋๋ก ํฉ๋๋ค.
// App.js
const handleLogin = () => {
sessionStorage.setItem("isLoggedIn", true);
setIsLoggedIn(true);
setIsPopupVisible(false); // ํ์
๋ซ๊ธฐ
};
const handleLogout = () => {
sessionStorage.removeItem("isLoggedIn");
setIsLoggedIn(false);
setIsPopupVisible(true); // ๋ก๊ทธ์์ ํ ํ์
๋ค์ ํ์
};
2.3 ์ฌ์ฉ์ ์ ๋ณด ์ด๊ธฐํ
๋ก์ปฌ ์คํ ๋ฆฌ์ง์ ์ฌ์ฉ์ ์ ๋ณด๊ฐ ์์ ๊ฒฝ์ฐ ๋น ๋ฐฐ์ด์ ์ ์ฅํ๋ ์ฝ๋๋ ์ถ๊ฐํ์ต๋๋ค. initializeUserStorage
ํจ์๋ ์ ํ๋ฆฌ์ผ์ด์
์์ ์ ์คํ๋๋ฉฐ, "users"๋ผ๋ ํค๋ก ๋น ๋ฐฐ์ด์ ์ ์ฅํ์ฌ ์ฌ์ฉ์๊ฐ ์์ ๊ฒฝ์ฐ ๊ธฐ๋ณธ๊ฐ์ ์ค์ ํฉ๋๋ค.
// utils/storage.js
export const initializeUserStorage = () => {
if (!getFromLocalStorage("users")) {
saveToLocalStorage("users", []);
}
};
์ด ํจ์๋ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์์๋ ๋ ํธ์ถ๋๋ฉฐ, ๋ก์ปฌ ์คํ ๋ฆฌ์ง์ ์ฌ์ฉ์ ์ ๋ณด๊ฐ ์์ ๊ฒฝ์ฐ ๋น ๋ฐฐ์ด์ ์ ์ฅํฉ๋๋ค. ์ด๋ ์ฌ์ฉ์๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฒ์ ์ฌ์ฉํ ๋ ๋น ์ฌ์ฉ์ ๋ชฉ๋ก์ ์ค์ ํ๊ณ , ์ดํ์ ์๋ก์ด ์ฌ์ฉ์ ์ ๋ณด๊ฐ ์ ์ฅ๋ ์ ์๋๋ก ํฉ๋๋ค.
3. ์ฝ๋ ์ค๋ช
3.1 ์ํ ๊ด๋ฆฌ
๋ก๊ทธ์ธ ํ์
์ปดํฌ๋ํธ๋ isSignUp
, form
, error
, keepLogin
์ํ๋ฅผ ๊ด๋ฆฌํฉ๋๋ค.
isSignUp
:true
์ผ ๊ฒฝ์ฐ ํ์๊ฐ์ ํผ์ ํ์ํ๊ณ ,false
์ผ ๊ฒฝ์ฐ ๋ก๊ทธ์ธ ํผ์ ํ์ํฉ๋๋ค.form
: ์ฌ์ฉ์๊ฐ ์ ๋ ฅํemail
,password
,confirmPassword
๊ฐ์ ์ ์ฅํฉ๋๋ค.error
: ์๋ฌ ๋ฉ์์ง๋ฅผ ์ ์ฅํ์ฌ ์ ํจ์ฑ ๊ฒ์ฌ ์คํจ ์ ์ฌ์ฉ์์๊ฒ ์ค๋ฅ๋ฅผ ์๋ ค์ค๋๋ค.keepLogin
: ๋ก๊ทธ์ธ ์ ์ง ์ฒดํฌ๋ฐ์ค ์ํ๋ฅผ ๊ด๋ฆฌํฉ๋๋ค.
const [isSignUp, setIsSignUp] = useState(false); // true๋ฉด ํ์๊ฐ์
๋ชจ๋
const [form, setForm] = useState({
email: "",
password: "",
confirmPassword: "",
});
const [error, setError] = useState("");
const [keepLogin, setKeepLogin] = useState(false);
3.2 ๋ก์ปฌ ์คํ ๋ฆฌ์ง ์ด๊ธฐํ
initializeUserStorage
ํจ์๋ ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง๋ ๋ ๋ก์ปฌ ์คํ ๋ฆฌ์ง๋ฅผ ์ด๊ธฐํํ๋ ์ญํ ์ ํฉ๋๋ค. users
๋ผ๋ ํค๋ก ์ ์ฅ๋ ์ฌ์ฉ์ ๋ชฉ๋ก์ด ์์ผ๋ฉด ๋น ๋ฐฐ์ด์ ์ ์ฅํ์ฌ, ์ดํ ๋ก๊ทธ์ธ ๋ฐ ํ์๊ฐ์
์์ ์ฌ์ฉ์๊ฐ ์ ์์ ์ผ๋ก ๋ฑ๋ก๋๋๋ก ํฉ๋๋ค.
useEffect(() => {
initializeUserStorage();
}, []);
3.3 ๋ก๊ทธ์ธ ์ฒ๋ฆฌ
์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ ๋ฒํผ์ ํด๋ฆญํ๋ฉด, ์
๋ ฅํ ์ด๋ฉ์ผ๊ณผ ๋น๋ฐ๋ฒํธ๋ฅผ ๋ก์ปฌ ์คํ ๋ฆฌ์ง์์ ๊ฐ์ ธ์จ ์ฌ์ฉ์ ๋ชฉ๋ก๊ณผ ๋น๊ตํ์ฌ ์ธ์ฆํฉ๋๋ค. ๋ก๊ทธ์ธ ์ฑ๊ณต ์, isLoggedIn
๊ฐ์ ๋ก์ปฌ ์คํ ๋ฆฌ์ง์ ์ ์ฅํ๊ณ , keepLogin
์ฒดํฌ๋ฐ์ค ์ํ์ ๋ฐ๋ผ ๋ก๊ทธ์ธ ์ํ๋ฅผ ์ ์งํฉ๋๋ค.
const handleLogin = () => {
const { email, password } = form;
if (!email || !password) {
setError("์์ด๋์ ๋น๋ฐ๋ฒํธ๋ฅผ ์
๋ ฅํด์ฃผ์ธ์.");
return;
}
const users = getFromLocalStorage("users");
const user = users.find(
(user) => user.email === email && user.password === password
);
if (!user) {
setError("์์ด๋ ๋๋ ๋น๋ฐ๋ฒํธ๊ฐ ์๋ชป๋์์ต๋๋ค.");
return;
}
saveToLocalStorage("isLoggedIn", true);
if (keepLogin) {
saveToLocalStorage("keepLogin", true);
}
alert("๋ก๊ทธ์ธ ์ฑ๊ณต!");
onLogin();
onClose();
};
3.4 ํ์๊ฐ์ ์ฒ๋ฆฌ
ํ์๊ฐ์ ๊ธฐ๋ฅ์์๋ ์ด๋ฉ์ผ๊ณผ ๋น๋ฐ๋ฒํธ ํ์ธ์ ํตํด ์๋ก์ด ์ฌ์ฉ์๋ฅผ ๋ก์ปฌ ์คํ ๋ฆฌ์ง์ ์ ์ฅํฉ๋๋ค. ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ์ด๋ฉ์ผ์ด ์ด๋ฏธ ๋ฑ๋ก๋์ด ์๋์ง ํ์ธํ๊ณ , ๋น๋ฐ๋ฒํธ๊ฐ ์ผ์นํ๋์ง ํ์ธํ๋ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ์ํํฉ๋๋ค.
const handleSignUp = () => {
const { email, password, confirmPassword } = form;
if (!email || !password || !confirmPassword) {
setError("๋ชจ๋ ํ๋๋ฅผ ์
๋ ฅํด์ฃผ์ธ์.");
return;
}
if (password !== confirmPassword) {
setError("๋น๋ฐ๋ฒํธ๊ฐ ์ผ์นํ์ง ์์ต๋๋ค.");
return;
}
// ์ ์ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ
const users = getFromLocalStorage("users");
const isEmailUsed = users.some((user) => user.email === email);
if (isEmailUsed) {
setError("์ด๋ฏธ ์ฌ์ฉ ์ค์ธ ์ด๋ฉ์ผ์
๋๋ค.");
return;
}
// ์๋ก์ด ์ ์ ์ถ๊ฐ
const newUser = { email, password };
saveToLocalStorage("users", [...users, newUser]);
alert("ํ์๊ฐ์
์ฑ๊ณต! ๋ก๊ทธ์ธ ํด์ฃผ์ธ์.");
setIsSignUp(false);
setForm({ email: "", password: "", confirmPassword: "" });
};
3.5 ํ๋ฉด ์ ํ
์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ ํ์
์์ ๋ก๊ทธ์ธ ๋๋ ํ์๊ฐ์
์ ์ ํํ ์ ์๋๋ก ๋ฒํผ์ ์ ๊ณตํฉ๋๋ค. isSignUp
์ํ์ ๋ฐ๋ผ ๋ก๊ทธ์ธ๊ณผ ํ์๊ฐ์
ํ๋ฉด์ ์ ํํ ์ ์์ต๋๋ค.
<button type="button" onClick={() => setIsSignUp(!isSignUp)}>
{isSignUp ? "์ด๋ฏธ ๊ณ์ ์ด ์๋์? ๋ก๊ทธ์ธ" : "๊ณ์ ์ด ์๋์? ํ์๊ฐ์
"}
</button>
3.6 ์ ์ฒด ์ฝ๋
SignInPopup.js
//components/SignInPopup.js
import React, { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import {
saveToLocalStorage,
getFromLocalStorage,
initializeUserStorage,
} from "../utils/storage";
import "../styles/components/SignInPopup.css";
const SignInPopup = ({ onClose, onLogin }) => {
const [isSignUp, setIsSignUp] = useState(false); // true๋ฉด ํ์๊ฐ์
๋ชจ๋
const [form, setForm] = useState({
email: "",
password: "",
confirmPassword: "",
});
const [error, setError] = useState("");
const [keepLogin, setKeepLogin] = useState(false);
const navigate = useNavigate();
useEffect(() => {
initializeUserStorage();
}, []);
const handleInputChange = (e) => {
setForm({ ...form, [e.target.name]: e.target.value });
};
const handleLogin = () => {
const { email, password } = form;
if (!email || !password) {
setError("์์ด๋์ ๋น๋ฐ๋ฒํธ๋ฅผ ์
๋ ฅํด์ฃผ์ธ์.");
return;
}
const users = getFromLocalStorage("users");
const user = users.find(
(user) => user.email === email && user.password === password
);
if (!user) {
setError("์์ด๋ ๋๋ ๋น๋ฐ๋ฒํธ๊ฐ ์๋ชป๋์์ต๋๋ค.");
return;
}
saveToLocalStorage("isLoggedIn", true);
if (keepLogin) {
saveToLocalStorage("keepLogin", true);
}
alert("๋ก๊ทธ์ธ ์ฑ๊ณต!");
onLogin();
onClose();
};
const handleSignUp = () => {
const { email, password, confirmPassword } = form;
if (!email || !password || !confirmPassword) {
setError("๋ชจ๋ ํ๋๋ฅผ ์
๋ ฅํด์ฃผ์ธ์.");
return;
}
if (password !== confirmPassword) {
setError("๋น๋ฐ๋ฒํธ๊ฐ ์ผ์นํ์ง ์์ต๋๋ค.");
return;
}
// ์ ์ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ
const users = getFromLocalStorage("users");
const isEmailUsed = users.some((user) => user.email === email);
if (isEmailUsed) {
setError("์ด๋ฏธ ์ฌ์ฉ ์ค์ธ ์ด๋ฉ์ผ์
๋๋ค.");
return;
}
// ์๋ก์ด ์ ์ ์ถ๊ฐ
const newUser = { email, password };
saveToLocalStorage("users", [...users, newUser]);
alert("ํ์๊ฐ์
์ฑ๊ณต! ๋ก๊ทธ์ธ ํด์ฃผ์ธ์.");
setIsSignUp(false);
setForm({ email: "", password: "", confirmPassword: "" });
};
const handleSignUpRedirect = () => {
navigate("/signUp");
onClose();
};
return (
<div className="popup-overlay">
<div className="popup-content">
<h1>{isSignUp ? "ํ์๊ฐ์
" : "๋ก๊ทธ์ธ"}</h1>
<form>
<input
type="email"
name="email"
placeholder="์ด๋ฉ์ผ"
value={form.email}
onChange={handleInputChange}
/>
<input
type="password"
name="password"
placeholder="๋น๋ฐ๋ฒํธ"
value={form.password}
onChange={handleInputChange}
/>
{isSignUp && (
<input
type="password"
name="confirmPassword"
placeholder="๋น๋ฐ๋ฒํธ ํ์ธ"
value={form.confirmPassword}
onChange={handleInputChange}
/>
)}
{error && <p className="error">{error}</p>}
{isSignUp ? (
<button type="button" onClick={handleSignUp}>
ํ์๊ฐ์
</button>
) : (
<>
<label>
<input
type="checkbox"
checked={keepLogin}
onChange={() => setKeepLogin(!keepLogin)}
/>
๋ก๊ทธ์ธ ์ ์ง
</label>
<button type="button" onClick={handleLogin}>
๋ก๊ทธ์ธ
</button>
</>
)}
</form>
<button type="button" onClick={() => setIsSignUp(!isSignUp)}>
{isSignUp ? "์ด๋ฏธ ๊ณ์ ์ด ์๋์? ๋ก๊ทธ์ธ" : "๊ณ์ ์ด ์๋์? ํ์๊ฐ์
"}
</button>
<button className="signUp-btn" onClick={handleSignUpRedirect}>
ํ์๊ฐ์
ํ์ด์ง๋ก ์ด๋
</button>
</div>
</div>
);
};
export default SignInPopup;
๐ ๊ฒฐ๊ณผ ํ๋ฉด
- ๋ก๊ทธ์ธ ํ์

- ํ์๊ฐ์ ํ์

- ์ฌ์ฉ์ ์ธ์ฆ


๐ก ์ ๋ฆฌ
์ด๋ฒ ํฌ์คํ ์์๋ ๋ก๊ทธ์ธ ํ์ ์ React๋ก ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ๋ค๋ค์ต๋๋ค. ๋ก๊ทธ์ธ ๋ฐ ํ์๊ฐ์ ๊ธฐ๋ฅ์ ํ๋์ ํ์ ์์ ์ฒ๋ฆฌํ๊ณ , ๋ก์ปฌ ์คํ ๋ฆฌ์ง๋ฅผ ํ์ฉํ์ฌ ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด๋ฅผ ๊ด๋ฆฌํ์ต๋๋ค. ์ด๋ฅผ ํตํด ์ฌ์ฉ์๋ ๋ก๊ทธ์ธ ์ํ๋ฅผ ์ ์งํ๊ณ , ๊ฐํธํ๊ฒ ํ์๊ฐ์ ์ ์งํํ ์ ์์ต๋๋ค.