[TIL/React] 2023/08/15 ๐ฐ๐ท
LogIn ์ํ, ์ ์ญ์์ ๊ด๋ฆฌํ๊ธฐ(feat. Redux Toolkit) ๐ > src/pages/LogInPage.js ๐ต > src/modules/authSlice.js ๐ต > ํด๊ฒฐ ๊ณผ์ ๐ข ๊ฐ์ ์ด๋ค action์ ํํจ์ ์์ด, ํนํ ๊ฐ๋ฐ์๋ ๋ฐ์์ ๋๋ต์ ํด์๋ ์ ๋๋ค. ์ ๋ํ ๊ทผ๊ฑฐ๋ถํฐ ์์ ํ๊ณ ์ ํ๋ค. ์ ์ญ ์ํ ๊ด๋ฆฌ๋, ์...
LogIn ์ํ, ์ ์ญ์์ ๊ด๋ฆฌํ๊ธฐ(feat. Redux Toolkit) ๐
src/pages/LogInPage.js ๐ต
import React, { useState, useEffect } from "react";
import styled from "@emotion/styled";
import { loginUser } from "../modules/authSlice";
import { useNavigate } from "react-router-dom";
import ComponentWrapper from "../components/common/ComponentWrapper";
import { useDispatch } from "react-redux";
import { useSelector } from "react-redux";
const LogInTitle = styled.p`
text-align: center;
margin: 0px;
font-weight: bolder;
font-size: 40px;
`;
const LogInFormWrapper = styled.div`
/* display: flex;
flex-direction: column;
justify-content: center; */
/* min-width: 375px;
width: 100%;
height: 500px; */
/* margin: 0 auto; */
`;
const FormLabel = styled.p`
font-size: 16px;
margin-bottom: 8px;
`;
const FormInput = styled.input`
padding: 20px;
margin-bottom: 16px;
border: 1px solid #ccc;
border-radius: 8px;
font-size: 16px;
width: 100%;
max-width: 600px;
`;
const SubmitButton = styled.button`
background-color: black;
color: #fff;
padding: 20px;
border: none;
border-radius: 8px;
font-size: 18px;
font-weight: bolder;
cursor: pointer;
width: 100%;
&:hover {
background-color: #fff;
color: black;
border: 2px solid black;
}
`;
const LogInPage = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const navigate = useNavigate();
const dispatch = useDispatch();
const isAuthenticated = useSelector((state) => state.auth.isAuthenticated);
const goToSignUp = () => {
navigate("/signup");
};
const handleSignIn = (e) => {
e.preventDefault();
dispatch(loginUser({ email, password }));
};
useEffect(() => {
if (isAuthenticated) {
navigate("/");
}
}, [isAuthenticated]);
return (
<ComponentWrapper
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
{/* ๋ชจ๋ฐ์ผ 900px ์ดํ */}
<form onSubmit={handleSignIn}>
<LogInTitle>๋ก๊ทธ์ธ</LogInTitle>
<LogInFormWrapper>
<h2>์ด๋ฉ์ผ ๋ก๊ทธ์ธ</h2>
<FormLabel>Email</FormLabel>
<FormInput
type="email"
placeholder="์์ด๋(์ด๋ฉ์ผ ์ฃผ์)๋ฅผ ์
๋ ฅํ์ธ์"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<FormLabel>Password</FormLabel>
<FormInput
type="password"
placeholder="๋น๋ฐ๋ฒํธ๋ฅผ ์
๋ ฅํ์ธ์"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<SubmitButton>๋ก๊ทธ์ธ</SubmitButton>
<div style={{ display: "flex", columnGap: "8px" }}>
<p style={{ fontWeight: "bolder" }}> ์ ์ก๊ฐ์ด ์ฒ์์ด์ ๊ฐ์?</p>
<p
style={{
color: "red",
fontWeight: "bolder",
cursor: "pointer",
}}
onClick={goToSignUp}
>
ํ์๊ฐ์
ํ๊ธฐ
</p>
</div>
</LogInFormWrapper>
</form>
</ComponentWrapper>
);
};
export default LogInPage;
src/modules/authSlice.js ๐ต
// authSlice.js
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import { auth } from "../firebase";
import { signInWithEmailAndPassword } from "firebase/auth";
// Firebase ์ธ์ฆ์ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์ ๋ก๊ทธ์ธ ์ฒ๋ฆฌ
export const loginUser = createAsyncThunk(
"auth/loginUser",
async (credentials) => {
const { email, password } = credentials;
console.log(credentials);
try {
const userCredential = await signInWithEmailAndPassword(
auth,
email,
password
);
console.log(userCredential);
return userCredential.user.email;
} catch (error) {
console.log(error);
throw error;
}
}
);
const authSlice = createSlice({
name: "auth",
initialState: {
user: null,
isAuthenticated: false,
},
extraReducers: (builder) => {
builder.addCase(loginUser.fulfilled, (state, action) => {
console.log(action.payload);
state.user = action.payload;
console.log(state.user);
state.isAuthenticated = true;
});
},
});
export default authSlice.reducer;
ํด๊ฒฐ ๊ณผ์ ๐ข
1. ๊ฐ์
์ด๋ค action์ ํํจ์ ์์ด, ํนํ ๊ฐ๋ฐ์๋ ``๊ทธ๋ฅ...` ๋ฐ์์ ๋๋ต์ ํด์๋ ์ ๋๋ค. `์ ์ญ ์ํ ๊ด๋ฆฌ``์ ๋ํ ๊ทผ๊ฑฐ๋ถํฐ ์์ ํ๊ณ ์ ํ๋ค.
์ ์ญ ์ํ ๊ด๋ฆฌ๋, ์ํํธ์จ์ด ์ ํ๋ฆฌ์ผ์ด์
๋ด์์ ์ฌ๋ฌ ์ปดํฌ๋ํธ๋ ๋ชจ๋ ๊ฐ์ ๊ณต์ ๋๋ ๋ฐ์ดํฐ์ ์ํ๋ฅผ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ๋ก ์ค ํ๋์ด๋ค. ๋ณต์กํ ๋ฐ์ดํฐ๋ฅผ ํ๋์ ํ์ผ์์ ๊ด๋ฆฌํจ์ผ๋ก์จ ์ฝ๋์ ์์ธก ๊ฐ๋ฅ์ฑ๊ณผ ๋๋ฒ๊น
์ ํจ์จ์ฑ, ์ฆ ``์์ฐ์ฑ์ ์ ๊ณ ``ํ๋ ๋ฐ์ ๊ทธ ๋ณธ์ง์ด ์๋ค.
2. ์ฝ๋ ์์ ๋ฐ ์๋ฌ

