2026년 6월, Cursor·Copilot·Windsurf를 “팀 생산성 파이프라인”으로 쓰는 법: 컨텍스트(AGENTS.md)·규칙(Rules)·에이전트 모드 실전 운영
들어가며
AI 코딩 도구를 6개월 이상 실전에 붙여본 팀에서 공통으로 부딪히는 문제는 “생성 품질”이 아니라 일관성(consistency)과 비용/속도, 그리고 컨텍스트 폭발입니다.
- PR 단위로 보면 비슷한 작업을 반복하는데도 결과가 들쭉날쭉하고,
- 에이전트가 workspace를 과하게 스캔해 느려지고, 컨텍스트가 금방 꽉 차서 대화가 압축(compaction)되며,
- 규칙/관례를 말로 매번 되풀이하다가 결국 “사람이 다시 고치는 비용”이 생깁니다. (reddit.com)
언제 쓰면 좋은가
- 모노레포/중간 규모 이상 서비스에서: 기능 추가, 리팩터링, 테스트 보강, 마이그레이션처럼 “여러 파일을 건드리는 작업”
- 팀 규약/아키텍처 경계가 명확하고, 그걸 도구에 파일로 주입할 수 있을 때(AGENTS.md, rules)
- 작업을 “계획→적용→검증”으로 나눠서 에이전트에게 위임하고, 사람은 리뷰/의사결정에 집중할 때
언제 쓰면 안 되는가
- 규칙이 아직 합의되지 않은 초기 프로젝트(에이전트가 만들어내는 “새 규칙”이 기술부채가 됨)
- 보안/컴플라이언스 때문에 코드베이스 컨텍스트를 외부 모델로 보내기 어려운데, 대안(온프렘/정책)이 준비되지 않은 경우
- “한 번에 다 해줘” 스타일로 사람 검증이 약한 조직(에이전트형 도구는 오류의 전파 속도도 빠릅니다)
🔧 핵심 개념
1) “에이전트형 IDE”로의 전환: intent-first 흐름
2026년 들어 Microsoft Build 메시지도 분명해졌습니다. 코드는 더 이상 “손으로만 쓰는 산출물”이 아니라, 의도를 표현하면 에이전트가 코드/수정/검증을 수행하고 개발자는 지시·검증·리뷰에 무게를 두는 흐름(“intent-first”)으로 이동 중입니다. (techradar.com)
이 변화가 Cursor/Windsurf 같은 VS Code-기반 AI-first IDE, 그리고 Copilot Agent Mode 확장으로 이어집니다.
2) 컨텍스트는 “많이”가 아니라 “잘”이 핵심: AGENTS.md / Rules / Memories
에이전트 성능을 좌우하는 건 모델보다 컨텍스트 엔지니어링인 경우가 많습니다. 최근 연구들은 저장소 레벨 구성 파일(예: AGENTS.md)이 사실상의 표준처럼 확산되고 있음을 보고합니다. (arxiv.org)
다만 “컨텍스트 파일을 크게 쓰면 항상 좋다”는 신화는 깨지고 있습니다.
- AGENTS.md 같은 컨텍스트 파일은 성공률을 낮추고 비용을 올릴 수도 있고(+20% 이상 비용 증가 관측), 불필요 요구사항이 작업 난이도를 올릴 수 있다는 평가도 있습니다. 그래서 “최소 요구사항(minimal requirements)” 위주로 써야 합니다. (arxiv.org)
- 즉, 컨텍스트는 백과사전이 아니라 제약조건/프로세스/검증 방법 중심의 작업 계약서가 되어야 합니다.
Windsurf는 이를 제품 기능으로 더 강하게 밀어붙입니다.
- Memories: 대화 중 자동 생성되어 로컬에 저장(워크스페이스 단위, 공유/커밋 아님).
~/.codeium/windsurf/memories/에 저장되며 크레딧을 소모하지 않는다고 명시합니다. (docs.windsurf.com) - Rules: 전역/워크스페이스/시스템(엔터프라이즈) 범위로 수동 정의. 워크스페이스 규칙은
.windsurf/rules/*.md에 두고,trigger로 always_on vs model_decision 같은 활성화 모드를 줄 수 있습니다. 또한 AGENTS.md도 같은 Rules 엔진으로 처리한다고 문서에 나옵니다. (docs.windsurf.com)
여기서 실무적으로 중요한 차이는:
- always_on 규칙은 매 메시지에 들어가서 일관성은 좋아지지만, 컨텍스트 비용/속도에 타격을 줍니다.
- model_decision은 설명만 상시 주고, 필요할 때만 전문을 읽게 하여 비용을 절약합니다. (docs.windsurf.com)
3) Copilot: “워크스페이스 자동 스캔”과 제어의 긴장
Copilot은 Agent Mode가 강해지면서 “@workspace 같은 명시적 스코프가 덜 필요해진다”는 논의가 커졌고, 실제로 workspace 자동 탐색이 기본이 되며 느려지고 컨텍스트를 빨리 소모한다는 사용자 불만/우회 팁이 공유됩니다. (reddit.com)
이 지점에서 Cursor/Windsurf의 “규칙/컨텍스트 구조화”가 상대적으로 빛을 봅니다. (Copilot은 조직/거버넌스 강점이 큰 대신, IDE 내부에서의 미세 제어는 제품/플랜/클라이언트별 편차가 있습니다.)
4) Windsurf의 포지션: Cascade + (클라우드) Devin
Windsurf는 스스로를 “agentic IDE”로 포지셔닝하고, Cascade를 깊은 코드베이스 이해 + 도구 + 실시간 사용자 행동 인지를 결합한 흐름으로 설명합니다. (windsurf.com)
또한 Windsurf 2.0 페이지에서는 로컬/클라우드 에이전트 협업, 그리고 “Devin”이라는 클라우드 자율 에이전트를 IDE에 통합했다고 소개합니다. (windsurf.com)
(중요: 이런 자율 실행 모델은 생산성 잠재치가 큰 만큼, 권한/검증/비용 통제 장치를 반드시 함께 설계해야 합니다.)
💻 실전 코드
목표: 실서비스 TypeScript API(Express)에서 “새 엔드포인트 추가 + DB 마이그레이션 + 테스트 + CI 통과”를 Cursor/Copilot/Windsurf 어디서든 재현 가능한 형태로 “에이전트 작업 단위”로 쪼개는 방법을 보여주겠습니다.
핵심은 “프롬프트 잘 쓰기”가 아니라 repo에 심어두는 컨텍스트(AGENTS.md)와 Windsurf Rules로 매번 같은 방식으로 일하게 만드는 것입니다.
0) 프로젝트 전제(현실적인 시나리오)
- Node 20, TypeScript, Express
- DB: Postgres + Prisma
- 테스트: Vitest + Supertest
- CI에서
pnpm lint && pnpm test && pnpm prisma migrate deploy가 돈다고 가정
1) AGENTS.md (repo 루트) — “최소 요구사항”만
아래 파일은 Cursor/Copilot/Windsurf 등 다양한 도구에서 “규칙 파일”로 쓰려는 의도로 작성합니다. (너무 길게 쓰지 않는 게 포인트) (arxiv.org)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# AGENTS.md - AI Agent Context (minimal)
## Project
- Node.js 20 + TypeScript
- Express API
- Prisma(Postgres)
- Tests: Vitest + Supertest
## Non-negotiables
1) No breaking changes to existing routes without updating tests.
2) Every API change must include:
- Prisma schema + migration (if DB affected)
- Request validation (zod)
- Integration test (supertest)
3) Must pass:
- pnpm lint
- pnpm test
## Workflow (do in order)
1) PLAN: list files you will touch and why.
2) APPLY: implement in small commits (or clearly separated patches).
3) VERIFY: show commands to run + expected output summary.
## Conventions
- Prefer small pure functions.
- Use `src/routes/*` for route handlers.
- Use `src/services/*` for business logic.
2) Windsurf 전용: .windsurf/rules/api-rule.md — 비용/속도 최적화를 위한 model_decision
Windsurf 문서에 따르면 workspace rules는 .windsurf/rules/*.md에 두고, trigger:로 활성화 방식을 정합니다. 규모가 커질수록 always_on은 비용이 커지니 “설명은 상시, 내용은 필요 시 로드”로 갑니다. (docs.windsurf.com)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
---
trigger: model_decision
description: "When editing API routes/services, enforce zod validation + integration tests + prisma migration discipline."
---
# API Rule (Windsurf)
## Required patterns
- Validate request with zod at route boundary.
- Business logic in src/services, not in routes.
- If DB model changes: update prisma/schema.prisma and create migration.
## Test pattern
- Add/modify a vitest integration test under test/integration/*
- Use supertest against the express app instance.
3) 실제 변경 작업: “POST /v1/projects/:id/tags” 추가
요구사항:
- 프로젝트에 태그를 추가하는 엔드포인트
- 태그는 중복 없이 upsert
- 반환:
{ projectId, tags: string[] } - DB 스키마:
ProjectTag(projectId, tag)unique
(A) Prisma 스키마 & 마이그레이션
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// prisma/schema.prisma
model Project {
id String @id @default(cuid())
name String
tags ProjectTag[]
}
model ProjectTag {
id String @id @default(cuid())
projectId String
tag String
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
@@unique([projectId, tag])
@@index([projectId])
}
1
2
3
# migration
pnpm prisma migrate dev --name add_project_tags
pnpm prisma generate
예상 결과(요약):
migrations/*add_project_tags*/migration.sql생성- Prisma Client 갱신
(B) 서비스 레이어: upsert + 조회
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// src/services/projectTags.ts
import { PrismaClient } from "@prisma/client";
export class ProjectTagsService {
constructor(private prisma: PrismaClient) {}
async addTags(projectId: string, tags: string[]) {
const normalized = [...new Set(tags.map(t => t.trim()).filter(Boolean))];
if (normalized.length === 0) {
return this.getTags(projectId);
}
await this.prisma.$transaction(async (tx) => {
for (const tag of normalized) {
await tx.projectTag.upsert({
where: { projectId_tag: { projectId, tag } },
update: {},
create: { projectId, tag },
});
}
});
return this.getTags(projectId);
}
async getTags(projectId: string) {
const rows = await this.prisma.projectTag.findMany({
where: { projectId },
orderBy: { tag: "asc" },
select: { tag: true },
});
return rows.map(r => r.tag);
}
}
(C) 라우트: zod 검증 + 응답 형태 고정
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// src/routes/projects.ts
import { Router } from "express";
import { z } from "zod";
import { PrismaClient } from "@prisma/client";
import { ProjectTagsService } from "../services/projectTags";
const prisma = new PrismaClient();
const tagsService = new ProjectTagsService(prisma);
const router = Router();
const addTagsSchema = z.object({
tags: z.array(z.string()).min(1),
});
router.post("/v1/projects/:id/tags", async (req, res, next) => {
try {
const projectId = req.params.id;
const body = addTagsSchema.parse(req.body);
const tags = await tagsService.addTags(projectId, body.tags);
res.json({ projectId, tags });
} catch (err) {
next(err);
}
});
export default router;
(D) 통합 테스트: “중복 제거 + 정렬 + 회귀 방지”
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// test/integration/projects.tags.test.ts
import request from "supertest";
import { describe, it, expect, beforeAll } from "vitest";
import { PrismaClient } from "@prisma/client";
import { createApp } from "../../src/app"; // express app factory라고 가정
const prisma = new PrismaClient();
const app = createApp();
describe("POST /v1/projects/:id/tags", () => {
let projectId: string;
beforeAll(async () => {
const p = await prisma.project.create({ data: { name: "demo" } });
projectId = p.id;
});
it("adds tags (dedupe + trim) and returns sorted list", async () => {
const res = await request(app)
.post(`/v1/projects/${projectId}/tags`)
.send({ tags: [" api ", "backend", "api"] })
.expect(200);
expect(res.body.projectId).toBe(projectId);
expect(res.body.tags).toEqual(["api", "backend"]);
});
});
1
2
pnpm test
# 예상: 1 test passed
4) 이걸 Cursor/Copilot/Windsurf에서 “에이전트 작업”으로 굴리는 프롬프트 운영
- 공통 템플릿(에이전트에게 요구할 출력): 1) PLAN: 변경 파일 목록
2) PATCH: 파일별 diff
3) VERIFY: 실행 커맨드 + 예상 결과 - Copilot은 workspace를 크게 스캔해 느려질 수 있으니(사례 공유 다수), “이번 작업 범위 파일만”을 먼저 지정하거나, 커스텀 에이전트/컨텍스트 첨부 방식으로 컨텍스트를 외과수술처럼 줄이는 전략이 유효합니다. (reddit.com)
- Windsurf는 Rules의
model_decision을 활용해 “필요할 때만 규칙 전문 로드”로 비용을 줄입니다. (docs.windsurf.com)
⚡ 실전 팁 & 함정
Best Practice 1) “AGENTS.md는 한 장짜리 계약서”로 유지
연구 결과상 컨텍스트 파일이 길어질수록 항상 이득이 아닙니다. 오히려 성공률을 낮추고 비용을 올릴 수 있으니,
- 필수 제약 + 검증 커맨드 + 디렉터리 구조만 남기고
- 배경 설명/역사/회의록은 넣지 마세요. (arxiv.org)
Best Practice 2) always_on 남발 금지: “설명은 상시, 전문은 온디맨드”
Windsurf Rules는 활성화 모드를 제공하고, always_on은 매 메시지 컨텍스트 비용을 고정적으로 먹습니다.
규칙이 많아질수록:
- always_on: 일관성↑ / 비용↑ / 응답 지연↑
- model_decision: 비용↓ / 누락 위험↑(설명(description)을 잘 써야 함) (docs.windsurf.com)
Best Practice 3) “자율성”은 권한이 아니라 “검증 단계”로 통제
Windsurf는 Cascade를 강한 에이전트로, 더 나아가 클라우드 자율 에이전트(Devin)까지 내세웁니다. (windsurf.com)
자율성이 커질수록 생산성도 커지지만, 잘못된 대규모 수정의 리스크도 같이 커집니다. 실무에서는:
- 에이전트가 바꾼 파일이 N개 이상이면 자동으로 “테스트/린트/빌드”를 강제
- DB 마이그레이션이 생기면 reviewer를 2명으로 늘리는 등 “가드레일”을 CI/코드리뷰 정책으로 거는 게 안전합니다.
흔한 함정/안티패턴
- (1) “우리 아키텍처를 전부 AGENTS.md에 써두면 완벽해지겠지”
→ 컨텍스트 과적재로 비용만 증가하고, 오히려 불필요 제약 때문에 작업이 꼬일 수 있습니다. (arxiv.org) - (2) Copilot Agent Mode에서 workspace 스캔이 기본이 되어 “느리고 부정확”해졌는데, 원인이 모델이라고 착각
→ 실제로는 컨텍스트 스코프/첨부 전략 문제인 경우가 많습니다. (reddit.com) - (3) 에이전트 결과를 “한 번에 머지”
→ 에이전트형 도구는 작은 실수도 여러 파일로 빠르게 전파합니다. 작게 쪼개서 검증이 기본입니다.
🚀 마무리
2026년 6월 기준 Cursor/Copilot/Windsurf를 “AI 도우미”가 아니라 개발 생산성 시스템으로 쓰려면 결론은 단순합니다.
1) 컨텍스트를 파일로 고정(AGENTS.md)하되, 최소 요구사항만 적는다. (arxiv.org)
2) 규칙은 always_on으로 때려박지 말고, Windsurf처럼 온디맨드 규칙( model_decision ) 전략을 쓴다. (docs.windsurf.com)
3) 에이전트의 자율성은 “권한”이 아니라 검증 단계(PLAN→APPLY→VERIFY)로 제어한다. (CI/리뷰 정책까지 포함)
도입 판단 기준
- 팀이 “규칙을 문서화하고 CI로 강제”할 문화가 있다 → Windsurf/ Cursor 같은 AI-first IDE의 효과가 큼
- 엔터프라이즈 거버넌스/기존 IDE 유지가 최우선 → Copilot 중심 + 컨텍스트 스코프 운영을 강화
- 어떤 도구든, 규칙 파일/컨텍스트 파일을 먼저 설계하지 않으면 생산성은 금방 정체됩니다.
다음 학습 추천
- Windsurf의 Memories/Rules 구조를 팀 단위 운영 관점에서 정리(전역 vs 워크스페이스 vs AGENTS.md 분리) (docs.windsurf.com)
- “컨텍스트 파일이 오히려 해가 될 수 있다”는 연구 결과를 읽고, 우리 팀 AGENTS.md를 최소화하는 리팩터링을 한 번 해보세요. (arxiv.org)
원하면, 당신 팀 스택(언어/프레임워크/레포 구조/CI) 기준으로 AGENTS.md 템플릿과 Windsurf rules(trigger 설계)를 더 구체적으로 커스터마이즈해서 드릴게요.