Lighthouse of FE biginner

[클린 코드] 가독성 좋은 코드 - 변수 본문

클린코드

[클린 코드] 가독성 좋은 코드 - 변수

[FE] Lighthouse 2024. 6. 17. 14:28

 

코드를 작성하다보면 기본값으로 사용할 리터럴 이나 상수로 사용해야할 리터럴이 있다. 이런 리터럴들은 변하지 않는 값이기 때문에 보통 식에서 변수로 사용하는 것이 아닌 리터럴로 사용할 때가 종종 있다.

예를 들면 얼마전에 팀에서 공통으로 사용할 커스텀 훅을 작성할 때 기본 값을 사용한 케이스가 있었다.

if (excelSheet?.width) {
  sheet.getColumn(colNumber).width = excelSheet.width[colNumber - 1];
} else if (cell.value) {
  const valueLength = cell.value.toString().length;
  const colWidth = sheet.getColumn(colNumber).width ?? 10;

  // Set Default Column Width
  const adjustedWidth =
    colWidth && colWidth > 10
      ? colWidth
      : 10;

  // Set Column width
  sheet.getColumn(colNumber).width =
    colWidth > 50
      ? 50
      : adjustedWidth < valueLength
      ? valueLength * 1.2
      : adjustedWidth;
}

 

위 코드는 엑셀 열의 기본 너비를 적용하는 로직이다.

코드를 살펴보면 자주 등장하는 숫자가 있다. 10과 50이다. 코드를 작성한 나는 이 숫자들의 의미를 알고있다. 10은 열의 기본 값이고, 50은 열 너비의 MAX 값 이다.

만약 3개월 뒤 미래의 내가 이 코드를 봤을 때 무슨 생각이 들것인가? 3개월 뒤의 내가 이 코드를 봤을 때 한번에 코드의 의도를 파악할 수 있을까? 혹은 같이 작업하는 팀원이 이 코드를 봤을 때 해당 숫자들의 의미를 명확하게 알 수 있을까?

 

이런 값들을 변수로 선언해서 사용한다면 협업하기 좋은 코드를 작성할 수 있다. 만약 리터럴이 변수로 선언해서 사용해야 할까 라는 생각이 든다면 아래의 리스트를 고민해보자

 

1. 작성한 로직에서 자주 등장하나요?

2. 의미를 담고 있는 리터럴인가요?

3. 해당 리터럴을 담고 있는 식에서 리터럴 자체의 의미를 한눈에 알아볼 수 있나요?

 

위 리스트 중 두 항목 이상이 해당된다면 변수로 선언해서 사용해야 한다.

const DEFAULT_COL_WIDTH_SIZE = 10;
const MAX_COL_WIDTH_SIZE = 50;

if (excelSheet?.width) {
  sheet.getColumn(colNumber).width = excelSheet.width[colNumber - 1];
} else if (cell.value) {
  const valueLength = cell.value.toString().length;
  const colWidth = sheet.getColumn(colNumber).width ?? DEFAULT_COL_WIDTH_SIZE;

  // Set Default Column Width
  const adjustedWidth =
    colWidth && colWidth > DEFAULT_COL_WIDTH_SIZE
      ? colWidth
      : DEFAULT_COL_WIDTH_SIZE;

  // Set Column width
  sheet.getColumn(colNumber).width =
    colWidth > MAX_COL_WIDTH_SIZE
      ? MAX_COL_WIDTH_SIZE
      : adjustedWidth < valueLength
      ? valueLength * 1.2
      : adjustedWidth;
}

 

두 가지 상수를 선언했다. 그리고 숫자 리터럴 대신 로직에서 상수로 대치했다. 이제 로직을 봤을때 무엇을 하는 코드인지 더욱 확실하게 파악이 될 것 이다.

