Node

[Node.js] 세션(Session)에 대하여 알아보기

YaluStar 2023. 3. 14. 00:44

안녕하세요.

이번에는 세션(Session)에 대하여 알아보겠습니다.

 

1. Session

  • 웹 서버에 저장되는 쿠키
  • 사용자가 웹 브라우저를 통해 접속한 시점부터 연결을 끝내는 시점까지의 시간 동안 일련의 요구를 하나의 상태로 보고 그 상태를 유지시킨다.
  • Ex) 로그인 유지

 

2. 동작 방식

  • 클라이언트가 서버에 접속 시 세션 ID를 발급받습니다.
  • 클라이언트는 세션 ID에 대해 쿠키를 사용해서 저장하고 가지고 있습니다.
  • 클라이언트는 서버에 요청할 때, 이 쿠키의 세션 ID를 서버에 전달해서 사용합니다.
  • 서버는 세션 ID를 전달받아서 별다른 작업 없이 세션 ID로 세션에 있는 클라이언트 정보를 가져옵니다.
  • 클라이언트 정보를 가지고 서버 요청을 처리하여 클라이언트에게 응답합니다.

 

3. 쿠키와 세션 차이 (간단하게)

  • 쿠키는 로컬, 세션은 서버에 저장한다.
  • 보안은 세션이 더 좋다.
  • 속도는 쿠키가 더 좋다.

 

4. 설치

npm install express-session

 

5. 연습하기

index.js

const express = require('express');
const session = require('express-session');
const port = 8080;
const app = express();

app.set("view engine", "ejs");

app.use("/static", express.static(__dirname+"/static"));
app.use(express.urlencoded({ extended: false }));
app.use(express.json());

// 세션 미들웨어 등록
// 그 외 여러 가지 옵션이 있지만, 자주 사용하는 애들만 사용해봄
app.use(session({
    // 임의의 문자열을 가지고 세션을 암호화를 하겠다.
    secret: '1234',
    // true 일 경우 모든 요청마다 세션에 변화가 없어도 세션을 다시 저장한다.
		// 대부분 false로 사용한다.
    resave: false,
    // 초기화되지 않은 세션을 저장할지 선택한다. / 대부분 true로 사용한다.
    saveUninitialized: true,
    // 이 밑으로는 생략 가능 (안써도 괜찮음)
    // 세션 ID의 쿠키에 대한 옵션 (일반 쿠키랑은 다름)
    // cookie: {
    //     httpOnly: true,
    //     maxAge: 30000
    // },
    // true이면 https(보안서버)에서만 작동한다.
    // secure: 
    
}));

app.get('/', (req, res) => {
    res.send('세션 수업');
});

app.get('/setSession', (req, res) => {
    req.session.user = 'test';
    // req.session.id는 사용금지라고 함

    console.log('세션 : ', req.session.user);
    res.send('세션 생성 성공');
    // 세션은 서버에 저장되지만 req 객체를 타는 이유는 클라이언트마다 세션ID를 가지고 있는데,
    // 서버는 세션ID를 구분해야 하기 때문에 클라이언트가 가지고 있는 고유의 세션ID를 가지고 오기 위해서 req 객체를 사용한다.
});

app.listen(port, () => {
    console.log('server open: ', port);
});

 

실행 결과

 

실행 결과 - 콘솔 창

 

 

실습코드

더보기

 

 

index.js 

const express = require('express');
const session = require('express-session');
const port = 8080;
const app = express();

app.set("view engine", "ejs");

app.use("/static", express.static(__dirname+"/static"));
app.use(express.urlencoded({ extended: false }));
app.use(express.json());

// 세션 미들웨어 등록
app.use(session({
    secret: '1234',
    resave: false,
    saveUninitialized: true,
}));

app.get('/', (req, res) => {
    console.log(req.session.user);
    if(req.session.user) {
        console.log('로그인 한 상태');
        res.render('index', {isLogin: true});
    } else {
        console.log('로그인 하지 않은 상태');
        res.render('index', {isLogin: false});
    }
});

app.get('/login', (req, res) => {
    res.render('login');
});

// 임시 계정
const user = { id: 'test', pw: '1234'};

app.post('/login', (req, res) => {
    if(req.body.id == user.id && req.body.pw == user.pw) {
        console.log('로그인 성공');
        req.session.user = req.body.id;
        res.send(true);
    } else {
        console.log('로그인 실패');
        res.send(false);
    }
});

app.delete('/logout', (req, res) => {
    req.session.destroy((err) => {
        if(err) throw err;

        console.log('로그아웃 성공');
        res.send(true);
    })
});

app.listen(port, () => {
    console.log('server open: ', port);
});

 

/views/index.ejs

<!DOCTYPE html>
<html lang="en, ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Session 실습</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <style>
        a {
            text-decoration: none;
            color: white;
        }
        div {
            height: 700px;
        }
    </style>
    
</head>
<body>
    <div class="row">
        <div class="col-12" style="margin: auto">
            <button id="loginBtn" class="btn btn-primary" style="margin-bottom: 0.5rem;"><a href='/login'>로그인 페이지</a></button>
            <button id="registerBtn" class="btn btn-primary"><a href='#'>회원가입 페이지</a></button>
            <button id="logoutBtn" class="btn btn-primary" onclick="logout()">로그아웃</button>
        </div>
    </div>

    <script>
        const loginBtn = document.getElementById('loginBtn');
        const registerBtn = document.getElementById('registerBtn');
        const logoutBtn = document.getElementById('logoutBtn');
        if('<%= isLogin %>' == 'true') {
            loginBtn.style.display = 'none';
            registerBtn.style.display = 'none';
            logoutBtn.style.display = 'block';
        } else {
            loginBtn.style.display = 'block';
            registerBtn.style.display = 'block';
            logoutBtn.style.display = 'none';
        }

        function logout() {
            axios({
                method: 'delete',
                url: '/logout'
            }).then((response) => {
                document.location.href = '/';
                alert('로그아웃 되었습니다.');
            });
        }
    </script>
</body>
</html>

 

/views/login.ejs

<!DOCTYPE html>
<html lang="en, ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Session 실습</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <style>
        div {
            height: 700px;
        }
    </style>
    <script>
        function login() {
            const form = document.getElementById('loginForm');
            axios({
                method: 'post',
                url: '/login',
                data: {
                    id: form.id.value,
                    pw: form.pw.value
                }
            }).then((response) => {
                if(response.data) {
                    document.location.href = '/';
                    alert(form.id.value + '님 환영합니다.');
                } else {
                    alert('아이디 또는 비밀번호가 틀렸습니다.');
                    document.location.href = '/login';
                }
            });
        }
    </script>
</head>
<body>
    <div class="row">
        <div class="col-12" style="margin: auto">
            <form id="loginForm">
                <fieldset>
                    <legend>로그인</legend>
                    아이디 : <input type="text" name='id' placeholder="아이디를 입력하세요."><br>
                    비밀번호 : <input type="text" name='pw' placeholder="비밀번호 입력하세요."><br>
                    <button id="loginBtn" class="btn btn-primary" onclick="login()">로그인</button>
                </fieldset>
            </form>
        </div>
    </div>
</body>
</html>

 

실행결과 - html

 

실행결과 - 콘솔 창

 

이상으로 Node.js의 세션(session)에 대하여 알아보았습니다.

감사합니다.

 

반응형