Window 10 환경에서 node.js를 사용했습니다.
npm init 부터 로그인 UI까지 만드는 과정을 기록합니다.
편의상 node로 프론트화면까지 구성합니다.
기본적으로 node는 설치가 되어 있다고 생각하고 진행합니다.
1. express-generator로 프로젝트 생성
원하는 경로에 새로운 디렉터리를 만들어요.
저는 node-express-auth
라는 이름으로 디렉터리를 하나 만들었요.
이제 경로 내에 들어가 express-generator로 node 기본 구조를 만들 거예요.
express로 프로젝트 생성
$ express ex-auth -e --git
의존 패키지 설치
$ cd ex-auth
$ npm install
$ npm install bootstrap --save
$ npm install jquery --save
로그인 화면을 조금 더 이쁘게 꾸미기 위해 Bootstrap까지 의존 패키지를 설치했어요.
express-generator로 프로젝트 구성하는 방법이나 자세한 설명은 아래 글을 참고하세요.
Node.js :: express-generator 로 개발환경 세팅
2. 프로젝트 실행
프로젝트 실행 (기본)
$ npm start
pm2가 설치되어 있지 않으신 분은 기본으로 실행하시면 되고,
프로젝트 실행 (pm2)
$ pm2 start bin/www --name "ex-auth" --watch
pm2가 설치되어 있으시면 pm2로 실행하시면 됩니다.
pm2 설치 및 사용 방법이 궁금하시면 아래 글을 참고해 주세요.
3. 라우트 설정
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
...
app.use('/', indexRouter);
app.use('/users', usersRouter);
라우터가 2개 있어요.
어차피 연습이니까 기본 구조를 최대한 그대로 사용할 생각입니다.
indexRouter
에는 login 페이지로 이동할 수 있는 부분을 추가할 것이고
userRouter
에는 login 화면 및 실제 처리작업을 추가할 것입니다.
4. 로그인 페이지 생성
로그인 페이지로 이동시키는 화면 만들기
<!DOCTYPE html>
<html>
<head>
<title>
<%= title %>
</title>
</head>
<body>
<h2>이곳은 index 페이지입니다.</h2>
<a href="/users">로그인 페이지로 이동</a>
</body>
</html>
index.ejs에 로그인 페이지로 이동할 수 있도록 코드를 수정합니다.
로그인 페이지 생성
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
res.render('users/login', { title: 'Express - Login' });
});
module.exports = router;
login.ejs를 바라볼 수 있도록 수정합니다.
수정했으니 login.ejs를 만들어야겠죠?
<!DOCTYPE html>
<html>
<head>
<title>
<%= title %>
</title>
<link rel="stylesheet" href="/bootstrap.min.css" id="bootstrap-css">
<link rel='stylesheet' href='/stylesheets/style.css' />
<script src="/jquery.min.js"></script>
<script src="/bootstrap.min.js"></script>
</head>
<body>
<form name="loginfrm" action="/users/login_process" method="post">
<div class="form-group">
<label for="email">이메일</label>
<input type="email" class="form-control" id="email" name="email" aria-describedby="emailHelp" placeholder="이메일을 입력하세요." required>
</div>
<div class="form-group">
<label for="password">비밀번호</label>
<input type="password" class="form-control" id="password" name="password" placeholder="비밀번호를 입력하세요." required>
</div>
<button type="submit" class="btn btn-primary">로그인</button>
</form>
</body>
</html>
Bootstrap과 Jquery를 npm으로 설치하지 않았다면 각각 CDN사용법으로 호출하시면 됩니다.
그러나 npm으로 설치했다면 오류가 발생할 거예요.
각각의 경로를 잡아주지 않아서 발생한 오류입니다.
그리고 form 부분이 중요한데요,
<form name="loginfrm" action="/users/login_process" method="post">
action에는 이동하고자 하는 routing된 경로를 입력해야 하고
우리는 처리페이지를 만드는 것이기 때문에 method에는 post로 입력해야 해요.
Bootstrap, Jquery 경로 설정
...
app.use(express.static(path.join(__dirname, 'public')));
// Bootstrap, Jquery 경로
app.use(express.static(__dirname + '/node_modules/jquery/dist'));
app.use(express.static(__dirname + '/node_modules/bootstrap/dist/css'));
app.use(express.static(__dirname + '/node_modules/bootstrap/dist/js'));
app.use('/', indexRouter);
app.use('/users', usersRouter);
...
여기까지 했다면 이제 로그인 페이지를 확인할 수 있습니다.
- localhost:3000/users
5. 로그인 처리
우선 user.js에 로그인 처리하는 부분을 추가할 건데요.
하나하나 짚어보면서 할게요.
express-session 패키지 설치
$ npm install express-session
먼저 express-session을 설치해 주세요.
var express = require('express');
var session = require('express-session')
app.use(session({
secret: 'session-secret123!@#',
resave: false,
saveUninitialized: false,
}));
app.js 파일 내에서 기존 express 객체가 초기화된 곳 아래에 session을 추가해 주세요.
그리고 서비스에 session 객체를 연결합니다.
secret
session에 사용할 암호입니다. 해당 암호는 절대 외부에 공개되어서는 안 되며, 어차피 별도로 사용할 일도 없으니 예측이 전혀 불가능한 암호로 하는 것이 좋습니다.
지금은 편의상 app.js 소스 내에 바로 적었지만, 따로 config 파일같은 곳에 변수로 저장해 사용하는 것이 맞습니다.resave
true일 경우 클라이언트 요청 시 기존에 있던 session에 변경사항이 없을 경우에도 해당 session을 다시 저장한다.
false일 경우 클라이언트 요청 시 기존에 있던 session에 변경사항이 없으면 해당 session은 그대로 둔다.
기본값은 true입니다.saveUninitialized
true일 경우 요청 시 session에 저장할 내용이 없더라도 session을 저장한다.
false일 경우 요청 시 session에 저장할 내용이 없으면 session을 저장하지 않는다.
즉, session을 수정하면 저장되고, session을 수정하지 않으면 저장하지 않는다.
공식적으로는 false로 사용할 것을 권유하고 있습니다. 서버의 저장공간도 아낄 수 있습니다.
아마 클라이언트의 서버 접근 횟수를 추적하는 목적으로 true를 사용할 수도 있겠네요.
기본값은 true입니다.
로그인 처리 페이지
router.post('/login_process', (req, res, next) => {
let post = req.body;
console.log(post);
res.send('res login_process');
});
req.body를 사용하면 post로 받은 데이터를 사용할 수 있어요.
console.log를 찍어놓고, 로그인 페이지에서 이메일과 패스워드 입력 후 로그인 버튼을 눌러보세요~
실행중인 서비스에 로그를 보면 console이 찍힌 것을 확인할 수 있습니다.
- login_process로 이동된 후 consolg.log 결과
req.body.email
, req.body.password
이런 식으로 파라미터들을 가져올 수 있어요.
그럼 데이터가 잘 넘어오는 것을 확인했으니 본격적으로 session을 활용해 로그인 처리하는 부분을 만들어 볼게요.
💣 반드시 express-session 관련 내용을 거친 후에 이곳을 봐주세요!
router.post('/login_process', (req, res, next) => {
let post = req.body;
let email = post.email;
let password = post.password;
req.session.is_logined = true;
req.session.ss_email = email;
console.log(req.session);
res.send('res login_process');
});
준비된 session을 활용할 거예요.
다시 로그인 화면으로 이동 후 이메일과 비밀번호를 입력하고 로그인을 눌러보세요.
- login_process로 이동된 후 consolg.log 결과
console을 확인하면 Session을 확인할 수 있어요.
나머지 옵션은 별도로 주지 않았기에 기본으로 설정된 값으로 되어 있으며,
is_logined
랑, ss_email
이 세션에 등록된 것을 볼 수 있어요.
세션이 정상적으로 등록되는 것을 확인했으니 이제 로그인 완료 시키면서 index 페이지로 보낼게요.
router.post('/login_process', (req, res, next) => {
let post = req.body;
let email = post.email;
let password = post.password;
req.session.is_logined = true;
req.session.ss_email = email;
req.session.save(function () {
res.redirect(`/`);
});
});
- localhost:3000
로그인은 되었고, index페이지로 이동했지만 index페이지에 로그인 체크를 하지 않았으니, 이제 로그인 여부에 따라 구분하는 코드를 삽입할게요.
6. 로그인 체크
router.get('/', function(req, res, next) {
// res.render('index', { title: 'Express' });
let is_logined = req.session.is_logined;
let ss_email = req.session.ss_email;
res.render('index', {
title: 'Express',
is_logined: is_logined,
ss_email: ss_email
})
});
session의 값을 가져와 로그인 여부랑 누가 로그인 했는지를 가져왔어요.
근데 귀찮아서 이렇게 하기는 했는데, 이 소스를 모든 곳에 다 추가할 수는 없잖아요.
그래서 별도의 공통함수를 만드는 것이 좋아요.
만드는 김에 UI까지 만들어서 출력하는 걸로 하죠!
보통 로그인/로그아웃 UI는 공통으로 쓰니까요~
루트경로 아래네 lib/login.js 를 새로 만들게요.
module.exports = {
isLogin:function(req, res) {
return req.session.is_logined;
},
loginStatusUI:function(req, res) {
let loginStatusUI = '<a href="/users">login</a>';
if (this.isLogin(req, res)) {
loginStatusUI = `<b>${req.session.ss_email}</b>님 안녕하세요. | <a href="/users/logout_process">logout</a>`;
}
return loginStatusUI;
}
}
isLogin
로그인 체크 여부를 판단loginStatusUI
로그인 체크 여부에 따라 UI구현
router.get('/', function(req, res, next) {
// res.render('index', { title: 'Express' });
res.render('index', {
title: 'Express',
loginStatusUI: login.loginStatusUI(req, res),
})
});
index.js를 다시 수정했어요.
물론 나중에는 로그인UI 부분을 별도로 관리해야겠지만 편의상 일단은 이렇게 사용할게요.
이제 테스트를 해볼까요?
localhost:3000 (로그인 전)
localhost:3000/users
localhost:3000 (로그인 후)
7. 로그아웃
loginStatusUI 내에서 /users/logout_process
경로로 이동하면 로그아웃 되도록 UI를 만들었어요.
이제 logout_process
처리하는 부분을 만들거예요.
router.get('/logout_process', (req, res, next) => {
req.session.destroy(function(err){
res.redirect('/');
});
});
session을 제거해버리면 됩니다.
로그아웃 처리까지 완료했습니다.
8. 세션 저장하기
아마 지금까지 수정하면서 서버가 리로드되면 계속 세션이 끊겼을 거예요.
express-session은 기본적으로 메모리 저장소에 세션을 보관해요.
즉, 서버 또는 클라이언트가 끊기면 세션도 끊긴다는 말입니다.
그럼 매번 접속할 때마다 로그인 해야 돼요ㅜㅜ
세션이 끊기는 걸 방지하기 위해서는 서버측에 세션을 물리적으로 저장해야 해요.
session-file-store라고 세션을 파일로 저장하는 방법이 있습니다.
여기서는 session-file-store만 소개할 거고 express-mysql-session을 사용할 수도 있는데 이 부분은 다음 글에서 소개하도록 할게요.
session-file-store 패키지 설치
$ npm install session-file-store
var session = require('express-session')
var FileStore = require('session-file-store')(session)
...
app.use(session({
secret: 'session-secret123!@#',
resave: false,
saveUninitialized: false,
store:new FileStore(),
}));
상단에 FileStore 모듈을 불러오는 부분을 추가합니다.
그 후 아까 session 지정했던 부분에 store 옵션을 추가해요.
그러고 다시 서버를 재시작하면 루트경로에 sessions라는 디렉터리가 생겼을 거예요.
물론 아직 아무것도 없을 거예요.
이제 아까처럼 로그인을 한 번 해볼까요?
- 로그인 후 session 물리적 저장소
이제 서버를 껐다켜보세요. 더 이상 로그아웃이 되지 않죠?
세션 설정 시 쿠키의 다양한 옵션들도 줄 수 있지만 나중에 별도의 글로 작성할게요.
다음 글은 db를 연동하여 로그인 정보 및 session을 db에 저장하도록 할게요.
9. 전체 소스 코드
https://github.com/gogoma-code/node-express-auth.git (branch::ex-auth)
참고자료
'Programming > Node.js' 카테고리의 다른 글
Connection Pool 사용 시 release() 코드 위치의 중요성 (0) | 2023.09.22 |
---|---|
Node.js + express-session + db(MariaDB/MySQL) 연동 예제 :: 로그인 구현 (0) | 2022.07.11 |
Node.js :: express-generator 로 개발환경 세팅 (0) | 2022.07.06 |
Node.js :: 버전 변경하기 / nvm 활용 (0) | 2022.06.27 |
Node.js :: Express 로 Cookie 올바르게 활용하기 (0) | 2022.06.08 |