1 회원가입 UI제작
1) SigninScreen.js 추가하기
- 회원가입 라우팅 페이지를 랜더링하기 위해서 SigninScreen.js파일을 screens폴더아래에 추가한다.
const SigninScreen = {
after_render: () => {
},
render: () => {
return `
<div class="form-container">
<form id="signin-form">
<ul class="form-items">
<li>
<h1> Sign-In </h1>
</li>
<li>
<label for="email">Email</label>
<input type="email" name="email" id="email"/>
</li>
<li>
<label for="password">Password</label>
<input type="password" name="password" id="password"/>
</li>
<li>
<button type="submit" class="primary"> Signin </button>
</li>
<li>
<div>
New User?
<a href="/#/register">Create your account</a>
</div>
</li>
</ul>
</form>
</div>
`;
},
};
export default SigninScreen;
|
[ root\frontend\src\screens\SigninScreen.js ]
2) index.js 추가하기
- 회원가입 라우팅을 추가한다.
import {parseRequestUrl} from './utils'; import HomeScreen from './screens/HomeScreen';
import ProductScreen from './screens/ProductScreen';
import Error404Screen from './screens/Error404Screen';
import CartScreen from './screens/CartScreen';
import SigninScreen from './screens/SigninScreen'; // 추가...
const routes = {
'/' : HomeScreen,
'/product/:id':ProductScreen,
'/cart/:id': CartScreen,
'/cart': CartScreen,
'/signin': SigninScreen, // 추가...
}
const router = async() => {
const request = parseRequestUrl();
// 중략...
|
[ root\frontend\src\index.js ]
3) 라우팅 실행
- 라우팅이 정상적으로 이뤄지는지 테스트한다.
- \root\frontend\> npm start
4) CSS적용하기
- 회원가입 폼에 css를 적용한다.
/* Form */ .form-container{
display: flex;
justify-content: center;
align-items:flex-start; height:100%;
}
.form-items{
display: flex;
flex-direction: column;
width: 32rem;
padding: 2rem;
border: 0.1rem #c0c0c0 solid;
border-radius: 0.5rem;
list-style-type:none;
}
.form-items li{
display:flex;
flex-direction: column;
margin-bottom: 1rem;
margin-top: 1rem;
}
.form-container h1{
font-size: 2.5rem;
}
|
[ root\frontend\style.css ]
flex를 적용한 결과는 아래와 같다.
2 유저 로그인
1) 'body-parser', 'express-async-handler', 'jsonwebtoken' npm모듈 설치
- root\> npm install --save body-parser
- root\> npm install --save express-async-handler
- root\> npm install --save jsonwebtoken
2) server.js 수정
- 로그인 창에 입력된 정보는 post방식으로 서버에 전달된다. body-parser모듈을 사용한다면, Post방식으로 전달된 데이터를 받을 수 있다. body-parser모듈을 추가하고, 미들웨어로 지정한다.
import express from 'express'; import cors from 'cors';
import mongoose from 'mongoose';
import config from './config';
import bodyParser from 'body-parser'; // 추가
import data from './data.js';
import userRouter from './routers/userRouter';
dbMain().then( () => {
// 중략...
}
const app = express();
app.use(cors());
app.use(bodyParser.json()); // 추가
app.use('/api/users', userRouter );
app.get('/api/products', (req, res) => {
res.send(data.products);
});
app.get('/api/products/:id', (req, res) => {
// 중략... |
[ root\backend\server.js ]
3) userRouter.js 수정 & 추가
- 프로미스 구문을 express라우터에 적용하기 위해서 expressAsyncHandler모듈을 추가한다. 해당 모듈 덕분에 createUser값이 서버에 저장되기 전까지 res.send( )구문은 실행되지 않는다.
import express from 'express'; import User from '../models/userModel';
import expressAsyncHandler from 'express-async-handler'; // 추가
import { generateToken } from '../utils'; // 추가
const userRouter = express.Router();
userRouter.get(
'/createadmin',
expressAsyncHandler(async(req, res) => { // 수정
try{
const user = new User({
name: 'admin',
email: 'blogtest@gmail.com',
password: 'blogtest@',
});
const createUser = await user.save();
res.send(createUser);
}catch(err){
res.status(500).send({ message: err.message })
}
}) //expressAsyncHanlder End
);
// signin라우터 추가 userRouter.post(
'/signin',
expressAsyncHandler(async(req, res) => {
const signinUser = await User.findOne({
email: req.body.email,
password: req.body.password,
});
if(!signinUser){
res.status(401).send({
message: 'Invalid Email or Password'
})
}else{
res.send({
_id: signinUser._id,
name: signinUser.name,
email: signinUser.email,
isAdmin: signinUser.isAdmin,
token: generateToken(signinUser),
})
}
}) //expressHandler End
);
export default userRouter;
|
[ root\backend\routers\userRouter.js ]
- '/signin' 라우터의 경우, 서버에 쿼리한 결과가 signinUser변수에 저장되며, 해당 반환값을 프론트에 전달한다.
- 비밀번호를 암호화하는 jsonwebtoken 모듈이 없는 상태이므로 backend\폴더 아래에 서버용 utils.js 파일을 생성한다.
4) 서버용 utils.js 생성
- jwt(json-web-token)모듈은 사용자 정보를 기반으로 토큰을 발행한다. jwt를 사용하면 간편하게 사용자 인증을 처리할 수 있다. 따로 세션을 만들지 않고, 발행된 토큰을 비교함으로써 인증을 진행하기 때문에 Auth보다 편리하다.
import jwt from 'jsonwebtoken'; import config from './config';
export const generateToken = (user) => {
return jwt.sign({
_id: user._id,
name: user.name,
email: user.email,
isAdmin: user.isAdmin
}, config.JWT_SECRET )
}
|
[ root\backend\utils.js ]
5) 서버용 config.js 생성
- 프론트에서 서버주소를 저장한 config.js를 생성한 것처럼 서버에서는 환경변수 데이터가 저장된 config.js가 필요하다. config.js에 사용되는 dotenv모듈은 process.env에 전역으로 접근할 수 있다.
import dotenv from 'dotenv'; dotenv.config();
export default{
MONGODB_URL: process.env.MONGODB_URL,
JWT_SECRET: process.env.JWT_SECRET,
}
|
[ root\backend\config.js ]
6) .env 추가
- JWT_SECRET변수를 추가한다.
MONGODB_URL=mongodb://localhost/blogtest_db JWT_SECRET=somethingsecret |
[ root\.env ]
7) server.js 미들웨어 추가
- 유효성 에러와 관련된 미들웨어를 server.js에 추가한다.
import express from 'express'; // 중략...
app.get('/api/products/:id', (req, res) => {
const product = data.products.find((x) => x._id === req.params.id);
if(product){
res.send(product);
}else{
res.status(404).send({message: 'product Not Found!'});
}
});
app.use((err, req, res, next) => { // <--추가
const status = err.name && err.name === 'ValidationError' ? 400 : 500;
res.status(status).send({ message: err.message });
}) // 추가-->
app.listen(5000, () => {
console.log('server at http://localhost:5000');
});
|
[ root\backend\server.js ]
8) SigninScreen.js 추가
- 로그인 인증이 끝난 뒤에 이뤄지는 기능(인덱스 페이지로 이동)을 추가한다.
import { signin } from '../api';
const SigninScreen = {
after_render: () => { // <-- 추가
document.getElementById('signin-form')
.addEventListener('submit', async(e) => {
e.preventDefault();
const data = await signin({
email: document.getElementById('email').value,
password: document.getElementById('password').value,
});
if(data.error){
alert(data.error);
}else{
document.location.hash = '/';
}
}) // 추가 -->
},
render: () => {
// 중략... export default SigninScreen;
|
[ root\frontend\src\screens\SigninScreen.js ]
9) api.js 추가
- 로그인에 성공했을 때, POST방식으로 'localhost:5000/api/signin'경로에 있는 유저 정보를 받아올 수 있다. 인증 미들웨어를 통과한 상태에서 axios모듈은 POST방식으로 해당 경로에 접근할 수 있다. api.js의 signin함수는 axios를 통해 유저 정보를 반환한다.
// 중략... export const signin = async({email, password}) => { // <-- 추가 try{
const response = await axios({
url: `${apiUrl}/api/users/signin`,
method: 'POST',
header: {
'Content-Type': 'application/json',
},
data:{
email,
password
},
});
if(response.statusText !== 'OK'){
throw new Error(response.data.message);
}
return response.data;
}catch(err){
console.log(err);
return { error: err.response.data.message || err.message }
}
} // 추가 -->
|
[ root\backend\config.js ]
10) 테스트
- 관리자 아이디로 로그인을 진행해본다. 비밀번호나 아이디를 틀리게 입력했을 때, 아래와 같은 오류가 발생한다.
userRouter.js에 입력한 관리자 아이디와 비밀번호를 정확하게 입력해주면, 아래와 같이 index페이지로 이동한다.
'웹개발 자료실 > No프레임워크 쇼핑몰제작Code' 카테고리의 다른 글
E-commerce Vanila JS [10편] 회원가입 | 인증 | 로그아웃 (0) | 2021.12.11 |
---|---|
E-commerce Vanila JS [9편] 로그인 인증(2) (0) | 2021.12.10 |
E-commerce Vanila JS [7편] 몽고DB 연결 (0) | 2021.12.09 |
E-commerce Vanila JS [6편] Cart 제작 (0) | 2021.12.08 |
E-commerce Vanila JS [5편] 랭킹, 상세페이지 제작 (1) | 2021.12.06 |
댓글