같이 일하는 팀원이 이 코드를 봤을 때 작성자에게 무슨 의미의 코드인지 물어보지 않아도 될 것 이다. 커뮤니케이션 비용이 감소한다.
또한 이 코드를 해석하기 위해 몇 단계를 거치지 않아도 됨으로써 코드 분석에 사용하는 비용이 줄어들게 될 것이다.

 

친절한 변수씨

코딩을 하는데 있어서 가장 쉬운 일은 변수를 선언하는 것 이다. 하지만 이처럼 쉬운 일 속에서 가장 주의해야 하는 점은 변수 명을 친절하게 선언해야 한다는 것 이다.

가끔 일을 하다보면 자기 혼자만 알아볼 수 있는 변수 명을 사용하는 사람을 볼 수 있는데, 정말 속에서 열불이 터진다.

 

가급적 변수 명은 다른 사람이 이 코드를 보는 관점에서 작성했으면 좋겠다.

 

가령 아래와 같은 코드가 있다.

const isLoading = Object.keys(otherOptions).some((key) => {
  let flag = false;
  if (otherOptions[key].isLoading) flag = true;
  if (isUndefined(otherOptions[key].options)) flag = true;
  return flag;
});

 

로직을 살펴보면 boolean 값을 리턴하는구나! 를 알 수 있다. 근데 이게 어디에 사용하는 변수인지, 무엇을 위한 변수인지 알기가 힘들다.

변수 명칭만 간단하게 isOptionsLoading 으로 변경한다면 이 변수가 옵션 값들이 로딩중인지 판단하는 변수구나! 를 알 수 있게 된다.

 

표현식을 변수에 담아서

얼마전 리팩토링 도중에 아래와 같은 식이 한 컴포넌트에서 여러번 사용되는 것을 봤다.

tabValue === 1

 

tabValue 가 1 인지 판단하는 식이다. 근데 이게 뭔데? 라는 생각이 먼저 들었다. 이 식은 해당 컴포넌트에서 네 곳 이상 사용되고 있었기 때문이다.

 

결국 해당 식이 무엇을 뜻하는지 살펴보기 위해 800라인 이상 작성된 컴포넌트를 뜯어보기 시작했고 여러 곳을 거쳐서 이 식이 무엇을 뜻하는지 알 수 있었다.

 

바로 선택된 탭이 월별 탭 이였을 때 이다.

 

만약 내가 해당 프로젝트를 초기부터 진행했던 개발자라면 쉽게 코드를 이해할 수 있었을 것이다. 하지만 4~5년 이상 된 프로젝트에 투입된지 얼마 안된 개발자는 해당 코드가 무엇을 뜻하는지 알기 어렵다.

 

위 식을 변수로 선언한다면 식의 의미를 알기 위해 여러 곳을 거쳐야 하는 수고를 덜 수 있지 않을까?

const isMonthly = tabValue === 1;



개발자에게 있어서 가장 중요한 일은 지금 당장 돌아가는 코드, 내가 만족하는 코드가 아니라 다른 개발자가 파악하기 쉬운 코드, 친절한 코드 이다.

 

만약 해당 프로젝트가 정말 단발성 프로젝트이며 유지보수가 필요가 없다면 그건 본인의 마음대로 라고 생각한다. (프로젝트 초기부터 단발성으로 계획하고 시작하는 프로젝트가 있을까?)

하지만 프로젝트에 유지보수가 필요하다면 코드는 꼭 남이 파악하기 쉬운지를 고민해보고, 만약 시간이 부족해서 일단 돌아가는 대로 작성한다면 꼭 시간을 투자해 리팩토링 하는 시간을 가졌으면 좋겠다.

 

가장 쉬운 방법으로 프로젝트의 퀄리티를 높일수 있기 때문이다.

'클린코드' 카테고리의 다른 글

[클린코드] 함수의 클린코드  (2) 2024.11.20
[클린코드] 반복되는 값, 리터럴  (1) 2024.08.22
[클린코드] TypeScript `any`  (0) 2024.08.15