원티드 프리온보딩 - 로그인 기능 구현하기 1
원티드 프리온보딩 - 로그인 기능 구현하기 1강 복습
로그인이란?
사용자가 시스템에 접근하거나 동작을 수행하는 것을 제어하고 기록하기 위한 컴퓨터 보안 절차
로그인이 필요한 이유와 구현을 위해 해야하는 것
1. 사용자 식별
- 해당 페이지에 접근하는 사용자가 누구인지 구분하기 위해
2. 접근 및 동작 제어
2-1. 권한이 없는 자원에 접근하지 않는 구조 만들기
- 관리자 전용 페이지와 데이터를 일반 유저가 접근하지 못하도록
- github repo의 setting 버튼이 관리자를 제외하고는 보여지지 않도록 설정
2-2. 권한이 없는 자원의 존재를 모르도록 하기
- 관리자 페이지의 주소를 일반 유저가 직접 입력했을 때 오류 페이지를 보여줌으로써 권한이 없는 페이지&데이터를 숨기기
3. 인증 정보 관리하기
- 로그인이 계속 유지될 수 있도록 token을 쿠키, 로컬스토리지, 섹션스토리지에 저장
- 인증 정보를 저장해두지 않는다면 장바구니에 추가할 때도 로그인을 해야하고, 장바구니로 이동할 때도 로그인을 해야함
실제 서비스를 구성하는 페이지들
로그인이 필요한 페이지
1
2
3
4
5
6
7
8
9
10
11
12
const pageWithLogin = () => {
const { isLogged, routeToLoginPage } = useLoginState();
// 로그인이 되지 않은 경우에는 로그인 페이지로 이동
if (!isLogged) {
routeToLoginPage();
// 라우팅 되기 전 잠깐이라도 로그인이 필요한 컨텐츠를 보여주지 않도록 설정
return <> 로그인 페이지로 이동합니다...</>;
}
return <div>로그인이 필요한 페이지 코드</div>;
};
로그인이 필요하지 않은 페이지
1
2
3
const pageWithoutLogin = () => {
return <div>로그인이 필요 없는 페이지 코드</div>;
};
로그인 여부 확인 로직 모듈화 Authorization
- 매번 로그인 여부를 확인할 코드를 작성하는 것 대신 모듈화 해서 관리
1
2
3
4
5
6
7
8
9
10
11
12
const Authorization = ({ children }) => {
const { isLogged, routeToLoginPage } = useLoginState();
// 로그인이 되지 않은 경우에는 로그인 페이지로 이동
if (!isLogged) {
routeToLoginPage();
// 라우팅 되기 전 잠깐이라도 로그인이 필요한 컨텐츠를 보여주지 않도록 설정
return <> 로그인 페이지로 이동합니다...</>;
}
return <>{children}</>;
};
로그인 화면 만들기
1. username, password를 입력받을 입력창 만들기
2. 입력한 정보를 받아올 버튼 만들기
3. 로그인 목업 API
4. 유저 정보 받아오기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import React from "react";
import { useState } from "react";
// 임의로 만든 더미
const users = [
{
username: "blueStragglr",
password: "1234",
userInfo: { name: "blueStragglr" }
},
{ username: "hyemin", password: "1234", userInfo: { name: "hyemin" } }
];
// 임의로 만든 token
const _secret = "1234qwer!@#$";
const login = async (username, password) => {
const user = users.find(
(user) => user.username === username && user.password === password
);
return user
? {
message: "SUCCESS",
token: JSON.stringify({ username: user.username, secret: _secret })
}
: null;
};
const getUserInfo = async (token) => {
const parsedToken = JSON.parse(token);
if (!parsedToken?.secret || parsedToken.secret !== _secret) return null;
const loggedUser = users.find((user) => {
if (user.userInfo.name === parsedToken.user.name) return user;
});
return loggedUser ? loggedUser.userInfo : null;
};
const LoginWithMockAPI = () => {
const [userInfo, setUserInfo] = useState(null);
const loginSubmitHandler = async (event) => {
event.preventDefault();
const formData = new FormData(event.currentTarget);
const loginResonse = await login(
formData.get("username"),
formData.get("password")
);
if (!loginResonse) return;
const userInfo = await getUserInfo(loginResonse.token);
if (!userInfo) return;
setUserInfo(userInfo);
};
return (
<div>
<h1>Login with Mock API</h1>
<form onSubmit={loginSubmitHandler}>
<label className="label">
Username:
<input type="text" name="username" />
</label>
<label className="label">
Password:
<input type="password" name="password" />
</label>
<button type="submit" value="Submit">
Submit
</button>
</form>
<div>
<h2>User info</h2>
{JSON.stringify(userInfo)}
</div>
</div>
);
};
export default LoginWithMockAPI;
form Data 받아오는 방법
1. new FormData
사용하기
- 사용자가 입력할 때마다 렌더링이 발생하지 않음
- 단순한 값을 받아올 때 주로 사용
- 실시간으로 제어하기 어려움
.get(name)
으로 값 가져와서 사용
1
2
3
4
5
6
7
8
9
10
11
12
const loginSubmitHandler = async (event) => {
event.preventDefault();
const formData = new FormData(event.currentTarget);
const loginResonse = await login(
formData.get("username"),
formData.get("password")
);
// ...
};
2. useState
사용하기
- 사용자가 입력할 때마다 렌더링이 발생
- 실시간으로 제어할 수 있음 (특수문자, 이메일주소, 핸드폰번호 체크 등)
- 부모컴포넌트 전체가 렌더링돼서 부담될 때는 input만 따로 컴포넌트로 만들고 input 컴포넌트 안에서 useState 사용해서 전체 렌더링 막기
- 자식 컴포넌트로 관리하면 부모 컴포넌트는 렌더링이 되지 않고 자식 컴포넌트만 렌더링되기때문
느낀점
formData를 이용해 제출된 값을 가져올 수 있다는 점을 배웠고,
loginSubmitHandler, 로그인 함수까지는 작성을 했으나 getUserInfo 함수는 왜 사용되는지 무슨 역할을 하는지 알지 못하여 작성하지 못하였다. getUserInfo()가 무슨 역할을 하는지 따로 공부해야겠다.
This post is licensed under CC BY 4.0 by the author.