(Javascript) 4. Refactoring

김동우·2021년 7월 17일
0

wecode

목록 보기
17/32

잠깐! 시작하기 전에

이 글은 wecode에서 실제 공부하고(이제 사전 스터디는 아닙니다.), 이해한 내용들을 적는 글입니다. 글의 표현과는 달리 어쩌면 실무와는 전혀 상관이 없는 글일 수 있습니다.

또한 해당 글은 다양한 자료들과 작성자 지식이 합성된 글입니다. 따라서 원문의 포스팅들이 틀린 정보이거나, 해당 개념에 대한 작성자의 이해가 부족할 수 있습니다.

설명하듯 적는게 습관이라 권위자 발톱만큼의 향기가 조금은 날 수 있으나, 엄연히 학생입니다. 따라서 하나의 참고자료로 활용하시길 바랍니다.

글의 내용과 다른 정보나 견해의 차이가 있을 수 있습니다.
이럴 때, 해당 부분을 언급하셔서 제가 더 공부할 수 있는 기회를 제공해주시면 감사할 것 같습니다.


서론

벌써 위코드 생활을 시작한지 2주가 되었습니다.

시간이 정말 빠르다는 것을 실감하고 있습니다.

주말에는 평일에 작성한 코드를 다시 한 번 돌아보기로 했으니, 오늘은 Refactoring을 진행하고 느꼈던 점들에 대해 써보겠습니다.

Javascript Refactoring

저는 Code Refactoring은 현재 스스로의 수준을 판단할 수 있는 가장 효과적인 방법이라고 생각합니다.

지금의 저는 Javascript의 기본적인 개념을 공부하고 있지만, 더 많은 지식을 가진 상태의 저는 또 다른 방향을 제시할 수 있을 것 같습니다.

또한 지식이라는 표현은 꼭 Javascript에 해당하는 지식을 말하는 것이 아닙니다.

저는 더 나은 플로우를 구성할 수 있는 능력은 다양한 분야의 지식과 경험에서 나온다고 생각합니다.

당장 제게 필요한 것은 Javascript의 경험과 자료구조 정도일 것 같지만요.

그러니 오늘도 열심히 공부해서 어제의 나를 객관적으로 평가할 수 있도록 나아가봅시다.

아름다운 코드의 기준

Refactoring을 할 때, 서로 다른 관점으로 코드를 바꾼다고 생각합니다.

개인적으로 제가 생각하는 아름다운 코드는 현재 제가 알고 있는 최선의 방법, 또는 기존의 코드보다 뛰어난 무언가를 가진 코드입니다.

그렇게 작은 범위의 시야로 Refactoring을 진행해야 한다고 생각하는 이유는 코드행 모두 의미를 가지고 있어야 한다는 집착이 있기 때문인 것 같습니다.

반대로, 아예 처음부터 플로우를 새로 고민해보는 사람도 있으실 것 같습니다만, 지금 수준의 저는 내부에서 외부로 진행되는 것 같습니다.

즉, 코드행의 당위성을 검사하고, 더 나은 방식이 있는지를 먼저 고민한 다음 함수의 당위성을 검사하는 순서입니다.

이를 통해 플로우 전체를 현재보다 더 나은 수준으로 변경하는 방식이 됩니다.

새로 설계해서 동일한 기능을 유지한 채 전체를 바꾸는 능력은 아직 저에게는 먼 미래라고 생각이 드네요.

변경 과정

1. 원본 함수 내 코드 점검

먼저, 원본 함수 내 코드를 점검한다는 말은 동일한 기능을 가진 메서드가 존재하는지 다시 한 번 생각해보는 일로 시작합니다.


function createComments(idString, textString) {
  const photoComments = document.querySelector(`.photo__comments`);
  const commentsIdText = [idString, textString];

  const commentsDesc = document.createElement(`div`);

  commentsIdText.forEach((x) => {
    let commentsWrap = document.createElement(`div`),
      commentsAnchor = document.createElement(`a`);

    commentsAnchor.innerHTML = `${x}`;
    commentsWrap.appendChild(commentsAnchor);
    commentsDesc.appendChild(commentsWrap);
    commentsDesc.className = `comments__desc`;
  });

  const commentsLikeOrDelete = document.createElement(`div`),
    commentsLikeBtn = document.createElement(`button`),
    commentsLike = document.createElement(`i`),
    commentsDelete = document.createElement(`button`);

  commentsLikeOrDelete.classList.add(`comments__desc-button-block`);
  commentsLike.classList.add(`far`);
  commentsLike.classList.add(`fa-heart`);

  commentsLikeBtn.id = `commentsLikeButton` + photoComments.childElementCount;
  commentsDelete.id = `commentsDeleteButton` + photoComments.childElementCount;

  commentsDelete.innerHTML = `삭제`;

  commentsLikeBtn.appendChild(commentsLike);
  commentsLikeOrDelete.appendChild(commentsLikeBtn);
  commentsLikeOrDelete.appendChild(commentsDelete);
  commentsDesc.appendChild(commentsLikeOrDelete);

  commentsDesc.id = `comments` + photoComments.childElementCount;

  photoComments.appendChild(commentsDesc);
}

