TIL . Refactoring Checklist

노도·2022년 3월 11일
0
post-thumbnail

1. Code Refactoring

코드는 계속 많은 추가와 수정을 겪는다. 이를 "유지보수" 라고 칭함.
유지보수를 용이하려면 코드의 가독성과 확장성이 좋아야한다.

Refactoring 란,

'소프트웨어의 겉보기 동작은 그대로 유지한 채, 코드를 이해하고 수정하기 쉽도록,내부 구조를 변경하는 기법' 

쉽게 말해 코드의 가독성과 확장성을 좋게 만드는 작업을 뜻함.
이를 통해 좋은 코드가 무엇인지 고민하며 실력향상에 도움된다.

2. Basic

2-1 console.log 지우기

테스트가 끝난 콘솔은 모두 지우자, 'console.log'는 테스트를 할 때는 필수적이지만 최종 결과물에는 포함되면 안된다.

ex.

function add(a, b) {
  return a + b;
}
function add(a, b) {
  console.log(a);
  console.log(b);
  console.log(a);
  console.log(b);
  console.log(a);
  console.log(b);
  console.log(a);
  console.log(b);
  console.log(a);
  console.log(b);
  console.log(a);
  console.log(b);

  return a + b;
}

위 두 코드는 동작상으로는 어떤 차이도 없다.

console.log는 인자로 들어온 a, b값을 확인하기 위한 테스트의 용도

이러한 console.log가 최종 결과물에 남아있다면 가독성을 해칠 수 있다.

또한 기존의 console.log가 잔존한 상태로 새로운 테스트를 위해 console.log 를 추가했을 때 기존의 console.log와 혼재되어서 내가 진짜로 확인하고 싶은 값이 무엇인지 알기 어려워진다.

코드의 가독성, 다른 팀원을 위한 console.log를 지우는 것은 기본적인 컨벤션

따라서 반드시 테스트를 끝낸 console.log는 지워야한다.

2-2. id ・ class명, 변수명, 함수명

id ・ class, 변수, 함수의 이름에서 의미가 직관적으로 드러나게 작성해주세요 코드는 쓰는 경우보다 읽히는 경우가 훨씬 많다!

프로그래머가 가장 힘들어하는 일 중 대표적인 것이 이름짓기.

변수, 함수, id ・ class의 이름에서 의미가 직관적으로 드러나게 작성해야 함.
왜 이렇게 어려운 이름짓기(naming)에 신경을 써야할까?

// bad
let value = "Tom";
let value2 = "Cruise"

// good
let firstName = "Tom"
let lastName = "Cruise"

밑의 firstName과 lastName이라는 변수명을 보면 각각의 변수가 이름과 성을 나타내고있다는것을 바로 알 수 있다.

이처럼 변수명은 해당 변수가 어떤 의미를 나타내고 있는지 명확하고 직관적으로 이해가 되도록 지어주어야 한다.

// bad
const data = ["tory", "mozzi"];

// good
const petsOfYeonuk = ["tory", "mozzi"];

data, value 등의 포괄적인 이름은 지양해야 한다.

good의 예시에서는 변수명을 보고 이 배열이 어떤 값을 담고있는지(petsOfYeonuk) 바로 이해할 수 있다.

개발자가 보내는 시간 중 코드를 짜는 시간은 10% 밖에 안된다고 함 

나머지 90% 시간은 모두 코드를 읽고 해석하면서 시간을 보낸다고 합니다.

그렇기 때문에 내가 짠 코드를 미래의 내가, 그리고 협업하는 다른 팀원들이 읽기 쉽게 만드는 일은 가장 기본이면서 가장 중요한 일입니다.

따라서, 모두 명확하고 직관적인 네이밍을 통해서 가독성이 좋은 코드를 짜셔야 합니다.

2-3. 들여 쓰기

프로그래밍 언어에서 규칙성 있는 들여 쓰기는 가독성 측면에서 매우 중요합니다.

1번 예시

const thisIsButton = document.getElementsByClassName('login-btn')[0];

thisIsButton.addEventListener('click', function() {
const password = document.getElementById('password').value;
const rePassword = document.getElementById('re-password').value;

if (!password) {
alert('비밀번호를 입력해주세요!');
return;
}
  
if (!rePassword) {
alert('비밀번호 확인을 입력해주세요!');
return;
}

if (password !== rePassword) {
alert('비밀번호가 맞지 않습니다!');
return;
}

alert('회원가입 성공!!');
});

