Ch.24 디버깅 — 에러 메시지 읽는 법

React 디버깅 실전

React 대표 에러 3가지를 해결할 수 있다React DevTools로 컴포넌트를 검사할 수 있다체계적인 디버깅 프로세스를 적용할 수 있다

화면이 안 바뀐다? 무한 렌더링?

React에서는 일반 JS와 다른 종류의 버그가 발생합니다. state가 안 바뀌거나, 무한 렌더링에 빠지거나, key 경고가 뜹니다.

React만의 에러들, 어떻게 빠르게 해결할까?

React 에러는 패턴이 정해져 있습니다. 대표 에러 3가지디버깅 체크리스트를 알면 빠르게 해결할 수 있습니다.


article

핵심 내용

React 에러의 80%는 이 3가지 패턴입니다

// ❌ 에러 1: key 경고
// Warning: Each child in a list should have
// a unique "key" prop.

// 원인: map으로 리스트 렌더링 시 key 누락
{items.map((item) => (
  <li>{item.name}</li>  // ❌ key 없음
))}

// ✅ 해결
{items.map((item) => (
  <li key={item.id}>{item.name}</li>
))}
// ❌ 에러 2: useEffect 무한 루프
// 화면이 멈추거나 API를 수백 번 호출

function Component() {
  const [data, setData] = useState(null);

  // ❌ 의존성 배열 없음 → 매 렌더마다 실행 → 무한 루프
  useEffect(() => {
    fetch("/api/data")
      .then((r) => r.json())
      .then(setData);  // setData → 리렌더 → useEffect → ...
  });

  // ✅ 해결 — 빈 배열 추가 (마운트 시 1번만 실행)
  useEffect(() => {
    fetch("/api/data")
      .then((r) => r.json())
      .then(setData);
  }, []);  // ← 이것!
}
// ❌ 에러 3: state 직접 수정 — 화면이 안 바뀜
function TodoList() {
  const [todos, setTodos] = useState(["공부", "운동"]);

  // ❌ push는 원본을 수정 → React가 변경 감지 못함
  const addBad = () => {
    todos.push("독서");   // 원본 수정
    setTodos(todos);       // 같은 참조 → 리렌더 안됨
  };

  // ✅ 스프레드로 새 배열 생성
  const addGood = () => {
    setTodos([...todos, "독서"]);  // 새 배열 → 리렌더!
  };
}

React DevTools로 props와 state를 실시간 확인합니다

설치: Chrome 확장 프로그램 "React Developer Tools" 설치

Components 탭: 컴포넌트 트리 구조와 props/state 확인

값 수정: props/state 값을 직접 수정해 동작 테스트

렌더링 추적: Profiler 탭에서 리렌더 원인 확인

바이브 코더 팁 화면이 안 바뀔 때 React DevTools에서 해당 컴포넌트의 state를 확인하세요. 값이 바뀌지 않았다면 setter 함수 호출이 안 된 것, 값은 바뀌었는데 화면이 그대로면 렌더링 로직 문제입니다.

문제 → 재현 → 원인 → 수정 → 검증 체계적 디버깅 프로세스입니다

1. 문제 정의: "버튼 클릭 시 목록에 추가 안됨" — 정확히 서술

2. 재현: 버그가 발생하는 정확한 순서 파악

3. 원인 추정: console.log나 DevTools로 값 확인

4. 수정: 원인에 맞는 최소한의 수정 적용

5. 검증: 수정 후 버그 재현 시도 → 해결 확인

// 실전 디버깅 예시 — "목록에 추가가 안돼요"

// 1. 문제: 추가 버튼 클릭 → 화면 변화 없음

// 2. 재현: 텍스트 입력 → 추가 버튼 클릭 → 목록 그대로

// 3. 원인 추정: console.log로 확인
const addTodo = () => {
  console.log("1. 함수 호출됨");          // ✅ 출력됨
  console.log("2. input 값:", text);       // ✅ 값 있음
  todos.push({ text });                     // 🔴 원본 수정!
  console.log("3. todos:", todos);          // ✅ 추가됨 (but...)
  setTodos(todos);                          // 🔴 같은 참조!
};

// 4. 수정: 스프레드로 새 배열 생성
const addTodoFixed = () => {
  setTodos([...todos, { text }]);           // ✅ 새 배열!
};

// 5. 검증: 추가 버튼 클릭 → 목록에 표시됨 ✅

디버깅의 핵심 원칙 "한 번에 하나씩 바꾸고 테스트하기". 여러 군데를 동시에 수정하면 무엇이 문제였는지 알 수 없습니다.

useEffect에서 무한 루프가 발생하는 원인은?

state 배열에 push()로 요소를 추가하면 React가 리렌더링한다

디버깅 5단계 프로세스의 올바른 순서는?

key

핵심 용어

🌳

컴포넌트 트리

App → Layout → Page 같은 구조를 시각적으로 확인

📦

Props 확인

각 컴포넌트에 전달된 props 값을 실시간으로 확인

💾

State 확인

useState, useReducer의 현재 값을 확인

🔦

Highlight Updates

리렌더링되는 컴포넌트를 시각적으로 표시

edit_note

정리 노트

React 디버깅 핵심 정리

디버깅 5단계

1. 문제 정의
무엇이 잘못됐는지 명확하게 정리
2. 재현
버그가 발생하는 정확한 조건을 찾기
3. 원인 추정
console.log, DevTools로 원인 범위 좁히기
4. 수정
원인을 고치고 다른 곳에 영향 없는지 확인
5. 검증
수정 후 동일 조건에서 버그가 사라졌는지 테스트

체계적인 디버깅 순서(문제→재현→원인→수정→검증)를 습관으로 만드세요.

퀴즈와 인터랙션으로 더 깊이 학습하세요

play_circle인터랙티브 레슨 시작