본문 바로가기
프로그래밍/nodejs

[220208] 세션의 정의, 세션 구조 구현하기, 세션과 쿠키🍪의 관계

by 한코코 2022. 2. 9.

목차

1.   세션이 생겨난 이유

2.   세션 구현하기

3.   쿠키를 생성해서 서버에 저장하기

 

 


 

세션을 만든 이유 : 보안성을 위해.

이처럼 브라우저에 쿠키가 없으면 웹서버에 요청을 하며, 웹서버는 응답을 하며 🍪쿠키를 준다.

그 이후부터 브라우저는 쿠키를 같이 붙여서 웹서버에 요청을 하고, 웹서버는 쿠키를 붙여서 응답한다.

즉, 웹서버는 기본적으로 항상 쿠키를 받는다.

 

 

다만 문제가 있다면, 브라우저에 저장을 하다보니 다른 사람이 접근하기도 쉬워진다.

pc방을 예로 들어보자. A가 이용을 끝낸 후, B가 브라우저를 열어 쿠키를 확인하면 로그인정보가 고스란히 남아있다. 그걸 보고 게임머니나 각종 개인정보를 털어갈 수 도 있다. 이를 방지하기 위해, 쿠키를 서버에 저장하게 하는것이 세션이다.

 

 


 

구현할 기능 청사진

 

 

청사진대로 만든 코드

코드로 보는 흐름 / 클릭하면 크게 볼 수 있다.

 

더보기를 클릭하면 코드 전체를 볼 수 있다.

더보기

server.js

const express = require('express')
const nunjucks = require('nunjucks')
const {user,findUser} = require('./user')
//1개가 아니라 여러개일수 있으니까 {}넣는 습관잡기
//만든이유:이 데이터 안에 없으면 회원가입을 안했다는 소리
const app=express()

app.use(express.urlencoded({extended:true}))

app.set('view engine','html')
nunjucks.configure('views',{
    express:app,
})

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

app.get('/user/login',(req,res)=>{
    let msg = req.query.msg
    res.render('./user/login',{
        msg:msg
    })
    //이름은 같은 다른 폴더의 파일을 선택하지 않기 위해서 정확한 주소값을 적어주자
    //views폴더 기준으로 생각하기!
})

app.post('/user/login',(req,res)=>{
    //회원인 사람만 로그인을 시켜주자
    let userid = req.body.userid //post : 사용자가 입력한 값
    let userpw = req.body.userpw //post : 사용자가 입력한 값
    let loginFlag = findUser(userid,userpw)
    if(loginFlag){
        //성공적일때 세션을 생성하고 메인으로 돌려줌
        res.redirect('/')
    } else {
        //실패일때 로그인폼으로 msg랑 같이 던져줌
        res.redirect('/user/login?msg=아이다와 패스워드가 일치하지 않습니다')
    }
})

app.listen(3000,()=>{
    console.log('server 3000')
})

 

 

user.js

//회원명단 데이터
let user = [
    {
        userid:'admin',
        userpw:'admin',
        username:'관리자',
    },
    {
        userid:'web7722',
        userpw:'1234',
        username:'곽인구',
    },
    {
        userid:'test',
        userpw:'test',
        username:'테스트용',
    },
]

//server.js에서 작성하다보니 너무 길어져서 여기에 함수로 뺌
function findUser(id,pw){
    //user : 서버 관리자가 가지고 있는 정보 --> user.js
    //1단계(응답으로 쿠키 주기 전 상태) : 폼에서 받은값 == user변수에 있는 내용 -> true?
    // user 배열에 우선 접근
    for(let i=0; i<user.length; i++){
        if(user[i].userid===id && user[i].userpw===pw){
            return true //true값으로 빠져나감
        }
    }
    return false
}

//내보내야할게 여러개가 될 수 있으니까 객체로 만들어놓는 습관 만들어놓으면 좋음.
module.exports={
    user:user,
    findUser:findUser,
}

 

 

index.html

<!DOCTYPE html>
<html lang="en">
<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>Document</title>
</head>
<body>
    <h1>
        <a href="/">Logo</a>
    </h1>
    메인페이지
    <ul>
        <li><a href="/user/login">로그인</a></li>
        <li><a href="/board/list">게시판</a></li>
    </ul>
</body>
</html>

 

 

login.html

