⛳️ 인프런 - cs 지식의 정석 강의를 듣고 학습한 내용입니다.
HTTP는 상태를 유지하지 않는(stateless) 프로토콜이다. 즉, 요청이 끝나면 서버는 클라이언트에 대한 정보를 유지하지 않는다.

하지만 로그인 상태는 사용자 경험에서 중요하기 때문에 웹에서 사용자의 인증 상태를 유지해야 하는데,
그 방법으로 크게 세션기반 인증과 토큰기반 인증이 있다.

npm install escape-html express express-session
const escapeHtml = require('escape-html'); // 입력값을 안전하게 변환
const express = require('express');
const session = require('express-session');
const app = express();
// 세션 설정
app.use(session({
name: 'session-id',
secret: '9e8821c8ef4ab43ba09310af54e98caedc13e314efdea720bf513b9b3675faf4', // 세션 암호화 키
resave: false,
saveUninitialized: false,
}));
// 인증 미들웨어
const isAuthenticated = (req, res, next) => {
if (req.session.user) next(); // 세션이 있다면 다음 단계로
else next('route'); // 세션이 없으면 로그인 페이지로 이동
};
// 로그인 상태 확인
app.get('/', isAuthenticated, (req, res) => {
res.send(`${escapeHtml(req.session.user)}님 환영합니다!`);
});
app.get('/', (req, res) => {
res.send(`
<p>로그인</p>
<form action="/login" method="post">
Username: <input name="user"><br>
Password: <input name="pass" type="password"><br>
<input type="submit" value="Login">
</form>
`);
});
// 로그인 요청 처리
app.post('/login', express.urlencoded({ extended: false }), (req, res) => {
if (req.body.user === 'kundol' && req.body.pass === '1234') {
req.session.regenerate((err) => {
if (err) return next(err);
req.session.user = req.body.user; // 세션에 사용자 정보 저장
req.session.save((err) => {
if (err) return next(err);
res.redirect('/');
});
});
} else {
res.redirect('/');
}
});
// 서버 실행
app.listen(3000, () => {
console.log('Server running at http://localhost:3000');
});
npm install express cookie-parser jsonwebtoken cors
const express = require('express');
const jwt = require('jsonwebtoken');
const cookieParser = require('cookie-parser');
const cors = require('cors');
const app = express();
const PORT = 3000;
// 비밀키
const ACCESS_TOKEN_SECRET = 'access_secret_key';
const REFRESH_TOKEN_SECRET = 'refresh_secret_key';
// 사용자 데이터 (가상)
const user = {
username: 'kundol',
email: 'kundol@gmail.com',
};
// 옵션
const accessOpt = { expiresIn: '10m' };
const refreshOpt = { expiresIn: '1d' };
// 미들웨어 설정
app.use(cors());
app.use(express.json());
app.use(cookieParser());
// 로그인 엔드포인트
app.post('/login', (req, res) => {
const accessToken = jwt.sign(user, ACCESS_TOKEN_SECRET, accessOpt);
const refreshToken = jwt.sign(user, REFRESH_TOKEN_SECRET, refreshOpt);
res.cookie('jwt', refreshToken, { httpOnly: true, secure: true });
res.json({ accessToken });
});
// 토큰 갱신
app.post('/refresh', (req, res) => {
const refreshToken = req.cookies.jwt;
if (!refreshToken) return res.status(401).json({ message: 'Unauthorized' });
jwt.verify(refreshToken, REFRESH_TOKEN_SECRET, (err, user) => {
if (err) return res.status(403).json({ message: 'Forbidden' });
const newAccessToken = jwt.sign(user, ACCESS_TOKEN_SECRET, accessOpt);
res.json({ accessToken: newAccessToken });
});
});
// 서버 실행
app.listen(PORT, () => {
console.log(`Server running at http://localhost:${PORT}`);
});
| 구분 | 세션기반 인증 | 토큰기반 인증 |
|---|---|---|
| 상태 유지 방식 | 서버에서 세션 데이터를 저장 | 토큰 자체에 인증 정보를 포함 |
| 확장성 | 서버 메모리나 DB에 종속, 확장성 낮음 | Stateless 방식, 확장성 높음 |
| 보안 | 서버에서 데이터를 관리하므로 비교적 안전 | 토큰 탈취 시 보안 위협 |
| 대표 구현 방식 | 세션 ID → 쿠키로 저장 | JWT를 활용 |