1. Express-session
✔︎ 세션 관리용 미들웨어 패키지
✔︎ 설치
npm install express-session
✔︎ Documents
https://www.npmjs.com/package/express-session
2. Express-session 동작
✔︎ 세션 데이터는 쿠키 자체에 저장되지 않고 쿠키에는 세션 ID만 저장한다. 세션 데이터는 서버 측에 저장된다.
✔︎ 세션 객체를 생성하고 클라이언트와의 상호작용을 위한 준비 단계인 초기화(Initialization)를 수행.
✔︎ 세션 데이터를 Store(세션저장소)에 저장한다. 지원하는 Store는 다양하며 redis, mongodb 등이 있다.
✔︎ 미들웨어로 동작하며 request 에 세션 데이터를 로드하며, response에 세션ID를 추가한다.
✔︎ 세션 미들웨어가 요청을 처리하는 순서는 다음과 같다.
초기화가 발생하고 세션 스토어에 저장된 후, req.session 객체가 로드되어 현재 요청의 세션 데이터에 접근할 수 있게 됩니다. 이런 방식으로 세션은 클라이언트와 서버 간에 유지되며, 세션 스토어는 그 데이터를 영구적으로 저장
﹅ 세션 초기화 (Initialization):
세션 초기화는 최초 요청 또는 세션 쿠키의 유효하지 않은 경우에 새로운 세션을 시작하고 초기 데이터를 생성, 클라이언트에게 세션ID를 부여하는 것을 의미합니다. 아래 초기화 과정을 보면 알겠지만 결국 서버<->클라 간의 SID 검증이 끝나야 세션이 초기화 됐다고 할 수 있다.
세션 초기화 과정:
➤클라이언트 요청: 사용자가 웹 애플리케이션에 접속하면 먼저 클라이언트는 서버에 요청을 보냅니다.
➤SID 생성: 서버는 이 요청을 받으면 새로운 세션을 시작하고 고유한 세션 식별자(SID)를 생성합니다. SID는 클라이언트를 고유하게 식별하는 역할을 합니다.
➤SID 전달: 서버는 생성된 SID를 클라이언트에게 반환하고, 주로 세션 쿠키의 형태로 클라이언트에게 전달합니다. 이 세션 쿠키는 클라이언트의 브라우저에 저장됩니다.
➤클라이언트 저장: 클라이언트는 받은 SID를 저장하고 보관합니다. 이것은 주로 브라우저 쿠키로 저장됩니다.
➤후속 요청: 이후 클라이언트가 서버에 추가적인 요청을 보낼 때, 클라이언트는 저장된 SID를 함께 보냅니다.
➤SID 확인: 서버는 클라이언트가 보낸 SID를 확인하고, 이 SID를 사용하여 세션을 식별합니다.
➤세션 활성화: SID가 확인되고 일치하면 해당 세션이 활성화되며, 서버에서는 세션 데이터를 사용하고 관리할 수 있습니다. 이것을 세션 초기화라고 합니다.(세션의 초기화 여부를 나타내는 내부적인 속성인 initialized가 true로 설정된다.)
﹅ 스토어에 저장 (Store):
초기화된 세션 데이터는 서버 측에서 사용하거나 클라이언트의 요청과 응답 간에 데이터를 저장하기 위해 세션 스토어(예: 메모리 스토어, 데이터베이스)에 저장됩니다.
세션 스토어에 저장된 세션 데이터는 일반적으로 세션의 지속성을 제공하며, 세션 유지를 위한 중요한 역할을 합니다.
﹅ req.session에 로드 :
클라이언트의 요청 처리 중, express-session 미들웨어는 세션 데이터를 세션 스토어에서 로드하여 req.session 객체에 채웁니다.
이로 인해 개발자는 req.session을 통해 현재 요청과 관련된 세션 데이터를 읽고 쓸 수 있게 됩니다.
3. Express-session 옵션
// express-session 미들웨어
app.use(
session({
secret: SESSION_KEY,
// store: MemoryStore, // default
resave: true, // default
saveUninitialized: false, // default 는 true
cookie: {
path: '/', // default
httpOnly: true, // default
secure: false, // default
maxAge: null, // default
},
name: 'connect.sid', // default
})
);
✔︎ store: 세션 데이터를 저장하는 저장소
➤ 기본값인 MemoryStore는 현재 어플리케이션이 이 돌아가는 서버의 메모리 자체를 저장소로 사용한다는 의미 (예를들면 변수가 저장되는 메모리)
➤ 기본값인 MemoryStore를 사용하면 분산된 시스템에서 데이터를 공유할 수 없다.
➤ 세션 저장소로 Redis나 MongoDB를 사용하도록 설정할 수 있다.
✔︎ resave: 모든 요청에 대해 (세션데이터 변경이 없어도) 세션 데이터를 스토어에 다시 저장(갱신)할지 설정하는 옵션
➤ true: 매번 스토어에 데이터를 저장한다. 쿠키에 maxAge를 30분으로 설정해놨을때 모든 요청에대해 세션쿠키의 만료시간이 갱신되어 스토어에 저장되는걸 볼 수 있다.
➤ false: 세션 데이터의 변경이 이루어졌을때만 스토어에 저장한다. 서버 부하를 줄일 수 있음
➤ 말그대로 're'save 이기때문에 초기화 되지 않은 세션은 저장하지 않음 (saveUninitialized 가 false 일때겠지)
✔︎ saveUninitialized : 초기화 되지 않은 세션의 데이터도 스토어에 저장할지 설정하는 옵션
➤ 서버가 클라이언트에게 SID를 받은후에 '그래 내가 알고있는 SID네 OK' 하는게 초기화 된것
➤ true: 최초 요청에 대해서 서버에서 세션ID를 생성해서 클라이언트에게 전달할때도 세션데이터를 스토어에 저장한다. 예를들면 로그인하지 않은 유저도 세션ID를 부여받고 서버와 통신할 수 있게되어서 비로그인상태에서 장바구니같은걸 쓸 수 있다.
➤ false: 초기화되지 않는 세션(최초요청)서버에서 세션을 생성하긴 하지만 저장하지 않는다.(클라이언트에게도 전달되지 않음), 세션에 변경사항이 생긴다면 초기화가 진행되고 세션은 저장되며 클라이언트에게도 전달된다.
✔︎ cookie : 세션 쿠키에 대한 설정
➤ path : 쿠키가 적용되는 경로를 설정하는 옵션, 이 경로 문자열은 현재 요청의 URL 경로와 비교됩니다. 쿠키는 현재 요청의 경로와 path 옵션에 설정된 경로가 부분적으로 일치하는 경우에만 전송됩니다. 즉, 클라이언트는 해당 경로에서만 쿠키를 사용할 수 있습니다.
➤ domain : 현재 요청의 호스트와 비교되며, 쿠키는 현재 요청의 호스트와 domain 옵션에 설정된 도메인이 일치하는 경우에만 전송됩니다.
➤ httpOnly : 쿠키를 JavaScript로 접근할 수 없도록 만드는 옵션
➤ secure : 쿠키를 HTTPS 연결을 통해서만 전송하도록 만드는 옵션
➤ expires : 특정 날짜와 시간을 사용하여 만료 일자를 지정
➤ maxAge : 만료되기까지의 시간을 지정하여 만료 일자를 지정 (expires 와 maxAge 중 나중에 설정된 값으로 덮어씌워집니다.)
✔︎ name : 세션 쿠키의 이름입니다. 기본값은 connect.sid 입니다.
✔︎ secret : 쿠키를 암호화하는데 사용되는 키 (세션 ID도 쿠키에 담긴다.)
✔︎ genid : 새로운 session ID를 생성하는 함수를 설정
4. Express-session 적용 (간단한 로그인)
➤ MemoryStore 사용해서 세션 저장
➤ 매요청마다 세션 스토어에 저장된 세션 데이터 확인
➤ 로그인 처리 / 로그아웃 처리시 세션 생성 및 제거
➤ 세션의 데이터 여부로 로그인여부 확인후 프로필 확인
const express = require('express');
const session = require('express-session');
const app = express();
// Env
const PORT = 8080;
const SESSION_KEY = 'MySessionSecretKey'; // 세션 ID 생성에 사용하는 키
// EJS 템플릿 엔진으로 테스트
app.set('view engine', 'ejs');
// express-session 미들웨어
app.use(
session({
secret: SESSION_KEY,
resave: false, // default 는 true
saveUninitialized: false, // default 는 true
// store: MemoryStore, // default
cookie: {
path: '/', // default
httpOnly: true, // default
secure: false, // default
maxAge: 10 * 60000, // default는 NULL
},
name: 'connect.sid', // default
})
);
app.use((req, res, next) => {
console.log(req.sessionStore); // check session Store
//모든 세션(연결)들을 볼수있음
req.sessionStore.all((err, sessions) => {
console.log('seesions', sessions);
next();
});
});
app.get('/', (req, res) => {
res.render('sessionTest');
});
app.get('/login', (req, res) => {
// 로그인 과정 생략
// 회원인거 확인 후 세션에 저장 > 세션 초기화 및 저장 진행
req.session.isLogin = true;
res.send(req.session.isLogin);
});
app.get('/profile', (req, res) => {
if (req.session.isLogin) {
res.send('로그인 되어있기 때문에 회원 정보를 보여줘도 됌');
return;
}
res.status(401).send('로그인이 필요합니다.');
});
app.get('/logout', (req, res) => {
req.session.destroy((err) => {
if (err) {
console.log(err);
return;
}
res.send({
msg: '로그아웃 됨',
reqSession: req.session,
});
});
});
app.listen(PORT, () => {
console.log('서버시작' + PORT);
});
'Nodejs' 카테고리의 다른 글
[Nodejs] 쿠키와 세션 인증 그리고 JWT (0) | 2023.10.21 |
---|---|
[Nodejs] Express JWT 토큰 발급/검증 (0) | 2023.10.19 |
[Nodejs] Express에서 redis를 session storage로 사용 (0) | 2023.10.15 |
[Nodejs] 싱글 스레드 (1) | 2023.10.04 |
[Nodejs] 동기/비동기, 블로킹/논블로킹 (0) | 2023.10.02 |