<!DOCTYPE html>
<html lang="en">
<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>Document</title>
    {% if msg %}
    <script type="text/javascript">
        alert("{{msg}}")
    </script>
    {% endif %}
</head>
<body>
    <h1>
        <a href="/">Logo</a>
    </h1>
    로그인 페이지
    <form method="post" action="/user/login">
        <input type="text" name="userid">
        <input type="text" name="userpw">
        <input type="submit" value="로그인">
    </form>
</body>
</html>

 


 

간단한 세션 기능 설명

  • 엄청나게 길고 괴상한 key를 만들어서 이름과 일대일로 연결시킨다.
  • key를 쿠키에 저장한다.
  • 정보를 찾으려면 쿠키에 있는 key로 조회해야한다.

 


 

 

세션의 구조를 구현하기

login에서 정보를 받아 사용할거니까, app.post 안에 이어서 작성한다.

정보를 담을 session 객체가 필요하므로 전역변수로 먼저 선언해둔다.

const session = {}

 

 

이름과 일대일 매칭을 시킬 길고 괴상한 key를 Math.random()함수로 작성해주기로 했다.

const privateKey = parseInt(Math.random()*1000000000000)
//정수값을 만들기 위한 곱셈
//나머지 소수값을 버리기 위한 parseInt

 

 

user.js에서 이미 갖고있는 값login form에서 입력받은 값과 같은지 먼저 확인해야한다.

만약 같다면 새로운 변수 useritem을 만들어 그 안에 해당 user.js에서 이미 갖고있는 객체를 저장한다.

let useritem

for(let i=0; i<user.length; i++){
   if(user[i].userid===userid){
       useritem = {...user[i]} //얕은복사
       
       //useritem = user[i] --> 얕은복사
       //뭘 쓰던지 상관은 없음
   }
}

 

 

미리 만들어둔 랜덤함수값 privateKey를 session 안에 넣어서 useritem의 값들과 매칭시켜 저장한다.

session[privateKey] ={
    userid:useritem.userid, //뽑아온 객체의 userid
    username:useritem.userpw
}

 

 

이미 갖고있던 객체값 useritem과 key값과 매칭시켜 저장한 session의 출력값을 보면 차이를 알 수 있다.

console.log('useritem : ',useritem)
console.log('session : ',session)

session에서 key값과 매칭되어 새로운 객체로 저장되어 있는 것을 확인할 수 있다.

 

 

전체코드는 더보기를 누르면 볼 수 있다.

더보기

server.js 에서 app.post 내용만 업데이트 됨

app.post('/user/login',(req,res)=>{
    let userid = req.body.userid //post : 사용자가 입력한 값
    let userpw = req.body.userpw //post : 사용자가 입력한 값
    let loginFlag = findUser(userid,userpw)
    
    
    if(loginFlag){
        //성공적일때 세션을 생성하고 메인으로 돌려줌
        const privateKey = parseInt(Math.random()*1000000000000)

       let useritem
        /*
        session객체 안에서 key값에 대한 속성값 만들기
        그 안에 객체 만들것
        */
       for(let i=0; i<user.length; i++){
           //이미 갖고있는 값 === 입력받은값
           if(user[i].userid===userid){
               //useritem = user[i] 얕은복사
               useritem = {...user[i]} //깊은복사 - 상관은 없음
           }
       }
       console.log('useritem : ',useritem)
        //const item = user.filter(v=>v.userid===userid) //일치하는 객체 뽑아오기
        session[privateKey] ={ //뽑아온 값을 key와 매칭시켜서 저장함
            userid:useritem.userid,
            username:useritem.userpw
        }
        console.log('session : ',session)

        //key값에 무작위의 랜덤정수값 넣기
        res.setHeader('Set-Cookie',`connect.id=${privateKey}`)
        res.redirect('/')
    } else {
        //실패일때 로그인폼으로 msg랑 같이 던져줌
        res.redirect('/user/login?msg=아이디와 패스워드가 일치하지 않습니다')
    }
})

 


 

 

쿠키를 생성해서 저장하기

세션을 구현했으니 쿠키를 생성해서 브라우저 헤더에 저장해줘야한다.

key값 변수는 connet.id로 다들 자주 쓴다고하니 기억해두자.

res.setHeader('Set-Cookie',`connect.id=${privateKey}`)
res.redirect('/')

쿠키가 잘 생성되어있는걸 확인할 수 있다.

댓글