프로그래밍 언어/NODE JS

connect-redis

· 코딩마이데이

멀티 프로세스 간 세션 공유를 위해 레디스와 익스프레스를 연결해주는 패키지입니다. 기존에는 로그인할 때 express-session의 세션 아이디와 실제 사용자 정보가 메모리에 저장됩니다.

따라서 서버가 종료되어 메모리가 날아가면 접속자들의 로그인이 모두 풀려버립니다. Warning: connect.session() MemoyStore is not designed for a production environment, as a will leak memory, and will not scale past a single process라는 경고 메시지도 발생합니다.

이를 해결하기 위해 세션 아이디와 실제 사용자 정보를 데이터베이스에 저장합니다. 이때 사용하는 데이터베이스가 레디스입니다. 다른 데이터베이스를 사용해도 되지만 주로 레디스를 많이 사용합니다. 메모리 기반의 데이터베이스라서 성능이 우수하기 때문입니다.

$ npm i redis connect-redis

 

레디스를 사용하려면 connect-redis 패키지뿐만 아니라 레디스 데이터베이스를 설치해야 합니다. 서버에 직접 설치할 수도 있지만 레디스를 호스팅해주는 서비스를 쓰는 것이 편리합니다. 바로 redislabs입니다.

 

redistants 웹 사이트(https://redis.io/)에 접속합니다.

 

상단 메뉴에서 LOGIN을 누릅니다.

 

회원가입이 되어 있지 않으므로 이메일을 입력하고 Get Started Free를 누릅니다.

 

가입 후 클라우드와 지역(region)을 선택합니다. 일부 지역만 무료 옵션을 제공하므로 무료  옵션을 제공하는 지역을 골라야 합니다.

 

원하는 데이터베이스 이름을 입력하고 Activate 버튼을 누릅니다.

 

레디스 호스팅이 생성되었습니다.

 

이제 Endpoint와 Redis Password를 복사해 .env에 붙여 넣습니다. 이제 EndPoint에서 Host와 Port를 분리합니다.  설정 값은 여러분의 설정값을 넣으시면 됩니다.

COOKIE_SECRET=nodebirdsecret
KAKAO_ID=5d4daf57becfd72fd9c919882552c4a6
SEQUELIZE_PASSWORD=[비밀번호]
REDIS_POST=redis-11707.c340.ap-northeast-2-1.ec2.cloud.redislabs.com:11707
REDIS_PORT=18954
REDIS_RASSWORD=R47bhFIgp3gPJCPirkCPK1Buvr32o7RW

 

app.js

const express = require("express");
const cookieParser = require("cookie-parser");
const morgan = require("morgan");
const path = require("path");
const session = require("express-session");
const nunjucks = require("nunjucks");
const dotenv = require("dotenv");
const passport = require("passport");
const helmet = require("helmet");
const hpp = require("hpp");
const redis = require("redis");
const RedixStore = require("connect-redis")(session);

dotenv.config();
const redisClient = redis.createClient({
  url: `redis://${process.env.REDIS_HOST}:${process.env.REDIS_PORT}`,
  password: process.env.REDIS_PASSWORD,
});

const pageRouter = require("./routes/page");
const authRouter = require("./routes/auth");
const postRouter = require("./routes/post");
const userRouter = require("./routes/user");
const { sequelize } = require("./models");
const passportConfig = require("./passport");
const logger = require("./logger");

const app = express();
passportConfig(); // 패스포트 설정
app.set("port", process.env.PORT || 8001);
app.set("view engine", "html");
nunjucks.configure("views", {
  express: app,
  watch: true,
});

sequelize
  .sync({ force: false })
  .then(() => {
    console.log("데이터베이스 연결 성공");
  })
  .catch((err) => {
    console.error(err);
  });

if (process.env.NODE_ENV === "production") {
  app.use(morgan("combined"));
  app.use(helmet({ contentSecurityPolicy: false }));
  app.use(hpp());
} else {
  app.use(morgan("dev"));
}
app.use(express.static(path.join(__dirname, "public")));

app.use(morgan("dev"));
app.use(express.static(path.join(__dirname, "public")));
app.use("/img", express.static(path.join(__dirname, "uploads")));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser(process.env.COOKIE_SECRET));
const sessionOption = {
  resave: false,
  saveUninitialized: false,
  secret: process.env.COOKIE_SECRET,
  cookie: {
    httpOnly: true,
    secure: false,
  },
  store: new RedixStore({ client: redisClient }),
};
if (process.env.NODE_ENV === "production") {
  sessionOption.proxy = true;
}
app.use(session(sessionOption));
app.use(passport.initialize());
app.use(passport.session());

app.use("/", pageRouter);
app.use("/auth", authRouter);
app.use("/post", postRouter);
app.use("/user", userRouter);

app.use((req, res, next) => {
  const error = new Error(`${req.method} ${req.url} 라우터가 없습니다.`);
  error.status = 404;
  logger.info("hello");
  logger.error(error.message);
  next(error);
});

app.use((err, req, res, next) => {
  console.error(err);
  res.locals.message = err.message;
  res.locals.error = process.env.NODE_ENV !== "production" ? err : {};
  res.status(err.status || 500);
  res.render("error");
});

module.exports = app;

 

connect-redis 패키지로부터 RedisStore 객체를 require합니다. 이때 session을 인수로 넣어서 호출하는 것을 잊지 마세요. connect-redis는 express-session에 의존성이 있습니다.

redis 패키지의 createClient 메서드로 redisClient 객체를 생성합니다. 이때 url과 password 속성에 접속 정보를 입력합니다. 여기서는 dotenv.config()보다 코드가 아래에 있어야 한다는 점에 주의합니다. .env 파일에 적힌 process.env 객체의 값들은 dotenv.config() 이후에 생성됩니다.

express-session 미들웨어에는 store 옵션을 추가합니다. 기본적으로는 메모리에 세션을 저장하지만, 이제는 RedisStore에 저장합니다. RedisStore의 옵션으로 client 속성에 redisClient 객체를 연결하면 됩니다.

이제 세션 정보가 메모리 대신 레디스에 저장됩니다. 따라서 로그인 후 서버를 껐다 켜도 로그인이 유지됩니다. 실제 서비스에서 서버 업데이트 시 로그인이 풀리는 형상을 막을 수 있습니다.

'프로그래밍 언어 > NODE JS' 카테고리의 다른 글

nvm, n  (0) 2026.05.04
helmet, hpp  (0) 2026.04.26
winston  (0) 2026.04.23
pm(2)  (0) 2026.04.20
pm2(1)  (0) 2026.04.17