쿠키와 세션 완벽 가이드
쿠키(Cookie)란?
쿠키는 웹사이트가 사용자의 브라우저에 저장하는 작은 텍스트 파일입니다. 웹사이트는 쿠키를 통해 사용자의 설정이나 선호도를 기억할 수 있습니다.
쿠키의 주요 특징
- 클라이언트(브라우저) 측에 저장
- 만료 기간 설정 가능
- 도메인별로 저장되어 관리
- 용량 제한 있음 (보통 4KB)
쿠키 생성 예제 (Express)
app.get('/set-cookie', (req, res) => {
res.cookie('user', 'john', {
maxAge: 24 * 60 * 60 * 1000, // 24시간
httpOnly: true, // JS 접근 방지
secure: true, // HTTPS에서만 전송
sameSite: 'strict' // CSRF 방지
});
res.send('쿠키가 설정되었습니다.');
});
쿠키 조회
app.get('/get-cookie', (req, res) => {
const userCookie = req.cookies.user;
res.send(`사용자 쿠키: ${userCookie}`);
});
세션(Session)이란?
세션은 서버에 저장되는 사용자별 정보입니다. 클라이언트는 세션 ID만 가지고 있고, 실제 데이터는 서버에서 관리합니다.
세션의 주요 특징
- 서버 측에 저장
- 메모리 또는 데이터베이스에 저장
- 보안성이 쿠키보다 높음
- 서버 자원을 사용
세션 구현 예제 (Express)
const session = require('express-session');
app.use(session({
secret: 'your-secret-key',
resave: false,
saveUninitialized: true,
cookie: {
secure: true,
httpOnly: true,
maxAge: 24 * 60 * 60 * 1000
}
}));
// 세션 저장
app.post('/login', (req, res) => {
const { username, password } = req.body;
// 로그인 검증 후
req.session.user = {
id: 1,
username: username,
isLoggedIn: true
};
res.send('로그인 성공');
});
// 세션 확인
app.get('/profile', (req, res) => {
if (req.session.user) {
res.send(`안녕하세요, ${req.session.user.username}님`);
} else {
res.status(401).send('로그인이 필요합니다.');
}
});
쿠키와 세션의 차이점
저장 위치
- 쿠키: 클라이언트
- 세션: 서버
보안성
- 쿠키: 클라이언트에서 확인 가능
- 세션: 클라이언트에서 확인 불가
리소스
- 쿠키: 클라이언트의 리소스 사용
- 세션: 서버의 리소스 사용
용량 제한
- 쿠키: 약 4KB
- 세션: 서버 환경에 따라 다름
보안 고려사항
쿠키 보안
- httpOnly 플래그
res.cookie('auth', token, { httpOnly: true });
- secure 플래그
res.cookie('auth', token, { secure: true });
- sameSite 설정
res.cookie('auth', token, { sameSite: 'strict' });
세션 보안
세션 ID 관리
app.use(session({
secret: process.env.SESSION_SECRET,
name: 'sessionId', // 기본 connect.sid 변경
rolling: true, // 요청마다 만료시간 갱신
resave: false,
saveUninitialized: false
}));
세션 탈취 방지
// 세션 재생성
app.post('/login', (req, res) => {
req.session.regenerate((err) => {
if (err) next(err);
req.session.user = user;
res.redirect('/');
});
});
실제 구현 시나리오
로그인 구현
app.post('/login', async (req, res) => {
const { username, password } = req.body;
try {
const user = await User.findOne({ username });
const valid = await bcrypt.compare(password, user.password);
if (valid) {
req.session.user = {
id: user.id,
username: user.username
};
res.redirect('/dashboard');
} else {
res.status(401).send('로그인 실패');
}
} catch (error) {
res.status(500).send('서버 오류');
}
});
로그아웃 구현
app.post('/logout', (req, res) => {
req.session.destroy((err) => {
if (err) {
return res.status(500).send('로그아웃 실패');
}
res.clearCookie('connect.sid');
res.redirect('/login');
});
});
인증 미들웨어
const authMiddleware = (req, res, next) => {
if (req.session && req.session.user) {
next();
} else {
res.status(401).redirect('/login');
}
};
// 미들웨어 사용
app.get('/dashboard', authMiddleware, (req, res) => {
res.render('dashboard', { user: req.session.user });
});
성능 최적화
- 세션 저장소 선택
const RedisStore = require('connect-redis').default; const redis = require('redis'); const redisClient = redis.createClient(); app.use(session({ store: new RedisStore({ client: redisClient }), secret: 'your-secret-key' }));
- 쿠키 크기 최적화
- 필요한 정보만 저장
- 만료 기간 적절히 설정
'개발&프로그래밍' 카테고리의 다른 글
[HTTP] 웹 브라우저 동작 원리 : URL 입력부터 화면 표시까지 (0) | 2025.02.21 |
---|---|
[HTTP] URL 구조 파헤치기 (0) | 2025.02.20 |
[HTTP] HTTP 메서드 완벽 가이드: RESTful API의 기초 (0) | 2025.02.19 |
[HTTP] 개발자가 꼭 알아야 할 HTTP 상태 응답 코드 (0) | 2025.02.19 |
[HTTP] X-Forwarded-For 헤더 이해하기 (0) | 2025.02.14 |
댓글