[Express] 쿠키로 다크모드 구현

2023. 8. 8. 23:08공부 중/Node.js

1. 쿠키를 활용해서 다크모드 구현하기

 

기존 페이지는 리로딩할 때마다 다크모드가 꺼지는 문제가 있었다.

 

그래서 다른 페이지로 이동하거나 리로딩해도 다크모드가 그대로 유지되도록 해보자.

 


가. 쿠키 생성

 

다크모드에 관한 정보를 저장하는 쿠키를 만든다.

 

1) cookie-parser 설치

npm install cookie-parser

 

 

2) 미들웨어 추가

// app.js
const cookieParser = require('cookie-parser');
const checkCookie = require('./lib/checkCookie.js');

...

app.use(cookieParser());
app.use(checkCookie.checkDarkMode);

...
// ./lib/checkCookie.js

const express = require('express');

module.exports.checkDarkMode = (req, res, next)=>{
    res.cookie('dark-mode', true);    
    next();
}

cookieParser와 새로 만든 checkCookie.checkDarkMode 미들웨어를 추가한다.

 

  • app.use(checkCookie.checkDarkMode); : 모든 요청에 대하여 checkCookie.checkDarkMode를 실행한다.

 

사실 모든 요청마다 checkCookie.checkDarkMode가 필요한 것은 아니라서 http get method에만 동작하도록 수정한다.

 

app.get('*', checkCookie.checkDarkMode);

 

 

dark-mode 쿠키가 생성된 것을 알 수 있다.

 


나. 쿠키 읽기

 

지금까지는 매번 dark-mode 쿠키의 값이 true로 초기화된다.

 

쿠키가 없으면 생성해야 하지만 기존에 쿠키가 존재한다면 다시 생성하지 않도록 수정한다.

 

+ 쿠키의 이름을 darkMode로, default 값을 false로 수정한다.

module.exports.checkDarkMode = (req, res, next)=>{
    if(req.cookies.darkMode === undefined)
        res.cookie('darkMode', false);    
    next();
}

 


다. 페이지 로딩 때 모드 반영하기

 

1) 클라이언트에서 원하는 쿠키값을 읽는 방법

 

쿠키와 document.cookie

 

ko.javascript.info

// 주어진 이름의 쿠키를 반환하는데,
// 조건에 맞는 쿠키가 없다면 undefined를 반환합니다.
function getCookie(name) {
  let matches = document.cookie.match(new RegExp(
    "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
  ));
  return matches ? decodeURIComponent(matches[1]) : undefined;
}

위에 코드를 응용해서 다음 코드를 추가한다.

 

...

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

 

 

2) 페이지 로딩 때 쿠키값을 읽어서 모드 적용하기

// darkMode.js <- color.js에서 개명함.

...

function nightDayHandler() {
  if(getCookie('darkMode') === 'true'){
    Body.setBackgroundColor("black");
    Body.setColor("white");
    Links.setColor("white");
    Lists.setColor("black");
  } else {
    Body.setBackgroundColor("white");
    Body.setColor("black");
    Links.setColor("black");
    Lists.setColor("white");
  }
}

nightDayHandler()가 호출되면 쿠키값에 맞춰 밝기를 조절한다.

 

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>WEB - ${req.title}</title>
        <link rel="stylesheet" href="/static/css/style.css">
        <script src="/static/js/crudBtn.js"></script>
        <script src="/static/js/darkMode.js"></script>
        <script>nightDayHandler()</script>
</head>

<script>nightDayHandler()</script>을 추가해서 페이지가 로딩될 때 쿠키값대로 다크모드를 적용하려고 했다.

 

3) Uncaught TypeError: Cannot read properties of null (reading 'style')

darkMode.js:3 Uncaught TypeError: Cannot read properties of null (reading 'style')
    at Object.setBackgroundColor (darkMode.js:3:35)
    at nightDayHandler (darkMode.js:38:10)
    at (index):12:17

아직 DOM에 완전히 자리 잡기 전에 스크립트가 동작해서 Cannot read properties of null error를 발생했다.

 

문제를 해결하기 위해서는 DOM에 콘텐츠가 완전히 로딩되었는지 기다리는 리스너를 추가한다.

 

<script>
    document.addEventListener("DOMContentLoaded", ()=>{
        nightDayHandler();
    });
