리액트 코드 모범 사례 (airbnb 기반)

Sheryl Yun·2023년 7월 29일
0

리액트 Best Practice

목록 보기
1/4
post-thumbnail

1. JSX props의 true 생략

  • props 자체가 true 값이기 때문에 ={true} 안 줘도 됨 (false는 ={false}로 명시해야)

Bad

return (
  <Navbar showTitle={true} />
);

Good

return(
  <Navbar showTitle />  
)

2. 삼항연산자 사용하기

  • if-else보다 삼항연산자를 쓰면 코드도 줄일 수 있고 가독성도 올라간다.

Bad

const { role } = user;

if (role === ADMIN) {
  return <AdminUser />
} else {
  return <NormalUser />
} 

Good

const { role } = user;

return role === ADMIN ? <AdminUser /> : <NormalUser />

3. switch 말고 객체에서 O(1)로 가져오기

  • switch문은 case를 하나씩 확인하며 내려가므로 O(N)의 시간 복잡도
  • 객체에서 key로 바로 가져오면 O(1)이 되는 효과!

Bad

const { role } = user;

switch(role) {
  case ADMIN:
    return <AdminUser />
  case EMPLOYEE:
    return <EmployeeUser />
  case USER:
    return <NormalUser />
}

Good

const { role } = user;

const components = {
  ADMIN: AdminUser,
  EMPLOYEE: EmployeeUser,
  USER: NormalUser,
};

const Component = components[role];

return <Component />;

4. Fragment 쓰기

  • 아무 기능이 없는 div는 Fragment로 바꿔주면 브라우저에서 따로 DOM을 생성하지 않는다.

Bad

return (
  <div>
     <Component1 />
     <Component2 />
     <Component3 />
  </div>  
)

Good

return (
  <>
     <Component1 />
     <Component2 />
     <Component3 />
  </>  
)

5. 렌더링되는 JSX 안에 함수 넣지 않기

  • 한 줄 짜리 코드를 밖으로 빼는 게 더 어지러워보여도 빼야 한다.
  • 렌더링 내부 로직은 최대한 간결하게 유지하는 게 좋기 때문이다.

Bad

return (
    <button onClick={() => dispatch(ACTION_TO_SEND_DATA)}>
      This is a bad example 
    </button>  
)

Good

const submitData = () => dispatch(ACTION_TO_SEND_DATA)

return (
  <button onClick={submitData}>  
    This is a good example 
  </button>  
)

6. Memo 적재적소에 활용하기

  • 리액트의 최적화는 대부분 '리렌더링'에 관한 문제이다.
  • React.memo를 사용하여 불필요한 컴포넌트의 리렌더링을 막을 수 있다.

Bad

  • count 변수를 ChildrenComponent가 아닌 부모 컴포넌트의 button에서만 쓰고 있다.
  • 하지만 count가 바뀌면서 ChildrenComponent도 매번 리렌더링된다.
import React, { useState } from "react";

export const TestMemo = () => {
  const [userName, setUserName] = useState("Sheryl");
  const [count, setCount] = useState(0);
  
  const increment = () => setCount((count) => count + 1);
  
  return (
    <>
      <ChildrenComponent userName={userName} />
      <button onClick={increment}>Increment</button>
    </>
  );
};

const ChildrenComponent =({ userName }) => {
  console.log("rendered", userName);
  return <div>{userName}</div>;
};

Good

  • ChildrenComponent를 메모이제이션(memo)해주면 관련 없는 state가 변경되었을 때 리렌더링되지 않는다.
import React, { useState } from "react";

const ChildrenComponent = React.memo(({userName}) => {
    console.log('rendered');
    return <div> {userName}</div>;
})

7. CSS를 JS 안에 넣자 (CSS-in-JS 사용)

  • 컴퓨터는 JS를 파싱하는 것보다 CSS를 파싱하는 것이 더 힘들다.

Bad

  • CSS 파일을 분리해서 인라인 + 클래스명으로 스타일을 지정한 상태
// CSS FILE
.body {
  height: 10px;
}

// JSX
return <div className='body'></div>

Good

  • JSX 바깥에서 자바스크립트 객체로 CSS를 선언하고 JSX에 삽입
  • 이것도 Bad 스타일처럼 인라인 스타일을 사용했기 때문에 그냥 CSS-in-JS(예: styled-components)를 사용하는 게 좋을 듯 하다.
const bodyStyle = {
  height: "10px"
}

return <div style={bodyStyle}></div>

8. 객체 디스트럭쳐링 사용하기

  • 이것도 코드가 한 줄 더 늘어나지만 Best Practice에 속한다.

Bad

return (
  <>
    <div>{user.name}</div>
    <div>{user.age}</div>
    <div>{user.profession}</div>
  </>  
)

Good

const { name, age, profession } = user;

return (
  <>
    <div>{name}</div>
    <div>{age}</div>
    <div>{profession}</div>
  </>  
)

9. 문자열 props는 중괄호가 필요 없다

  • 문자열은 쌍따옴표("")로만 묶어주면 됨

Bad

return(
  <Navbar title={"My Special App"} />
)

Good

return(
  <Navbar title="My Special App" />  
)

10. JSX에서 JS 코드 제거하기

  • 이것도 JSX에서 함수를 밖으로 빼 주는 것과 동일하다.
  • JSX 내부 코드는 최대한 간결하게!

