1. 세션과 쿠키란?
세션과 쿠키 둘은 클라이언트와 서버 간의 상태 정보를 저장하고 교환하는 데 사용된다.
세션과 쿠키가 뭔지 자세히 알아보자.
세션(Session)
세션은 서버 측에서 사용자 상태를 저장하는 방법이다. 사용자가 웹사이트에 로그인하면 서버는 해당 사용자를 식별할 수 있는 고유한 세션을 생성한다. 이 세션에는 사용자 ID, 권한, 로그인 시간 등 사용자의 상태 정보가 포함될 수 있다. 세션의 주요 특징은 다음과 같다.
- 서버 측 저장 : 세션 정보는 서버의 메모리나 데이터베이스에 저장된다.
- 세션 ID : 각 세션은 고유한 세션 ID로 식별된다. 이 세션 ID는 클라이언트에게 쿠키로 전송되어 이후 요청에 포함된다.
- 유효 기간 : 세션은 일정 시간이 지나면 자동으로 만료될 수 있다. 이는 보안 강화를 위해 설정된다.
- 보안성 : 세션 ID가 유출되면 보안 문제가 발생할 수 있으므로, 세션 관리에 주의가 필요하다.
쿠키(Cookie)
쿠키는 클라이언트 측에서 상태 정보를 저장하는 방법이다. 웹 서버는 클라이언트의 브라우저에 소량의 데이터를 쿠키 형태로 저장하고, 클라이언트는 이후 요청 시 이 쿠키를 서버에 전송한다. 쿠키의 주요 특징은 다음과 같다:
- 클라이언트 측 저장 : 쿠키는 클라이언트의 브라우저에 저장된다.
- 키-값 쌍 : 쿠키는 키-값 쌍 형태로 데이터를 저장하며, 주로 세션 ID와 같은 정보를 포함한다.
- 유효 기간 : 쿠키는 설정된 유효 기간 동안 브라우저에 유지되며, 만료 시간이 지나면 삭제된다.
- 자동 전송 : 클라이언트가 동일한 도메인에 요청을 보낼 때마다 브라우저는 자동으로 쿠키를 포함시켜 서버에 전송한다.
2. 세션과 쿠키 동작 흐름
웹 애플리케이션에서 클라이언트와 서버 간의 인증 방식 중 하나로 세션-쿠키 인증 방식이 자주 사용된다. 아래는 세션-쿠키 인증 방식의 전반적인 흐름이다.
1. 사용자 로그인 요청
- 사용자가 로그인 폼에 사용자 이름과 비밀번호를 입력하고, 이 정보를 서버로 전송한다.
2. 서버에서 사용자 인증
- 서버는 전송된 사용자 이름과 비밀번호를 데이터베이스와 비교하여 사용자를 인증한다.
- 인증에 성공하면 서버는 세션을 생성한다. 이 세션에는 사용자의 상태 정보(예: 사용자 ID, 권한 등)가 포함된다.
서버측 코드
const express = require('express');
const bcrypt = require('bcryptjs');
const session = require('express-session');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
app.use(session({ secret: 'your-secret-key', resave: false, saveUninitialized: true }));
// 가상의 사용자 데이터베이스
const users = [
{ id: 1, username: 'user1', password: '$2a$10$V6F/7T/o0H1jVz5xZ6Jv1OKe4Cn/4qG/nSIk7cC4j9HLqjCJ5eCqm' } // 'password123'의 해시값
];
app.post('/login', (req, res) => {
const { username, password } = req.body;
const user = users.find(u => u.username === username);
if (!user) {
return res.json({ success: false, message: 'Invalid username or password' });
}
bcrypt.compare(password, user.password, (err, isMatch) => {
if (isMatch) {
req.session.userId = user.id;
res.json({ success: true });
} else {
res.json({ success: false, message: 'Invalid username or password' });
}
});
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
3.세션 ID 생성 및 저장
- 서버는 세션을 생성한 후, 이 세션을 식별할 수 있는 고유한 세션 ID를 생성한다.
- 이 세션 ID는 서버의 세션 저장소(메모리, 데이터베이스 등)에 저장된다.
- 위 서버측 코드에서 express-session 미들웨어가 세션 ID를 생성하고, 메모리에 저장한다.
4.클라이언트에게 쿠키로 세션 ID 전송
- 서버는 생성된 세션 ID를 클라이언트에게 쿠키로 전송한다. 이 쿠키는 HTTP 응답 헤더에 포함되어 있다.
- 쿠키는 브라우저에 저장되고, 설정된 유효 기간 동안 유지된다.
- express-session 미들웨어가 이 작업을 자동으로 처리한다.
5.클라이언트의 요청에 세션 ID 포함
- 클라이언트(브라우저)는 이후 서버에 요청을 보낼 때마다 쿠키에 저장된 세션 ID를 함께 전송한다. 이는 자동으로 이루어진다.
6.서버에서 세션 ID 확인
- 서버는 클라이언트의 요청을 받을 때, 전송된 쿠키에서 세션 ID를 확인한다.
- 서버는 이 세션 ID를 세션 저장소에서 찾아, 해당 세션에 저장된 사용자 상태 정보를 로드한다.
7.요청 처리 및 응답 전송
- 서버는 세션 정보를 사용하여 클라이언트의 요청을 처리한다. 예를 들어, 사용자가 로그인한 상태인지 확인하고, 권한에 따라 접근을 허용하거나 거부할 수 있다.
- 처리 결과는 HTTP 응답으로 클라이언트에게 전송된다.
app.get('/protected', (req, res) => {
if (!req.session.userId) {
return res.status(401).json({ message: 'Unauthorized' });
}
res.json({ message: 'Welcome to the protected route, user ' + req.session.userId });
});
8.세션 종료
- 사용자가 로그아웃을 요청하면, 서버는 세션 저장소에서 해당 세션을 삭제하고, 클라이언트에게 세션 쿠키를 만료시켜 더 이상 유효하지 않도록 한다.
- 세션의 유효 기간이 만료되면, 서버는 자동으로 세션을 삭제할 수도 있다. (만들기 나름)
app.post('/logout', (req, res) => {
req.session.destroy(err => {
if (err) {
return res.status(500).json({ message: 'Logout failed' });
}
res.clearCookie('connect.sid');
res.json({ message: 'Logout successful' });
});
});