웹 개발
개발 초보가 프론트엔드 버그를 찾을 때 빠지기 쉬운 함정
복잡한 문제로 보이지만 실제로는 간단한 원인인 경우가 많다. 먼저 확인해야 할 것들.
프로젝트가 복잡해질수록 문제도 복잡해 보인다. 그런데 실제로는 간단한 원인인 경우가 많다. 특히 초보자들이 빠지기 쉬운 함정이 있다.
브라우저 캐시를 의심한다
가장 먼저 할 일은 캐시를 지우는 것이다.
# 개발 서버 종료 후 캐시 정리
rm -rf .next
rm -rf dist
rm -rf node_modules/.cache
그리고 브라우저 캐시도 지운다:
- Chrome: Cmd/Ctrl + Shift + Delete
- 혹은 DevTools에서 Network 탭의 "Disable cache" 체크
변경사항이 안 보이면 대개 캐시 문제다.
콘솔의 에러 메시지를 정확히 읽는다
Browser DevTools를 켠다. Console 탭을 본다. 에러가 있으면 무조건 확인한다.
Uncaught TypeError: Cannot read property 'map' of undefined
이 에러가 있으면 어딘가 배열이 undefined인 상태로 .map()을 호출했다는 뜻이다.
실제로 페이지에 도달했는지 확인한다
URL을 다시 확인한다. 404 페이지는 아닌가?
curl -I https://example.com/blog/post
응답 코드가 200인지, 404인지, 3xx 리다이렉트인지 확인한다.
API 호출이 실제로 일어나는지 본다
DevTools의 Network 탭에서 요청을 본다.
- 요청이 보내졌나?
- 응답 상태가 200인가, 500인가?
- 응답 본문이 비어있지는 않나?
API 문제라면 여기서 드러난다.
변수 값을 직접 출력한다
간단하지만 효과적인 방법이다:
const data = await fetchData()
console.log('data:', data) // 직접 출력
console.log('type:', typeof data) // 타입 확인
React DevTools를 켜서 컴포넌트의 props와 state를 본다.
조건부 렌더링 로직을 확인한다
if (loading) return <Loading />
if (!data) return <Error />
return <Content data={data} />
이 순서가 맞나? 데이터가 없을 때 먼저 체크하는 게 맞다.
또는 옵셔널 체이닝을 쓰는 게 나을 수도 있다:
return <div>{data?.name}</div>
의존성 배열을 확인한다 (React)
useEffect(() => {
fetchData()
}, []) // 빈 배열은 마운트할 때 1번만 실행
Effect가 한 번도 실행되지 않거나 무한 실행되면, 여기서 확인해야 한다.
useEffect(() => {
fetchData()
}, [userId]) // userId가 바뀔 때마다 실행
타입을 확인한다
TypeScript를 쓴다면 타입 에러가 있나?
npm run type-check
혹은 IDE에서 빨간 밑줄이 없나?
최근 코드 변경사항을 돌아본다
git diff
git log -5 --oneline
최근에 뭘 바꿨는지 본다. 그 변경사항이 이 문제와 연관되지 않았나?
단순하게 만들어본다
문제를 재현하는 최소한의 예제를 만든다.
function SimpleTest() {
return <div>Hello World</div>
}
이것부터 시작해서 조금씩 복잡해진다. 어디서 문제가 생기는지 추적한다.
로컬과 배포 환경의 차이를 본다
로컬에서는 괜찮은데 배포 후에 문제가 생긴다면, 환경 변수나 API 엔드포인트를 확인한다.
# 로컬
echo $API_URL
# 배포 환경
ssh user@server "echo $API_URL"
다르면 거기가 원인이다.
결론
초보자들은 복잡한 원인을 찾으려고 한다. 하지만 대개는 캐시, 에러 메시지 놓침, 변수 값 확인 부족 같은 간단한 실수다. DevTools를 켜고, 콘솔 에러를 읽고, 변수 값을 출력해보면 대부분의 문제를 찾을 수 있다.