Today Sangmin Learned
728x90

몇 달 전에, 개발 용어 위키를 위한 JS 태그 작업을 하고자 JavaScript 코드를 아래와 같이 작성했다.

/* add Tag by click or press enter, comma, space */
var elements = document.getElementById("element");
var taskSubmit = document.getElementById("btn_add_task");
var taskBox = document.querySelector("#text_task");
var taskList = document.getElementById("list_tasks");
var taskLi = document.querySelectorAll("ul li");

/* Prevent input other than Korean, English and numbers */
taskBox.addEventListener("keyup", removeSpecial);
function removeSpecial(e) {
  e.target.value = e.target.value.replace(/[^ㄱ-힣a-zA-Z0-9+#]/gi, "");
}
/* Prevent duplicate tags */
var checkSame = [];
/* click */
$("#text_task").keyup(function (e) {
  var keyCode = e.keyCode;
  if (e.keyCode == 13 || e.keyCode == 188 || e.keyCode == 32) {
    var task = taskBox.value.trim().toLowerCase();
    var newLi = document.createElement("li");
    var input = document.createElement("input");
    input.type = "hidden";
    input.value = task;
    input.name = "tagList";
    var removeBtn = document.createElement("button");
    var element = newLi.appendChild(document.createTextNode(task));
    if (taskBox.value != "" && checkSame.includes(task) === false) {
      checkSame.push(task);
      taskList.appendChild(newLi);
      newLi.appendChild(input);
      newLi.appendChild(removeBtn);
      removeBtn.innerHTML = "X";
      taskBox.value = "";
      removeBtn.addEventListener("click", function () {
        removeBtn.parentNode.removeChild(removeBtn);
        newLi.parentNode.removeChild(newLi);
        checkSame.splice(checkSame.indexOf(task), 1);
      });
    } else {
      taskBox.value = "";
      alert("중복된 태그입니다.");
    }
  }
});

taskSubmit.addEventListener("click", clickFunction, false);
function clickFunction(e) {
  var keyCode = e.keyCode;
  var task = taskBox.value.trim().toLowerCase();
  var newLi = document.createElement("li");
  var removeBtn = document.createElement("button");
  var element = newLi.appendChild(document.createTextNode(task));
  if (taskBox.value != "" && checkSame.includes(task) == false) {
    checkSame.push(task);
    e.preventDefault();
    taskList.appendChild(newLi);
    newLi.appendChild(removeBtn);
    removeBtn.innerHTML = "X";
    taskBox.value = "";
    removeBtn.addEventListener("click", function () {
      removeBtn.parentNode.removeChild(removeBtn);
      newLi.parentNode.removeChild(newLi);
      checkSame.splice(checkSame.indexOf(task), 1);
    });
  } else {
    taskBox.value = "";
    alert("중복된 태그입니다.");
  }
}

이 난잡한 코드들은, 아래 영상의 기능을 구현하기 위한 것이다.

 

클릭 및 keyup을 통해 태그 추가하기

이 JavaScript 코드가 동작을 잘 하긴 하지만, 문제는 '단지 구현만 되도록 만든 코드'였다는 점이다. 처음에 keyup으로 이벤트 리스너를 줬을 때, click 이벤트로는 먹지 않았고 그래서 그냥 중복되었다는 것을 알고 있음에도 불구하고 click에 대한 이벤트 리스너를 또 만들어서, 거기다가 똑같은 내용을 또 추가했다.

그래서 작동은 되지만 전혀 좋은 코드라고 볼 수가 없었다. 즉 재사용이 불가능한 코드라는 점이다.. 그래서 하나를 하더라도 제대로 하자는 생각을 하게 되었고, 그에 따라 개발자 친구의 말에 따라 코드 리팩토링을 했다. 우선 첫 번째 목표는, click과 keyup 각각에 대해 둘 다 작동을 제대로 할 수 있도록 하나의 통일된 function을 만드는 것이었다.

두 개에 동시에 사용될 코드라고 한다면, 우선 e.keyCode에 대한  if문부터 없애야 했다. 그래서 이를 없앤 후 

function tagFunction() {
  const task = taskBox.value.trim().toLowerCase();
  const newLi = document.createElement("li");
  const input = document.createElement("input");
  input.type = "hidden";
  input.value = task;
  input.name = "tagList";
  const removeBtn = document.createElement("button");
  const element = newLi.appendChild(document.createTextNode(task));
  if (taskBox.value != "" && checkSame.includes(task) === false) {
    checkSame.push(task);
    taskList.appendChild(newLi);
    newLi.appendChild(input);
    newLi.appendChild(removeBtn);
    removeBtn.innerHTML = "X";
    taskBox.value = "";
    removeBtn.addEventListener("click", function () {
      removeBtn.parentNode.removeChild(removeBtn);
      newLi.parentNode.removeChild(newLi);
      checkSame.splice(checkSame.indexOf(task), 1);
    });
  } else if (checkSame.includes(task) === true) {
    taskBox.value = "";
    alert("중복된 태그입니다.");
  }
}

이와 같은 형태로 나타냈다. 그 다음에, click에 대해서는 바로 tagFunction이 실행될 수 있도록

taskSubmit.addEventListener("click", tagFunction, false);

이와 같이 처리했고, keyup에 대해서는, keyCode에 대한 if문이 필요했기 때문에

taskBox.addEventListener("keyup", function (e) {
  const keyCode = e.keyCode;
  if (e.keyCode == 188 || e.keyCode == 32 || e.keyCode == 13) {
    tagFunction();
  }
});

이와 같이 188 (,), 32(스페이스바), 13(엔터) 을 눌렀을 때 tagFunction이 실행되도록 하였다.

종합하면, 

/* add Tag by click or press enter, comma, space */
var elements = document.getElementById("element");
var taskSubmit = document.getElementById("btn_add_task");
var taskBox = document.querySelector("#text_task");
var taskList = document.getElementById("list_tasks");
var taskLi = document.querySelectorAll("ul li");

/* Prevent input other than Korean, English and numbers */
taskBox.addEventListener("keyup", removeSpecial);
taskSubmit.addEventListener("click", removeSpecial);
function removeSpecial(e) {
  e.target.value = e.target.value.replace(/[^ㄱ-힣a-zA-Z0-9+#]/gi, "");
}
let checkSame = [];
taskBox.addEventListener("keyup", function (e) {
  const keyCode = e.keyCode;
  if (e.keyCode == 188 || e.keyCode == 32 || e.keyCode == 13) {
    tagFunction();
  }
});
taskSubmit.addEventListener("click", tagFunction, false);
function tagFunction() {
  const task = taskBox.value.trim().toLowerCase();
  const newLi = document.createElement("li");
  const input = document.createElement("input");
  input.type = "hidden";
  input.value = task;
  input.name = "tagList";
  const removeBtn = document.createElement("button");
  const element = newLi.appendChild(document.createTextNode(task));
  if (taskBox.value != "" && checkSame.includes(task) === false) {
    checkSame.push(task);
    taskList.appendChild(newLi);
    newLi.appendChild(input);
    newLi.appendChild(removeBtn);
    removeBtn.innerHTML = "X";
    taskBox.value = "";
    removeBtn.addEventListener("click", function () {
      removeBtn.parentNode.removeChild(removeBtn);
      newLi.parentNode.removeChild(newLi);
      checkSame.splice(checkSame.indexOf(task), 1);
    });
  } else if (checkSame.includes(task) === true) {
    taskBox.value = "";
    alert("중복된 태그입니다.");
  }
}

이와 같은 방식인 것이다. 쓸 데 없는 중복은 좀 줄였으나 아직 코드가 좋은 코드라고 생각하진 않는다. 위에 코드에서

$("#text_task").keyup(function(e) { ... });

이 부분은, Vanilla JS로 바꿨을 때 오류가 났던 거라 어쩔 수 없이 jQuery로 한 건데, 이 부분도 해결이 되어서 다행이다.

profile

Today Sangmin Learned

@steadily-worked

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!