07 - 커서 AI를 사용한 디버깅: 3배 더 빨라짐
디버깅은 개발자의 삶에서 가장 시간이 많이 걸리는 활동 중 하나입니다. 내부 연구 Microsoft와 Google의 보고에 따르면 고위 개발자는 30~40%의 비용을 지출합니다. 버그를 찾고 수정하는 데 생산적인 시간을 투자합니다. AI 네이티브 IDE의 등장으로 비율이 무너지고 있습니다. 최적화된 작업 흐름으로 Cursor를 사용하는 분은 최대 절감 효과를 보고합니다. AI가 오류가 없기 때문이 아니라 디버깅에 소요되는 시간이 65%에 이릅니다. 고독하고 종종 좌절감을 느끼는 프로세스를 체계적이고 체계적인 협업으로 전환합니다.
이 글은 단순히 "AI에게 버그 수정을 요청"하는 방법을 보여주는 것이 아닙니다. 탐험해보자 디버깅 전용 커서의 특정 기능부터 디버그 모드 도입 커서 2.2 사용 시스템에 버그봇 PR의 적극적인 검토를 위해, TypeScript의 메모리 누수, 경쟁 조건 및 불안정한 테스트에 대한 고급 전략 통과 그리고 각도. 디버깅을 예술로 바꾸는 반복 가능한 워크플로를 구축하는 방법을 배우게 됩니다. 검증 가능한 엔지니어링 프로세스를 모호하게 만듭니다.
이 기사에서 배울 내용
- Cursor 2.2의 디버그 모드 작동 방식과 런타임 로그를 기반으로 하는 에이전트 루프
- Bugbot: 자동 자동 수정을 통해 풀 요청에 대한 사전 버그 감지
- 즉각적인 스택 추적 분석을 위한 Cmd+K 워크플로 및 인라인 채팅
- 커서의 소스 맵을 사용하여 TypeScript/Angular 디버거 구성
- 메모리 누수, 경쟁 조건 및 불안정한 테스트에 대한 AI 전략
- Chrome DevTools 및 기본 VS Code 디버거와의 통합
- 전체 주기: 재현 - 격리 - 계측 - 수정 - 검증
- 실제 측정항목을 사용한 기존 디버깅과 AI 지원 디버깅 간의 비교
Cursor IDE 및 AI 네이티브 개발 시리즈의 기사
| # | Articolo | 수준 |
|---|---|---|
| 1 | 커서 IDE: 개발자를 위한 전체 가이드 | 초보자 |
| 2 | 커서 규칙: 프로젝트에 대한 AI 구성 | 중급 |
| 3 | 에이전트 모드: 명령으로 코드베이스 수정 | 중급 |
| 4 | 계획 모드 및 백그라운드 에이전트 | 고급의 |
| 5 | 커서 후크: 작업 흐름 자동화 | 중급 |
| 6 | MCP 및 커서: IDE를 데이터베이스 및 API에 연결 | 고급의 |
| 7 | 현재 위치 - Cursor AI를 사용한 디버깅: 3배 더 빨라짐 | 중급 |
| 8 | 2026년 커서 vs 윈드서핑 vs 코파일럿 | 초보자 |
| 9 | 전문적인 작업 흐름: 커서가 있는 각도 | 고급의 |
전통적인 디버깅의 문제점
문제가 무엇인지 알아내기 위해 스택 추적을 3시간 동안 관찰한 사람
에 undefined nullable 필드에서는 우리가 말하는 내용을 정확히 알고 있습니다. 디버깅
전통적인 방법은 인지 비용이 엄청납니다. 프로그램의 상태를 머릿속에 유지해야 합니다.
가설을 세우고, 로그를 추가하고, 버그를 재현하고, 결과를 해석하고, 반복합니다.
흐름의 모든 중단 - 추가할 새 로그, 이동할 중단점 -
집중이 깨집니다.
디버깅을 위해 커서를 사용하는 개발자는 이 프로세스를 제거하지 않지만 속도를 높입니다. 근본적으로. 핵심은 AI가 전체 맥락을 동시에 염두에 둘 수 있다는 점이다. 고급 논리에 집중하는 동안 코드베이스를 살펴보세요. 커서 2.2 공식화 이 접근 방식은 디버그 모드, 완전히 새로운 에이전트 루프 구축 런타임 정보 및 사람의 검증에 관한 것입니다.
기존 디버깅과 AI 지원 디버깅: 숫자
| 활동 | 전통적인 | 커서 AI와 함께 | 저금 |
|---|---|---|---|
| 스택 추적 분석 | 15~30분 | 2~5분 | ~80% |
| 근본 원인 식별 | 1~4시간 | 20~45분 | ~70% |
| 수정 및 확인 | 30~90분 | 10~25분 | ~65% |
| 메모리 누수 조사 | 2~6시간 | 45~90분 | ~70% |
| 경쟁 조건 감지 | 4~12시간 | 1~3시간 | ~75% |
| 불안정한 테스트 안정화 | 2~8시간 | 30~60분 | ~80% |
디버그 모드: 커서 2.2 에이전트 루프
2025년 12월 10일에 Cursor는 버전 2.2를 출시했습니다. 디버그 모드, IDE 역사상 가장 중요한 기능 중 하나입니다. 간단한 일이 아니죠 AI와 VS Code 디버거 통합: 완전히 재설계된 에이전트 루프 런타임 정보 및 인간 협업에 관한 것입니다.
디버그 루프의 작동 방식
일반 지원 디버깅과 비교했을 때 근본적인 차이점은 디버그 모드에서는 이를 찾지 않는다는 것입니다. 즉시 수정 사항을 생성합니다. 대신 다음과 같은 5단계 프로세스를 따릅니다.
디버그 모드 루프
- 가설 분석: 커서는 코드베이스를 읽고 여러 가설을 생성합니다. 원인을 안다고 가정하지 않고 무엇이 잘못되었을 수 있는지에 대해
- 수단: 에이전트는 특정 지점에 대상 런타임 로그를 추가합니다. 문제의 가능한 원인으로 확인됨
- 안내 재생: 커서가 사용자에게 버그 재현을 요청합니다. 계측을 제자리에 두고 런타임 데이터를 수집합니다.
- 타겟 수정: 실제 데이터를 기반으로 최소한의 수정사항을 제안합니다. 추측에 따라 다시 작성하는 대신 정확하고
- 점검 및 청소: 점검 후 모든 장비를 제거합니다. 커밋을 위해 깨끗한 diff를 준비 상태로 남겨두기
디버그 모드를 활성화하려면 Composer 패널을 열고 버튼 옆의 드롭다운을 클릭하세요. "디버그 모드"를 입력하고 선택하십시오. 그 순간부터 에이전트는 이 루프에서 작동합니다. 변경 사항을 직접 진행하는 대신.
// Esempio di come Cursor strumenta il codice durante Debug Mode
// File: src/app/services/payment.service.ts
// PRIMA della strumentazione
async processPayment(order: Order): Promise<PaymentResult> {
const cart = await this.cartService.getCart(order.userId);
const total = this.calculateTotal(cart);
return this.paymentGateway.charge(order.paymentMethod, total);
}
// DOPO la strumentazione aggiunta da Cursor Debug Mode
async processPayment(order: Order): Promise<PaymentResult> {
console.log('[DEBUG:cursor] processPayment called', {
orderId: order.id,
userId: order.userId,
paymentMethod: order.paymentMethod
});
const cart = await this.cartService.getCart(order.userId);
console.log('[DEBUG:cursor] cart retrieved', {
cartId: cart?.id,
itemCount: cart?.items?.length,
cartIsNull: cart === null
});
const total = this.calculateTotal(cart);
console.log('[DEBUG:cursor] total calculated', { total, cartTotal: cart?.total });
const result = await this.paymentGateway.charge(order.paymentMethod, total);
console.log('[DEBUG:cursor] payment result', { success: result.success, error: result.error });
return result;
}
// Dopo la riproduzione, Cursor vede nei log:
// [DEBUG:cursor] cart retrieved { cartId: undefined, itemCount: undefined, cartIsNull: false }
// Questo rivela che cart esiste ma items e undefined - bug trovato!
계측 접근 방식은 추측을 제거하므로 집중적이고 강력합니다. 대신에 가설을 기반으로 코드를 다시 작성하면 Cursor는 조치를 취하기 전에 구체적인 증거를 수집합니다. 최종 결과는 항상 최소 차이입니다. 리팩토링 없이 필요한 수정만 수행됩니다. 동의하지 않은 기능의 요청 또는 추가.
디버그 모드가 가장 효과적인 경우
- 항상 재현되지 않는 간헐적인 버그(경합 조건, 타이밍 문제)
- 익숙하지 않은 레거시 코드의 문제
- 실제 데이터가 있는 프로덕션에서만 나타나는 버그
- 여러 라이브러리에 걸친 심층 스택 추적 오류
- 명시적인 오류가 없는 예기치 않은 동작(자동 오류)
디버그 모드이며 명백한 컴파일 오류나 TypeScript 오류에는 덜 유용합니다. Cmd+K 인라인이 훨씬 빠릅니다.
Bugbot: PR에 대한 사전 예방적 버그 감지
디버그 모드는 버그가 나타난 후 수정하지만, 버그봇 노력하다 생산에 도달하기도 전에 차단하세요. 2025년 7월 버전 1 출시 2026년 1월 Bugbot v11을 통해 크게 향상되었으며 프로세스에 통합되었습니다. 각 풀 요청을 자동으로 분석하여 코드 검토를 수행합니다.
버그봇 작동 방식
Bugbot은 각각 순서가 있는 여러 병렬 패스를 사용하여 PR 차이를 분석합니다. 모델에서 다양한 추론을 자극하기 위해 다양한 변경을 수행합니다. 결과가 나오네요 오탐(false positive)을 줄이기 위해 다수결 투표와 결합됩니다. 이 접근 방식은 인간 리뷰어로 구성된 앙상블은 눈에 띄지 않는 실제 버그를 잡아내는 것으로 나타났습니다. 전통적인 코드 리뷰에서는
// Esempio di configurazione Bugbot rules in .cursor/bugbot.rules
// Queste regole personalizzano cosa Bugbot considera un bug nel tuo progetto
# Regole per progetto Angular/TypeScript
## Patterns Pericolosi
- Flag qualsiasi uso di 'any' in funzioni pubbliche dei servizi
- Segnala operatori non-null assertion '!' su proprietà di input Angular
- Evidenzia subscribe() senza corrispondente unsubscribe() o takeUntilDestroyed()
- Avvisa quando una migration SQL non ha rollback corrispondente
## Invarianti del Progetto
- I componenti non devono accedere direttamente all'HttpClient, solo ai servizi
- Tutti i form devono avere validazione lato client E lato server
- Non usare localStorage direttamente, usa StorageService
## Falsi Positivi da Ignorare
- I file *.spec.ts possono usare 'any' per i mock
- I file di configurazione possono avere assert non-null
Bugbot Autofix: 자동 수정
Bugbot v11e의 가장 강력한 기능 자동 수정: Bugbot이 식별한 경우 PR의 버그는 수정 사항을 구현하기 위해 자동으로 클라우드 에이전트를 열 수 있습니다. 에이전트는 PR에 대한 설명이나 추가 커밋으로 변경 사항을 제안합니다. 검토자는 한 번의 클릭으로 수정 사항을 승인하거나 거부할 수 있습니다.
// Bug trovato da Bugbot su PR #142:
// File: src/app/components/user-profile/user-profile.component.ts
// PROBLEMA: Memory leak - Observable non viene unsubscribed
@Component({
selector: 'app-user-profile',
template: `<div>{{ user?.name }}</div>`
})
export class UserProfileComponent implements OnInit {
user: User | null = null;
constructor(private userService: UserService) {}
ngOnInit() {
// BUGBOT: Observable subscription senza unsubscribe
// Causa memory leak quando il componente viene distrutto
this.userService.getCurrentUser().subscribe(user => {
this.user = user;
});
}
}
// FIX PROPOSTO DA BUGBOT AUTOFIX:
@Component({
selector: 'app-user-profile',
template: `<div>{{ user?.name }}</div>`
})
export class UserProfileComponent {
private destroyRef = inject(DestroyRef);
user: User | null = null;
constructor(private userService: UserService) {
this.userService.getCurrentUser()
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(user => {
this.user = user;
});
}
}
Bugbot은 끊임없이 진화하고 있습니다. 커서가 버전을 실험 중입니다. 항상 켜져 있는 PR을 기다리는 대신 지속적으로 코드베이스를 스캔하고 다음 주요 릴리스 Bugbot이 코드를 실행하여 자체 버그 보고서를 먼저 확인할 수 있도록 허용합니다. 그들을 신고합니다.
Cmd+K 및 인라인 채팅을 사용한 빠른 디버깅
대부분의 일상적인 버그에는 디버그 모드와 Bugbot이 강력한 도구이지만 때로는 너무 크다. Cursor e의 명백한 버그를 수정하는 가장 빠른 방법 통해 명령+K (인라인 편집) 및 채팅 패널.
즉각적인 스택 추적 분석
콘솔이나 터미널에 예외가 나타나면 가장 효율적인 작업 흐름은 다음과 같습니다.
- 콘솔에서 전체 스택 추적을 선택하세요.
- 누르다
Cmd+Shift+L채팅 컨텍스트에 선택 항목을 추가하려면 - 당신은 다음과 같이 씁니다: "이 스택 추적을 분석하고 근본 원인을 식별하십시오. 코드에서 문제가 있는 위치를 보여주고 최소한의 수정 사항을 제안하십시오."
커서는 오류의 첫 번째 줄만 읽는 것이 아닙니다. 스택의 파일 경로를 따릅니다. 프로젝트에서 관련 코드를 검색하고 호출 체인을 정신적으로 재구성합니다. 예외가 발생했습니다.
// Stack trace reale di un'app Angular con NgRx
ERROR TypeError: Cannot read properties of undefined (reading 'items')
at CartComponent.getItemCount (cart.component.ts:47:35)
at CartComponent_Template (cart.component.html:12:18)
at executeTemplate (core.mjs:11223)
at refreshView (core.mjs:11094)
at refreshComponent (core.mjs:12147)
at refreshChildComponents (core.mjs:11060)
// Cosa chiedi a Cursor:
// "Questo stack trace viene da un'app Angular con NgRx.
// CartComponent.getItemCount accede a items su una proprietà
// che risulta undefined. Analizza cart.component.ts e lo store
// corrispondente per trovare dove il dato non viene inizializzato."
// Cursor risponde analizzando:
// 1. cart.component.ts - come viene acceduto lo store
// 2. cart.reducer.ts - lo stato iniziale del reducer
// 3. cart.selectors.ts - i selettori usati nel componente
// E identifica:
// PROBLEMA in cart.reducer.ts:
const initialState: CartState = {
// 'items' manca! Lo stato iniziale non ha la proprietà
loading: false,
error: null
// items: [] <-- questa riga manca
};
// FIX:
const initialState: CartState = {
items: [], // aggiunto
loading: false,
error: null
};
상황별 인라인 수정을 위한 Cmd+K
문제 라인을 이미 식별한 경우, 명령+K 그리고 더 많은 방법 수정 사항을 빠르게 적용합니다. 문제가 있는 코드를 선택하고 Cmd+K를 누른 후 설명하세요. 문제는 자연어입니다. 커서는 선택한 코드만 수정합니다. 파일의 나머지 부분을 탭하세요.
// Selezioni questo codice in un service Angular e premi Cmd+K:
getUserData(id: string) {
return this.http.get(`/api/users/${id}`);
}
// Scrivi: "aggiungi gestione errori, tipizzazione forte con User interface,
// e timeout di 5 secondi"
// Cursor genera:
getUserData(id: string): Observable<User> {
return this.http.get<User>(`/api/users/${id}`).pipe(
timeout(5000),
catchError((error: HttpErrorResponse) => {
if (error.status === 404) {
return throwError(() => new Error(`User ${id} not found`));
}
if (error.name === 'TimeoutError') {
return throwError(() => new Error('Request timed out'));
}
return throwError(() => new Error('Failed to load user data'));
})
);
}
디버깅 중 체크포인트 및 롤백
디버깅 및 시스템 시 자주 간과되는 기능 체크포인트 커서의. 여러 수정 가설을 탐색할 때 현재 상태를 저장할 수 있습니다. 코드베이스를 체크포인트로 설정하고 상황이 악화되면 롤백합니다.
체크포인트를 사용한 워크플로
- 복잡한 버그 디버깅을 시작하기 전에 체크포인트를 저장하세요.
- 커서를 사용하여 첫 번째 수정 가설을 시도해 보세요.
- 테스트 실행: 실패하면 한 번의 클릭으로 체크포인트를 재설정합니다.
- 깨끗한 상태에서 시작하여 두 번째 가설을 테스트합니다.
- 테스트가 통과할 때까지 계속
이는 고전적인 "상황을 악화시켰고 어떻게 되돌릴 수 있는지 모르겠습니다"라는 문제를 제거합니다. 솔루션 탐색이 훨씬 덜 위험해집니다.
커서에서 TypeScript/Angular 디버거 구성
커서는 VS Code와 동일한 디버깅 엔진을 사용합니다.
launch.json 당신은 동일하게 작동한다는 것을 알고 있습니다. 차이점은 커서
무슨 일이 일어나고 있는지 해석하는 데 도움이 되도록 프로세스 주변에 AI 레이어를 추가합니다.
문제를 더 빠르게 해결하세요.
TypeScript용 소스 맵 설정
효과적인 TypeScript 디버깅을 위한 핵심 요구 사항은 올바른 구성입니다. 소스 맵 중. 이것이 없으면 디버거는 대신 컴파일된 JavaScript 파일을 가리킵니다. 소스 TypeScript 파일보다 디버깅하는 동안 코드를 읽을 수 없게 됩니다.
// tsconfig.json - configurazione base per debugging
{
"compilerOptions": {
"target": "ES2022",
"module": "ES2022",
"sourceMap": true, // OBBLIGATORIO per debugging TS
"inlineSources": true, // Include sorgente nelle source maps
"inlineSourceMap": false, // Usa file .map separati
"outDir": "./dist",
"strict": true,
"moduleResolution": "node"
}
}
// .vscode/launch.json - configurazione per Angular con Chrome
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Angular App",
"type": "chrome",
"request": "launch",
"url": "http://localhost:4200",
"webRoot": "${workspaceFolder}/src",
"sourceMapPathOverrides": {
"webpack:///./src/*": "${webRoot}/*"
},
"skipFiles": [
"node_modules/**",
"**/*.spec.ts"
]
},
{
"name": "Debug Jest Tests",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/node_modules/.bin/jest",
"args": [
"--runInBand",
"--no-coverage",
"${file}"
],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"env": {
"NODE_ENV": "test"
}
},
{
"name": "Debug Node.js Server",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/src/server/index.ts",
"runtimeArgs": ["--require", "ts-node/register"],
"sourceMaps": true,
"envFile": "${workspaceFolder}/.env.local"
}
]
}
일단 구성되면 launch.json, 다음을 사용하여 디버거를 시작할 수 있습니다. F5
VS Code처럼 말이죠. 커서와의 차이점은 중단점이나 정수를 선택할 수 있다는 것입니다.
디버그 패널에서 기능을 실행하고 AI에게 동작을 설명하도록 요청하거나
변수에 예상치 못한 값이 있는 이유를 제안합니다.
트릭: 커서의 기본 TypeScript 비활성화
대규모 프로젝트(단일 저장소, 100개 이상의 모듈이 있는 작업 공간)에서는 TypeScript 언어 서버 커서는 많은 메모리를 소모할 수 있습니다. 속도가 느려지거나 충돌이 발생하는 경우 다음을 추가하세요. Cursor의 내부 TypeScript 대신 프로젝트의 TypeScript를 사용하도록 구성합니다.
// .cursor/settings.json
{
"typescript.enableNativePreview": false,
"typescript.tsdk": "./node_modules/typescript/lib"
}
AI를 사용한 메모리 누수, 경쟁 조건 및 불안정한 테스트
이 세 가지 범주의 버그는 역사적으로 디버깅하기 가장 어렵습니다. 그것들은 결정적이지 않습니다. 간헐적으로 발생하며 종종 생산 중에만 발생합니다. 또는 부하가 걸려서 분리하려고 하면 제거되는 경우가 많습니다. 커서의 AI는 여기서 중요한 이점은 코드를 정적으로 분석할 수 있다는 것입니다. 식별하다 패턴 이러한 버그가 나타나기 전에도 이러한 버그가 발생합니다.
Angular의 메모리 누수: 진단 및 수정
Angular에서 가장 일반적인 메모리 누수는 관리되지 않는 RxJS 구독입니다. 하지만 그들은 존재한다 Cursor가 특정 프로젝트에서 인식하는 방법을 배우는 다른 많은 문제 패턴.
// Prompt efficace per ricerca memory leak:
// "Analizza questo componente e identifica tutti i possibili
// memory leaks. Includi: subscriptions non gestite, event listeners
// non rimossi, interval/timeout non cancellati, e reference circolari."
// Componente con multipli leak:
@Component({
selector: 'app-dashboard',
template: `...`
})
export class DashboardComponent implements OnInit {
data: any[] = [];
private subscription: Subscription;
constructor(
private dataService: DataService,
private router: Router,
private renderer: Renderer2,
private elementRef: ElementRef
) {}
ngOnInit() {
// LEAK 1: Subscription senza unsubscribe
this.subscription = this.dataService.getStream()
.subscribe(data => this.data = data);
// LEAK 2: Event listener sul document non rimosso
document.addEventListener('keydown', this.handleKeyPress.bind(this));
// LEAK 3: Interval non cancellato
setInterval(() => this.refreshData(), 5000);
// LEAK 4: Router events subscription
this.router.events.subscribe(event => {
console.log(event);
});
}
handleKeyPress(event: KeyboardEvent) { /* ... */ }
refreshData() { /* ... */ }
}
// VERSIONE CORRETTA (generata da Cursor):
@Component({
selector: 'app-dashboard',
template: `...`
})
export class DashboardComponent implements OnInit, OnDestroy {
data: any[] = [];
private destroyRef = inject(DestroyRef);
private intervalId: ReturnType<typeof setInterval> | null = null;
private boundHandleKeyPress: (event: KeyboardEvent) => void;
constructor(
private dataService: DataService,
private router: Router
) {}
ngOnInit() {
// FIX 1: takeUntilDestroyed per tutte le subscriptions
this.dataService.getStream()
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(data => this.data = data);
// FIX 2: Listener con cleanup esplicito
this.boundHandleKeyPress = this.handleKeyPress.bind(this);
document.addEventListener('keydown', this.boundHandleKeyPress);
// FIX 3: Interval con riferimento per cleanup
this.intervalId = setInterval(() => this.refreshData(), 5000);
// FIX 4: Router events con takeUntilDestroyed
this.router.events
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(event => console.log(event));
}
ngOnDestroy() {
document.removeEventListener('keydown', this.boundHandleKeyPress);
if (this.intervalId) {
clearInterval(this.intervalId);
}
}
handleKeyPress(event: KeyboardEvent) { /* ... */ }
refreshData() { /* ... */ }
}
경쟁 조건: 진단 패턴
여러 비동기 HTTP 요청이 있을 때 Angular의 경쟁 조건이 자주 발생합니다. 예측할 수 없는 순서로 완료되거나 구성 요소 상태가 업데이트될 때 완료됩니다. 구성 요소가 파괴된 후.
// Race condition classica in Angular: richieste HTTP concorrenti
// L'utente digita velocemente nel search box - ogni keystroke
// lancia una nuova richiesta, ma non necessariamente arrivano in ordine
// PROBLEMA:
@Component({
selector: 'app-search',
template: `
<input (input)="onSearch($event)">
<div *ngFor="let result of results">{{ result.title }}</div>
`
})
export class SearchComponent {
results: SearchResult[] = [];
constructor(private searchService: SearchService) {}
onSearch(event: Event) {
const query = (event.target as HTMLInputElement).value;
// RACE CONDITION: se digiti "an" poi "ang", la risposta per "an"
// potrebbe arrivare DOPO quella per "ang", mostrando risultati sbagliati
this.searchService.search(query).subscribe(results => {
this.results = results;
});
}
}
// SOLUZIONE con switchMap (generata da Cursor):
@Component({
selector: 'app-search',
template: `
<input [formControl]="searchControl">
<div *ngFor="let result of results$ | async">{{ result.title }}</div>
`
})
export class SearchComponent {
searchControl = new FormControl('');
private destroyRef = inject(DestroyRef);
results$ = this.searchControl.valueChanges.pipe(
debounceTime(300), // Attendi 300ms dopo l'ultimo keystroke
distinctUntilChanged(), // Ignora se il valore non cambia
filter(query => (query?.length ?? 0) >= 2), // Min 2 caratteri
switchMap(query => // Cancella la richiesta precedente
this.searchService.search(query ?? '').pipe(
catchError(() => of([])) // Gestisce errori senza rompere lo stream
)
),
takeUntilDestroyed(this.destroyRef)
);
constructor(private searchService: SearchService) {}
}
불안정한 테스트: 안정화 전략
불안정한 테스트(간헐적으로 통과하고 실패하는 테스트)가 문제 중 하나입니다. 현대 개발 중 가장 실망스러운 것. 커서는 식별에 특히 효과적입니다. 테스트와 테스트된 코드, 패턴을 동시에 분석할 수 있기 때문입니다. 타이밍의.
// Flaky test in Angular: problema con async/await e timing
// Questo test fallisce circa il 30% delle volte
// FLAKY TEST:
it('should update user when form is submitted', fakeAsync(() => {
const fixture = TestBed.createComponent(UserFormComponent);
const component = fixture.componentInstance;
fixture.detectChanges();
component.nameControl.setValue('John Doe');
component.onSubmit();
// Problema: il test non aspetta il completamento dell'Observable
expect(component.successMessage).toBe('User updated successfully');
}));
// Cosa chiedi a Cursor:
// "Questo test e flaky - fallisce intermittentemente. Analizza il
// componente UserFormComponent e identifica perchè il test non e
// deterministico. Proponi una versione stabile del test."
// RISPOSTA DI CURSOR - analisi del problema:
// Il componente usa un Observable con delay, il test non lo aspetta correttamente
// TEST STABILE (generato da Cursor):
it('should update user when form is submitted', fakeAsync(() => {
const userServiceSpy = jasmine.createSpyObj('UserService', ['updateUser']);
userServiceSpy.updateUser.and.returnValue(of({ success: true }).pipe(delay(100)));
TestBed.configureTestingModule({
declarations: [UserFormComponent],
providers: [
{ provide: UserService, useValue: userServiceSpy }
]
});
const fixture = TestBed.createComponent(UserFormComponent);
const component = fixture.componentInstance;
fixture.detectChanges();
component.nameControl.setValue('John Doe');
component.onSubmit();
// Avanza il tempo virtuale di 100ms per completare il delay
tick(100);
fixture.detectChanges();
expect(component.successMessage).toBe('User updated successfully');
expect(userServiceSpy.updateUser).toHaveBeenCalledOnceWith({
name: 'John Doe'
});
}));
AI가 지원하는 성능 프로파일링
성능 디버깅은 별도의 분야입니다. 오류를 찾는 것이 아니라 오류를 찾는 것입니다. 왜 무언가가 느린지 이해하십시오. 커서는 Chrome과 같은 전용 프로파일러를 대체하지 않습니다. DevTools 또는 Angular DevTools이지만 해석 프로세스 속도가 크게 향상됩니다. 데이터 프로파일링 및 최적화 구현.
커서를 사용하여 성능 프로필 분석
가장 효과적인 워크플로우를 제공하고 기본 도구를 사용하여 성능 데이터를 캡처한 후 분석 및 수정 사항 구현을 위해 커서에 결과가 표시됩니다.
// Esempio di workflow: ottimizzare un componente Angular lento
// Hai identificato con Angular DevTools che questo componente
// causa 850ms di change detection su ogni input
// Componente problematico (dati dal profiler):
@Component({
selector: 'app-large-table',
template: `
<table>
<tr *ngFor="let item of processedItems">
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
<td>{{ formatDate(item.createdAt) }}</td>
<td>{{ calculateTotal(item) }}</td>
</tr>
</table>
`
})
export class LargeTableComponent {
@Input() items: RawItem[] = [];
// PROBLEMA 1: getter ricalcolato ad ogni change detection
get processedItems() {
return this.items.map(item => this.processItem(item));
}
// PROBLEMA 2: funzione chiamata nel template - ricreata ogni volta
formatDate(date: Date): string {
return new Intl.DateTimeFormat('it-IT').format(date);
}
// PROBLEMA 3: calcolo costoso nel template
calculateTotal(item: RawItem): number {
return item.prices.reduce((acc, price) => acc + price.amount, 0);
}
private processItem(item: RawItem): ProcessedItem { /* ... */ }
}
// VERSIONE OTTIMIZZATA (generata da Cursor con spiegazione):
@Component({
selector: 'app-large-table',
template: `
<table>
<tr *ngFor="let item of processedItems; trackBy: trackById">
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
<td>{{ item.formattedDate }}</td>
<td>{{ item.total }}</td>
</tr>
</table>
`,
changeDetection: ChangeDetectionStrategy.OnPush // FIX 3: OnPush CD
})
export class LargeTableComponent {
private _items: RawItem[] = [];
processedItems: ProcessedItem[] = [];
@Input() set items(value: RawItem[]) {
this._items = value;
// FIX 1: calcola solo quando input cambia, non ad ogni CD
this.processedItems = value.map(item => this.processItem(item));
}
// FIX 2: trackBy per evitare ricreazione DOM inutile
trackById(index: number, item: ProcessedItem): string {
return item.id;
}
private dateFormatter = new Intl.DateTimeFormat('it-IT');
private processItem(item: RawItem): ProcessedItem {
return {
...item,
// Pre-calcola tutto durante la trasformazione
formattedDate: this.dateFormatter.format(item.createdAt),
total: item.prices.reduce((acc, price) => acc + price.amount, 0)
};
}
}
Chrome DevTools와 통합
고급 성능 디버깅을 위해 가장 강력한 워크플로는 Chrome DevTools를 결합합니다. 커서로. Chrome에서 성능 또는 메모리 프로필을 캡처하고 데이터를 내보내고 커서에게 코드베이스의 맥락에서 해석하도록 요청하세요.
// Workflow con Chrome DevTools + Cursor
// 1. In Chrome DevTools > Performance, cattura un profilo
// Identifica i frame lenti (rossi) e le funzioni costose
// 2. Copia il nome delle funzioni costose nel profile:
// "component_factory.ts:847 - ComponentFactory.create - 234ms"
// 3. Porta in Cursor:
// "Ho profilato la mia app Angular e component_factory.create
// richiede 234ms nei frame lenti. Il profiler mostra che viene
// chiamata quando l'utente cambia route. Analizza il sistema
// di routing e lazy loading e identifica dove i componenti
// vengono ricreati invece di essere riutilizzati."
// 4. Per heap snapshots (memory leaks):
// - In Chrome DevTools > Memory, prendi due heap snapshots:
// uno prima e uno dopo un'operazione sospetta
// - Confronta: Objects allocated between snapshots
// - Copia i tipi di oggetti con crescita anomala in Cursor:
// "Il heap snapshot mostra un aumento di 15MB in
// 'EventEmitter' instances dopo navigazione back/forward.
// Analizza i componenti che usano EventEmitter e identifica
// dove non vengono destroyati correttamente."
디버깅 워크플로: 재현, 격리, 수정, 테스트
하나의 강력한 기능을 갖는 것만으로는 충분하지 않습니다. 진정한 경쟁 우위는 통합에서 비롯됩니다. 반복 가능하고 체계적인 작업 흐름에서 이러한 도구를 사용할 수 있습니다. 개발자가 수행하는 작업 흐름은 다음과 같습니다. 커서를 사용하면 생산성이 향상됩니다.
1단계: 최대한의 맥락으로 플레이
코드를 터치하기 전에 버그에 대해 사용 가능한 모든 정보를 수집하세요. 커서로, 이는 가능한 가장 풍부한 컨텍스트를 AI에 제공하는 것을 의미합니다.
// Template per il primo messaggio di debugging in Cursor Chat:
/*
BUG REPORT:
- Comportamento atteso: [descrizione]
- Comportamento osservato: [descrizione]
- Frequenza: [sempre / intermittente al X%]
- Ambiente: [dev / staging / prod]
- Ultima modifica correlata: [commit hash o feature]
ERROR OUTPUT:
[incolla lo stack trace completo]
PASSI PER RIPRODURRE:
1. [passo 1]
2. [passo 2]
FILES PROBABILMENTE COINVOLTI:
- src/app/services/order.service.ts
- src/app/components/checkout/checkout.component.ts
@codebase analizza i file rilevanti e proponi le prime 3 ipotesi
sulla root cause, ordinate per probabilità.
*/
2단계: 최소한의 테스트로 격리
가장 가능성이 높은 가설을 확인한 후 커서에게 테스트 생성을 요청하세요. 버그를 별도로 재현합니다. 여기에는 두 가지 이점이 있습니다. 가설 테스트 자동 회귀 테스트를 제공합니다.
// Prompt per creare un test di isolamento:
// "Sulla base dell'analisi, il bug sembra essere in OrderService.calculateDiscount()
// quando items ha elementi con quantity: 0. Crea un unit test Jest che riproduce
// esattamente questo scenario e verifica il comportamento corretto."
// Cursor genera:
describe('OrderService.calculateDiscount', () => {
let service: OrderService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(OrderService);
});
// Test che riproduce il bug
it('should handle items with zero quantity without throwing', () => {
const orderWithZeroQty = {
items: [
{ id: '1', price: 100, quantity: 2 },
{ id: '2', price: 50, quantity: 0 }, // caso problematico
{ id: '3', price: 75, quantity: 1 }
],
discountCode: 'SAVE10'
};
// BUG: questo throw invece di restituire 0
expect(() => service.calculateDiscount(orderWithZeroQty)).not.toThrow();
expect(service.calculateDiscount(orderWithZeroQty)).toBe(17.5);
});
});
3단계: 증분 확인으로 수정
격리 테스트가 완료되면 수정 사항을 적용하고 즉시 확인하세요. 역 TDD 접근 방식 - 먼저 회귀 테스트를 수행한 다음 수정합니다. 예: 빠르게 반복할 수 있기 때문에 Cursor를 사용하면 특히 효과적입니다.
// Prompt per la fix:
// "Il test di isolamento conferma il bug. Il problema e in calculateDiscount
// quando quantity e 0 causa una divisione per zero nel calcolo del prezzo
// unitario medio. Fixa calculateDiscount gestendo il caso quantity === 0
// e assicurati che tutti i test esistenti continuino a passare."
// Cursor analizza e genera la fix:
calculateDiscount(order: Order): number {
const validItems = order.items.filter(item => item.quantity > 0); // FIX
if (validItems.length === 0) {
return 0;
}
const subtotal = validItems.reduce(
(sum, item) => sum + (item.price * item.quantity),
0
);
const discount = this.discountService.getDiscount(order.discountCode);
return subtotal * (discount / 100);
}
4단계: 전체 회귀 테스트
수정 후 커서에게 버그를 다루는 완전한 테스트 모음을 생성하도록 요청하세요. 문제가 재발하지 않도록 고정 및 관련 엣지 케이스.
// Prompt finale:
// "La fix e applicata e il test di isolamento passa. Ora genera una suite
// completa di test per calculateDiscount che copre: items normali,
// items con quantity 0, lista vuota, discount code invalido,
// e ordini con tutti gli items a quantity 0."
// Cursor genera 8 test cases che coprono tutti gli edge cases
// e aggiunge JSDoc al metodo spiegando il comportamento atteso
AI 지원 디버깅 모범 사례
1. 항상 정확한 상황
AI 지원 디버깅은 제공하는 컨텍스트만큼만 우수합니다. 모호한 프롬프트와 정확한 프롬프트의 차이는 다음과 같습니다. 10분 2시간 작업.
효과적인 디버깅 프롬프트를 위한 원칙
- 전체 스택 추적: 첫 번째 줄뿐만 아니라 항상 5~10줄
- 예상되는 동작과 관찰된 동작: 둘 다 설명한다
- 파일 컨텍스트: 미국
@filename.ts관련 파일을 포함하려면 - 최종 수정 날짜: 버그가 최근에 발생했다면 커밋이나 기능을 인용하세요.
- 환경: dev/staging/prod의 동작이 자주 변경됩니다.
- 빈도: 항상/간헐적으로/부하가 있는 경우에만
2. AI 수정을 맹목적으로 신뢰하지 마세요
AI는 원인이 아닌 증상을 해결하는 수정 사항을 생성할 수 있습니다. 올바른 작업흐름 e 항상: 제안된 수정 사항을 이해하고, 테스트를 통해 확인하고, 의식적으로 승인합니다.
안티 패턴: 수정 사항을 이해하지 못한 채 수정 사항 수용
"바이브 디버깅" 패턴 - AI에게 버그 수정을 요청하고 첫 번째 버그를 수락합니다. 제안을 이해하지 못한 채 생산에 밀어 넣는 것이 가장 빠른 축적 방법입니다. 기술 부채. 각 수정 사항은 다음과 같아야 합니다.
- 논리적 수준에서 발생합니다.
- 하나 이상의 테스트로 확인됨
- 의도하지 않은 부작용이 있는지 검토했습니다.
3. 디버깅에 커서 규칙 사용
AI를 훈련시키는 디버깅 관련 커서 규칙을 설정할 수 있습니다. 프로젝트 패턴에 따라 규칙을 위반하는 수정을 방지합니다.
// .cursor/rules/debugging.mdc
---
name: Debugging Standards
globs: ["src/**/*.ts", "src/**/*.spec.ts"]
---
# Standard di Debugging per Questo Progetto
## Quando proponi un fix per un bug:
1. Spiega la root cause in massimo 3 frasi
2. Mostra PRIMA il codice problematico con commento // PROBLEMA:
3. Mostra POI la versione corretta con commento // FIX:
4. Aggiungi un test di regressione per il caso problematico
## Pattern da evitare nei fix:
- Non usare 'any' come fix temporanea per errori TypeScript
- Non aggiungere try/catch senza gestione specifica dell'errore
- Non usare '!' (non-null assertion) per silenziare errori nullable
- Non modificare i test per farli passare invece di fixare il codice
## Pattern preferiti:
- Usa Optional Chaining (?.) per accessi nullable
- Usa Nullish Coalescing (??) per default values
- Usa type guards per narrowing
- Usa catchError con specifici tipi di errore in RxJS
4. 문서화로 세션 디버그
고급 모범 사례 및 디버깅 세션을 기회로 삼아 문서. 복잡한 버그를 수정한 후 커서에게 생성을 요청하세요. 발견된 문제와 그 이유를 문서화하는 코드의 설명 주석 채택된 솔루션이 올바른 솔루션입니다.
// Prompt post-fix:
// "Il bug e risolto. Aggiungi un commento JSDoc a calculateDiscount
// che documenta: il bug che abbiamo trovato (divisione per zero
// con quantity 0), la soluzione adottata (filter prima del calcolo),
// e un link al test di regressione."
// Cursor genera:
/**
* Calcola lo sconto totale per un ordine basato su un codice sconto.
*
* Nota: gli items con quantity === 0 vengono esclusi dal calcolo
* per evitare errori di divisione per zero nel calcolo del prezzo
* unitario medio. Questo comportamento e testato in:
* order.service.spec.ts > 'should handle items with zero quantity'
*
* @param order - L'ordine con items e codice sconto
* @returns Il valore dello sconto in euro (0 se nessun item valido)
*/
calculateDiscount(order: Order): number {
디버깅 도구 및 통합
Datadog과의 통합
프로덕션에서 Datadog을 사용하는 팀의 경우 공식 커서 확장을 사용하면 다음을 수행할 수 있습니다. 생산 모니터링 데이터를 IDE로 직접 가져옵니다. 당신은 추가할 수 있습니다 커서로 로그 포인트를 확인하고 에이전트에게 도움을 요청하세요. 실제 로그와 추적을 기반으로 프로덕션의 버그를 해결합니다.
Datadog + 커서 설정
- Cursor Extensions(VS Code 호환)에서 Datadog 확장 설치
- 설정에서 Datadog 자격 증명 구성
- 디버그 세션에서는 다음을 사용합니다.
@datadog실제 로그를 컨텍스트로 가져오기 위해 - 커서에게 생산 오류와 소스 코드의 상관관계를 묻습니다.
Angular DevTools 및 커서
브라우저의 Angular DevTools 및 Angular 관련 문제에 대한 탁월한 프로파일러 (변경 감지, 구성요소 트리, 종속성 주입) 문제를 발견했을 때 프로파일러에서 코드 분석을 위해 정보를 커서로 가져옵니다.
// Workflow Angular DevTools + Cursor
// 1. Apri Angular DevTools (F12 > Angular tab)
// 2. Profila la change detection: ogni barra rossa = frame lento
// 3. Clicca sul componente lento - vedi le proprietà e il tempo CD
// 4. In Cursor, porta il contesto:
// "Angular DevTools mostra che ProductListComponent impega 450ms
// per la change detection. Il profiler indica che il re-render
// avviene 47 volte in 1 secondo durante lo scroll.
// @product-list.component.ts analizza e ottimizza la change
// detection strategy e l'uso degli input."
// Cursor risponderà con:
// - Analisi del componente
// - Identificazione dei problemi (mancanza di OnPush, trackBy, ecc.)
// - Implementazione ottimizzata
기존 디버깅과 AI 지원 디버깅: 언제 무엇을 사용할지
AI가 모든 디버깅 접근 방식을 대체하지는 않습니다. 디버깅하는 시나리오가 있습니다. 전통적인 매뉴얼이며 심지어 우수하거나 보완적입니다.
가이드: 사용할 접근 방식
| 대본 | 권장 접근 방식 | 도구 |
|---|---|---|
| TypeScript/컴파일 오류 | Cmd+K 인라인 | 커서 인라인 편집 |
| 런타임 오류가 있는 스택 추적 | 파일 컨텍스트와 채팅 | 커서 채팅 + @file |
| 간헐적인 버그/경합 상태 | 디버그 모드 | 커서 디버그 모드(2.2) |
| 점진적인 메모리 누수 | 프로파일러 + AI 분석 | Chrome DevTools + 커서 채팅 |
| 성능 회귀 | 프로파일러 + AI 최적화 | Angular DevTools + 커서 |
| 알 수 없는 레거시 코드의 버그 | 디버그 모드 + @codebase | 커서 디버그 모드 + 컨텍스트 |
| 하드웨어/저수준 디버깅 | 네이티브 디버거 | gdb/lldb, 수동 중단점 |
| 보안 취약점 | 수동 코드 검토 | 커서 + 전문가의 인간 검토 |
결론: AI 지원 디버깅 문화 구축
Cursor AI를 사용한 디버깅은 단순히 도구의 문제가 아니라 변화입니다. 정신의. 가장 생산적인 개발자는 AI에게 "버그 수정을 요청"하지 않습니다. AI와의 구조화된 대화, 정확한 맥락 제공, 테스트를 통한 가설 검증, 모든 유형의 문제에 적합한 도구를 사용합니다.
Cursor 2.2의 디버그 모드는 질적 도약을 나타냅니다. 효과적인 디버깅을 위한 코드베이스 전문가. 가설 중심 접근 방식 런타임 계측은 추측에 소요되는 시간을 크게 줄여줍니다. 버그봇이 움직인다 코드 검토 시 버그 감지 부담의 일부를 줄여 횟수를 줄입니다. 프로덕션에 도달하는 버그.
Angular 팀의 경우 역사적으로 중요한 영역에서 특히 중요한 이점을 얻었습니다. 더 어렵다: 구독 누출, Observable의 경쟁 조건, 불안정한 비동기 테스트 및 변경 감지 성능. 커서는 이러한 패턴을 알고 인식합니다. 경험이 부족한 개발자라면 몇 시간이 걸릴 수도 있습니다.
AI 지원 디버깅을 시작하기 위한 체크리스트
- 구성
launch.json소스 맵이 활성화된 경우 - 능력
sourceMap: true에서tsconfig.json - 프로젝트 디버깅 표준에 대한 커서 규칙 생성
- 디버깅 프롬프트에서 "BUG REPORT" 템플릿을 연습해 보세요.
- 코드베이스의 실제 버그에 대해 디버그 모드를 실험해 보세요.
- 풀 요청을 사용하는 경우 Bugbot 구성(GitHub/GitLab)
- 워크플로 통합: 재현 - 테스트 - 수정 - 커서로 확인
Cursor IDE 시리즈는 계속됩니다
디버깅 문서를 완료했습니다. 시리즈의 다른 기사를 계속 진행하세요.
- 다음 기사: 2026년 커서 vs 윈드서핑 vs 코파일럿 - 현재 시장의 AI FDI 전체 비교
- 완전한 워크플로우를 위해: 전문적인 작업 흐름: 커서가 있는 Angular 프로젝트
- 확인을 자동화하려면 다음을 수행하십시오. 커서 후크: 작업 흐름 자동화
관련 크로스 시리즈: MCP 및 커서 디버깅을 위해 데이터베이스의 실제 데이터와 시리즈 현대적인 각도 특정 Angular 모범 사례를 확인하세요.







