본문으로 건너뛰기

Cursor로 React 앱 디버깅: 도구, 팁 및 워크플로우

Cursor React Debugging

React 애플리케이션을 디버깅하는 것은 컴포넌트 계층 구조, 상태 관리 복잡성, 비동기 데이터 흐름 때문에 어려울 수 있습니다. Cursor의 통합 디버깅 도구와 AI 지원을 통해 문제를 더 빠르게 식별하고 수정할 수 있습니다. 이 가이드에서는 React 특화 디버깅 워크플로우를 다룹니다.

사전 요구 사항​

시작하기 전에 다음이 필요합니다:

  • Cursor 설치 (최신 버전)
  • 설정된 React 프로젝트
  • 설치된 React DevTools 브라우저 확장 프로그램 (선택 사항이지만 권장)

Cursor에서 디버깅 설정​

Launch 구성​

React 디버깅을 위해 .vscode/launch.json 생성:

{
"version": "0.2.0",
"configurations": [
{
"name": "Debug React App",
"type": "chrome",
"request": "launch",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}",
"sourceMapPathOverrides": {
"webpack:///src/*": "${webRoot}/src/*"
}
},
{
"name": "Debug Next.js",
"type": "node",
"request": "launch",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev"],
"env": {
"NODE_OPTIONS": "--inspect"
},
"console": "integratedTerminal"
}
]
}

Source Maps​

빌드 구성에서 소스 맵이 활성화되어 있는지 확인하세요:

// vite.config.ts
export default defineConfig({
build: {
sourcemap: true,
},
});

// next.config.js
const nextConfig = {
productionBrowserSourceMaps: true,
};
module.exports = nextConfig;

React 컴포넌트 디버깅​

JSX의 중단점​

컴포넌트 파일에 직접 중단점을 설정하세요:

// src/components/UserProfile.tsx
import { useState, useEffect } from 'react';

export function UserProfile({ userId }: { userId: string }) {
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);

useEffect(() => {
async function fetchUser() {
setLoading(true);
const response = await fetch(`/api/users/${userId}`);
// 여기에 중단점 설정
const data = await response.json();
setUser(data);
setLoading(false);
}

fetchUser();
}, [userId]);

if (loading) return <div>Loading...</div>;
if (!user) return <div>User not found</div>;

return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
}

조걶 중단점​

중단점을 마우스 오른쪽 버튼으로 클릭하여 조건을 설정하세요:

Condition: userId === "12345"

조건이 충족될 때만 중단점이 트리거됩니다.

상태 디버깅 기법​

컨텍스트가 포함된 콘솔 로깅​

Cursor의 AI를 사용하여 전략적인 로그를 추가하세요:

이 컴포넌트의 상태 변경을 추적하는 console.log 문을 추가해주세요

Cursor가 추가합니다:

useEffect(() => {
console.log('[UserProfile] userId changed:', userId);

async function fetchUser() {
console.log('[UserProfile] fetching user...');
const response = await fetch(`/api/users/${userId}`);
const data = await response.json();
console.log('[UserProfile] received data:', data);
setUser(data);
}

fetchUser();
}, [userId]);

React DevTools 통합​

React DevTools는 브라우저에서 실행되지만, Cursor에서 컴포넌트 데이터를 참조할 수 있습니다:

  1. 브라우저에서 React DevTools 열기
  2. 컴포넌트 트리 검사
  3. 컴포넌트 props/state 복사
  4. Cursor 채팅에 붙여넣어 분석
이 컴포넌트가 무한히 다시 렌더링됩니다. DevTools의 props와 state는 다음과 같습니다:
[데이터 붙여넣기]

무엇이 루프를 일으키나요?

훅 문제 해결​

useEffect 의존성​

일반적인 문제: 누락되거나 잘못된 의존성 배열.

// Before - buggy
useEffect(() => {
fetchData(query);
}, []); // Missing dependency

// After - fixed
useEffect(() => {
fetchData(query);
}, [query]); // Correct dependency

Cursor에게 훅을 감사하도록 요청하세요:

이 파일의 모든 useEffect 훅에서 누락된 의존성을 검토해주세요

커스텀 훅 디버깅​

// src/hooks/useLocalStorage.ts
import { useState, useEffect, useCallback } from 'react';

export function useLocalStorage<T>(key: string, initialValue: T) {
// 저장된 값 가져오기
const [storedValue, setStoredValue] = useState<T>(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
console.error(`Error reading localStorage key "${key}":`, error);
return initialValue;
}
});

// useState setter의 래퍼 버전 반환
const setValue = useCallback(
(value: T | ((val: T) => T)) => {
try {
const valueToStore = value instanceof Function ? value(storedValue) : value;
setStoredValue(valueToStore);
window.localStorage.setItem(key, JSON.stringify(valueToStore));
} catch (error) {
console.error(`Error setting localStorage key "${key}":`, error);
}
},
[key, storedValue]
);

return [storedValue, setValue] as const;
}
훅 규칙 위반