상당히 길지만, 결과는 viewport에 댓글 한 줄을 구현할 뿐인 코드입니다.

입력받은 id, text로 댓글을 구현하고, 오른쪽에 좋아요와 삭제 버튼을 만들기 위한 코드입니다.

그 외에 좋아요, 삭제 기능을 위한 id 값을 button에 할당해주고 있습니다.

이제 이 코드를 수정해봅시다.

2. 보다 나은 메소드 사용

우선, 해당 코드에는 innerHTML 값을 할당하는 코드행이 있습니다.

그런데, innerHTML이라는 값이 언뜻 보기에는 String 값을 text 형태로 표현하는 것으로 보입니다.

MDN에서 급하게 innerText, innerHTML 메소드를 검색하며 사용했으니, 당연히 정확한 기능을 모를 수 밖에 없었습니다.

그렇다면 본래의 innerHTML은 어떤 기능을 수행하는지 다시 한 번 읽어봅시다. (출처 - MDN)

코드부터 허겁지겁 보느라 놓쳤지만, 마크업을 가져오거나 설정합니다. 라는 문구를 통해 태그를 직접 설정할 수 있다는 가정으로 이어질 수 있습니다.

그렇다면

"createElement() 메소드가 아닌 Element.innerHTML 로 HTML template을 직접 타이핑하여 집어넣을 수 있지 않을까 ?"

하는 생각을 가지고 Refactoring을 진행해봅시다.


function createComments(idString, textString) {
  const photoComments = document.querySelector(`.photo__comments`),
    commentsDesc = document.createElement(`div`);

  let commentsCount = photoComments.childElementCount;

  if (commentsDesc !== null) {
    commentsDesc.innerHTML = `<div class = "comments__desc">
          <div><a href="">${idString}</a></div>
          <div><a href="">${textString}</a></div>
          <div class = "comments__desc-button-block">
            <button id = "likeButton${commentsCount}" class = "comments__like-button"><i class = "far fa-heart"></i></button>
            <button id = "deleteButton${commentsCount}" class = "comments__delete-button">삭제</button>
        </div>`;
    photoComments.appendChild(commentsDesc);
  }
  
  // 이벤트 함수 호출은 무시하셔도 됩니다.
  // commentslikeButtonEvent();
  // commentsDeleteButtonEvent();
  // 이벤트 함수 호출은 무시하셔도 됩니다.
}

자, 운이 좋아 단번에 간단히 바꿀 수 있었습니다.

심지어 기존의 코드보다 직접 HTML tag 구조를 명확히 알 수 있습니다.

사용하는 메소드의 수가 적어진 것은 물론이며, 추후 레이아웃이 바뀌더라도 코드를 쉽게 수정할 수 있게 되었습니다.

이제야 Refactoring의 목적인 유지보수성 향상을 체감할 수 있게 되었습니다.

해당 1, 2 과정을 반복하고, 최대한 모든 함수를 쪼갤 수 있는 과정이 끝나면 호출 위치를 변경하는 등의 플로우 변경이 이어집니다.

결국 내부의 수정을 먼저 진행하고, 다시 전체적인 함수 블럭을 끼워맞추게 되는 것 같습니다.

Refactoring 과정만 봐도 스스로의 수준이 한참 부족하다는 생각을 조금 더 하게 되는 것 같습니다.

마치며

간단한 예시만 작성했지만, 실제로 위 코드 외에 다양한 수정이 현재 제 파일 내에서 이루어지고 있습니다.

그간 관심에도 없던 클로저를 처음으로 써보고, 변수선언을 어느 환경에 넣을지 본격적으로 고민하기도 합니다.

제가 아는 기본적인 개념을 모두 동원하고, 부족하면 더 찾아서 공부하고 있으니 분명 더 좋은, 아름다운 코드가 나오지 않을까 기대하고 있습니다.

추후에 정말 다양한 경험과 지식을 보유한 상태로 위의 코드를 다시 한 번 보고 싶다는 생각이 들기도 합니다.

Refactoring은 어쩌면 스스로와 코드 사이의 추억을 떠올리게 해주는 낭만이 있는지도 모르겠습니다.

그럼 이번 글은 여기서 마치겠습니다.

읽어주셔서 감사합니다.

0개의 댓글