노드를 사용한 포트폴리오를 만들려고 인프런에서 강의를 찾아보다가 무료로 학습이 가능한 컨텐츠가 있길래 한번 들어보자 하고 들어봤는데 괜찮은 것 같아서 끝까지 완강하였다. 첫번째 학습은 따라하느라 정신없어서 내용 이해가 잘 안됐지만 두번째 학습부턴 노트에 필기하며 최대한 이해하려고 노력했다. 이 곳에다 학습한 내용을 정리하려고 한다.
1 ) Node.js를 다운 받는다.
- 터미널에서 npm init을 입력하고 package.json을 생성한다.
2 ) express.js를 다운 받는다.
- npm i express --save
3 ) 몽고DB에 연결한다.
- Mongoose는 간단하게 MongoDB를 편하게 쓸 수 있는 tool이다.
const mongoose = require('mongoose');
mongoose.connect(config.mongoURI, {
useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true, useFindAndModify: false
}).then(() => console.log('MongoDB Connected...'))
.catch(err => console.log(err));
4 ) 몽고DB Model & schema
- 모델은 schema를 감싸는 역할을 한다.
const User = mongoose.model('User', userSchema);
- 스키마는 정보들을 지정하는 틀을 만드는 역할을 한다.
// mongoose 모듈을 이용하여 mongoDB 에서 쉽게 테이블이 생성가능함
const userSchema = mongoose.Schema({
name: {
type: String,
maxlength: 50
},
email: {
type: String,
trim: true,
unique: 1
},
password: {
type: String,
minlength: 5
},
lastname: {
type: String,
maxlength: 50
},
role: {
type: Number,
default: 0
},
image: String,
token: {
type: String
},
tokenExp: {
type: Number
}
});
5 ) 회원가입 기능 만들기
- 서버에서 데이터를 받을 때 필요한 미들웨어 body-parser을 설치.
- npm i body-parser --save
- body-parser는 클라이언트 POST request data의 body로 부터 파라미터를 편하게 추출을 한다.
- body-parser를 사용하지 않을 시 express POST request 처리 시 undefined error가 발생함.
// bodyParser 두 개는 클라이언트에서 온 정보를 서버에서 분석하여 가져올 수 있게 하는 것
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.post('/api/users/register', (req, res) => {
const user = new User(req.body);
});
6 ) Nodemon 설치
- Nodemon은 서버를 재시작 할 필요없이 refresh하면 데이터가 업데이트 된다.
- npm i nodemon --save-dev ( 로컬 환경에서만 사용할려고, production 빌드시 플러그인이 포함되지 않는다. )
7 ) 비밀 정보 보호
- 개발 환경에 따라 로컬인지 배포 모드인지 구분하여 다르게 해줘야 한다.
if(process.env.NODE_ENV === 'production') {
module.exports = require('./prod');
} else {
module.exports = require('./dev');
}
8 ) Bcrypt로 암호화 하기
- 데이터 베이스에 암호를 그대로 저장하면 보안성이 취약하다.
- Bcrypt를 이용하여 비밀번호를 암호화 하고 데이터 베이스에 저장.
// server index.js
app.post('/api/users/register', (req, res) => {
// 회원 가입 할 때 필요한 정보들을 client에서 가져오면
// 이것들을 데이터 베이스에 넣어준다.
const user = new User(req.body);
// save 동작이 실행되기 전에 Bcrypt를 이용하여 비밀번호 암호화!
//MongoDB의 method
user.save((err, userInfo) => {
if (err) {
return res.json({ success: false, err});
}
return res.status(200).json({
success: true
});
});
});
const bcrypt = require('bcrypt');
const saltRounds = 10;
userSchema.pre('save', function (next) {
const user = this;
//비밀번호를 암호화 시킨다.
if (user.isModified('password')) {
bcrypt.genSalt(saltRounds, (err, salt) => {
if (err) {
return next(err);
}
bcrypt.hash(user.password, salt, (err, hash) => {
if (err) {
return next(err);
}
user.password = hash;
next();
});
});
} else {
next();
}
});
9 ) 로그인 기능 만들기
app.post('/api/users/login', (req, res) => {
// 요청 된 이메일을 데이터베이스에 있는지 찾는다.
User.findOne({email: req.body.email}, (err, user) => {
if (!user) {
return res.json({
loginSuccess: false,
message: "제공 된 이메일에 해당하는 유저가 없습니다."
});
}
// 요청 된 이메일이 데이터베이스에 있다면 비밀번호가 맞는지 확인
user.comparePassword(req.body.password, (err, isMatch) => {
if (!isMatch) {
return res.json({loginSuccess: false, message: "비밀번호가 틀렸습니다."})
}
// 비밀번호가 맞다면 토큰을 생성하기
user.generateToken((err, user) => {
if (err) {
return res.status(400).send(err);
}
// 토큰을 저장한다 어디에? 쿠키, 로컬스토리지 여기에서는 쿠키에다가 토큰을 저장
res.cookie("x_auth", user.token)
.status(200)
.json({loginSuccess: true, userId:user._id});
});
});
});
});
- DB에서 요청받은 이메일을 찾는다 ( User.findOne( ) )
- 요청 한 이메일이 DB에 있다면 비밀번호가 맞는지 확인
userSchema.methods.comparePassword = function (plainPassword, cb) {
// plainPassword 1234567 암호화 된 비밀번호 $2b$10$lSf61ieg5NSJjMsleWGUdeSNSdFswqNJFr.kvVzhVhGhOIn6cXQ3a
bcrypt.compare(plainPassword, this.password, function (err, isMatch) {
if (err) {
return cb(err);
}
cb(null, isMatch);
});
}
- 비밀번호가 맞다면 token을 생성(Jsonwebtoken)
const jwt = require('jsonwebtoken')
userSchema.statics.findByToken = function (token, cb) {
const user = this;
// 토큰을 decode(복호화) 한다.
jwt.verify(token, 'secretToken', function (err, decoded) {
// 유저 아이디를 이용해서 유저를 찾은 다음에
// 클라이언트에서 가져온 token과 DB에 보관 된 토큰이 일치하는지 확인
user.findOne({'_id': decoded, 'token': token}, function (err, user) {
if(err) {
return cb(err);
}
cb(null, user);
})
})
}
'Programming > Node.js' 카테고리의 다른 글
[Node.js] Express body-parser 너 뭐냐? (0) | 2021.10.13 |
---|---|
[MongoDB] mongoose.connection.on() & once() (0) | 2021.10.13 |
[Express.js] middleware란?? (0) | 2021.10.01 |
Node.js 교과서 express 미들웨어 (0) | 2020.11.27 |
따라하며 배우는 노드, 리액트 시리즈 - 기본 강의 Node.js part2 (0) | 2020.09.17 |