[Node.js] 쿠키 생성, 읽기

 

0. 참고자료

Node.js – 쿠키와 인증 – 생활코딩


1. 쿠키?

쿠키는 사용자가 방문한 웹사이트에서 사용자의 브라우저에 전송하는 작은 텍스트 조각입니다. 쿠키가 있으면 웹사이트에서 사용자의 방문에 관한 정보를 기억하여 다음번에 사이트에 방문했을 때 번거로운 작업을 피하고 더 유용하게 사이트를 활용할 수 있습니다. 브라우저, 앱 또는 기기, 픽셀, 로컬 저장소를 식별하는 데 사용되는 고유 식별자 같은 기타 기술도 이 목적으로 사용될 수 있습니다…

쿠키의 등장은 웹의 개인화에 있어서 중요한 사건이다.

개인화의 대한 요구가 1994년 넷스케이프사의 론 몬툴리가 쿠키를 고안했다.

웹서버의 정보를 웹브라우저에 저장해서 개인화, 인증, 사용자 추적 등의 기능을 구현할 수 있다.

그 결과 사람마다 선택과 취향에 맞는 웹 페이지를 보여줄 수 있게 되었다.

쿠키는 주로 세 가지 목적을 위해 사용됩니다 :

  1. 세션 관리(Session management)
    : 서버에 저장해야 할 로그인, 장바구니, 게임 스코어 등의 정보 관리
  2. 개인화(Personalization)
    : 사용자 선호, 테마 등의 세팅
  3. 트래킹(Tracking)
    : 사용자 행동을 기록하고 분석하는 용도

출처 : https://policies.google.com/technologies/cookies?hl=ko

출처 : https://developer.mozilla.org/ko/docs/Web/HTTP/Cookies


2. 쿠키 생성

Cookie – HTTP | MDNMDN

쿠키는 웹 브라우저와 웹서버가 주고받는 정보이므로 HTTP 프로토콜에 속한다.

HTTP 요청을 수신할 때, 서버는 응답과 함께 [Set-Cookie] 헤더를 전송할 수 있습니다.

쿠키는 보통 브라우저에 의해 저장되며, 그 후 쿠키는 같은 서버에 의해 만들어진 요청(Request)들의 Cookie HTTP 헤더 안에 포함되어 전송됩니다.

response.setHeader('Set-Cookie', ['type=ninja', 'language=javascript']);
Code language: JavaScript (javascript)

위의 코드에서 세팅된 헤더는 response.writeHead()에 의해서 세팅된 헤더와 합쳐진다.

res.writeHead(200, {
    'Set-Cookie': 'myCookie=Hello, this is my Cookie',
    'Content-Type': 'text/html'
});
res.end('<h1>Cookie has been set</h1>');
Code language: JavaScript (javascript)

처음부터 response.writeHead()를 사용해서 쿠키를 생성할 수 있다.

  • 'Content-Type': 'text/html' : 쿠키는 MIME 타입과는 관계없다. 응답 본문의 미디어 타입과는 독립적으로 작동한다. 꼭 html이 아니라도 된다. 여기서 res.end()의 내용이 html이라서 그렇다.
//다른 예시
var http = require('http');
http.createServer(function(request, response){
    response.writeHead(200, {
        'Set-Cookie':['yummy_cookie=choco', 'tasty_cookie=strawberry']
    });
    response.end('Cookie!!');
}).listen(3000);
Code language: JavaScript (javascript)

Content-Type 없어도 됩니다.

처음 접속하면 쿠키가 생성된 것을 확인할 수 있다.두 번째 접속에는 쿠키를 보내기도 하고 받기도 했다.

새로 고침 할 때마다 웹 브라우저는 서버로 쿠키를 보낸다.

  • 주의!

Cookie 헤더는 선택적(optional)이고, 만약 브라우저의 사생활 보호 설정(privacy settings)이 쿠키를 block할 경우 생략될 수도 있습니다.


3. 쿠키 읽기

var http = require('http');

function parseCookies(cookieString) {
    let cookies = {};
    if (cookieString) {
        let itemStrings = cookieString.split('; ');
        itemStrings.forEach(item => {
            let parts = item.split('=');
            cookies[parts[0]] = parts[1];
        });
    }
    return cookies;
}

http.createServer(function(request, response){
    const cookies = parseCookies(request.headers.cookie);
    response.writeHead(200, { 'Content-Type': 'text/html' });
    response.end(`<h1>${cookies.yummy_cookie || 'No yummy_cookie found'}, ${cookies.tasty_cookie || 'No tasty_cookie found'}</h1>`);
    //response.writeHead(200, {
    //    'Set-Cookie':['yummy_cookie=choco', 'tasty_cookie=strawberry']
    //});
    //response.end('Cookie!!');
}).listen(3000);
Code language: JavaScript (javascript)