์ ์ฝ๋๋ ๋ก๊ทธ์ธ์ form ํ๊ทธ์ ์ฐ๋๋์ด ์๋ ํจ์์ด๋ค. ํต์ฌ์ dispatch์ด๋ค. form ํ๊ทธ ๋ด๋ถ์์ ์ ๊ณตํ๋ email๊ณผ password๋ฅผ reducer๋ก ์ ๋ฌํ๋ ์ ๋์, ์ต์ํ์ ์ญํ ๋ง์ ์ํํ๊ณ ์๋ค. ์ ์ญ ์ํ์ ๋ณธ์ง์ ๋ง๊ฒ ๋ฐ์ดํฐ์ ์ํ์ ๋ํ ๊ฐ๊ณต์ ํด๋น ํจ์์์ ์ด๋ฃจ์ด์ง์ง ์์ ๊ฒ์ด๋ค.

์ฌ์ฉ์ ๋ก๊ทธ์ธ์ ์ฒ๋ฆฌํ๋ ๋น๋๊ธฐ ํจ์๋ค. dispatch๋ฅผ ํตํด ์ ๋ฌํ email๊ณผ password๋ ์ ํจ์๊ฐ ๋ฐ์ ๊ฒ์ด๋ค.

์ฒ์์๋ ๊ตฌ๊ธ๋ง์ ํตํด ``auth.signInWith~~`` ๋ฐฉ์์ผ๋ก ์ฝ๋๋ฅผ ์์ฑํ๋๋ฐ, ์ ์๋ฌ๊ฐ console์ ์ฐํ๋ค. firebase V9์์ ํจ์ ์ฌ์ฉ ๋ฐฉ์์ด ๋ฌ๋ผ์ก๊ธฐ์ ๋ฐ์ํ ์๋ฌ์๋ค. ์ ์ฝ๋์ฒ๋ผ auth๋ฅผ sign ํจ์ ๋ด๋ถ์ ๋ฃ์ด์ฃผ๋ ๋ฐฉ์์ผ๋ก ํด๊ฒฐํ๋ค.
reference: https://velog.io/@seondal/Firebase-v9๋ถํฐ-๋ฌ๋ผ์ง-์ธ์ฆ๋ชจ๋-์ฌ์ฉ๋ฒ#2-auth-๊ด๋ จ-ํจ์๋ค-์ฌ์ฉ

