[Session] Session 개념 정리
현대 서비스 회사들이 많이 애용하는 세션에 관하여 설명을 드리려합니다.
JWT Token을 활용한 로그인방법도 있지만, 이번 시간에는 Session 로그인이 어떠한 과정에 의해 활용이되는지 알아보는 시간을 갖도록하겠습니다.

우선, 세션과 쿠키라는 두 가지의 용어에 대한 이해가 필요합니다.
먼저, 왜 쿠키와 세션을 사용하여야 하는가?
이에대한 답변을 내놓으려면, http 프로토콜의 특징을 먼저 알아야 하는데, 간략히
1. 비연결 지향(클라이언트가 서버에 요청했을 때 그 요청에 맞는 응답을 보낸 후 연결을 바로 끊는 형식)
2. Stateless (상태정보를 유지 안함 - 첫번 째 통신에서 데이터를 주고받았다 하여도, 두 번째 통신에서 이전 데이터를 유지하지 않음)
의 한계로 인해 사용한다고 알고있으면 되겠습니다.
쿠키
웹 서버가 생성하여 웹 브라우저로 전송하는 작은 정보 파일입니다.
웹 브라우저는 수신한 쿠키를 미리 정해진 기간 동안 또는 웹 사이트에서의 사용자 세션 기간 동안 저장합니다. 이러한 쿠키를 웹 브라우저는 향후 사용자가 웹 서버에 요청(Request)할 때 관련 쿠키를 첨부합니다.
웹 브라우저는 사용자 기기의 지정된 파일에 쿠키를 저장하는데, 예를 들어, Google Chrome 웹 브라우저는 모든 쿠키를 "Cookies"라는 파일에 저장합니다
(개발자 도구를 열고 "애플리케이션" 탭을 클릭한 다음 왼쪽 메뉴에서 "쿠키"를 클릭하면 브라우저에 저장된 쿠키를 확인할 수 있습니다.)

이러한 쿠키는 '사용자 세션'과, '개인화', '추적'에 사용됩니다.
사용자 세션
쿠키는 웹 사이트 활동을 특정 사용자와 연결하는 데 도움이 됩니다.
세션 쿠키에는 사용자 세션과 해당 사용자의 관련 데이터 및 콘텐츠를 일치시키는 고유 문자열(문자와 숫자의 조합)이 포함되어 있습니다.
개인화
쿠키가 웹 사이트에서 사용자 행동 또는 기본 설정이 "기억" 되는 데 도움이 되므로 웹 사이트에서 사용자 경험이 맞춤화 될 수 있습니다.
추적
일부 쿠키에는 사용자가 방문한 웹 사이트가 기록됩니다. 이 정보는 다음에 브라우저가 해당 서버에서 콘텐츠를 로드할 때 쿠키를 생성한 서버로 전송됩니다. 예를 들면, 어느 이커머스 회사의 청바지 제품 페이지를 사용자가 보고 있다는 사실이 기록되면, 다음에 해당 추적 서비스를 사용하는 웹 사이트를 로드할 때 청바지 광고가 뜰 수 있는 형식으로 활용이 됩니다.
이러한 쿠키의 유형은 [ 세션 쿠키, 영구 쿠키, 인증 쿠키, 추적 쿠키, 좀비 쿠키 ]와 같이 여러종류가 있지만, 우리가 오늘 유의깊게 볼 부분은 '세션 쿠키'부분입니다.
세션쿠키 : 세션 쿠키는 웹 사이트에서 사용자의 세션을 추적하는 데 도움이 됩니다. 세션 쿠키는 사용자의 세션이 종료된 후, 즉 사용자가 웹 사이트에서 계정에서 로그아웃하거나 웹 사이트를 종료하면 삭제됩니다. 세션 쿠키는 만료일이 없으므로 세션이 끝나면 삭제되어야 함을 브라우저에 알립니다.
그렇다면 '세션'은 무엇일까요?
세션
세션의 개념적 정의는, 시간이 제한된 양방향 Link이며, 두 개 이상의 통신장치 또는 종단 간에 대화형 표현과 정보 교환을 가능하게 하는 TCP/IP 프로토콜의 상대적으로 높은 계층입니다.
특정 시점에 설정되고, 이후 특정 시점에 해제(종료)되는데, 상태 비저장 통신과 달리 통신하려면 통신 당사자 중 적어도 하나가 현재 상태 정보를 보유하고, 세션 기록에 대한 정보를 저장해야합니다.
또한, 서버측에서 관리되는 브라우저가 종료되기 전까지 클라이언트의 요청을 유지해줍니다.

