저번 포스팅에서 세션이 무엇인지에 대해 다뤄보았었다. 이번에는 express-session 패키지를 사용해서 세션을 만들어 보고 간단한 로그인 기능을 구현해보도록 하자.
< 목차 >
- express-session 세팅하기
- 로그인 기능 구현하기
< express-session 세팅하기 >
우선 로그인 기능이 작동하는 원리를 간단하게 살펴보자. 사용자가 아이디와 패스워드를 입력해서 웹서버로 요청을 보내면 웹서버는 자신이 갖고 있는 데이터와 사용자가 입력한 데이터가 일치하는지 확인하는 작업을 거치게 된다. 그리고 데이터가 일치하는지의 여부에 따라 세션을 생성할지 말지를 결정한다. 사용자가 입력한 데이터가 서버쪽 데이터와 일치할 경우 서버는 세션을 생성해서 쿠키 형태로 사용자의 브라우저에 전송하게 된다.
세션은 기본적으로 쿠키를 사용해야 한다. (쿠키가 없이는 세션도 없다.) 클라이언트가 서버에 요청을 보냈을 때 서버쪽에서는 응답과 동시에 쿠키를 생성해서 브라우저에 저장한다. 그리고 서버는 특정 메모리 공간에 해당 정보를 담게 된다. 브라우저에 저장된 쿠키에는 key가 담겨 있고 서버의 메모리 공간에는 key: value 값이 담겨있다. 쿠키가 생성되었다면 클라이언트는 이후의 모든 요청들에 쿠키를 담아서 서버에게 보내게 된다. 그렇다면 서버 입장에서는 요청이 들어올 때마다 쿠키를 체크해주는 작업이 수행되어야 한다. 미들웨어를 사용해서 이러한 작업을 처리해주게 되는데 이 때 사용되는 것이 바로 express-session 이다.
서버는 메모리, 파일, 데이터베이스와 같은 공간에 세션정보를 저장하게 되는데 우리가 사용할 것은 메모리이다. 세션을 만들어서 메모리 공간에 담아두고 사용하는 방식으로 구현해보고자 한다. express를 사용해서 서버를 만들고 템플릿 엔진으로는 nunjucks를 사용할 것이다.
로그인 기능을 만들기 위해 "express-session" 패키지를 사용해 세션을 생성하는 기능을 구현할 것이고 "memorystore" 라는 패키지를 사용해 메모리 공간에 세션을 담을 수 있도록 설정할 것이다. "npm install express-session" , "npm install memorystore" 로 각각의 패키지를 다운 받고 기본적인 세팅 작업을 진행해보자.
const express = require('express')
const nunjucks = require('nunjucks')
const session = require('express-session')
const Memorystore = require('memorystore')(session)
const app = express();
app.set('view engine', 'html')
nunjucks.configure('./views', {
express: app,
watch: true
})
let maxAge = 60*1000
const sessionObj = {
secret: "wegf6124@#$@#!", // salt -> 암호화를 할 때 필요한 요소값
resave: false,
saveUninitialized: true,
store: new Memorystore({ checkPeriod: maxAge }), // 서버를 저장할 공간 설정,
// checkPeriod : 서버쪽 세션의 유효기간
cookie: {
maxAge: maxAge
}
// 브라우저 쿠키의 유효기간
}
app.use(session(sessionObj))
// session() -> 세션을 생성해주는 미들웨어
app.use(express.urlencoded({extended: true}))
app.get('/', (req, res)=>{
console.log(req.session)
res.render('index.html')
})
app.listen('3000', ()=>{
console.log('server onload')
})
const session = require('express-session') 으로 불러온 session은 미들웨어이다. 세션을 생성해주는 미들웨어로써 app.use(session( )) 형태로 사용된다. session( ) 미들웨어에는 내부적으로 next()가 담겨 있어서 app.use 라우터 안에 session( )을 넣어서 사용하면 어떤 요청이 들어올 때마다 항상 실행되는 미들웨어가 된다. 그리고 session( ) 미들웨어는 req 객체 안에 session이라는 객체를 만들어준다.
session( ) 안에는 객체 형태의 인자값이 들어가게 되는데 위에서는 sessionObj 라는 객체를 만들어서 session( )의 인자값으로 전달했지만 아래와 같이 직접 session( ) 안에 작성해도 무방하다.
let maxAge = 60*1000
app.use(session({
secret: "wegf6124@#$@#!",
resave: false,
saveUninitialized: true,
store: new Memorystore({ checkPeriod: maxAge }),
cookie: {
maxAge: maxAge
}
}))
session( )의 인자값으로 들어가는 객체의 속성들 중에서 secret은 암호화를 담당한다. 암호화를 함으로써 세션id가 겹치지 않도록 하는 효과를 가져올 수 있다. 속성값으로는 암호화를 할 때 필요한 요소값인 salt를 넣어준다. (임의로 아무 값이나 넣어줘도 된다.)
store를 통해서는 세션을 저장할 공간을 설정할 수 있다. 세션을 저장하는 주체는 서버이기 때문에 서버의 메모리에 저장할 것인지, 파일에 저장할 것인지, 아니면 데이터베이스에 저장할 것인지를 지정해줘야 한다. 이때 사용하는 것이 store 속성이다. (여기서는 메모리에 저장하도록 했다.) 그리고 checkPeriod를 통해 store의 유효기간을 설정해 줄 수도 있다. 단위는 1000=1초 이며 checkPeriod 속성값으로 서버쪽 세션의 유효기간을 설정할 수 있다.
cookie는 쿠키의 설정을 담당하는 속성이다. 쿠키 정보에는 HttpOnly, Path, Max-Age 등 다양한 여러가지 내용이 들어갈 수 있기 때문에 객체 형태로 값을 넣는다. 쿠키의 만료시간, 쿠키의 범위 같은 것을 지정할 때 cookie 속성을 사용한다. (여기서는 maxAge로 유효기간만 설정해 주었다.)
< 로그인 기능 구현하기 >
Node.js를 이용해 실행할 서버 파일인 server.js 파일은 다음과 같다.
기본적인 세팅을 진행해줬고 라우터를 사용해 메인페이지를 분리해서 제작하였다. 메인페이지 파일은 routes 디렉토리 안에 index.js 파일로 존재하고 해당 파일은 다음과 같다.
메인페이지 파일에서도 라우터를 사용해 로그인 페이지와 게시판 페이지를 분리해서 제작하였다. 게시판 페이지 같은 경우 'Auth'라는 미들웨어를 따로 만들어서 회원인지 아닌지를 검증하는 작업을 거치도록 하였다. Auth 미들웨어를 사용하면 "/board" uri로 접근할 때 로그인 한 상태인지 아닌지를 체크할 수 있게 된다.
가장 핵심이 되는 로그인 기능이 구현되는 파일이다. 2번 과정을 통해 사용자가 입력한 아이디, 패스워드를 가지고 서버에 저장된 사용자 데이터를 필터링하는 과정을 거치게 된다. 일치하는 데이터가 있다면 3번에 의해 req.session 객체 안에 user 속성값을 추가해서 사용자 정보를 넣어주는 작업을 해준다. 그리고 res.redirect를 이용해 메인페이지로 보내버린다. 메인페이지에서는 1번에 의해 req.session 객체의 user 정보를 user라는 변수에 담아 index.html 파일로 보내준다. index.html 파일에서는 nunjucks 문법을 활용해 req.session 객체에 user 속성값의 존재 유무에 따라 다른 페이지를 랜더하는 코드를 작성해주면 된다.
만약 서버에 저장된 사용자 데이터 중에서 사용자가 입력한 아이디, 패스워드와 일치하는 데이터가 없으면 alertMove() 함수의 리턴값을 res.send()의 인자값으로 넣어 웹브라우저에게 보내준다. (alertMove 함수는 필자가 만든 함수로 해당 함수에 대해서는 밑에서 다루고 있다.)
사용자가 로그아웃 버튼을 눌러 '/user/logout' 으로 접속하면 req.session.destroy() 메소드를 사용해 세션을 삭제해주도록 한다. 이때도 마찬가지로 alertMove 함수를 실행해 res.send()의 인자값으로 넣어준다.
이제 메인페이지의 html 파일인 index.html , 로그인페이지의 login.html , alertMove() 함수가 담겨있는 alertMove.js 파일 , 사용자 데이터가 담겨있는 user.js 파일을 살펴보자.
템플릿 엔진 nunjucks를 활용해서 req.session 객체 안에 user 속성값이 존재할 경우 메인페이지가 다른 구성을 갖도록 하였다. 그리고 메인페이지 파일 안에 있는 Auth 미들웨어에 의해 로그인하지 않은 상태로는 게시판 사이트에 접속할 수 없게된다.
user.js 파일은 사용자의 데이터가 저장되어 있는 파일이다. models 디렉토리 안에 생성하였으며 사용자가 로그인페이지에서 아이디와 패스워드를 입력하면 user.js 파일에 저장되어 있는 사용자 데이터에서 사용자가 입력한 값과 일치하는 데이터를 찾는 과정을 거치게 된다.
alertMove() 함수가 담겨있는 alertMove.js 파일이다. util 디렉토리 안에 생성하였고 두개의 매개변수를 가지는 함수로 만들었다. 첫번째 매개변수는 alert() 함수에 의해 브라우저에 경고창이 뜰 때 경고창 안에 들어갈 텍스트를 받는 매개변수이다. 두번째 매개변수는 브라우저에서 실행되는 location 함수의 경로를 받는 매개변수이다.
이상으로 간단한 웹서버를 만들어서 'express-session'을 활용해 로그인 기능을 구현해 보았다. 아래의 동영상은 실제로 동작하는 과정을 보여주고 있다.
'Node > Express' 카테고리의 다른 글
Node.js - express (12) Buffer , Hash , JWT (0) | 2022.03.03 |
---|---|
Node.js - express (11) express.json() (0) | 2022.02.15 |
Node.js - express (9) express.Router() 사용하기 (0) | 2022.02.10 |
Node.js - express (8) 라우터와 미들웨어 (router & middleware) (0) | 2022.02.10 |
Node.js - express (7) 세션(session) (2) | 2022.02.09 |