클론코딩의 장점은 앞서간 사람의 깔끔한 코드를 볼 수 있다는 것이다.
그러나 단점은 새로운 스택 등이 나왔을 때, 자칫 겉만 핥은 채로 넘어갈 수 있다는 것이다.
그것을 주의해야한다.
참고
아래의 코드는 passport 사이트에서 찾은 참고 코드다.
var express = require('express');
var passport = require('passport');
var Strategy = require('passport-local').Strategy;
var db = require('./db');
// Configure the local strategy for use by Passport.
//
// The local strategy requires a `verify` function which receives the credentials
// (`username` and `password`) submitted by the user. The function must verify
// that the password is correct and then invoke `cb` with a user object, which
// will be set at `req.user` in route handlers after authentication.
passport.use(new Strategy(
function(username, password, cb) {
db.users.findByUsername(username, function(err, user) {
if (err) { return cb(err); }
if (!user) { return cb(null, false); }
if (user.password != password) { return cb(null, false); }
return cb(null, user);
});
}));
// Configure Passport authenticated session persistence.
//
// In order to restore authentication state across HTTP requests, Passport needs
// to serialize users into and deserialize users out of the session. The
// typical implementation of this is as simple as supplying the user ID when
// serializing, and querying the user record by ID from the database when
// deserializing.
passport.serializeUser(function(user, cb) {
// 모든 정보를 저장하는 것은 사용자 정보가 크다면, 메모리가 많이 소모되기 때문에,
// id만 저장하고, 이후 deserialize시에 id를 이용하여 db에서 유저를 확인함.
cb(null, user.id);
});
passport.deserializeUser(function(id, cb) {
db.users.findById(id, function (err, user) {
if (err) { return cb(err); }
cb(null, user);
});
});
// Create a new Express application.
var app = express();
// Use application-level middleware for common functionality, including
// logging, parsing, and session handling.
app.use(passport.initialize());
app.use(passport.session());
app.post('/login',
passport.authenticate('local', { failureRedirect: '/login' }),
function(req, res) {
res.redirect('/');
});
app.listen(3000);
이를, 제로초는 다음과 같이 구현했다.
//app.js
const express = require("express");
const app = express();
const passportConfig = require("./passport");
passportConfig();
app.use('garadori')
...[후략]
// passport/index.js
const passport = require("passport");
const local = require("./local");
module.exports = () => {
passport.serializeUser(() => {});
passport.deserializeUser(() => {});
local();
};
// passport/local.js
const passport = require("passport");
const { Strategy: LocalStrategy } = require("passport-local");
const { User } = require("../models");
module.exports = () => {
passport.use(
new LocalStrategy(
{
usernameField: "email",
passwordField: "password",
},
async (email, password, done) => {
try {
const user = await User.findOne({
where: { email },
});
if (!user) {
done(null, false, { reason: "존재하지 않는 이메일입니다!" });
}
const result = await bcrypt.compare(password, user.password);
if (result) {
return done(null, user);
}
return done(null, false, { reason: "비밀번호가 틀렸습니다." });
} catch (err) {
console.error(err);
return done(err);
}
}
)
);
};
// routes/user.js
router.post("/login", (req, res, next) => {
passport.authenticate("local", (err, user, info) => {
if (err) {
console.error(err);
return next(err);
}
if (info) {
return res.status(401).send(info.reason);
}
return req.login(user, async (loginErr) => {
if (loginErr) {
console.log(loginErr);
return next(loginErr);
}
return res.status(200).json(user);
});
})(req, res, next);
});
참고
- passport.authenticate를 사용하는 방식이 맨 윗 코드와 다르다.(윗 코드는 middleware 위치에 들어갔지만, 제로초 코드는 route handler 내부에서 실행되고 있다.)
이유는 여기를 보면 '맨 아래' 다음과 같은 부분이 있다.
- 'local'이라는 string strategy에 따라 정해진다. 예를 들어 twitter-strategy를 사용하기 위해
npm install pass-twitter
를 하여 import 후 새로운 strategy를 만든다면, 해당 전략을 사용하기 위해passport.authenticate('twitter',...)
를 하면 된다.
이렇게 구현하면, app.js
에 모든 코드를 다 몰아넣었던 처음코드와 달리,
모듈화 할 수 있다는 것을 배웠다. (원리를 아는 것과 사용하는 것은 역시 거리가 멀다...)😵💫😵💫😵💫