Bad

return (
  <ul>
    {posts.map((post) => (
      <li 
      	onClick={event => console.log(event.target, 'clicked!')}
        key={post.id}
      >
      	{post.title}
      </li>
    ))}
  </ul>
);

Good

const onClickHandler = (event) => {
   console.log(event.target, 'clicked!'); 
}

return (
  <ul>
    {posts.map((post) => (
      <li key={post.id} onClick={onClickHandler}>{post.title}</li>
    ))}
  </ul>
);

11. 템플릿 리터럴 사용하기

  • 문자열을 '+'로 연결하는 것보다 템플릿 리터럴이 더 가독성이 좋다.

Bad

const userDetails = user.name + "'s profession is" + user.proffession

return (
  <div> {userDetails} </div>  
)

Good

const userDetails = `${user.name}'s profession is ${user.proffession}`

return (
  <div> {userDetails} </div>  
)

12. import 순서 일관성 있게

  • 일관성은 '예측 가능성'이다.
  • import 문이 여러 줄일 때 해당 파일에서 어떤 것이 import가 되었는지 확인하기 편하도록 예측 가능한 순서와 한 줄 띄우기를 적당히 사용한다.

Bad

import React from 'react';
import ErrorImg from '../../assets/images/error.png';
import styled from 'styled-components/native';
import colors from '../../styles/colors';
import { PropTypes } from 'prop-types';

Good

  • 보통 많이 사용하는 import문 순서
    • 프레임워크 내장(built-in): 'react', 'next/head' 등
    • 외부 패키지: 'styled-components' 등
    • 내부 파일: '../../assets/images/error.png' 등
  • 이 순서 간 import문 사이에 한 줄씩 띄우기
import React from 'react';

import { PropTypes } from 'prop-types';
import styled from 'styled-components/native';

import ErrorImg from '../../assets/images/error.png';
import colors from '../../styles/colors';

13. 암묵적 return (화살표 함수 return문 축약)

  • 화살표 함수일 때 1줄 짜리 return 문은 중괄호와 return 키워드 생략 가능
  • 객체를 리턴할 때는 '()' 사용으로 축약 가능

Bad

const add = (a, b) => {
  return a + b;
}

// 객체
const getObj = () => {
	return { a: key, b: value }
}

Good

const add = (a, b) => a + b;

// 객체
const getObj = () => ({ a: key, b: value });

14. 컴포넌트 네이밍 케이스 (Pascal vs. Camel)

  • 컴포넌트는 무조건 파스칼, 나머지는 카멜 케이스

Bad

  • 변수 선언에 파스칼을 사용
import reservationCard from './ReservationCard';

const ReservationItem = <ReservationCard />;

Good

  • 컴포넌트(<ReservationCard />)만 파스칼로, 나머지는 카멜 케이스로
import ReservationCard from './ReservationCard';

const reservationItem = <ReservationCard />;

15. 컴포넌트 props 이름에 예약어(키워드) 사용하지 말기

Bad

  • style은 원래 기본적인 브라우저 태그에 사용하는 키워드
<MyComponent style="dark" />

<MyComponent className="dark" />

Good

  • 개발자 자체 커스텀 키워드 사용하기 (예: 'variant')
<MyComponent variant="fancy" />

16. JSX props에만 쌍따옴표 (나머지는 홑따옴표)

Bad

<Foo bar='bar' />

<Foo style={{ left: "20px" }} />

Good

  • JSX의 props 값에만 쌍따옴표("") 사용하기
<Foo bar="bar" />

<Foo style={{ left: '20px' }} />

17. '컴포넌트'를 넘기는 props는 파스칼 케이스로

Bad

<Component
  UserName="hello"
  phone_number={12345678}
/>

Good

<MyComponent
  userName="hello"
  phoneNumber={12345678}
  Component={SomeComponent}
/>

18. return 문의 여러 줄인 JSX는 '()'로 묶기

Bad

  • '()'로 감싸주지 않고 작성해서 JSX 형태가 이상함
return <MyComponent variant="long">
           <MyChild />
         </MyComponent>;

Good

return (
    <MyComponent variant="long">
      <MyChild />
    </MyComponent>
);

19. 컴포넌트에 children이 없으면 self-closing 태그 사용

Bad

<SomeComponent variant="stuff"></SomeComponent>

Good

<SomeComponent variant="stuff" />

20. 함수 이름 앞에 언더바('_') 쓰지 말기

Bad

const _onClickHandler = () => {}

Good

const onClickHandler = () => {}

21. img 태그에 alt 꼭 추가 + alt에 'picture'나 'image' 넣지 않기

  • img 태그라면 어차피 스크린 리더가 읽을 때 '이미지'라고 인지한 상태
    • alt에 'picture'나 'image' 단어를 넣으면 중복적인 의미가 된다.

Bad

// alt 태그를 안 씀
<img src="hello.jpg" />

// alt 텍스트에 'picture'라는 단어 포함
<img src="hello.jpg" alt="Picture of me rowing a boat" />

Good

  • alt 텍스트에는 'picture'나 'image'라는 단어를 넣을 필요가 없다.
<img src="hello.jpg" alt="Me waving hello" />

참고 자료

21 Best Practices for a Clean React Project

profile
데이터 분석가 준비 중입니다 (티스토리에 기록: https://cherylog.tistory.com/)

0개의 댓글