...
자바스크립트 쿠키 다루기
노드 쿠키 다루기에 앞서, 자바스크립트로 쿠키 다루는 법을 먼저 공부하고 오는 것을 추천한다.
쿠키 전송 서버 만들기
const http = require('http');
http
.createServer((req, res) => {
// 만일 쿠키가 있으면, 읽는다.
console.log(req.url, req.headers.cookie);
// Set-Cookie: 브라우저에게 쿠키를 설정하라고 헤더에 요청 명령
res.writeHead(200, { 'Set-Cookie': 'mycookie=test' });
res.end('Hello Cookie');
})
.listen(8084, () => {
console.log(111);
});
쿠키를 생성하고, 웹페이지 새로고침을 하면,
이제 브라우저가 쿠키를 가지고 서버에게 요청(Request) 하게 된다.
그래서 서버쪽에서는 요청한 클라이언트가 누구인지 알수 있게된다.
이러한 로직이 로그인 로직이라고 보면 된다.
쿠키 로그인 로직 만들기
cookie.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>쿠키&세션 이해하기</title>
</head>
<body>
<form action="/login"> <!-- get 요청 -->
<input id="name" name="name" placeholder="이름을 입력하세요" />
<button id="login">로그인</button>
</form>
</body>
</html>
cookie.js
const http = require('http');
const fs = require('fs').promises;
const url = require('url');
const qs = require('querystring');
// 쿠키 문자열을 자바스크립트 객체로 변환하는 함수
const parseCookies = (cookie = '') =>
cookie
.split(';')
.map(v => v.split('='))
.reduce((acc, [k, v]) => {
acc[k.trim()] = decodeURIComponent(v);
return acc;
}, {});
http
.createServer(async (req, res) => {
// 먼저 저장되어있는 쿠키가 있는지 없는지 검사
const cookies = parseCookies(req.headers.cookie); // 변환 -> { mycookie: 'test' }
// 주소가 /login으로 시작하는 경우
// cookie.html의 form에서 action이 /Login으로, submit하면 발동
if (req.url.startsWith('/login')) {
const { query } = url.parse(req.url); // url을 객체로 만들어 query키만 빼옴
const { name } = qs.parse(query); // query키의 값인 문자열을 또 객체화해서 name키만 빼옴. 이 값은 쿠키에 저장될꺼임
// 쿠키 유효 시간을 현재시간 + 5분으로 설정
const expires = new Date();
expires.setMinutes(expires.getMinutes() + 5);
res.writeHead(302, {
Location: '/',
// HttpOnly는 자바스크립트로 쿠키에 접근할 수 없게 한다. 보안을 위해.
'Set-Cookie': `name=${encodeURIComponent(name)}; Expires=${expires.toGMTString()}; HttpOnly; Path=/`,
});
res.end();
// name이라는 쿠키가 있는 경우, 로그인 된 경우
} else if (cookies.name) {
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end(`${cookies.name}님 안녕하세요`);
// 쿠키가 비었을 경우, 로그인 페이지 html을 띄움
} else {
try {
const data = await fs.readFile('./cookie.html');
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.end(data);
} catch (err) {
res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end(err.message);
}
}
})
.listen(8084, () => {
console.log('8084번 포트에서 서버 대기 중입니다!');
});
세션 사용하기
const http = require('http');
const fs = require('fs').promises;
const url = require('url');
const qs = require('querystring');
const parseCookies = (cookie = '') =>
cookie
.split(';')
.map(v => v.split('='))
.reduce((acc, [k, v]) => {
acc[k.trim()] = decodeURIComponent(v);
return acc;
}, {});
// 세션 데이터 저장용 객체
const session = {};
http.createServer(async (req, res) => {
const cookies = parseCookies(req.headers.cookie);
if (req.url.startsWith('/login')) {
const { query } = url.parse(req.url);
const { name } = qs.parse(query);
const expires = new Date();
expires.setMinutes(expires.getMinutes() + 5);
const uniqueInt = Date.now(); // 세션 키. 다른사람과 겹치면 안됨.
session[uniqueInt] = {
name,
expires,
};
res.writeHead(302, {
Location: '/',
// 브라우저에는 나중에 보안적으로 통신할 식별할수있는 고유한 세션값을 보낸다.
'Set-Cookie': `session=${uniqueInt}; Expires=${expires.toGMTString()}; HttpOnly; Path=/`,
});
res.end();
// 세션쿠키가 존재하고, 위에 선언한 세션 객체에서 정보가 존재하고, 만료 기간이 지나지 않았다면
} else if (cookies.session && session[cookies.session].expires > new Date()) {
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
// 세션 객체에서 정보를 가져온다. cookie.session은 세션객체의 키 명으로만 사용
res.end(`${session[cookies.session].name}님 안녕하세요`);
} else {
try {
const data = await fs.readFile('./cookie2.html');
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.end(data);
} catch (err) {
res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end(err.message);
}
}
})
.listen(8085, () => {
console.log('8085번 포트에서 서버 대기 중입니다!');
});
쿠키에는 이제 session이라는 이름과 알수없는 값이 저장된다.
이제 서버에 요청할대 이 쿠키값을 보내게 되고, 서버에서는 쿠키 값을 세션 키 명으로 조회해 정보를 전송해준다.
따라서 세션 통신은, 배운바와 같이 클라이언트 단에서 중요한 정보가 조작되는 일을 방지할 수 있는 것이다.
인용한 부분에 있어 만일 누락된 출처가 있다면 반드시 알려주시면 감사하겠습니다
이 글이 좋으셨다면 구독 & 좋아요
여러분의 구독과 좋아요는
저자에게 큰 힘이 됩니다.