React 깨끗하고 유지보수하기 쉬운 코드 작성법

2025. 2. 16. 21:14·React
728x90

React로 개발할 때 코드의 품질을 유지하는 것은 매우 중요합니다. 잘 구조화된 코드는 유지보수와 확장이 쉬워지고, 협업할 때도 이해하기가 더 간단해집니다. 이번 글에서는 React를 사용할 때 고려해야 할 베스트 프랙티스(Best Practices) 를 정리해보겠습니다.


1. 컴포넌트를 작게 유지하자

React에서는 컴포넌트를 작은 단위로 분리하는 것이 핵심입니다.
하나의 컴포넌트가 너무 크면 재사용성이 떨어지고, 수정이 어려워집니다.

X 좋지 않은 예제 (너무 많은 역할을 하는 컴포넌트)

function Dashboard() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState("");

  function handleClick() {
    setCount(count + 1);
  }

  function handleChange(event) {
    setText(event.target.value);
  }

  return (
    <div>
      <h1>대시보드</h1>
      <p>숫자: {count}</p>
      <button onClick={handleClick}>증가</button>
      <input type="text" value={text} onChange={handleChange} />
    </div>
  );
}

위 코드는 버튼과 입력 필드의 상태 관리를 한 곳에서 처리하고 있어, 역할이 애매~~~ 합니다.

O 개선된 예제 (역할을 분리)

function Counter({ count, onIncrease }) {
  return (
    <div>
      <p>숫자: {count}</p>
      <button onClick={onIncrease}>증가</button>
    </div>
  );
}

function TextInput({ text, onChange }) {
  return <input type="text" value={text} onChange={onChange} />;
}

export default function Dashboard() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState("");

  return (
    <div>
      <h1>대시보드</h1>
      <Counter count={count} onIncrease={() => setCount(count + 1)} />
      <TextInput text={text} onChange={(e) => setText(e.target.value)} />
    </div>
  );
}

!! 핵심 원칙:

  • 하나의 컴포넌트는 하나의 책임만 가지도록 한다.
  • 재사용이 가능한 작은 컴포넌트로 분리한다.

2. 상태 관리를 신중하게 하자

모든 상태를 useState로 관리하면 불필요한 리렌더링이 발생할 수 있습니다.
상태를 어디에 위치시킬지 신중하게 고민해야 합니다.

X 잘못된 상태 관리 (불필요한 상태)

function UserProfile({ user }) {
  const [name, setName] = useState(user.name);

  return <h1>{name}</h1>;
}

위 코드에서는 user.name을 직접 사용하면 되는데 굳이 useState로 다시 상태를 생성했습니다.

O 개선된 코드

function UserProfile({ user }) {
  return <h1>{user.name}</h1>;
}

!! 상태 관리 팁:

  • 가능하면 상태를 줄이고, 필요한 곳에서만 관리하자.
  • 상태가 변하지 않는 값이라면 props로 전달하는 것이 더 효율적이다.

3. useEffect 남용하지 않기

useEffect는 React에서 중요한 기능이지만, 불필요하게 사용하면 코드가 복잡해지고 성능 저하를 초래할 수 있습니다.

X 불필요한 useEffect 사용 예제

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);

  useEffect(() => {
    fetch(`/api/users/${userId}`)
      .then((res) => res.json())
      .then((data) => setUser(data));
  }, [userId]);

  if (!user) return <p>로딩 중...</p>;

  return <h1>{user.name}</h1>;
}

위 코드에서는 useEffect를 사용하여 데이터를 가져오지만,
이 작업은 컴포넌트 내부가 아니라 별도의 API 훅으로 분리하는 것이 더 깔끔합니다.

O 개선된 코드 (커스텀 훅 활용)

function useUser(userId) {
  const [user, setUser] = useState(null);

  useEffect(() => {
    fetch(`/api/users/${userId}`)
      .then((res) => res.json())
      .then((data) => setUser(data));
  }, [userId]);

  return user;
}

function UserProfile({ userId }) {
  const user = useUser(userId);

  if (!user) return <p>로딩 중...</p>;

  return <h1>{user.name}</h1>;
}

!! 핵심 원칙:

  • useEffect는 꼭 필요한 경우에만 사용하자.
  • API 호출이나 비즈니스 로직은 커스텀 훅(Custom Hook) 으로 분리하면 코드가 깔끔해진다.

