Javascript 안티 패턴 #1

작업 경험에 따른 지양하는 코드에 관한 이야기


들어가며

‘배열을 순환할 때 왜 for문만 사용하는 것인가’에서 시작한 저의 좋지 않은 코드 습관에 대해 돌아보고자 개인적인 경험으로 작성하게 되었습니다.
(XE 그룹 노션에 먼저 게시한 주제였으며 1차 글에 관한 내용을 보완하여 작성하였습니다.)

👎 script로 inline style 입히기

평소 사용하지 않았던 inline style을 javascript로 써보자는 단순한 생각에서 사용하게 되었습니다. 그 결과 class 제어와 다르게 드러나는 단점에 대해 여실히 겪을 수 있었습니다.


// javascript
inputArea[i].addEventListener('focusin', (event) => {
  const target = event.currentTarget;
  target.style.borderBottomColor = '#42588a';
});
<!-- 브라우저 -->
<div class="input_area" style="border-bottom-color: rgb(190, 201, 212);">
  <input type="text" id="inputStyle0101" placeholder="Placeholder" />
</div>
  • 코드가 길어짐
    javascript 코드에서나 개발자도구 element 탭에서나 클래스 제어에 비해 코드의 길이가 길어집니다. 가독성을 떨어뜨리며 수정이 번거롭습니다.
  • 스타일 오류를 일으킴
    DOM을 복사할 때 개발자도구 element 탭에서 하는 경우가 많습니다. 그럼 당연히 script로 넣어진 스타일까지 복사되는데 프로젝트에 투입되어 html를 사용하는 모든 작업자가 이 부분에 대해 의식하고 있는 경우는 많지 않았습니다. 후에 스타일 오류가 있다고 해서 확인해 보면 inline style까지 넣은 경우가 대부분이었습니다.
  • script 파일 수정에 대한 부담감이 있을 수 있음(특히 개발 막바지의 경우)
    script 작업의 경우 UI 개발에서 코드는 개발자와 공유 되며, 그 후 개발자에 의해 수정 및 가공이 됩니다. 그렇기에 간단한 수정도 개발자와 공유되어야 합니다. 특히 공통 모듈이 아니라면 개발자 모두가 그 수정된 코드에 대해 반영이 필요한 거죠. 그래서 CSS 수정으로 UI 선에서 마칠 수 있는 수정 건이 20개의 개발 소스에 적용이 필요한 작업으로 될 수 있습니다.

👉 모든 경우는 아니지만 스타일 요소 제어는 class 사용을 지향

👎 함수 문법의 복합 사용

  • 함수 선언문
    선언 위치에 관련 없이 내부적으로 호이스팅이 됨
  • 함수 표현식
    함수 호출 후 함수를 선언하며 함수 내부가 실행되지 않을 수 있으며 호이스팅에 대한 비용이 발생함
// 함수 선언문
function agreeAllAciton() {
  // 중략 ..
}

// 함수 표현식
const checkedAllAction = () => {
  // 중략 ..
};

위와 같은 문법으로 구분하여 쓸 수 있는데
아래 코드는 addEventListener 실행 후 함수 선언, 의미에 맞지 않은 let을 사용하고 있습니다.
let checkedAll = document.querySelector('input[data-role="checked-all"]');
// 함수 호출
checkedAll.addEventListener('click', checkedAllAction);

// 함수 선언(함수 표현식)
const checkedAllAction = () => {
  if (checkedAll.checked) {
    checkedAllList.forEach((checkbox) => {
      checkbox.checked = true;
    });
  }
};

함수의 복합적인 문법의 사용은 코드의 통일성을 떨어뜨립니다. 또한 함수는 문법과 위치에 따라 호이스팅(끌어올림)과 함수 미실행 등의 오류를 발생시키기 때문에 함수 실행을 이해하고 통일된 문법을 사용하는 것이 필요합니다.

👉 호이스팅을 고려한 함수표현식 선언

const checkedAll = document.querySelector('input[data-role="checked-all"]');

// 함수 선언(함수 표현식)
const checkedAllAction = () => {
	// 중략 ..
};

// 함수 호출
checkedAll.addEventListener('click', checkedAllAction);
};



👎 비객체화 코드

// javascript
const inputText = document.querySelector('input');

if (inputText !== null && btnValueReset.value.lenght > 0) {
  const onResetText = () => {
    e.target.value = '';
  };
  setfocus() => {},
  setDisabled() => {},
	// 중략

  inputText.addEventListener('input', onResetText);
}

비객체화 코드로 작업할 때 선택자(변수 btnValueReset)에 대한 캐시 여부,함수 선언, 함수 호출의 형태로 작업하게 됩니다. 이런 문법은 비슷한 코드를 양상 시키기 때문에 재사용성을 떨어뜨려 코드 퀄리티를 낮추는 원인이 될 수 있습니다.

👉 코드 객체화

const onInputText = {
  setReset(e) => {
    e.target.value = '';
  },
  setfocus() => {},
  setDisabled() => {},
	// 중략
};

const inputText = document.querySelector('input');
  if(btnValueReset !== null && btnValueReset.value.lenght > 0) {
		inputText.addEventListener('input', onInputText.setReset(e));
  }
});



마치며

일반적인 Javascript 안티 패턴의 내용은 아니지만, 경험에 의한 내용이다 보니 의의가 있는 시간이었습니다. 다음 편에서는 이 글을 쓰게 된 계기인 반복 구문에 관한 내용을 작성할 예정입니다.

고맙습니다. - 끄읕 -


추천 글