Express에서 Session 기반 인증 구현 - LM-channel-team-project/wooggooms GitHub Wiki

세션이란?

세션은 HTTP에서 클라이언트와 서버 사이의 연결을 확인하기 위한 정보입니다. 클라이언트가 웹 서버에 요청을 보내면 클라이언트에 세션 ID가 할당되어 쿠키로 저장됩니다. 그리고 클라이언트가 세션 ID를 가지고 데이터를 다시 요청하면 서버는 해당 ID에 대응되는 클라이언트 정보로 응답합니다.

인증 절차

인증 방식에 대해 쿠키와 세션밖에 모르던 당시, 로그인한 사용자에 대한 인증을 유지하기 위해 세션을 사용했습니다. 그리고 보안을 위해선 세션을 직접 구현하는 것보다 라이브러리를 사용하고 업데이트를 하는 것이 좋다는 조언에 따라 express-session 미들웨어를 활용했습니다.

image

클라이언트가 처음 HTTP 요청을 하면 그 요청에는 세션 쿠키가 포함되어 있지 않습니다. 따라서 세션 미들웨어는 세션 ID를 할당하고 세션 객체에는 빈 객체가 저장됩니다. 이 때 saveUninitialized 옵션이 false라면 세션 객체가 저장소에 저장되지 않습니다.

클라이언트가 세션 ID를 가진 상태에서 다시 HTTP 요청을 하면 세션 쿠키를 통해 서버로 ID를 전달합니다. 세션 미들웨어는 세션 스토어에서 ID에 대응되는 데이터를 읽고, 그것을 세션 객체에 저장합니다.

미들웨어 옵션

app.use(
  session({
    secret: process.env.SESSION_SECRET,
    store: dbConfig.db,
    resave: false,
    saveUninitialized: false,
  })
);

secret

  • 세션 ID를 발급할 때 사용되는 키입니다.
  • 추측될 수 없는 값이 사용되어야 하고, 주기적인 업데이트가 필요합니다.
  • config.json 파일을 사용할 경우 매번 require가 필요하기 때문에 dotenv로 환경 변수를 설정했습니다.

store

  • 세션을 저장할 때 사용되는 저장소를 결정합니다.
  • 기본값은 메모리이며, MySQL 데이터베이스를 사용했습니다.

resave

  • 모든 요청이 있는 동안에 세션의 수정 여부와 관계없이 저장소에 다시 저장할지를 결정합니다.
  • 세션 쿠키에 만료 날짜가 포함되지 않고, 요청마다 active 상태로 만들 필요가 없기 때문에 false를 적용했습니다.

saveUninitialized

  • 첫 HTTP 요청에서 세션이 Uninitialized 상태일 때 빈 객체를 저장소에 적용할지를 결정합니다.
  • 재방문한 사용자를 식별할 이유가 없으므로 false를 적용했습니다.

보완점

세션에는 다음과 같은 한계점이 있습니다.

  • 서버 메모리에 저장한다면 사용자의 수만큼 메모리를 차지하고, 데이터베이스에 저장한다면 과부하를 줄 수 있습니다.
  • 사용자가 늘어났을 때 더 많은 트래픽을 처리하기 위해 세션을 분산시키는 시스템을 설계하는 과정이 복잡하고 어렵습니다.
  • 세션 하이재킹과 같은 보안 취약점이 있습니다. (express-session에서는 secret으로 HMAC을 활용해 방지합니다.)

세션 기반 인증을 구현해본 경험을 바탕으로, 앞으로는 토큰 기반의 인증방식인 JWT를 배워보고 적용해볼 계획입니다.