본문 바로가기
경일/nodejs

[nodejs] 세션 이용해서 로그인기능 만들기

by dev_kong 2022. 2. 8.
728x90
728x90

0. 목차

1. 개요

2. 세션

3. 세션으로 로그인기능 구현

1. 개요

오늘은 세션으로 로그인 기능을 구현하는걸 해보기로 함.

그럼 우선 세션이 뭔지

세션과 쿠키의 차이점은 뭔지 

아는게 우선이다.

2. 세션

우선 쿠키는

https://kong-dev.tistory.com/129

 

[nodejs] 쿠키 먹는거 말고

0.목차 1. http 통신 2. 브라우저 3. 쿠키 1. http 통신 서버에 요청을 보낼때는 일정한 규격에 따라 요청을 해야한다. 그런데 이 규격만 맞춰 준다면 새로운 내용을 작성해서 보내줄 수도 있다. 이제

kong-dev.tistory.com

이런거다.

ㅎ.

 

쿠키방식의 가장 큰 특징으로는

데이터가 브라우저에 저장된다는 점이다.

 

반면 세션은 

쿠키를 전달하긴 하지만,

그 쿠키를 암호화 해서 열쇠처럼 사용한다.

그리고 데이터 자체는 서버에 저장하는데,

이 데이터는 쿠키에 저장된 암호화된 열쇠가 있어야만 사용가능하다.

 

그렇기때문에,

세션의 경우는 데이터가 많으면 많을 수록,

서버에 부하가 걸리기 쉽다.

 

그럼에도 세션 방식을 사용하는 이유는

보안성에 있다.

 

브라우저에 저장된 정보는 쉽게 확인과 조작이 가능하지만,

서버에 저장된 정보는 확인과 조작이 어렵기 때문에 보안적으로 조금. 조금더 안전하다. 

3. 세션으로 로그인 기능 구현

그럼 이제 세션으로 로그인 기능을 구현 해보자.

 

3-1. 셋팅

우선 셋팅부터

const express = require('express');
const nunjucks = require('nunjucks');

const app = express();

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

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

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

app.listen(3000);

뚝-딱

 

3-1. 임시데이터 생성

어제는 server.js 파일에 임시데이터를 생성했었지만,

오늘은 model 이란 폴더를 따로 만들고

그안에서 user.js 라는 파일을 따로 생성한뒤

module.exports 를 통해 export 해준뒤

server.js 에서 require 로 데이터를 가져오는 방식으로 해보려고 한다.

 

let userList = [
  {
    id: 'peanut1234',
    pw: '567890',
    name: 'peanut',
  },
  {
    id: 'kong1234',
    pw: '123456',
    name: 'kong',
  },
  {
    id: 'pea1234',
    pw: '654321',
    name: 'pea',
  },
];

module.exports = { userList };

임시데이터

 

const { userList } = require('./model/user.js');

server.js 에 모듈 추가

 

3-2. 기능개발

메인 페이지 구성

로그인 페이지 구성

 

이제 로그인 페이지에 id 와 pw 를 입력하고

로그인 버튼을 눌러서 submit 을 때려서 /user/login 에 post 요청을 날리면,

server에서는

입력된 id 와 pw 가 가지고 있는 유저정보와 일치하는지 확인한 후

일치하면 로그인을 시켜주고,

일치하지 않으면, 등록되지 않은 사용자라는 알림을 띄어준 후,

다시 /user/login 페이지로 되돌려 보내주면 된다.

 

app.post('/user/login', (req, res) => {
  const { userid, userpw } = req.body;

  const [user] = userList.filter((v) => v.id === userid && v.pw === userpw);
  if (user) {
  } else {
  }
});

우선 여기 까지만 짰다.

input 에 입력된 값이 req.body 에 저장 됐고,

그중 userid 와 userpw 를 변수에 담았다.

 

그리고 filter method를 이용해서 입력된 값과 데이터에 저장 되어있는 값을 비교해서 일치하는 객체를 user라는 변수에 담았다.

만약 일치하는 값이 없다면, 

user는 undefined 가 돼서, falsy 값이 될 것이므로,

else 문이 실행될 것이고,

일치하는 값이 있다면, user는 truthy 값이 되므로 

if 문이 실행될 것이다.

 

우선 일치하지 않을 경우만 먼저 만들어보자.

나는 일치하지 않는 경우에는 알림창을 띄우고 login 페이지로 돌아가게 하고 싶다고 했다.

 

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

app.post('/user/login', (req, res) => {
  const { userid, userpw } = req.body;

  const [user] = userList.filter((v) => v.id === userid && v.pw === userpw);
  if (user) {
    res.send('login ^^');
  } else {
    res.redirect('/user/login?msg=등록되지 않은 사용자 입니다');
  }
});

 

/user/login 의 get 부분까지 수정했다.

 

이제 일치하는 경우를 만들어주자.

쿠키를 만들어주는데,

쿠키의 value를 랜덤한 숫자로 만들어줄거다.