2번 예시

const thisIsButton = document.getElementsByClassName('login-btn')[0];

thisIsButton.addEventListener('click', function() {
const password = document.getElementById('password').value;
const rePassword = document.getElementById('re-password').value;

  if (!password) {
        alert('비밀번호를 입력해주세요!');
    return;
  }
  
  if (!rePassword) {
    alert('비밀번호 확인을 입력해주세요!');
        return;
   }

  if (password !== rePassword) {
    alert('비밀번호가 맞지 않습니다!');
        return;
  }

           alert('회원가입 성공!!');
 });

3번 예시


const thisIsButton = document.getElementsByClassName('login-btn')[0];

thisIsButton.addEventListener('click', function() {
  const password = document.getElementById('password').value;
  const rePassword = document.getElementById('re-password').value;

  if (!password) {
    alert('비밀번호를 입력해주세요!');
    return;
  }
  
  if (!rePassword) {
    alert('비밀번호 확인을 입력해주세요!');
    return;
  }
  
  if (password !== rePassword) {
    alert('비밀번호가 맞지 않습니다!');
    return;
  }
  
  alert('회원가입 성공!!');
});

3번 예시는 규칙성 있는 들여 쓰기로 인해 코드의 가독성이 좋다.

javascript는 2칸 들여 쓰기를 컨벤션, 즉 국룰이다 ㅋㅋ

3. HTML

3-1. Semantic Tag의 사용

지금 나에게 가장 필요한 것,,!!

Semantic Tag를 적절하게 사용하는 것은 가독성 ・ SEO측면에서 너무나 중요. 'div', 'span' 태그를 남발하기 보다는 상황에 맞게 적절한 태그를 사용

ex.
1번

셀프 리팩토링 리팩토링이무엇일까요? 리팩토링은 소프트웨어의 겉보기 동작은 그대로 유지한 채,
코드를 이해하고 수정하기 쉽도록 내부 구조를 변경하는 기법입니다.

2번

제목:셀프 리팩토링 

본문: 
리팩토링이무엇일까요? 리팩토링은 소프트웨어의 겉보기 동작은 그대로 유지한 채,
코드를 이해하고 수정하기 쉽도록 내부 구조를 변경하는 기법입니다.

한결 이해하기 쉬워졌다.

위에서 어디가 제목이고, 어디가 본문인지 구분을 지어준 것 처럼 HTML에서는 tag를 이용해서 문서의 각 부분이 어떤 의미를 지니고 있는지 표시(Markup)할 수 있다.

위의 문서를 HTML로 표현해보면

<article>
  <h1>셀프 리팩토링</h1>
  <p>
    리팩토링이무엇일까요? 리팩토링은 소프트웨어의 겉보기 동작은 그대로 유지한
    채, 코드를 이해하고 수정하기 쉽도록 내부 구조를 변경하는 기법입니다.
  </p>
</article>

이처럼 Semantic Tag를 이용해서 작성하면 사람과 웹 브라우저 모두 읽기 편함.
따라서, SEO 최적화, 접근성 향상, 가독성 높은 코드 등의 이점을 얻을 수 있습니다.

또하나의 예시를 보고가자
ex.

semantic vs non-semantic tag

<!-- non-semantic  -->
<div style="font-size:32px">제목</div>

<!-- semantic  -->
<h1>제목</h1>
<!-- non-semantic  -->
<div class="mentorList">
  <div>Joonsik</div>
  <div>Jongtaek</div>
  <div>Seonghoon</div>
  <div>Dohyun</div>
  <div>Yeonuk</div>
</div>

<!-- semantic  -->
<ul class="mentorList">
  <li>Joonsik</li>
  <li>Jongtaek</li>
  <li>Seonghoon</li>
  <li>Dohyun</li>
  <li>Yeonuk</li>
</ul>

3-2. img tag alt 속성

img tag를 사용하실 때 반드시 alt 속성 부여해주세요

img 태그를 사용하실 때는 아래와 같은 이유로 반드시 alt 속성을 부여해야 한다다.

  • 이미지가 로딩되지 않을 경우 alt 속성에 적힌 값이 보여짐.
  • 시각장애인의 경우 alt 속성을 통해 어떤 이미지가 보여지는지 알 수 있음.
  • SEO 검색엔진 최적화에서 어떤 img인지 인식하는 코드는 alt 속성임.
  • 위와 같은 이유로 alt 속성은 중요하기 때문에 src 속성보다 먼저 작성하는게 좋습니다.
