Ch.24 디버깅 — 에러 메시지 읽는 법
React 디버깅 실전
화면이 안 바뀐다? 무한 렌더링?
React에서는 일반 JS와 다른 종류의 버그가 발생합니다. state가 안 바뀌거나, 무한 렌더링에 빠지거나, key 경고가 뜹니다.
React만의 에러들, 어떻게 빠르게 해결할까?
React 에러는 패턴이 정해져 있습니다. 대표 에러 3가지와 디버깅 체크리스트를 알면 빠르게 해결할 수 있습니다.
핵심 내용
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단계 프로세스의 올바른 순서는?
핵심 용어
컴포넌트 트리
App → Layout → Page 같은 구조를 시각적으로 확인
Props 확인
각 컴포넌트에 전달된 props 값을 실시간으로 확인
State 확인
useState, useReducer의 현재 값을 확인
Highlight Updates
리렌더링되는 컴포넌트를 시각적으로 표시
정리 노트
React 디버깅 핵심 정리
디버깅 5단계
- 1. 문제 정의
- 무엇이 잘못됐는지 명확하게 정리
- 2. 재현
- 버그가 발생하는 정확한 조건을 찾기
- 3. 원인 추정
- console.log, DevTools로 원인 범위 좁히기
- 4. 수정
- 원인을 고치고 다른 곳에 영향 없는지 확인
- 5. 검증
- 수정 후 동일 조건에서 버그가 사라졌는지 테스트
체계적인 디버깅 순서(문제→재현→원인→수정→검증)를 습관으로 만드세요.
퀴즈와 인터랙션으로 더 깊이 학습하세요
play_circle인터랙티브 레슨 시작