</script>

 

 

이제 처음에 페이지를 로딩할 때 쿠키값대로 화면밝기가 조절된다.

 

출처 : https://isotropic.co/how-to-fix-cannot-read-property-style-of-null-in-javascript/

 


라. 버튼을 눌러서 모드 변경하기

 

1) 클라이언트에서 쿠키값을 변경하는 법

document.cookie = "user=John"; // 이름이 'user'인 쿠키의 값만 갱신함

버튼을 누르면 쿠키를 값을 바꾸고 쿠키값에 따라서 화면밝기를 바꾸도록 만든다.

 

function changeDarkMode(self) {
  if (self.value === "night") {
    document.cookie = "darkMode=false"; 
    self.value = "day";
  } else {
    document.cookie = "darkMode=true"; 
    self.value = "night";
  }
  nightDayHandler();
}
//html
<input type="button" value="night" onclick="changeDarkMode(this)"/> </div>

 

2) 버그 : /topic에서 버튼을 누르면 쿠키가 중복 생성됨

 

/에서는 문제없이 잘 돌아간다.

 

하지만 /가 아닌 /topic에서 버튼을 누르면 쿠키가 중복해서 생성되는 문제가 발생한다.

 

같은 쿠키가 두개 생성됨.
왼쪽의 night 버튼의 문제

 

버튼을 눌렀을 경우에만 버그가 발생하기 때문에 아래 코드의 문제일 가능성이 크다.

 

function changeDarkMode(self) {
  if (self.value === "night") {
    document.cookie = "darkMode=true"; 
    self.value = "day";
  } else {
    document.cookie = "darkMode=false"; 
    self.value = "night";
  }
  nightDayHandler();
}

/가 아닌 /topic에서 쿠키의 값을 수정하면 쿠키의 path/topic으로 설정되어 나타나는 문제다.

 

function changeDarkMode(self) {
  if (self.value === "night") {
    document.cookie = "darkMode=true; Path=/"; 
    self.value = "day";
  } else {
    document.cookie = "darkMode=false; Path=/"; 
    self.value = "night";
  }
  nightDayHandler();
}

path 옵션을 추가해서 해결한다.

 

3) 버그 : 버튼의 value 오류

 

버튼이 쿠키에 값을 받아와서 value를 선택하도록 수정한다.

 

지금은 쿠키의 값과는 상관없이 무조건 처음에는 night로 고정되어 있다.

 

쿠키값에 맞는 버튼의 value를 설정하도록 변경한다.

 

다크모드에서는 day가 표시되어야한다.

const NightDayBtn = {   // 추가!
  getValue: ()=>{
    let btn = document.getElementById("nightDayBtn");
    return btn.value;
  },
  setValue: ()=>{
    let btn = document.getElementById("nightDayBtn");
    if(getCookie('darkMode') === 'true'){
      btn.value = "day";
    }else{
      btn.value = "night";
    }
    console.log(btn.value);
  }
}
function nightDayHandler() {
  if(getCookie('darkMode') === 'true'){
    Body.setBackgroundColor("black");
    Body.setColor("white");
    Links.setColor("white");
    Lists.setColor("black");
    NightDayBtn.setValue();   // 추가!
  } else {
    Body.setBackgroundColor("white");
    Body.setColor("black");
    Links.setColor("black");
    Lists.setColor("white");
    NightDayBtn.setValue();   // 추가!
  }
}
function changeDarkMode() {
  if (NightDayBtn.getValue() === "night") {   // 변경!
    document.cookie = "darkMode=true; Path=/"; 
  } else {
    document.cookie = "darkMode=false; Path=/"; 
  }
  nightDayHandler();
}
<input id="nightDayBtn" type="button" value="night" onclick="changeDarkMode()"/> </div>

이제 nightDayHandler()만 실행하면 알맞은 버튼의 value가 설정된다.

 


 

'공부 중 > Node.js' 카테고리의 다른 글

[Express] Session이란?  (0) 2023.08.19
[Node.js] 쿠키의 한계  (0) 2023.08.10
[Node.js] 쿠키 옵션  (0) 2023.07.07
[Node.js] 세션 쿠키, 영구 쿠키  (0) 2023.07.06
[Node.js] 쿠키 생성, 읽기  (0) 2023.07.06