const server = http.createServer((req, res) => {
    const cookies = parseCookies(req.headers.cookie);
    ...
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.end(`<h1>${cookies.myCookie || 'No cookie found'}</h1>`);
    ...
Code language: JavaScript (javascript)
function parseCookies(cookieString) {
    let cookies = {};
    if (cookieString) {
        let itemStrings = cookieString.split('; ');
        itemStrings.forEach(item => {
            let parts = item.split('=');
            cookies[parts[0]] = parts[1];
        });
    }
    return cookies;
}
Code language: JavaScript (javascript)

cookieString은 yummy_cookie=choco; tasty_cookie=strawberry의 문자열에 불과하다.

그래서 사용하기 쉽게 객체로 파싱해야 한다.

위와 같이 함수를 직접 작성해서 추가해도 되지만 npm에서 cookie라는 모듈을 설치해서 사용해도 된다.

https://www.npmjs.com/package/cookie

$ npm install cookie
const cookie = require('cookie');
const cookies = cookie.parse(req.headers.cookie || '');

// 만약
// req.headers.cookie = 'foo=bar; equation=E%3Dmc%5E2'
// cookies = { foo: 'bar', equation: 'E=mc^2' }
Code language: JavaScript (javascript)

쿠키가 없는 경우 (첫 번째 접속) req.headers.cookieundefined되어 에러가 발생한다.

에러 처리까지 고려해라.


4. Node.js에서 쿠키

  • 직접 쿠키를 파싱하는 예시
const http = require('http');

const server = http.createServer((req, res) => {
    const cookies = parseCookies(req.headers.cookie);

    if (req.url === '/set-cookie') {
        res.writeHead(200, {
            'Set-Cookie': 'myCookie=Hello, this is my Cookie',
            'Content-Type': 'text/html'
        });
        res.end('<h1>Cookie has been set</h1>');
    } else if (req.url === '/get-cookie') {
        res.writeHead(200, { 'Content-Type': 'text/html' });
        res.end(`<h1>${cookies.myCookie || 'No cookie found'}</h1>`);
    } else {
        res.writeHead(404, { 'Content-Type': 'text/html' });
        res.end('<h1>Page not found</h1>');
    }
});

function parseCookies(cookieString) {
    let cookies = {};
    if (cookieString) {
        let itemStrings = cookieString.split('; ');
        itemStrings.forEach(item => {
            let parts = item.split('=');
            cookies[parts[0]] = parts[1];
        });
    }
    return cookies;
}

server.listen(3000, () => {
    console.log('Server is running on port 3000');
});
Code language: JavaScript (javascript)
  • cookie 모듈을 사용하는 예시
var cookie = require('cookie');
var escapeHtml = require('escape-html');
var http = require('http');
var url = require('url');

function onRequest(req, res) {
  // Parse the query string
  var query = url.parse(req.url, true, true).query;

  if (query && query.name) {
    // Set a new cookie with the name
    res.setHeader('Set-Cookie', cookie.serialize('name', String(query.name), {
      httpOnly: true,
      maxAge: 60 * 60 * 24 * 7 // 1 week
    }));

    // Redirect back after setting cookie
    res.statusCode = 302;
    res.setHeader('Location', req.headers.referer || '/');
    res.end();
    return;
  }

  // Parse the cookies on the request
  var cookies = cookie.parse(req.headers.cookie || '');

  // Get the visitor name set in the cookie
  var name = cookies.name;

  res.setHeader('Content-Type', 'text/html; charset=UTF-8');

  if (name) {
    res.write('<p>Welcome back, <b>' + escapeHtml(name) + '</b>!</p>');
  } else {
    res.write('<p>Hello, new visitor!</p>');
  }

  res.write('<form method="GET">');
  res.write('<input placeholder="enter your name" name="name"> <input type="submit" value="Set Name">');
  res.end('</form>');
}

http.createServer(onRequest).listen(3000);
Code language: JavaScript (javascript)

5. express에서 쿠키

const express = require('express');
const cookieParser = require('cookie-parser');

const app = express();
app.use(cookieParser());

// 쿠키 생성 라우트
app.get('/set-cookie', (req, res) => {
  res.cookie('myCookie', 'Hello, this is my Cookie', { maxAge: 900000, httpOnly: true });
  res.send('Cookie has been set');
});

// 쿠키 읽기 라우트
app.get('/get-cookie', (req, res) => {
  if (req.cookies.myCookie) {
    res.send(req.cookies.myCookie);
  } else {
    res.send('No cookie found');
  }
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});
Code language: PHP (php)

expresscookie-parser를 사용하여 쿠키를 생성하고 읽는 간단한 서버다.

express에서는 cookie-parser를 사용하여 간단하게 쿠키를 생성하고 읽을 수 있다.


댓글 남기기