이전에 코드에서 새로고침을 할 때 조회수가 증가하는 문제가 생겼다.

조회수 증가를 막아보자!

추가적으로 수정 시 현재 날짜를 반영하도록 구현해보자!

파일 목록

📦Board
┣ 📂board
┃┣ 📜list.html
┃ ┣ 📜modify.html
┃ ┣ 📜view.html
┃ ┗ 📜write.html
┣ 📂public
┃ ┗ 📂js
┃ ┃ ┣ 📜list.js
┃ ┃ ┣ 📜modify.js
┃ ┃ ┣ 📜view.js
┃ ┃ ┗ 📜write.js
┗ 📜index.html

구현

  • view 페이지에서 새로고침을 할 때 조회수 증가 막기
  • 수정 시 현재 날짜 반영

게시판 구현

게시판 구조

게시판 구조

view 페이지에서 새로고침을 할 때 조회수 증가 막기

나는 새로고침 증가 시 조회수를 막기 위해 boards 데이터에 refresh라는 속성을 추가해 주었다.

# public/js/write.js

 

const writeFrm = document.querySelector("#writeFrm");

// 데이터 기본 틀
class Board {
  constructor(indexNum, subjectStr, writerStr, contentStr) {
    this.index = indexNum;
    this.Subject = subjectStr;
    this.Writer = writerStr;
    this.Content = contentStr;
    this.date = recordDate();
    this.views = -1;
    this.refresh = false; // 추가된 부분
  }

  // 값 설정시 빈 값 체크
  set Subject(value) {
    if (value.length === 0) throw new Error("제목을 입력해주세요.");
    this.subject = value;
  }

  set Writer(value) {
    if (value.length === 0) throw new Error("작성자를 입력해주세요.");
    this.writer = value;
  }

  set Content(value) {
    if (value.length === 0) throw new Error("내용을 입력해주세요.");
    this.content = value;
  }
}

초기에 views속성을 처음에 -1로 설정해주고 refresh 속성을 false로 설정해주었다.

views 속성을 -1로 설정한 이유와 refresh 속성을 false로 설정한 이유는 view.js 코드에서 설명하겠다.

// 현재 날짜 반환 함수
const recordDate = () => {
  const date = new Date();
  const yyyy = date.getFullYear();
  let mm = date.getMonth() + 1;
  let dd = date.getDate();

  mm = (mm > 9 ? "" : 0) + mm;
  dd = (dd > 9 ? "" : 0) + dd;

  const arr = [yyyy, mm, dd];

  return arr.join("-");
};

// 글작성 버튼
const submitHandler = (e) => {
  e.preventDefault();
  const subject = e.target.subject.value;
  const writer = e.target.writer.value;
  const content = e.target.content.value;

  try {
    // boards 가져오기
    const boardsObj = JSON.parse(localStorage.getItem("boards"));

    // 객체 추가
    const index = boardsObj.length;
    const instance = new Board(index, subject, writer, content);
    boardsObj.push(instance);

    // boards 저장
    const boardsStr = JSON.stringify(boardsObj);
    localStorage.setItem("boards", boardsStr);
    location.href = "/board/view.html?index=" + index;
  } catch (e) {
    // 예외 발생시 메시지 출력
    alert(e.message);
    console.error(e);
  }
};

writeFrm.addEventListener("submit", submitHandler);

# public/js/list.js

let boardsStr = localStorage.getItem("boards");

// localStorage 초기값 지정
if (boardsStr === null) {
  const listStr = JSON.stringify([]);
  localStorage.setItem("boards", listStr);
  boardsStr = listStr;
}

const boardsObj = JSON.parse(boardsStr);

// 템플릿 생성
const template = (index, objValue) => {
  return `
  <tr>
  <td>${index + 1}</td>
  <td><a href="/board/view.html?index=${objValue.index}">${objValue.subject}</a></td>
  <td>${objValue.writer}</td>
  <td>${objValue.date}</td>
  <td>${objValue.views}</td>
  </tr>
  `;
};

// 템플릿 반영
const tbody = document.querySelector("tbody");

for (let i = 0; i < boardsObj.length; i++) {
  tbody.innerHTML += template(i, boardsObj[i]);
  // 추가된 부분
  boardsObj[i].refresh = false;
  const refreshStr = JSON.stringify(boardsObj);
  localStorage.setItem("boards", refreshStr);
}

 

list 페이지에서 게시글 목록을 출력해줄 때 boards 객체의 refresh 속성을 모두 false로 바꿔서 localStorage에 반영을 해준다.

그 이유는 view.js 부분에서 설명하도록 하겠다.

# public/js/view.js

const boardsStr = localStorage.getItem("boards");
const boardsObj = JSON.parse(boardsStr);

const idx = location.search;
const index = idx.split("=")[1];
const board = boardsObj[index];