4. Props 드릴링 줄이기 (Context 활용)

컴포넌트가 깊어질수록 props를 계속 전달하는 것은 비효율적입니다.
이를 해결하기 위해 Context API를 활용할 수 있습니다.

X Props 드릴링 문제

function Button({ theme }) {
  return <button style={{ backgroundColor: theme }}>버튼</button>;
}

function Toolbar({ theme }) {
  return <Button theme={theme} />;
}

export default function App() {
  const theme = "blue";
  return <Toolbar theme={theme} />;
}

 

O Context API로 개선

import { createContext, useContext } from "react";

const ThemeContext = createContext("blue");

function Button() {
  const theme = useContext(ThemeContext);
  return <button style={{ backgroundColor: theme }}>버튼</button>;
}

function Toolbar() {
  return <Button />;
}

export default function App() {
  return (
    <ThemeContext.Provider value="blue">
      <Toolbar />
    </ThemeContext.Provider>
  );
}

!! 핵심 원칙:

  • Context API를 사용하면 props 전달 없이 전역적으로 상태를 공유할 수 있다.
  • 다만, 너무 많은 상태를 Context에 저장하는 것은 성능 저하를 유발할 수 있으니 신중하게 사용하자.

5. 성능 최적화 (useMemo & useCallback 활용)

React는 상태가 변경될 때 모든 하위 컴포넌트가 리렌더링됩니다.
불필요한 렌더링을 줄이기 위해 useMemo와 useCallback을 활용할 수 있습니다.

O 예제 (useMemo & useCallback 사용)

import { useState, useMemo, useCallback } from "react";

export default function ExpensiveComponent() {
  const [count, setCount] = useState(0);

  const expensiveCalculation = useMemo(() => {
    return count * 2;
  }, [count]);

  const handleClick = useCallback(() => {
    setCount(count + 1);
  }, [count]);

  return (
    <div>
      <p>결과: {expensiveCalculation}</p>
      <button onClick={handleClick}>증가</button>
    </div>
  );
}

!! 핵심 원칙:

  • useMemo: 값이 변경되지 않으면 계산을 캐싱하여 불필요한 연산을 줄인다.
  • useCallback: 함수가 변경되지 않으면 같은 함수를 재사용하여 성능을 최적화한다.

마무리

React 개발에서 깔끔한 코드 구조를 유지하는 것은 유지보수성과 확장성을 높이는 중요한 요소입니다.

저도 아직 부족하지만, 공식 문서를 참고하며 열심히 정리해보았어요!

오늘도 열코 빡코🔥 읽어주셔서 감사합니다!

728x90
LIST

'React' 카테고리의 다른 글

React의 렌더링과 커밋 과정: 개념부터 이해하기  (4) 2025.02.23
React 상태(State)란 무엇인가?  (0) 2025.02.22
React에서 이벤트 처리하기  (1) 2025.02.21
React에서 상호작용 추가하기: 이벤트 핸들링과 상태 관리  (1) 2025.02.16
React에서 export default function vs export function 차이점  (0) 2025.02.16
'React' 카테고리의 다른 글
  • React 상태(State)란 무엇인가?
  • React에서 이벤트 처리하기
  • React에서 상호작용 추가하기: 이벤트 핸들링과 상태 관리
  • React에서 export default function vs export function 차이점
Mr. Joo
Mr. Joo
  • Mr. Joo
    삽질의 시작
    Mr. Joo
  • 전체
    오늘
    어제
    • 분류 전체보기 (180) N
      • Flutter (67)
      • Android (9)
      • Swift (4)
      • React (11)
      • 인공지능 (4)
      • CS (10)
      • 개발 뉴스 (72) N
      • IT 기기 (1)
      • 알면 유용한 정보 (2)
  • 인기 글

  • 태그

    android
    개발 이슈
    Flutter 기초
    DART
    기술
    앱개발
    개발 뉴스
    뉴스
    react
    Flutter
    오늘의 이슈
    개발
    이슈
    플러터
    기술 뉴스
    뉴스 모음
    앱
    앱 개발
    Dart 기초
    오늘의 뉴스
  • 최근 댓글

  • 최근 글

  • 250x250
  • hELLO· Designed By정상우.v4.10.3
Mr. Joo
React 깨끗하고 유지보수하기 쉬운 코드 작성법
상단으로

티스토리툴바