Better Code 작성하기

suyeonme·2021년 3월 27일
4

Etc

목록 보기
5/5

코드 리뷰 정리. 더 나은 코드를 작성합시다. 🤓

주의 사항

  • 코드를 수정할 때는, 항상 다른 컴포넌트에서 사용하는지 확인
  • 함수를 작성할 때, 이미 존재하는지 확인
  • 작업중인 코드는 stash 하기 (commit X)
  • 라이브러리 컴포넌트를 사용할 때는 항상 버전 체크

Barrel

barrel is a way to rollup exports from several modules into a single convenient module. The barrel itself is a module file that re-exports selected exports of other modules.

프로젝트 규모가 클 때,import/export를 간결하게 만들어주어서 가독성을 높일 수 있다. 또한 폴더내의 파일들을 한눈에 흩어보며 구조를 파악하기에도 용이하다.

  • 웹팩에서 tree-shaking이 제대로 되지 않아서 bundle size에 영향을 미칠 수 있을 수도 있다고 한다.

기존 코드

/* 파일 구조 
index.ts
interfaces/
  bear.interface.ts
  pig.interface.ts
  man.interface.ts
*/

// index.ts
import { Bear } from './interfaces/bear.interface';
import { Pig } from './interfaces/pig.interface';
import { Man } from './interfaces/man.interface';

Barrel 적용

/* 파일 구조 
index.ts
interfaces/
  bear.interface.ts
  pig.interface.ts
  man.interface.ts
  index.ts   <--- Barrel file
*/

// ./interfaces/index.ts
export * from './bear.interface';
export * from './man.interface';
export * from './pig.interface';

// index.ts
import { Bear, Pig, Man } from './interfaces';

Naming

  • 이름은 길어도 괜찮으니 의도가 분명히 드러나게 지을 것
  • 같은 컴포넌트의 이름은 무조건 통일할 것(styled-component를 사용할 때 옵션값으로 이름이 설정되기에 추후에 디버깅에 용이함)
    AdminTableStyle, AdminTableInput, AdminTableCell ...

Import

  • 가급적 absolute-path를 사용
  • import { Account } from '../../../../Accounts'와 같이 사용할 거면, 차라리 전체 경로를 사용할 것(import { Account } from 'containers/AdminPage/Accounts') -> 명확

Getter

  • meta 파일에서 오브젝트를 불러올 때는, 직접 불러오지 말고 getter을 사용 -> 오브젝트의 값이 임의로 변경되는 것을 방지
const ACCOUNT = { ... }
export const getAccount = () => ACCOUNT

// Using
const ACCOUNT = getAccount();

Destructuring

  • 바로 Event 값을 넘겨주고 싶을 때
onChange={({ target: { name, value } }) => handleChange(name, value)}

// onChange={(e) => handleChange(e.target.value)}
// const { name, value } = event.target

!!Operator

  • undefined | null | 0 인 경우 → true/falsy 반환(boolean)
  • Html에서 0(=false)을 표기하고 싶지 않은 경우
// (1)
<Message>
  {!!accountDomainArr?.length ? `(${accountDomainArr.length})` : ``}
</Message>

// (2)
const noValue = !!cell.value

Length

a.length === 0 && <Test /> 
!a.length && <Test /> // Better
  • search를 할때는, 항상 trim()해주기
if(typeof query === string) query = query.trim();

Switch Statement

// (1) Switch statement
const AdminPageTableCell = () => {
  switch (cellId) {
    case 'firstCreateTime':
      return <td {...cell.getCellProps()}>{moment(cell.render('Cell')).format('YYYY-MM-DD')}</td>
    case 'detail':
      return (
        <td {...cell.getCellProps()} style={{ textAlign: 'center' }}>
          <DetailLink row={row} onClickDetail={onClickDetail} />
        </td>
      )
    default:
   // ...
  }
}

// (2) Multiple if statement
const AdminPageTableCell = () => { 
  const data = [...];
  
  return (
    <div>
      {data.map(d => { 
        if(d.isDate) {
          return <p>{moment(d.value)}</p>
        }
        if(d.isDetail) {
          return <p><icon /></p>
        }
          return <p>{d.value}</p>
        })}
     <div>
  )
}

Performance

불필요한 Layout Process 줄이기

  • 첫번째의 경우 a.style.width를 하고 다른 작업을 하다가 b.style.width를 하게 되면 총 두번의 calcuration이 발생하게 된다. (layout process - painting)
  • 두번째의 경우 총 한번의 calcuration이 실행된다. (합쳐져서 계산)
// (1) Bad
a.style.width = 10;
// ...
// ...
b.style.width = 20;


// (2) Good
a.style.width = 10;
b.style.width = 20;
// ...
// ...

For Loop

  • a.length는 loop가 돌때마다 계산되어지기 때문에, 변수로 빼는게 좋다.
// (1) Bad
for(let i=0; i < a.length; i++) { // ... }

// (2) Good
const aLength = 5;
for(let i=0; i < aLength; i++) { // ... }
profile
Frontend Engineer.

0개의 댓글