React를 처음 배우면 마법 같은 useState와 useEffect에 빠져서 열심히 써보게 돼요. 그런데 어느 순간 예상치 못한 버그에 멘붕이 옵니다. 😵💫 "아니, 분명히 상태를 업데이트했는데 왜 값이 바뀌지 않지?" "왜 useEffect가 무한 루프 도는 거야?" 이런 경험, 다들 한 번쯤 있지 않나요? (고개 끄덕이면 동지 ✊) 이번 글에서는 주니어 개발자가 흔히 저지르는 12가지 실수를 정리하고, 해결 방법을 제안해볼게요.
🔥 실수 1. 여러 번 setState를 호출할 때 예상치 못한 결과 발생
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
setCount(count + 1);
};
🚨 위 코드를 실행하면 버튼을 클릭할 때마다 1씩 증가할 것 같지만, 사실 한 번만 증가합니다. 이유는 React의 상태 업데이트는 비동기적이기 때문이에요. 해결책은 업데이터 함수를 사용해서 이전 값을 가져오는 것!
✅ 해결책
setCount(prevCount => prevCount + 1);
setCount(prevCount => prevCount + 1);
이렇게 하면 이전 값이 보존되면서 두 번 업데이트됩니다.
🔥 실수 2. 조건부 렌더링에서 Hook을 조건적으로 호출하기
if (isVisible) {
useEffect(() => {
console.log("이펙트 실행!");
}, []);
}
🚨 React Hook은 무조건 렌더링 순서가 동일해야 해요. 하지만 위 코드처럼 조건문 안에서 호출하면, isVisible이 변할 때마다 useEffect의 실행 순서가 달라질 수도 있어서 오류가 납니다.
✅ 해결책
useEffect(() => {
if (isVisible) {
console.log("이펙트 실행!");
}
}, [isVisible]);
Hook을 조건문 안에 넣지 말고, 내부에서 조건을 확인하도록 수정해 주세요.
🔥 실수 3. 객체 상태를 직접 변경하기
const [user, setUser] = useState({ name: "철수", age: 20 });
const updateAge = () => {
user.age = 21; // ❌ 상태를 직접 변경
setUser(user); // 🚨 React는 이걸 감지하지 못함
};
🚨 React에서 상태를 직접 변경하면 변경 사항을 감지하지 못해서 리렌더링이 발생하지 않아요.
✅ 해결책 (객체를 복사한 후 업데이트)
setUser(prevUser => ({ ...prevUser, age: 21 }));
전개 연산자(...
)를 사용해서 새로운 객체를 만들어야 합니다.
🔥 실수 4. 많은 input이 있는 폼에서 각각의 상태를 관리하기
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
🚨 이렇게 하면 관리해야 할 상태가 많아지고 코드가 지저분해집니다.
✅ 해결책 (하나의 객체로 상태 관리)
const [form, setForm] = useState({ name: "", email: "", password: "" });
const handleChange = (e) => {
setForm(prevForm => ({ ...prevForm, [e.target.name]: e.target.value }));
};
이렇게 하면 handleChange
하나로 모든 입력 값을 관리할 수 있어요.
🔥 실수 5. 불필요한 useEffect 사용
const [price, setPrice] = useState(0);
const [total, setTotal] = useState(0);
useEffect(() => {
setTotal(price * 1.1);
}, [price]);
🚨 이렇게 하면 price가 바뀔 때마다 불필요한 리렌더링이 발생해요.
✅ 해결책 (그냥 변수로 계산하기)
const total = price * 1.1;
state에 저장할 필요 없이, 그냥 변수로 계산해서 사용하면 됩니다.
🚀 12가지 실수를 한눈에 보기 쉽게 정리!
# | 실수 유형 | 해결 방법 |
---|---|---|
1 | setState 여러 번 호출 시 예상치 못한 결과 | 업데이터 함수 사용 (prevState => prevState + 1 ) |
2 | 조건문 안에서 Hook 호출 | 조건문 밖에서 호출, 내부에서 조건 확인 |
3 | 객체 상태 직접 변경 | 새로운 객체를 생성 후 업데이트 |
4 | 폼에서 각각의 상태 관리 | 객체 하나로 상태 관리 |
5 | 불필요한 useEffect 사용 | 변수로 계산 |
6 | useEffect에서 데이터 가져오기 | React Query 또는 SWR 사용 |
7 | 클로저 문제로 인한 setInterval 버그 | useRef 또는 클린업 함수 사용 |
8 | 원시 값 vs 비원시 값 차이 이해 부족 | 객체를 dependency로 넣을 때 useMemo 활용 |
9 | 서버 컴포넌트에서 useState 사용 | use client 지시어 추가 |
10 | TypeScript에서 타입 명시 안 함 | `Post |
11 | 커스텀 Hook을 사용하지 않음 | 공통 로직을 커스텀 Hook으로 분리 |
12 | 비동기 요청 취소 안 함 | AbortController 로 이전 요청 취소 |
React 초보일 때는 이런 실수를 하면서 성장하는 거니까 너무 좌절하지 마세요! (저도 다 겪었습니다 😂) 하지만 이런 문제를 미리 알고 있으면 더 빠르게 성장할 수 있겠죠?
혹시 추가로 헷갈리는 부분이나 궁금한 점 있으면 댓글로 남겨주세요. 우리 같이 성장해봐요! 🚀
'코딩' 카테고리의 다른 글
무료 웹 스크래핑, AI로 자동화하는 방법 (0) | 2025.02.09 |
---|---|
React Hook, 왜 이렇게 복잡한 걸까요? (0) | 2025.02.09 |
HTML을 PDF로 html2pdf, react-pdf, puppeteer 비교 (0) | 2024.10.19 |
메타(Meta)가 React를 활용하는 방법 (0) | 2024.10.13 |
커서(Cursor)는 AI프로그래밍의 미래일까? (0) | 2024.10.11 |