무지개곰
article thumbnail

Express Session은 클라이언트와 서버 간의 세션 관리를 지원하는 미들웨어입니다. 세션은 클라이언트가 웹 서버에 접속한 후 해당 클라이언트의 상태 정보를 서버가 유지하는 것을 말합니다. 이를 통해, 로그인 상태 등의 사용자 정보를 유지하

고, 개인화된 서비스를 제공할 수 있습니다.

session에 대한 설명


Session

Session 기본 설정

  1. express-session 패키지 설치
npm i express-session

Express 애플리케이션에 express-session 미들웨어를 추가합니다.

const session = require("express-session");

app.use(
  session({
    secret: "rainbowbear",
    resave: false,
    saveUninitialized: true,
    store: new MemoryStore({
      checkPeriod: 24 * 60 * 60 * 1000, // 1 day
    }),
  })
);

express-session 미들웨어를 사용하기 위해서는 설정 옵션을 지정해야 합니다.

  • secret : 세션을 암호화하기 위한 비밀 키입니다. 반드시 지정해야 합니다.
  • resave : 세션 데이터가 변경되지 않았더라도 서버에 다시 저장할지 여부를 결정합니다.
  • saveUninitialized : 초기화되지 않은 세션 데이터를 저장할지 여부를 결정합니다.
  • store : session을 저장할 장소를 결정합니다. (MemoryStore에 저장하는 경우 서버를 끄거나 브라우저를 닫으면 저장되어 있던 session이 날아갑니다.)

session-file-store

const FileStore = require('session-file-store')(session);

const fileStoreOptions = {
  path: '/path/to/sessions',
};

app.use(session({
  secret: 'my-secret',
  resave: false,
  saveUninitialized: true,
  store: new FileStore(fileStoreOptions),
}));

express-mysql-session

const MySQLStore = require('express-mysql-session')(session);

const options = {
    host: 'localhost',
    port: 3306,
    user: 'session_user',
    password: 'session_password',
    database: 'session_database'
};

app.use(session({
    secret: 'my-secret',
    resave: false,
    saveUninitialized: true,
    store: new MySQLStore(options),
}));

MySQLStore에서 사용할 수 있는 options 요소는 다음과 같습니다.

 

host: MySQL 데이터베이스 서버의 호스트 이름입니다.

port: MySQL 데이터베이스 서버의 포트 번호입니다.

user: MySQL 데이터베이스에 접근하는 데 사용할 사용자 이름입니다.

password: MySQL 데이터베이스에 접근하는 데 사용할 암호입니다.

database: MySQL 데이터베이스의 이름입니다.

schema: MySQL 데이터베이스 스키마의 이름입니다.
tablename: 세션 데이터를 저장할 MySQL 테이블의 이름입니다.
createDatabaseTable: 테이블이 존재하지 않을 경우 자동으로 테이블을 생성할지 여부를 결정합니다. true로 설정하면 테이블이 자동으로 생성됩니다.
clearExpired: 만료된 세션 데이터를 자동으로 정리할지 여부를 결정합니다. true로 설정하면 만료된 세션 데이터가 자동으로 정리됩니다.

charset: MySQL 데이터베이스에서 사용할 문자 집합을 지정합니다.

connectionLimit: MySQL 데이터베이스와의 최대 동시 연결 수를 지정합니다.

checkExpirationInterval: 만료된 세션 데이터를 정리할 주기를 지정합니다.

expiration: 세션의 만료 시간을 지정합니다.

memorystore

const MemoryStore = require('memorystore')(session)

app.use(session({
  secret: 'my-secret-key',
  resave: false,
  saveUninitialized: true,
  store: new MemoryStore({
    checkPeriod: 86400000 // 1 day
  })
}))

Session 사용

express-session 미들웨어를 사용하면 세션 데이터는 req.session 객체를 통해 접근할 수 있습니다.

app.get("/numberUp", (req, res) => {
  if (req.session.number == undefined) {
    req.session.number = 1;
  } else {
    req.session.number++;
  }
  console.log(req.session.number);
  res.send({ data: req.session.number });
});

위와 같이 req.session 객체를 사용하여 req.session.number가 없다면 1로 지정하고 있다면 증가시킬 수 있습니다.

app.get("/delete", (req, res) => {
  req.session.destroy();
  console.log(req.session.number);
  res.send({ data: "삭제 완료" });
});

req.session.destory 함수는 저장된 세션을 삭제합니다.


Express에서 쿠키(Cookie)는 클라이언트 측에서 생성된 정보를 저장하는 작은 데이터 조각입니다. 클라이언트 측에서 쿠키를 생성하면, 해당 쿠키는 HTTP 요청 헤더에 포함되어 서버로 전송됩니다. 

cookie에 대한 설명

Cookie

Cookie 기본 설정

  1. cookie-parser 패키지 설치
npm i cookie-parser​

Express 애플리케이션에 cookie-parser 미들웨어를 추가합니다. cookieParser의 매개변수로 함호화하는데 쓰일 값을 줍니다.

const cookieParser = require("cookie-parser");

app.use(cookieParser("rainbowbear"));

쿠키를 생성하려면 res.cookie() 함수를 사용합니다. 다음은 res.cookie() 함수의 사용 예시입니다.

app.get("/", (req, res) => {
  res.cookie("username", "rainbowbear", {
    maxAge: 1000 * 60 * 60 * 24, // 쿠키의 유효 기간
    httpOnly: true, // 클라이언트에서 쿠키에 접근할 수 없도록 설정
    signed: true, // 쿠키를 서명하여 변조를 방지
  });
  res.send("Cookie set");
});