그리고 세션이란 객체를 만들어서 랜덤한 숫자를 key로 

로그인된 사용자의 정보를 value 로 담아줄거다.

 

우선 사용자의 정보를 담을 session 이란 객체를

전역에다 만들어 준 뒤에

 

const session = {}; //server.js 전역변수 선언

 

app.post('/user/login', (req, res) => {
  const { userid, userpw } = req.body;

  const [user] = userList.filter((v) => v.id === userid && v.pw === userpw);
  if (user) {
    const privateKey = Math.floor(Math.random() * 1000000000);
    session[privateKey] = user;
    console.log(session);
    res.send('login^^');
  } else {
    res.redirect('/user/login?msg=등록되지 않은 사용자 입니다');
  }
});

 

이렇게 해주었다.

유저정보와 일치하는 id 와 pw 를 입력한뒤,

로그인을 하면

 

console.log 로 출력한 세션과

res.send 로 전달해준 값이 모두 잘 동작한다.

 

반면 일치하지 않는 데이터가 전달되면,

alert 창이 뜨고,

/user/login 페이지로 돌아간다.

 

그리고 중요한 한가지 작업을 안해줬는데,

바로 만들어진 privateKey 를 브라우저에 쿠키로 만들어 줘야 한다.

 

app.post('/user/login', (req, res) => {
  const { userid, userpw } = req.body;

  const [user] = userList.filter((v) => v.id === userid && v.pw === userpw);
  if (user) {
    const privateKey = Math.floor(Math.random() * 1000000000);
    session[privateKey] = user;
    console.log(session);
    res.setHeader('Set-Cookie', `connect.id=${privateKey}; path=/`);
    res.redirect('/');
  } else {
    res.redirect('/user/login?msg=등록되지 않은 사용자 입니다');
  }
});

여기서 매우 중요한 것은 path 다.

cookie 는 현재 경로(/user/login)의 이전경로(/user) 부터 적용이된다.

나는 / 부터 적용되길 원하기 때문에

path를 직접 입력해줘야한다.

 

맞는 정보를 입력하고 로그인을 시도하면

메인페이지로 이동을 하고,

쿠키역시 잘 생성된 것을 볼 수 있다.

 

이제 로그인이 됐을때 화면구성이 바뀌도록 만들어주자.

쿠키가 있는지 없는지 검사해 주고.

 

있으면 쿠키의 value를 변수에 저장해서

session 에서 저장한 변수로 접근해서,

그 밸류값을 변수에 담아서 nunjuck로 전달해주면 된다.

 

app.get('/', (req, res) => {
  if (req.headers.cookie) {
    const [, privateKey] = req.headers.cookie.split('=');
    const userInfo = session[privateKey];
    res.render('index.html', {
      isLogin: true,
      userInfo,
    });
  } else {
    res.render('index.html', { isLogin: false });
  }
});

 

프로필 까지만 할거임.

 

위 화면에서 

profile을 누르면,

사용자의 정보가 나오고

 

만약 로그인 하지 않은 상태에서 /user/profile 로 접속한다면,

알림을 띄운 뒤에 

/user/login 으로 돌려보낼꺼다.

 

app.get('/user/profile', (req, res) => {
  if (req.headers.cookie) {
    const [, privateKey] = req.headers.cookie.split('=');
    const userInfo = session[privateKey];
    res.render('./user/profile.html', {
      userInfo,
    });
  } else {
    res.redirect('/user/login?msg=로그인부터 하세요');
  }
});

 

이렇게

 

그리고 로그인 안한상태에서 접속을 하면,

이렇게 건방진 메세지를 띄어주고

/user/login 으로 간다.

 

그리고 로그인이 된 상태에서 

접속하면

 

이렇게 이쁘게 보여준다.

 

logout 기능은 좀더 고민을 해봐야 될 것 같다.

처음엔 단순하게 

쿠키 삭제하고

세션 초기화 해주면 되는거 아닌가 했는데,

세션을 초기화 해주면 로그인 돼있던 모든 사용자가 로그아웃 되버릴꺼다.

마찬가지로 privateKey 를 통해

세션에서 해당하는 데이터를 찾아내서

그 데이터만 지워주는 방식으로 해야할것 같은데

그부분이 좀 흠. 애매하다.

좀더 고민을 해봐야할 듯 싶다.

 

생각해보니까

delete 이용해서 session 에서 privateKey 로 접근해서 해당 프로퍼티 지워주고,

쿠키까지 지워주면 된다.

쉽잖어..?

 

app.get('/user/logout', (req, res) => {
  if (req.headers.cookie) {
    if (req.headers.cookie) {
      const [, privateKey] = req.headers.cookie.split('=');
      delete session[privateKey];
      res.setHeader('Set-Cookie', 'connect.id=delete; Max-age=0; path=/');
      res.redirect('/');
    } else {
      res.redirect('/user/login?msg=로그인부터 하라니까요?!');
    }
  }
});

 

이렇게 해주면 로그아웃 까지 끝!

728x90
728x90

댓글