const beforeUrl = document.referrer;

// 조회수 수정된 부분
if (!board.refresh) {
  board.views++;
  board.refresh = true;
  const viewCountStr = JSON.stringify(boardsObj);
  localStorage.setItem("boards", viewCountStr);
} else {
  if (beforeUrl === " ") {
    board.views++;
    const viewCountStr = JSON.stringify(boardsObj);
    localStorage.setItem("boards", viewCountStr);
  }
}

만약 boards 데이터의 refresh가 false라면 조회수를 1 증가시키고 localStorage에 반영한다.

wirte.js에서 글을 작성하면 view 페이지로 넘어오게 되는데 이때 값이 1이 증가하게 되기 때문에 write.js에서 views의 초기값을 -1로 설정해주었다.

이렇게 하면 작성하고 view 페이지로 넘어오면 조회수가 0부터 시작한다.

만약 refresh 가 false라면 list 페이지에서 왔다고 보고 조회수를 1 증가시킨 뒤 boards 데이터의 refresh 속성을 true 바꾼다.

새로고침을 하게 되면 view.js 파일을 다시 로드하게 되는데 boards의 refresh 속성이 true이기 때문에 조회수가 증가하지 않는다. 

예외로 이전 url이 빈 값인 url 즉 url에 직접 입력해서 들어온 경우 조회수를 1 증가시킨다.

이 경우에도 새로고침을 해도 조회수가 증가하지 않는다.

// 데이터 출력
const viewFrm = document.querySelectorAll("#viewFrm > div");

for (let i = 0; i < viewFrm.length; i++) {
  const id = viewFrm[i].id;
  viewFrm[i].innerHTML += " " + board[id];
}

// 수정 버튼
const modifyBtn = document.querySelector("#modify");

const modifyBtnHandler = (e) => {
  location = "/board/modify.html" + idx;
};

modifyBtn.addEventListener("click", modifyBtnHandler);

// 삭제 버튼
const deleteBtn = document.querySelector("#delete");

const deleteBtnHandler = (e) => {
  boardsObj.splice(index, 1);
  for (let i = 0; i < boardsObj.length; i++) {
    boardsObj[i].index = i;
  }

  const setBoardsStr = JSON.stringify(boardsObj);
  localStorage.setItem("boards", setBoardsStr);
  location.href = "/board/list.html";
};

deleteBtn.addEventListener("click", deleteBtnHandler);

수정 시 현재 날짜 반영

const modifyFrm = document.querySelector("#modifyFrm");
const modifyFrmList = document.querySelectorAll("#modifyFrm > div");
const idx = location.search;
const index = location.search.split("=")[1];
const boardsObj = JSON.parse(localStorage.getItem("boards"));
const board = boardsObj[index];

// 게시글의 데이터 값 출력
for (let i = 0; i < modifyFrmList.length; i++) {
  const element = modifyFrmList[i].childNodes[1];
  const id = element.name;
  element.value = board[id];
}

// 작성한 입력 값이 빈 값인지 검사
const isEmpty = (subject, writer, content) => {
  if (subject.length === 0) throw new Error("제목을 입력해주세요");
  if (writer.length === 0) throw new Error("작성자를 입력해주세요");
  if (content.length === 0) throw new Error("내용을 입력해주세요");
};

// 현재 날짜 반환 함수
const recordDate = () => {
  const date = new Date();
  const yyyy = date.getFullYear();
  let mm = date.getMonth() + 1;
  let dd = date.getDate();

  mm = (mm > 9 ? "" : 0) + mm;
  dd = (dd > 9 ? "" : 0) + dd;

  const arr = [yyyy, mm, dd];

  return arr.join("-");
};

이전에 write.js에서 사용한 현재 날짜를 반환해주는 함수인 recordDate를 사용하였다.

// 수정완료 버튼
const modifyHandler = (e) => {
  e.preventDefault();
  const subject = e.target.subject.value;
  const writer = e.target.writer.value;
  const content = e.target.content.value;

  try {
    isEmpty(subject, writer, content);
    board.subject = subject;
    board.writer = writer;
    board.content = content;
    board.date = recordDate();

    const boardsStr = JSON.stringify(boardsObj);
    localStorage.setItem("boards", boardsStr);
    location.href = "/board/view.html" + idx;
  } catch (e) {
    alert(e.message);
    console.error(e);
  }
};

수정 완료 버튼을  누르면 recordDate함수를 호출해 반환 값을 boards의 데이터에 덮어쓰도록 구현하였다.

const backBtn = document.querySelector("#back");

// 뒤로가기 버튼
const backBtnHandler = (e) => {
  location.href = document.referrer;
};

modifyFrm.addEventListener("submit", modifyHandler);
backBtn.addEventListener("click", backBtnHandler);

게시판 구경하기

최종 결과물  👈 클릭