ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 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 페이지에서 새로고침을 눌러보자.

    로그인 되어있던 것이 풀리지 않았습니까?

    과연 왜 그런 것일까?

     

    여러분들은 이미 정답을 알고 있다.

    이번 게시글을 잘 읽어보면서 정답을 스스로 찾아보자.

     

Designed by Tistory.