세션의 작동 방식
- 사용자 인증 : 사용자는 서버에서 확인하는 자격 증명을 제공합니다.
- 세션 생성 : 인증이 성공하면 서버는 고유 식별자, 사용자 식별자, 세션 시작 시간, 만료 및 IP 주소 및 사용자 에이전트와 같은 추가 컨텍스트가 포함된 세션 기록을 생성하고, 스토리지에 저장합니다.
- 쿠키 저장 : 이 세션 식별자는 다시 전송되어 사용자 브라우저에 쿠키로 저장됩니다.
- 세션 유효성 검사 : 사용자 브라우저의 각 요청에는 이 쿠키가 포함되며, 서버는 스토리지에 쿼리하여, 세션의 유효성을 검사합니다. 유효한 경우 요청이 처리됩니다.
세션의 특징
- 세션ID는 브라우저마다 한 개만 생성되어, 웹 브라우저 컨테이너에 저장되는 형식이므로, 브라우저가 종료 시 소멸됩니다.
- 같은 브라우저 탭에서는 새로고침을 하여도 세션ID가 유지됩니다.
- 제한시간을 적용하여 만약 추가적인 응답이 없을 경우, session을 종료시킬 수 있습니다.
- 비정상적인 요청이 탐지된다면, session을 핸들링하는 당사자가 session을 종료시킬 수 있습니다.
*원칙상 프로토콜(https)의 암호화를 믿고 가는 토큰인증방식이기에, 통신과정에서의 보안성은 세션로그인과, jwt토큰을 활용한 인증방식과는 큰 차이가 안난다고 생각합니다.[혹시, 다른 의견을 가지신 분이 계신다면 답글남겨주시면 감사하겠습니다.]
단, jwt토큰은 expire time을 설정하여 구현 하기에, 추가적인 작업이 없는 한(black list, white list와 같은 추가적 작업)은 session방식이 낫다고도 볼 수 있을것같기도 합니다.
=> session login은 토큰이 탈취되었다고 판단시, session을 만료시키면 되기때문.
물론 어디까지나 통신과정에서의 보안성의 경우에 그렇다는 뜻이고, 토큰 인증과정에서의 보안성은 별도일것이라는 말씀을 드리고싶네요.
세션인증방식의 로그인 단점
- 서버에서 세션을 관리하여야하기때문에 클라이언트로부터 요청이 들어오면 해당 세션을 탐색하는데에 오버헤드가 발생합니다. 따라서 서버에 부하가 가해진다는 점이 있습니다.
- 각각의 서버가 세션을 관리하기때문에, 추후 로드밸런싱과 같은 서버분산에따라 세션관련 문제가 발생할 수 있습니다. 이를 해결하기위해 'sticky session'을 채택할 수 있습니다. [sticky session? 로드 밸런서가 동일한 클라이언트에서 들어오는 요청을 식별하고 항상 해당 요청을 동일한 서버로 보낼 수 있도록 하는 방법. - 추가적으로 궁금하시다면 https://traefik.io/glossary/what-are-sticky-sessions/ 를 참고해보시길 바랍니다.]
그렇다면 session 로그인 코드는?
Session 로그인 예제 [express.js]
간략한 예시를 들어 Node에서 session 로그인을 구현해보겠습니다.
npm install express express-session
express를 install한 후, 세션작업을 쉽게 구현해보기 위해 'express-session'을 설치합니다.
//Index.js
const express = require('express');
const sessions = require('express-session');
const app = express();
app.use(
sessions({
secret: 'some secret',
cookie: {
maxAge: 1000 * 60 * 60 * 24, // 24 hours
},
resave: true,
saveUninitialized: false,
})
);
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.listen(3000, () => {
console.log(`Server Running at port 3000`);
});
index.js의 코드 구성입니다.
여기서 유의깊게볼 점들이 있습니다.
- secret : 세션 ID 쿠키에 서명하는데 필요합니다. 추측할 수 없는 값을 사용하면 하이재킹 어택에 대한 가능성이 줄어듭니다.
- cookie : 세션 ID 쿠키에대한 구성이 포함된 객체입니다.
- resave : 요청 중에 세션 데이터가 수정되지 않은 경우에도 세션을 세션 저장소에 다시 저장하도록 합니다.
- saveUninitialized: "초기화되지 않은" 세션을 강제로 저장소에 저장합니다. 즉, 세션이 시작되지 않은 경우에도 세션을 저장소에 저장합니다.
이후, 'HomeHandler'라는 파일을 생성합니다.
//Home.js
module.exports = function HomeHandler(req, res) {
if (!req.session.userid) {
return res.redirect('/login'); // req.session.userid가 없다면 /login으로 redirect
}
res.setHeader('Content-Type', 'text/HTML');
res.write(`
<h1>Welcome back ${req.session.userid}</h1>
<a href="/logout">Logout</a>
`);
res.end();
};
이 후, 이 모듈에대한 선언을 index.js에서 해줍니다.
//Index.js
const HomeHandler = require('./Home.js');
app.get('/', HomeHandler);
그리고, login 페이지를 간단히 구현합니다.
//Login.js
module.exports = function LoginHandler(req, res) {
if (req.session.userid) {
return res.redirect('/');
}
res.setHeader('Content-Type', 'text/HTML');
res.write(`
<h1>Login</h1>
<form method="post" action="/process-login">
<input type="text" name="username" placeholder="Username" /> <br>
<input type="password" name="password" placeholder="Password" /> <br>
<button type="submit">Login</button>
</form>
`);
res.end();
};
이후, 다시 Index.js에서 login.js를 선언해줍니다.
//Index.js
const LoginHandler = require('./Login.js');
app.get('/login', LoginHandler);
다음으로, process-login 모듈을 만들어줍니다.
module.exports = function processLogin(req, res) {
if (req.body.username !== 'admin' || req.body.password !== 'admin') {
return res.send('Invalid username or password');
}
req.session.userid = req.body.username;
res.redirect('/');
}
* username과 password가 'admin'이라면 request.session.userid를 'admin'으로 세팅해준 후, '/' 경로로 redirect 해줍니다.
그렇지 않다면, 'Invalid username or password' 를 반환합니다.
이후, 이 또한 Index.js에 선언해줍니다.
//Index.js
const ProcessLoginHandler = require('./handlers/process-login.js');
app.post('/process-login', ProcessLoginHandler);
여기까지 하면 login에 대한 구현은 끝났고, log-out을 구현하자면,
//Logout.js
module.exports = function Logout(req, res) {
req.session.destroy();
res.redirect('/');
};
//Index.js
const LogoutHandler = require('./Logout.js');
app.get('/logout', LogoutHandler);
Logout.js와 Index.js에 선언을 각각 해주면 완성입니다.
이후, 터미널창에서 'npm run start'를 타이핑하고, localhost:3000으로 진입하면 간략한 session방식의 로그인, 로그아웃과정을 체험해볼 수 있습니다.
후기
제 개인적인 의견으로는, Jwt와, Session login방식은 어느방식이 더 좋은것보다는 상황에따라, 필요에따라 선택하는것이 중요한것같습니다. 단, 각각의 방식에따라 어떻게 작동이되는지를 이해하고, 추가적인 로직을 구현하여 적절한 보안성을 챙기는것이 중요한것같습니다. 이상입니다.
[출처]
Authentication: JWT usage vs session
What is the advantage of using JWTs over sessions in situations like authentication? Is it used as a standalone approach or is it used in the session?
stackoverflow.com
Session Based Authentication - roadmap.sh
Learn what is Session Based Authentication and how to implement it in Node.js
roadmap.sh
What Are Sticky Sessions | Traefik Labs
Thanks to sticky sessions, applications remember user preferences, keep users authenticated, etc. But how do they work exactly, and when should you use them?
traefik.io