Cursor로 시작하는 AI 코딩: 실전 프로젝트 튜토리얼
Cursor로 React + TypeScript Todo 앱 만들기. AI 컴포넌트 생성, 커스텀 훅, Tailwind CSS 통합, Vercel 배포까지 실전 프로젝트.
Cursor는 AI 기반 코드 편집기로, VS Code를 기반으로 만들어진 차세대 개발 도구입니다. GPT-5.5와 Claude를 활용하여 코드 작성, 리팩토링, 디버깅을 지원하며, 자연어로 코드를 생성하고 전체 코드베이스를 이해하는 능력을 갖추고 있습니다. 이 튜토리얼에서는 실제 프로젝트를 만들면서 Cursor의 강력한 기능을 배워봅니다.
1. Cursor 시작하기
1.1 설치 및 초기 설정
Step 1: Cursor 다운로드
- cursor.sh 접속
- 운영체제에 맞는 버전 다운로드 (Windows/Mac/Linux)
- 설치 프로그램 실행
Step 2: 계정 생성
- Cursor 실행
- 이메일 또는 GitHub 계정으로 가입
- 무료 플랜 시작 (월 2000회 요청)
Step 3: VS Code 확장 기능 가져오기
Cursor는 VS Code 설정과 확장 기능을 자동으로 가져올 수 있습니다.
Cmd/Ctrl + Shift + P > "Cursor: Import VS Code Settings"
1.2 Cursor의 핵심 기능
- Cmd+K (Ctrl+K): AI 코드 생성 및 편집
- Cmd+L (Ctrl+L): AI 채팅 창 열기
- Cmd+Shift+L: 코드베이스 전체 검색
- Tab: AI 자동완성 수락
- @-mentions: 특정 파일이나 문서 참조
1.3 AI 모델 설정
Settings (Cmd/Ctrl + ,) > Cursor Settings
- Primary Model: GPT-5.5, Claude Sonnet 5 중 선택
- Auto-completion: 활성화 권장
- Privacy Mode: 필요시 활성화
2. 실전 프로젝트: React Todo 앱 만들기
이제 Cursor를 사용하여 실제 프로젝트를 만들어봅시다. React와 TypeScript를 사용한 Todo 애플리케이션을 처음부터 끝까지 구현합니다.
2.1 프로젝트 초기화
Step 1: 새 프로젝트 생성
Cursor 터미널에서 다음 명령 실행:
npm create vite@latest todo-app -- --template react-ts
cd todo-app
npm install
Step 2: Cursor에서 프로젝트 열기
File > Open Folder > todo-app 선택
2.2 AI로 컴포넌트 생성하기
Step 1: Todo 타입 정의하기
새 파일 생성: src/types/todo.ts
Cmd+K (Ctrl+K)를 누르고 다음 프롬프트 입력:
Todo 애플리케이션을 위한 TypeScript 타입을 정의해주세요.
다음 속성을 포함:
- id (string)
- title (string)
- completed (boolean)
- createdAt (Date)
- priority (high/medium/low)
생성된 코드:
// src/types/todo.ts
export type Priority = 'high' | 'medium' | 'low';
export interface Todo {
id: string;
title: string;
completed: boolean;
createdAt: Date;
priority: Priority;
}
export interface TodoState {
todos: Todo[];
filter: 'all' | 'active' | 'completed';
}
Step 2: Todo 아이템 컴포넌트
새 파일 생성: src/components/TodoItem.tsx
Cmd+L (Ctrl+L)로 채팅 열고:
@todo.ts 타입을 사용하는 TodoItem 컴포넌트를 만들어주세요.
기능:
- Todo 항목 표시
- 완료 체크박스
- 삭제 버튼
- Priority badge (색상별)
- Tailwind CSS 사용
생성된 코드:
// src/components/TodoItem.tsx
import React from 'react';
import { Todo } from '../types/todo';
interface TodoItemProps {
todo: Todo;
onToggle: (id: string) => void;
onDelete: (id: string) => void;
}
export const TodoItem: React.FC<TodoItemProps> = ({
todo,
onToggle,
onDelete
}) => {
const priorityColors = {
high: 'bg-red-100 text-red-800',
medium: 'bg-yellow-100 text-yellow-800',
low: 'bg-green-100 text-green-800',
};
return (
<div className="flex items-center gap-3 p-4 bg-white rounded-lg shadow-sm border border-gray-200">
<input
type="checkbox"
checked={todo.completed}
onChange={() => onToggle(todo.id)}
className="w-5 h-5 text-blue-600 rounded focus:ring-2 focus:ring-blue-500"
/>
<div className="flex-1">
<p className={`text-lg ${todo.completed ? 'line-through text-gray-400' : 'text-gray-800'}`}>
{todo.title}
</p>
<div className="flex items-center gap-2 mt-1">
<span className={`text-xs px-2 py-1 rounded-full ${priorityColors[todo.priority]}`}>
{todo.priority}
</span>
<span className="text-xs text-gray-500">
{new Date(todo.createdAt).toLocaleDateString('ko-KR')}
</span>
</div>
</div>
<button
onClick={() => onDelete(todo.id)}
className="p-2 text-red-600 hover:bg-red-50 rounded-lg transition-colors"
aria-label="Delete todo"
>
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
</svg>
</button>
</div>
);
};
2.3 상태 관리 구현
Step 1: Custom Hook 생성
새 파일: src/hooks/useTodos.ts
AI 프롬프트:
@todo.ts 타입을 사용하는 useTodos 커스텀 훅을 만들어주세요.
기능:
- Todo 추가, 삭제, 토글
- LocalStorage에 자동 저장
- 필터링 (전체/활성/완료)
- 정렬 (날짜, 우선순위)
생성된 코드:
// src/hooks/useTodos.ts
import { useState, useEffect } from 'react';
import { Todo, TodoState, Priority } from '../types/todo';
const STORAGE_KEY = 'todos';
export const useTodos = () => {
const [state, setState] = useState<TodoState>(() => {
const saved = localStorage.getItem(STORAGE_KEY);
return saved
? JSON.parse(saved)
: { todos: [], filter: 'all' as const };
});
// LocalStorage에 자동 저장
useEffect(() => {
localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
}, [state]);
const addTodo = (title: string, priority: Priority = 'medium') => {
const newTodo: Todo = {
id: crypto.randomUUID(),
title,
completed: false,
createdAt: new Date(),
priority,
};
setState(prev => ({
...prev,
todos: [...prev.todos, newTodo],
}));
};
const toggleTodo = (id: string) => {
setState(prev => ({
...prev,
todos: prev.todos.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
),
}));
};
const deleteTodo = (id: string) => {
setState(prev => ({
...prev,
todos: prev.todos.filter(todo => todo.id !== id),
}));
};
const setFilter = (filter: TodoState['filter']) => {
setState(prev => ({ ...prev, filter }));
};
const getFilteredTodos = () => {
switch (state.filter) {
case 'active':
return state.todos.filter(todo => !todo.completed);
case 'completed':
return state.todos.filter(todo => todo.completed);
default:
return state.todos;
}
};
const sortByPriority = (todos: Todo[]) => {
const priorityOrder = { high: 0, medium: 1, low: 2 };
return [...todos].sort((a, b) =>
priorityOrder[a.priority] - priorityOrder[b.priority]
);
};
return {
todos: getFilteredTodos(),
filter: state.filter,
addTodo,
toggleTodo,
deleteTodo,
setFilter,
sortByPriority,
stats: {
total: state.todos.length,
active: state.todos.filter(t => !t.completed).length,
completed: state.todos.filter(t => t.completed).length,
},
};
};
2.4 메인 App 컴포넌트
App.tsx 수정
기존 내용을 선택하고 Cmd+K:
@useTodos @TodoItem 을 사용하는 완전한 Todo 애플리케이션을 만들어주세요.
포함할 기능:
- 새 Todo 추가 폼 (title, priority 선택)
- Todo 리스트 표시
- 필터 버튼 (전체/활성/완료)
- 통계 표시
- Tailwind CSS로 모던한 디자인
Cursor가 위 프롬프트만으로 폼, 필터 버튼, 통계 카드, 리스트 렌더링이 포함된 App 컴포넌트 전체를 생성합니다. 생성된 코드를 그대로 수락하기 전에 Diff 뷰에서 변경 내용을 한 번 검토하는 습관을 들이는 것이 좋습니다.
2.5 Tailwind CSS 설정
터미널에서 실행:
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
tailwind.config.js 수정 (Cmd+K 활용):
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
src/index.css에 Tailwind 추가:
@tailwind base;
@tailwind components;
@tailwind utilities;
3. Cursor 고급 기능
3.1 코드 리팩토링
코드 블록을 선택하고 Cmd+K:
이 코드를 성능과 가독성이 좋아지도록 리팩토링해주세요
3.2 테스트 코드 생성
함수를 선택하고 Cmd+L:
@useTodos.ts 의 addTodo 함수에 대한 유닛 테스트를 Vitest로 작성해주세요
생성된 테스트:
// src/hooks/useTodos.test.ts
import { renderHook, act } from '@testing-library/react';
import { describe, it, expect, beforeEach } from 'vitest';
import { useTodos } from './useTodos';
describe('useTodos', () => {
beforeEach(() => {
localStorage.clear();
});
it('should add a new todo', () => {
const { result } = renderHook(() => useTodos());
act(() => {
result.current.addTodo('Test todo', 'high');
});
expect(result.current.todos).toHaveLength(1);
expect(result.current.todos[0].title).toBe('Test todo');
expect(result.current.todos[0].priority).toBe('high');
expect(result.current.todos[0].completed).toBe(false);
});
it('should toggle todo completion', () => {
const { result } = renderHook(() => useTodos());
act(() => {
result.current.addTodo('Test todo');
});
const todoId = result.current.todos[0].id;
act(() => {
result.current.toggleTodo(todoId);
});
expect(result.current.todos[0].completed).toBe(true);
});
it('should delete a todo', () => {
const { result } = renderHook(() => useTodos());
act(() => {
result.current.addTodo('Test todo');
});
const todoId = result.current.todos[0].id;
act(() => {
result.current.deleteTodo(todoId);
});
expect(result.current.todos).toHaveLength(0);
});
});
3.3 문서화
함수 위에 커서를 두고 Cmd+K:
이 함수에 JSDoc 주석을 추가해주세요
3.4 버그 찾기
AI 채팅에서:
@App.tsx 를 검토하고 잠재적인 버그나 성능 문제를 찾아주세요
4. Cursor 생산성 팁
4.1 @-mentions 마스터하기
- @filename: 특정 파일 참조
- @folder: 폴더 전체를 컨텍스트로
- @web: 웹 검색 결과 포함
- @docs: 프로젝트 문서 참조
- @codebase: 코드베이스 전체 검색
4.2 효과적인 프롬프트 작성법
나쁜 프롬프트:
버튼 만들어줘
좋은 프롬프트:
@TodoItem.tsx 의 삭제 버튼과 같은 스타일로 수정(edit) 버튼을 추가해주세요.
Heroicons의 PencilIcon을 사용하고, 클릭 시 onEdit 콜백을 호출합니다.
4.3 키보드 단축키
| 단축키 | 기능 |
|---|---|
Cmd+K |
인라인 AI 편집 |
Cmd+L |
AI 채팅 열기 |
Tab |
AI 제안 수락 |
Cmd+Shift+L |
코드베이스 검색 |
Cmd+I |
새 파일 생성 (AI와 함께) |
5. 프로젝트 완성 및 배포
5.1 프로덕션 빌드
npm run build
5.2 Vercel 배포
Step 1: Vercel CLI 설치
npm i -g vercel
Step 2: 배포
vercel
배포 설정도 AI에게 물어볼 수 있습니다:
@Cmd+L: 이 프로젝트를 Vercel에 배포하기 위한 vercel.json 설정 파일을 만들어주세요
6. 자주 겪는 문제와 해결법
문제 1: AI가 잘못된 코드를 생성함
해결법:
- 더 구체적인 컨텍스트 제공 (@mentions 활용)
- "다시 생성해주세요. 이번에는 [구체적 요구사항]을 지켜서" 라고 요청
- 생성된 코드를 선택하고 "이 코드의 문제점을 찾아주세요" 요청
문제 2: 자동완성이 느림
해결법:
- Settings > Cursor Settings에서 "Faster completions" 활성화
- 대용량 파일은 작은 단위로 나눠서 작업
- 불필요한 파일은 .cursorignore에 추가
문제 3: API 사용량 초과
해결법:
- Pro 플랜 업그레이드 ($20/월, 무제한 요청)
- 자신의 API 키 사용 (Settings > Models)
- 불필요한 자동완성 끄기
7. Cursor vs 다른 AI 코딩 도구
| 도구 | 장점 | 단점 |
|---|---|---|
| Cursor | 코드베이스 전체 이해, 강력한 AI 채팅 | 많이 쓰려면 유료 플랜 필요 |
| GitHub Copilot | VS Code 통합, 안정성 | 컨텍스트 이해가 제한적 |
| Codeium | 무료, 다양한 에디터 지원 | AI 품질이 상대적으로 낮음 |
| Tabnine | 프라이버시 중시, 로컬 모델 | 온라인 모델 대비 성능 낮음 |
8. 고급 활용 사례
8.1 레거시 코드 마이그레이션
@old-component.js 를 TypeScript와 React Hooks로 마이그레이션해주세요.
- 클래스 컴포넌트 -> 함수형 컴포넌트
- PropTypes -> TypeScript 인터페이스
- this.state -> useState
- 모든 타입 정의 추가
8.2 API 클라이언트 자동 생성
다음 OpenAPI 스펙을 기반으로 TypeScript API 클라이언트를 생성해주세요:
@api-spec.yaml
axios를 사용하고, 모든 엔드포인트에 대한 타입 안전한 함수를 만들어주세요.
8.3 성능 최적화
@App.tsx 의 성능을 분석하고 다음 최적화를 적용해주세요:
1. 불필요한 리렌더링 방지 (React.memo, useMemo, useCallback)
2. 코드 스플리팅 (React.lazy)
3. 번들 크기 최적화
"Cursor는 단순한 자동완성 도구가 아닙니다. AI 페어 프로그래머가 옆에서 함께 일하는 것과 같습니다."
9. 베스트 프랙티스
9.1 프롬프트 작성 원칙
- 구체적이고 명확한 요구사항 제시
- 관련 파일과 컨텍스트 참조 (@mentions)
- 기대하는 출력 형식 명시
- 코딩 스타일과 컨벤션 언급
- 작업을 단계별로 나누기
9.2 코드 품질 유지
- AI가 생성한 코드는 반드시 리뷰
- 테스트 코드 작성
- 타입 안전성 확보
- 린터와 포매터 설정
- 코드 리뷰 프로세스 유지
결론
Cursor를 활용하면 코딩 속도를 2-3배 높일 수 있습니다. 다만 AI는 어디까지나 도구이며, 최종 판단은 개발자의 몫이라는 점을 기억하세요. 이 튜토리얼에서 배운 기법들을 실제 프로젝트에 적용하면서 자신만의 AI 코딩 워크플로우를 만들어보시기 바랍니다.
Happy Coding with AI!
참고 자료
- Cursor 공식 문서 — 설치·기능·설정 가이드
- Cursor GitHub — 기능 요청 및 이슈 트래커
- Cursor Directory — 프롬프트 템플릿 모음
- Cursor YouTube — 영상 튜토리얼
- Cursor Discord — 커뮤니티
- React 공식 문서 — 컴포넌트·훅 레퍼런스
- Vite 공식 문서 — 프로젝트 생성·빌드 설정
관련 스토리
MCP 서버 직접 만들기: Claude에 사내 도구 연결하는 실전 가이드
MCP(Model Context Protocol)로 사내 DB·API를 Claude에 연결하는 방법. TypeScript SDK로 서버 구축, 도구 정의, Claude Desktop 연동, 보안 주의사항까지 실전 코드로 정리.
LLM API 비용 최적화 실전 가이드: 90% 절감하는 6가지 방법
프롬프트 캐싱, 모델 라우팅, 배치 API, 컨텍스트 다이어트까지. 실제 측정 가능한 LLM 비용 절감 전략을 코드와 함께 정리했습니다.
AI를 활용한 코드 리뷰 자동화 가이드
GitHub Actions + GPT-5.5/Claude로 코드 리뷰 자동화. Python/TypeScript 구현, PR 자동 코멘트, 비용 최적화 전략까지.
Comments