Cursor는 조걶적으로 훅을 호출하거나 루프 낶에서 호출하는 등의 일반적인 훅 위반을 감지할 수 있습니다. 린터 통합을 사용하여 조기에 포착하세요.

Next.js 디버깅​

서버 사이드 디버깅​

API 라우트 및 서버 컴포넌트 디버깅:

{
"name": "Debug Next.js Server",
"type": "node",
"request": "launch",
"runtimeExecutable": "npx",
"runtimeArgs": ["next", "dev"],
"env": {
"NODE_OPTIONS": "--inspect=9230"
},
"port": 9230
}

API 라우트 중단점​

// app/api/users/route.ts
import { NextResponse } from 'next/server';

export async function GET() {
// 여기에 중단점 설정
const users = await prisma.user.findMany();

// 디버거에서 users 검사
return NextResponse.json({ users });
}

클라이언트 사이드 vs 서버 사이드​

컨텍스트디버깅 접근 방식
클라이언트 컴포넌트Chrome DevTools, React DevTools
서버 컴포넌트Cursor의 Node.js 디버거
API 라우트Node.js 디버거
미들웨어콘솔 로그 + Node.js 디버거

일반적인 React 문제 및 해결책​

무한 다시 렌더링​

증상: 브라우저가 멈추고 콘솔에 반복된 로그가 표시됩니다.

// Problem: every render creates new object reference
function Parent() {
const [count, setCount] = useState(0);

return (
<Child config={{ limit: 10 }} /> // New object every render!
);
}

// Solution: memoize the config
function Parent() {
const [count, setCount] = useState(0);
const config = useMemo(() => ({ limit: 10 }), []);

return <Child config={config} />;
}

오래된 클로저​

// Problem: callback captures old state
function Counter() {
const [count, setCount] = useState(0);

const logCount = useCallback(() => {
console.log(count); // Always logs initial value
}, []); // Missing dependency

// Solution: use functional updates or include dependency
const logCountFixed = useCallback(() => {
console.log(count);
}, [count]);
}

메모리 누수​

// Problem: state update after unmount
useEffect(() => {
let isMounted = true;

fetchData().then(data => {
if (isMounted) {
setData(data);
}
});

return () => {
isMounted = false;
};
}, []);

Cursor AI를 활용한 디버깅​

오류 분석​

오류 메시지를 Cursor에 붙여넣으세요:

React 앱에서 다음 오류가 발생합니다:
"Cannot read properties of undefined (reading 'map')"

컴포넌트 코드는 다음과 같습니다:
[코드 붙여넣기]

무엇이 잘못되었으며 어떻게 수정하나요?

성능 디버깅​

이 컴포넌트가 느리게 렌더링됩니다. 코드와 React DevTools 프로파일러 스크린샷은 다음과 같습니다:
[코드 붙여넣기]

어떻게 최적화할 수 있나요?

Cursor가 제안하는 일반적인 최적화:

  • useMemo를 사용하여 비용이 많이 드는 계산 메모이제이션
  • React.memo로 불필요한 다시 렌더링 방지
  • 긴 목록 가상화
  • 큰 컴포넌트 분할

상태 관리 디버깅​

Redux DevTools​

개발 환경에서 Redux DevTools 구성:

// store.ts
import { configureStore } from '@reduxjs/toolkit';

export const store = configureStore({
reducer: {
user: userReducer,
cart: cartReducer,
},
devTools: process.env.NODE_ENV !== 'production',
});

Zustand Store 검사​

// Debug Zustand store
import { useUserStore } from './stores/userStore';

// In browser console
const userStore = useUserStore.getState();
console.log(userStore);

디버깅 전 컴포넌트 테스트​

// src/components/__tests__/UserProfile.test.tsx
import { render, screen, waitFor } from '@testing-library/react';
import { UserProfile } from '../UserProfile';

describe('UserProfile', () => {
it('handles loading state', () => {
render(<UserProfile userId="1" />);
expect(screen.getByText('Loading...')).toBeInTheDocument();
});

it('handles error state', async () => {
render(<UserProfile userId="invalid" />);
await waitFor(() => {
expect(screen.getByText('User not found')).toBeInTheDocument();
});
});
});

디버깅 체크리스트​

문제먼저 확인할 사항
컴포넌트가 렌더링되지 않음조걶 반환 및 로딩 상태 확인
상태가 업데이트되지 않음setState 호출 및 의존성 배열 확인
props가 undefined부모 컴포넌트 prop 전달 확인
API 호출 실패네트워크 탭 및 오류 경계 검사
느린 성능불필요한 다시 렌더링 확인
타입 오류TypeScript 인터페이스가 데이터와 일치하는지 확인

디버깅용 키보드 단축키​

작업단축키
중단점 전환F9
디버깅 시작F5
Step overF10
Step intoF11
Step outShift + F11
계속F5
디버그 콘솔 열기Ctrl + Shift + Y

관련 리소스​

마지막 업데이트: 2025년 7월