๋ค์ ์๋ฌ๋ try ๋ฌธ ๋ด๋ถ์ return ๋ถ๋ถ์์ ๋ฐ์ํ๋ค. ์ง๋ ฌํ์ ๊ดํ ๋ด์ฉ์ ๋ค๋ฃจ๊ณ ์๋ค. ์ง๋ ฌํ ์์ฒด์ ๋ํด ๋ค๋ฃจ๋ฉด ์ฝ๋ฉ์ ์ฌ๊ธฐ์ ๋ฉ์ถ ๊ฒ ๊ฐ๋ค๊ณ ํ๋จํ๋ค. ๊ฐ๋จํ ์ ๋ฆฌํ๋ฉด, redux์ action์๋ ๋น์ง๋ ฌํ๋ ๊ฐ์ด ํฌํจ๋์ด ์์ผ๋ฉด ํด๋น ์๋ฌ๊ฐ ๋ฐ์ํ๋ค. firebase์ ์ฌ์ฉ์ ๊ฐ์ฒด๋ ๋ณต์กํ ๋ด๋ถ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๊ณ ์๊ธฐ์ ์ง๋ ฌํํ๊ธฐ ์ด๋ ต๋ค๊ณ ํ๋ค. ๋ฐ๋ผ์ ํ์ฌ๋ก์๋ ์ฌ์ฉ์ ๊ฐ์ฒด๋ฅผ ํต์ผ๋ก returnํ๋ ๊ฒ์ด ์๋๋ผ ํ์ํ ์ ๋ณด๋ง ์ถ์ถํ๋ ๋ฐฉ์์ ํํ๊ณ , ์๋ฌ๋ ์ฌ๋ผ์ก๋ค.
๊ฒฐ๋ก ์ ์ผ๋ก fulfilled ๋์์ ๋ ์ด๊ธฐ๊ฐ user๋ ์ฌ์ฉ์์ email๋ก ์ ๋ฐ์ดํธ ๋๋ค.
๋ค์์ ์ค๋ ๋ง์ฃผํ ๋ง์ง๋ง ์๋ฌ๋ค.

ํ์ด์ง ์ด๋์ ๋ํ ๋ก์ง์ useEffect ํจ์ ์ธ๋ถ์์ ์์ฑํ ํ์ ๋ฐ์ํ ์๋ฌ์๋ค.

isAuthentication์ ํตํด useEffect ๋ด๋ถ์์ ํ์ด์ง ์ด๋์ ์ฒ๋ฆฌํ๋ค. ์ฆ, ๋ก๊ทธ์ธ์ ์ฑ๊ณตํ๋ฉด home์ผ๋ก ์ด๋ํ๋ค. ๊ทธ๋ฐ๋ฐ ์ด๋์ด ์ ๋๋ค.