<!-- Bad  -->
<img src="/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" />

<!-- Good  -->
<img alt="Google Logo" src="/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" />

3-3. Self Closing Tag

Self Closing이 가능한 tag들은 Self Closing을 적용시키자

HTML tag는 일반적으로 여는태그(

) 와 닫는태그 (
)로 이루어있지만 스스로 닫을 수 있는(Self Closing) tag들이 있다.

불필요하게 모든 태그를 열고 닫으면 가독성을 해칠 수 있습니다.

<!-- Bad  -->
<input type="password"></input>

<!-- Good  -->
<input type="password" />

아래는 Self Closing을 적용할 수 있는 단일 tag들의 목록입니다.

- <br />
- <hr />
- <img />
- <meta />
- <link />
- <input />

4. CSS

4-1. CSS 속성 순서

CSS 속성은 레이아웃에 영향을 많이 주는 순서대로, 인접 속성끼리 묶어서 작성해주는게 좋습니다.

옷장을 생각해보면 기준없이 뒤섞여 있어도 옷에는 어떠한 영향도 미치지 않지만 자연스럽게 옷을 찾기 편하게 하기 위해 정리한다.

CSS 속성 또한
연관관계를 조금이라도 쉽게 파악하기 위해서 반드시 컨벤션을 지켜서
레이아웃에 영향을 많이 주는 순서대로 , 인접 속성끼리 묶어서 작성하는 습관을 들이자

권장되는 속성 순서는 아래와 같습니다.

- Layout Properties (position, float, clear, display)
- Box Model Properties (width, height, margin, padding)
- Visual Properties (color, background, border, box-shadow)
- Typography Properties (font-size, font-family, text-align, text-transform)
- Misc Properties (cursor, overflow, z-index)

4-2. 다른 CSS 선택자들 사이 한줄 띄우기

각자 다른 CSS 선택자들 사이에는 한 줄씩 공백을 주는 게 가독성 측면에서 좋다.

똑같은 두개의 예시코드에서 선택자 사이의 공백으로 인해 아래 예시 코드의 가독성이 훨씬 좋다.

가독성을 위해 다른 css 선택자들 사이는 한 줄 공백을 추가
ex.
1번

.login-btn {
  height: 2.5rem;
  margin: 0.625rem 0px;
  border: 0;
  border-radius: 0.3125rem;
  background-color: var(--disabled);
  color: var(--white);
  font-weight: 700;
  font-size: 0.9375rem;
}
.find-password {
  margin: 3.75rem 0 1.25rem 0;
  color: #00376b;
  text-align: center;
  font-size: 12px;
}
.enabled-btn {
  background-color: var(--enabled);
  cursor: pointer;
}
.disabled-btn {
  background-color: var(--disabled);
  cursor: default;
}
.login-btn {
  height: 2.5rem;
  margin: 0.625rem 0px;
  border: 0;
  border-radius: 0.3125rem;
  background-color: var(--disabled);
  color: var(--white);
  font-weight: 700;
  font-size: 0.9375rem;
}

2번

.find-password {
  margin: 3.75rem 0 1.25rem 0;
  color: #00376b;
  text-align: center;
  font-size: 12px;
}

.enabled-btn {
  background-color: var(--enabled);
  cursor: pointer;
}

.disabled-btn {
  background-color: var(--disabled);
  cursor: default;
}

4-3. 불필요한 style 속성 작성 지양

불필요한 style 속성은 작성할 필요가 없습니다.

block 요소에 불필요하게 display:block; 을 부여
block 요소에 불필요하게 width:100% 를 부여

위 두가지 예시처럼 불필요한 style 속성을 부여할 필요가 없다.
수많은 요소는 이미 display:block을 default style로 적용이 되고 있다.

각 HTML tag들이 어떤 default css value를 가지고 있는지 확인해서 불필요한 style 속성 작성을 지양 할 것.

아래의 참고자료 활용

각 속성들의 default (기본 값)

4-4. 레이아웃은 bottom-up 방식으로 구성

중요도 100%

레이아웃을 구성할 때 부모요소의 높이를 미리 정해두고 자식요소의 크기를 정하는 top-down 방식이 아닌, 자식요소의 높이에 따라 부모요소의 높이가 유동적으로 결정되는 bottom-up 방식으로 구성하기.