위 코드는 이름이 "username"이고 값이 "rainbowbear"인 쿠키를 생성합니다. 3번째 매개변수는 cookie에 대한 설정을 합니다. signed 옵션을 사용하여 서명된 쿠키를 생성할 수 있는데 서명된 쿠키는 클라이언트에서 쿠키의 값을 변경하면 서명이 검증되지 않아 쿠키카 무효화됩니다. signed 옵션을 사용하지 않으면 서명되지 않은 쿠키가 생성됩니다.

서명된 쿠키 사용하기

app.get('/autoLogin', function (req, res) {
    const loginState = req.signedCookies.loginState;
    res.send(`자동 로그인`);
});

req.signedCookies를 이용하여 서명된 쿠키를 이용할 수 있습니다.


Cookie 사용

클라이언트 측에서 생성된 쿠키는 req.cookies 객체를 통해 접근할 수 있습니다. 

app.get("/", (req, res) => {
  const username = req.cookies.username;
  if (username) {
    res.send("Welcome, " + username);
  } else {
    res.send("Who are you?");
  }
});

위 코드는 "username" 쿠키의 값을 읽어와 사용자 이름을 출력합니다.

Express의 쿠키는 다양한 옵션을 제공하며, 쿠키를 사용하여 세션 관리 등의 다양한 기능을 구현할 수 있습니다. 하지만, 보안에 관련된 취약점이 있을 수 있으므로, 중요한 정보는 서버 측에서 처리하는 것이 안전합니다.


Cookie와 Session의 차이

Cookie와 Session은 모두 웹 애플리케이션에서 클라이언트와 서버 간 상태를 유지하기 위한 기술입니다. 그러나 둘의 차이점이 존재합니다.

Cookie는 클라이언트(브라우저)에 저장되는 작은 데이터 파일입니다. 서버는 Set-Cookie 헤더를 사용하여 클라이언트에게 쿠키를 전송할 수 있습니다. 클라이언트는 쿠키를 저장하고 이후에 같은 서버에 요청할 때마다 쿠키를 함께 전송합니다. 쿠키는 클라이언트 측에서 관리되기 때문에 서버에서 언제든지 수정될 수 있습니다.

Session은 클라이언트와 서버 간의 상태를 유지하기 위한 데이터 저장 방식입니다. 서버 측에서 생성되며, 고유한 세션 ID를 클라이언트에게 제공합니다. 클라이언트는 이 세션 ID를 쿠키나 URL 매개변수 등을 통해 서버에 전송합니다. 서버는 세션 ID를 사용하여 클라이언트에 대한 정보를 저장하고 유지합니다. 세션은 서버 측에서 관리되기 때문에 클라이언트에서 조작할 수 없습니다.

따라서, Cookie는 클라이언트 측에서 관리되고 수정이 가능하지만, Session은 서버 측에서 관리되고 클라이언트에서 조작이 불가능합니다. 이러한 특징으로 인해 Session은 보안성이 높아 비밀번호나 개인정보 등 민감한 데이터를 저장하는 용도로 적합합니다. 반면에 Cookie는 로그인 정보나 사용자 설정 등을 저장하는 용도로 적합합니다.

session과 cookie 차이


cookie를 이용한 session 사용

session은 브라우저를 끄게 되면 초기화됩니다. 브라우저를 끄더라도 mysql 혹은 file로 저장해 둔 session을 불러와서 사용하고 싶은 경우 session의 ID를 cookie의 값으로 전달합니다. 클라이언트는 cookie에 저장된 session의 ID를 서버에 전달하고 서버는 session의 ID를 통하여 session의 정보를 불러옵니다.

app.get('/', function (req, res) {
    req.sessionStore.get('sessionID', function (err, session) {
        if (err) {
            console.error(err);
        } else {
            session.loginState = '로그인 중';
            req.sessionStore.set('sessionID', session, function (err) {
                if (err) {
                    console.error(err);
                } else {
                    res.send(`자동 로그인`);
                }
            });
        }
    });
});

req.sessionStore.get 메서드를 이용하여 session의 정보를 얻어올 수 있습니다. 1번째 변수는 쿠키의 값으로 저장한 session의 ID를 넣어줍니다. 2번째 매개변수는 콜백함수를 넣어줍니다. 값을 바꾼 이후 저장하는 방법은 req.sessionStore.set 메서드를 이용하여 저장합니다.


전체 코드

const express = require("express");
const session = require("express-session");
const MemoryStore = require("memorystore")(session);
const cookieParser = require("cookie-parser");

const app = express();

app.set("port", process.env.PORT || 8080);
app.use("/", express.static(path.join(__dirname, "build")));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(
  session({
    secret: "rainbowbear",
    resave: false,
    saveUninitialized: true,
    store: new MemoryStore({
      checkPeriod: 24 * 60 * 60 * 1000, // 1 day
    }),
  })
);
app.use(cookieParser("rainbowbear"));
app.use((req, res, next) => {
  if (process.env.NODE_ENV == "production") {
    morgan("combined")(req, res, next);
  } else {
    morgan("dev")(req, res, next);
  }
});

// session 사용
app.get("/number", (req, res) => {
  if (req.session.number == undefined) {
    req.session.number = 1;
  } else {
    req.session.number++;
  }
  console.log(req.session.number);
  res.send({ data: req.session.number });
});
app.get("/delete", (req, res) => {
  req.session.destroy();
  res.send({ data: "삭제 완료" });
});

// cookie 사용
app.get("/setCookie", (req, res) => {
  res.cookie("username", "rainbowbear");
  res.send("Cookie set");
});
app.get("/checkCookie", (req, res) => {
  const username = req.cookies.username;
  if (username) {
    res.send("Welcome, " + username);
  } else {
    res.send("Who are you?");
  }
});

app.listen(app.get("port"), () => {
  console.log("서버 열음");
});
profile

무지개곰

@무지개곰

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!