์์กด์ฑ ๋ฐฐ์ด์ ํน์ value๋ฅผ ์ ๋ ฅํด์ผ ํ๋ค. value๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค ํธ์ถ๋๋ฉฐ, ์ด๋ value๋ ๋ ๋๋ง๊ณผ ๊ด๋ จ๋ ๊ฐ์ด์ด์ผ ํ๋ค.

ํ... ๋ํ๋ฏผ๊ตญ ๋ง์ธ
More to read
Amazon VPC Architecture ์ดํดํ๊ธฐ
์๋ก์ด ํ๋ก์ ํธ๋ฅผ ๊ธฐํํ๋ฉฐ, ๊ฐ๋ฐ์์ ๋ฌด์์ ๊ฐ์ฅ ๋จผ์ ๊ณ ๋ฏผํด์ผ ํ๋์ง ๋ค์ ๋์๋ณด๊ฒ ๋์์ต๋๋ค.ํ๋๋ ํ๋ก ํธ์๋๊ฐ ๋ชจ๋ ์ค๊ณ์ ์ถ๋ฐ์ ์ด๋ผ๊ณ ๋ฏฟ์์ต๋๋ค. ์ ์ ๊ฐ ๋ฌด์์ ๋ณด๊ณ , ์ด๋ค ํ๋ฆ์์ ๋จธ๋ฌด๋ฅด๊ณ ์ดํํ๋์ง์ ๋ํ ์ดํด ์์ด ์๋น์ค๋ฅผ ๋ง๋ ๋ค๋ ๊ฑด ๋ถ๊ฐ๋ฅํ๋ค๊ณ ์๊ฐํ๊ธฐ
'์์ฌ์ดํธ'ํ๋ก ํธ์๋ ๊ด์ ์ผ๋ก ์๊ณ ๋ฆฌ์ฆ ์ดํดํ๊ธฐ
์ค๋๋ง์ ๋ฐฉ๋ฒ๋ก ์ ๊ดํ ๊ธ์ ์ฐ๊ฒ ๋์์ต๋๋ค. ์ต๊ทผ ์ํฉ์ ์ด๋ ์ต๋๋ค. SSAFY์์๋ ํ๋ฃจ์ ์์ฒญ๋ ์์ ์๊ณ ๋ฆฌ์ฆ ๋ฌธ์ ๋ค์ ๊ณผ์ ๋ก ์ํํ๊ฒ ๋ฉ๋๋ค. ๊ทธ ๊ณผ์ ์์, '๊ตฌํ๋ ฅ'์ด ๋งค์ฐ ๋จ์ด์ง๋ค๋ ์๊ฐ์ด ๋ค์์ต๋๋ค. ์์ ํ ์ด๋ ค์ด ๋ฌธ์ ๋ผ๋ฉด '์์ฌ์'์ด๋ผ๋ ๊ฐ์ ์กฐ์ฐจ ๋๋ผ์ง
SubnetVPC ์ค๊ณ์ ์์: IP์ Subnet
๋ฐ๋ณต๋๋ ๋ฃจํด ์์์ ์ป์ ์์ ๊ฐ์ ๋ฐํ ์ผ์, ์ด์ ๋ ๊ธฐ์ ์ ์คํํธ๋ผ์ ๋ํ๊ธฐ ์ํ ๊ฐ์ธ ํ๋ก์ ํธ์ ์ฐฉ์ํ๊ณ ์ ํฉ๋๋ค.์ด๋ฒ ํ๋ก์ ํธ์ ๋ชฉํ๋ ๋จ์ํ ํฌํธํด๋ฆฌ์ค ๊ตฌ์ถ์ ๋์ด, ์ค์ ์๋น์ค ์์ค์ ๋ธ๋ก๊ทธ ์์คํ ๊ตฌํ๊ณผ ๋ค๊ตญ์ด ์ฒ๋ฆฌ ์ ์ฉ ๋ฑ ์ค๋ฌด์ ๊ฐ๊น์ด ์ญ๋์ ํ ๋จ๊ณ