-
3-5. 노드 쿠키의 모든 것Node.js 2023. 4. 13. 16:04
I. 쿠키의 필요성
1. 요청에는 한 가지 단점이 있음
- 누가 요청을 보냈는지 모름(IP 주소와 브라우저 정보 정도만 알 수 있음)
- 로그인을 구현하면 되지만, 그러려면 쿠키와 세션이 필요
2. 쿠키 : 키=값의 쌍
- name=junu
- 매 요청마다 서버에 동봉해서 보냄
- 서버는 쿠키를 읽어 누구인지 파악
II. 쿠키 서버 만들기
1. 쿠키 넣는 것을 직접 구현
- writeHead : 요청 헤더에 입력하는 메서드
- Set-Cookie : 브라우저에게 쿠키를 설정하라고 명령
2. 쿠키 : 키=값의 쌍
- name=junu
- 매 요청마다 서버에 동봉해서 보냄
// cookie.js const http = require('http'); http.createServer((req, res) => { console.log(req.url, req.headers.cookie); res.writeHead(200, { 'Set-Cookie': 'mycookie=test' }); res.end('Hello Cookie'); }) .listen(8083, () => { console.log('8083번 포트에서 서버 대기 중입니다!'); });
위 코드를 실행시키고 나서 8083 포트에 접속한다.
그 다음 개발자도구(F12)를 열고, Network(네트워크) 탭에서 locathost > Headers 에 있는 Response Headers 를 살펴보면
아래와 같이 Set-Cookie: mycookie-test 를 확인할 수 있다.
또한 아래와 같이, Application(응용 프로그램) 탭에 있는 Cookies > http://localhost:8083 을 살펴보면 쿠키 정보를 확인할 수 있다.
쿠키의 유효기간(Expires)을 따로 설정하지 않는다면 Session 이 되는데, 이는 브라우저가 닫히기 전까지 유효하다는 뜻이다.
그리고 콘솔창을 확인해보면 아래와 같이 정보가 나와있는 것을 볼 수 있다.
이 때, / 요청과 /favicon.ico 요청이 있다.
favicon.ico 는 크롬에서 이 이미지를 알아서 요청하기 때문에 발생하는 요청으로, 그냥 무시하면 된다.
III. 헤더와 본문
http 요청과 응답은 헤더와 본문을 가짐
- 헤더는 요청 또는 응답에 대한 정보를 가짐
- 본문은 주고 받는 실제 데이터를 가짐
- 쿠키는 부가적인 정보이므로 헤더에 저장
IV. 쿠키로 나를 식별하기
쿠키에 내 정보를 입력
- parseCookies : 쿠키 문자열을 객체로 변환
- 주소가 /login 인 경우와 / 인 경우로 나뉨
- /login 인 경우 쿼리스트링으로 온 이름을 쿠키로 저장
- 그 외의 경우 쿠키가 있는지 없는지 판단
// cookie2.html <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>쿠키&세션 이해하기</title> </head> <body> <form action="/login"> <input id="name" name="name" placeholder="이름을 입력하세요" /> <button id="login">로그인</button> </form> </body> </html>
// cookie2.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으로 시작하는 경우 if (req.url.startsWith('/login')) { const { query } = url.parse(req.url); const { name } = qs.parse(query); const expires = new Date(); // 쿠키 유효 시간을 현재시간 + 5분으로 설정 expires.setMinutes(expires.getMinutes() + 5); res.writeHead(302, { Location: '/', '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}님 안녕하세요`); } 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(8084, () => { console.log('8084번 포트에서 서버 대기 중입니다!'); });
실행 결과 화면 ✨ cookie2.js 파일에서 /login 요청일 때, res.writeHead 를 주의깊게 살펴보자
① name=${encodeURIComponent(name)} : 이름 데이터를 인코딩해서 받아라.
- cookie 에서는 한글을 사용하면 보안적으로 문제가 되기 때문에, 한글을 입력할 수 없게끔 되어있다.
따라서, 한글 데이터를 전달받으려면 encodeURIComponent 로 인코딩하여 받아야한다.
(이거 안쓰면 쿠키에 이상한 글자가 들어갔다는 에러 발생)
② Expires=${expires.toGMTString()} : 쿠키의 만료기간(유효기간) 설정
- 위에서 말했듯이, 쿠키의 만료기간을 설정하지 않으면 Session 이 되고, 이는 브라우저 종료 시에 쿠키가 만료된다는 것을 의미한다.
반드시 필요한 설정은 아니지만 필요하다면, 해당 코드 3줄 상단에 있는 expires.setMinutes(expires.getMinutes() + 5) 처럼,
세션의 만료기간을 '현재시간으로부터 5분 후' 로 설정할 수 있다.
③ HttpOnly : JavaScript로 쿠키에 접근할 수 없게끔 한다.
- 보통 쿠키들은 JavaScript로 접근하게 되면 보안에 위협을 가하기 때문에, 특히 로그인을 위해 사용하는 쿠키에는 거의 필수적인 요소이다.
④Path=/ : / 아래에 있는 주소에서는 쿠키가 모두 유효하다.
위의 코드들을 잘 읽어보고 난 다음에 분석에 성공하셨다면, 직접 실습해보면서 따라하는 것을 추천한다.
그리고 ✨ 부분을 집중해서 공부하고 나면, 5분이라는 시간은 거뜬히 지났을 것이다.
그렇다면, 8084 페이지에서 새로고침을 눌러보자.
로그인 되어있던 것이 풀리지 않았습니까?
과연 왜 그런 것일까?
여러분들은 이미 정답을 알고 있다.
이번 게시글을 잘 읽어보면서 정답을 스스로 찾아보자.
'Node.js' 카테고리의 다른 글
3-7. 노드 https 와 http2 (0) 2023.04.14 3-6. 노드 세션(Session) 이해하고 사용하기 (0) 2023.04.14 3-4. 노드 POST, PUT, DELETE 요청 보내기 / HTTP status 코드(상태코드) (0) 2023.04.13 3-3. 노드 REST API 서버 만들기 (0) 2023.04.13 3-2. 노드 fs로 HTML 파일 읽어서 제공하기 (0) 2023.04.13