레이아웃을 구성할 때 부모요소의 크기를 고정적으로 정해둔다면,
자식요소의 크기가 변함에 따라서 부모요소의 크기가 유동적으로 변하지 않는다.

이런 상황에서 만약 자식요소의 크기가 변해야 한다면, 부모요소의 CSS도 같이 수정해줘야 하는 불편함이 생기고 겹겹이 쌓인다면 추후에 CSS 유지보수가 매우 힘들어진다.

다시 한번 기억합시다,

CSS 유지보수가 Javascript 유지보수보다 힘듭니다.

// bad
.feedList {
  height:100vh;
}

.feed{
  height:300px;
}

// good
.feedList {
  padding-top:20px;
}

.feed{
  height:300px;
}

feedList안에 여러개의 feed가 들어있는 상황을 가정해봅시다.
(feedList > feed * n)
bad의 경우 여러 feed들을 감싸고 있는 feedList에 고정 height를 부여했다.

feedList가 안에 feed가 몇개나 생성될 지 모르기에 feedList의 크기는 feed의 개수에 따라서 유동적으로 조정되어야 한다.

하지만 bad의 예시에서는 feedList는 고정 height를 가지고 있으므로 feed가 1개일 때도, 그리고 20개일 때도 똑같이 100vh의 height를 가지고 있다.

즉, 자식요소의 크기에 따라서 부모의 크기가 유동적으로 조정이 안되고 있다.

하지만 good의 예시를 보면 feedList에는 고정 height를 부여하지 않았다.
이 경우에는 feedList의 크기가 자식요소의 크기만큼 자동으로 조정된다.

즉, feedList의 높이가 내부의 자식요소의 높이 + 20px(padding-top 값) 로 유동적으로 변할 수 있게 된다.

앞으로,
레이아웃을 구성할 때는 자식요소에 따라 부모요소가 조정되도록 bottom-up 방식으로 구성하자

추가 ex.

고정 height를 부여해서 레이아웃에 문제가 생긴 상황

Bad Case 에는 빨간 박스에 고정 height를 부여하고 Good case에는 빨간 박스에 고정 height를 부여하지 않은 상황
Bad Case에는 빨간 박스에 고정 height가 부여되어있는 상황에서 자식요소들이 height값을 넘어서는 만큼 들어왔다
Good Case에서는 빨간 박스에 고정 height를 부여하지 않아서 자식요소의 크기만큼 자연스럽게 height가 늘어나고 있다.
지금은 overflow:visible 속성에 의해 둘 다 자식요소들이 모두 화면에 보이고 있기에 문제가 없다고 생각 될 수 있습니다. 하지만, 다음의 예시를 확인해보자

빨간 박스 아래에 파란 박스가 추가된 상황

Bad Case에서는 빨간 박스가 고정 height로 인해 자식요소의 크기만큼 영역을 차지하지 못하고 있어서 파란 박스가 빨간 박스와 겹쳐지는 현상이 발생한다.

하지만, Good Case에서는 빨간 박스에 고정 height를 부여하지 않아서 자식요소의 크기만큼 자연스럽게 빨간 박스의 height가 늘어나고 있다.

그래서 빨간 박스가 자식요소만큼 영역을 차지하게 되어서 파란색박스와 겹쳐지지 않고 정상적으로 보여지는 것을 알 수 있습니다.

지금은 단순히 2개의 박스의 상황이지만 만약 실제 프로젝트에서 여러 박스가 겹겹이 쌓여있는 상황이라면 문제를 파악하고 유지보수하기 힘들어진다.

이렇게 Refactoring Checklist 을 정리해봤고 
나에게 시멘틱 태그를 사용하는 것, 그리고 레이아웃은 bottom-up 방식으로 구성하는 것을 습관화 시켜야겠다. 최근에 첫번째 프로젝트에서 up-bottom 방식으로 구성하고 구현했을때 다시 뒤집어 엎고 진행을 했기 때문에 조금 더 크게 다가왔다. 

앞으로 성장을 위해 항상 코드를 짠 후에 Refactoring Checklist 를 활용하자

마지막으로,

코드의 가독성과 확장성을 좋게 만드는 작업은
좋은 코드가 무엇인지 고민하며 실력향상에 도움된다.

profile
유연한 사고로 빠르게 습득하기.

0개의 댓글