AI가 코딩을 바꾸는 자리는 여러 곳이지만, 개발자가 하루 종일 앉아 있는 곳은 IDE다. 그래서 IDE 안에 들어온 AI가 일하는 방식을 가장 먼저 바꿨다. 이 글은 그 자리를 채운 두 도구, GitHub Copilot과 Cursor를 한 편에서 다룬다. Copilot은 2021년에 미리보기로 나와 유료 구독자를 수백만 명 규모로 늘리며 AI 코딩 도구의 표준이 됐고, Cursor는 그 뒤에 나와 많은 개발자를 갈아타게 만들었다.
둘을 한 편에 묶는 이유가 있다. 출발점이 정반대이기 때문이다. Copilot은 기존 IDE에 AI를 얹는 방식이다 — VS Code·JetBrains·Neovim에 익스텐션으로 설치하고, 쓰던 편집기는 그대로 둔다. Cursor는 편집기 자체를 AI 중심으로 다시 만든 방식이다 — VS Code를 포크해 익숙한 화면은 유지하되 AI 기능을 편집기 깊숙이 심었다. 여기서 포크(fork)는 공개된 소스 코드를 통째로 복사해 별도 제품으로 키우는 것을 말한다.
그런데 출발점이 다른데도 두 도구가 채우는 자리는 같다. 타이핑하는 동안 이어질 코드를 제안하는 완성, 자연어로 묻고 답하는 채팅, 여러 파일을 한꺼번에 고치는 편집, 그리고 모델이 무엇을 읽고 답할지 정하는 컨텍스트 시스템이다. 여기서 모델은 코드와 글을 방대하게 읽어 다음에 올 말을 이어 쓰도록 만들어진 프로그램이고, 컨텍스트는 그 모델이 답을 만들 때 볼 수 있는 재료 전체를 말한다. 도구와 모델은 다른 것이다 — Copilot과 Cursor는 무엇을 보여 줄지 골라 모델에 넘기고 돌아온 답을 화면에 그리는 쪽이고, 모델은 그 자리에 갈아 끼울 수 있는 부품이다. Copilot의 Inline Completion·Chat·Edit·Agent 넷과 Cursor의 Tab·Ask·Agent·@ 참조 넷이 자리마다 마주 선다. 그래서 이 글은 도구별로 절을 나누지 않고 자리별로 나눈다. 완성에서 시작해 채팅, 멀티파일 편집, 컨텍스트, 규칙 파일, 보안을 차례로 지나면서 같은 자리에서 둘이 무엇을 다르게 하는지 보고, 마지막에 어느 쪽을 언제 고를지 정리한다. 두 도구 모두 기능과 이름이 자주 바뀌므로 화면의 이름보다 그 자리가 하는 일을 기준으로 읽는 편이 오래 간다.
인라인 완성
Ghost Text와 FIM
Copilot의 가장 기본 기능은 Inline Completion이다. 코드를 치는 동안 회색 글자로 제안이 나타나고 Tab을 누르면 그대로 들어온다. 이 회색 제안을 Ghost Text라고 부른다 — 아직 파일에 들어가지 않은, 수락하기 전까지는 없는 것으로 치는 글자다. Esc를 누르면 사라진다.
이 완성이 함수 한가운데서도 되는 이유가 FIM(Fill-In-Middle)이다. 보통의 언어 모델은 앞에서 뒤로만 이어 쓴다. 그래서 「지금까지 쓴 것」만 보고 다음을 만든다. FIM은 커서 앞의 코드(prefix)와 커서 뒤의 코드(suffix)를 모두 프롬프트에 넣고 그 사이를 채우도록 학습한 방식이다. 프롬프트는 모델에 실제로 들어가는 글 한 덩어리다 — 모델이 보는 것은 여기 든 것이 전부이고, 안 든 것은 모델에게 없는 것과 같다. 학습은 그렇게 짠 예를 수없이 보여 주며 모델을 만드는 과정이고, 그때 본 데이터가 모델이 나중에 내놓는 코드의 성향을 정한다 — 뒤에서 여러 번 나올 「학습 데이터」는 지나간 재료가 아니라 지금 나오는 출력에 남아 있는 것이다.
<PRE> ... 앞의 코드 ... <SUF> ... 뒤의 코드 ... <MID>
↑ 여기를 생성
실제로 이 차이는 크다. 이미 다 쓴 함수의 중간에 분기를 하나 넣어야 할 때, 앞만 보는 모델은 뒤에 이미 있는 반환문을 모르니 같은 반환문을 또 만든다. FIM은 뒤에 무엇이 있는지 알고 있으므로 그 자리에 맞는 조각만 만든다. 함수 시그니처를 먼저 적고 본문을 나중에 채우는 습관, 테스트를 먼저 적고 구현을 채우는 습관이 Copilot과 잘 맞는 것도 이 때문이다 — 뒤에 있는 코드가 그대로 힌트가 된다.
컨텍스트 빌더
프롬프트에 들어가는 것은 커서 앞뒤만이 아니다. 컨텍스트 빌더(context builder)는 완성을 요청할 때마다 현재 파일, IDE에 열린 다른 탭, 커서 위치, 프로젝트의 언어와 프레임워크 같은 정보를 자동으로 모아 프롬프트를 짜는 부품이다. 익스텐션이 이것을 만들어 GitHub 서버의 Copilot 서비스로 보내고, 서버의 모델이 FIM 방식으로 추론한 결과가 다시 편집기로 돌아와 Ghost Text가 된다. 추론은 이미 만들어 둔 모델을 한 번 돌려 답을 받는 일이다 — 모델을 만드는 학습과는 다른 일이고, 완성 제안 하나가 뜰 때마다 일어나는 쪽이 이 추론이다.
여기서 실무 팁 하나가 저절로 나온다. 관련 파일을 탭으로 열어 두는 것만으로 완성 품질이 오른다. 컨텍스트 빌더가 열린 탭을 읽기 때문이다. 데이터 모델을 정의한 파일과 그것을 쓰는 서비스 파일을 나란히 열어 두면, 서비스 쪽에서 완성을 요청할 때 그 필드 이름이 프롬프트에 들어 있다. 닫아 두면 모델은 필드 이름을 모른 채 그럴듯한 이름을 지어낸다 — 완성이 자꾸 없는 필드를 만들어 낸다면 먼저 볼 것이 열린 탭이다. 이 문단에 「모델」이 두 뜻으로 나왔다. 그냥 「모델」이라고 적은 것은 이 글 내내 답을 만드는 AI 모델이고, 데이터 모델처럼 코드 쪽을 가리킬 때는 그 말을 앞에 붙인다.
거꾸로 말하면 Copilot 완성의 시야는 열린 탭까지다. 수백 개 파일이 있는 프로젝트에서 지금 안 열려 있는 파일의 함수는 모른다. 이 한계가 뒤에서 볼 컨텍스트 시스템 절의 출발점이다.
Tab의 편집 예측
Cursor의 완성도 인라인 제안으로 나타나고 Tab으로 받는다는 점은 같다. 다른 것은 제안의 단위다. Copilot이 커서 자리에 이어질 코드를 만든다면, Cursor의 Tab은 다음에 할 편집을 예측한다. 변수 이름을 하나 바꾸면 그 변수를 쓰는 아래쪽 줄들에도 같은 수정 제안이 따라 나타나고, 함수 시그니처에 인자를 하나 더하면 호출부를 고치는 제안이 이어진다. Tab을 한 번 누르면 그 제안 하나가 들어오고, 계속 누르면 다음 제안 자리로 옮겨 간다.
이것이 왜 다른가는 이름 바꾸기를 해 보면 안다. 커서 자리만 보는 완성은 첫 번째 줄을 고친 뒤에는 할 일이 없다 — 나머지 자리는 사람이 찾아가 하나씩 고쳐야 한다. 편집 예측은 「이 사람이 지금 무엇을 하는 중인가」를 추측하고 그 작업의 나머지를 제안한다. 그래서 Cursor의 Tab은 새 코드를 쓸 때보다 이미 있는 코드를 고칠 때 차이가 크게 난다. 리팩터링을 하면서 Tab만 연달아 누르는 장면이 Cursor를 보여 주는 가장 흔한 데모인 이유다.
물론 예측이 늘 맞지는 않는다. 편집 예측은 「같은 패턴을 반복하려는 중」이라고 짐작하므로, 의도적으로 한 곳만 다르게 고치려는 자리에서는 원치 않는 제안이 따라붙는다. Tab을 누르기 전에 제안이 무엇을 바꾸는지 한 번 읽는 습관은 두 도구 어느 쪽에서든 같다.
주석과 타입 힌트
완성은 프롬프트에 든 것만큼만 좋아진다. 그리고 완성의 프롬프트는 사람이 따로 쓰는 것이 아니라 지금 파일에 적혀 있는 것이다. 그래서 완성 품질을 올리는 방법은 프롬프트 기술이 아니라 코드를 쓰는 습관에 가깝다. 세 가지가 확실히 든다.
첫째, 의도를 주석으로 먼저 적는다. 함수 이름만 있으면 모델은 이름에서 추측하지만, 「날짜 오름차순, 같은 날짜면 금액 내림차순」처럼 규칙을 주석에 적어 두면 정렬 키를 정확히 만든다. 도메인 규칙일수록 효과가 크다 — 사업자등록번호 체크섬처럼 모델이 이름만 보고는 알 수 없는 절차를 주석 두세 줄로 적어 주면 그 절차대로 완성된다.
# 주문 목록을 날짜 오름차순, 동일 날짜면 금액 내림차순으로 정렬
# 반환: 정렬된 Order 객체 리스트
def sort_orders(orders: list[Order]) -> list[Order]:
# 여기서 Copilot이 key 람다를 완성한다
둘째, 타입 힌트와 독스트링을 쓴다. 인자와 반환의 타입이 적혀 있으면 모델은 그 타입에 맞는 코드를 만든다. amount: float와 tax_rate: float를 가진 데이터클래스에 「세금 포함 총 금액」이라는 독스트링을 단 메서드를 시작하면 amount * (1 + tax_rate)가 바로 나온다. 타입이 없으면 문자열을 곱하는 코드가 나올 수도 있다.
@dataclass
class Invoice:
amount: float
tax_rate: float
def total(self) -> float:
"""세금 포함 총 금액"""
# 여기서 amount * (1 + tax_rate) 가 완성된다
셋째, 예시가 되는 함수를 앞에 둔다. validate_email이 정규식으로 검사하는 함수라면 바로 아래에 def validate_phone(phone: str) -> bool:까지만 적어도 같은 꼴로, 한국 전화번호 정규식을 넣어 완성된다. 모델은 파일 안의 패턴을 따라 하므로 파일 앞쪽에 잘 쓴 함수가 있으면 뒤쪽 함수도 그 수준을 따라온다. 반대로 앞쪽에 대충 쓴 함수가 있으면 그것도 따라 한다.
이 세 가지는 Cursor에서도 그대로 통한다. 완성이 프롬프트를 파일에서 읽는다는 사실은 두 도구가 같기 때문이다.
채팅
패널과 단축키
완성이 손 아래에서 일하는 기능이라면 채팅은 자연어로 묻고 답하는 창이다. 두 도구 모두 채팅을 두 자리에 둔다. 하나는 옆에 열리는 패널이고, 다른 하나는 코드 위에 바로 뜨는 인라인 채팅이다. 패널은 설명을 듣거나 긴 질문을 할 때, 인라인은 선택한 코드를 그 자리에서 고쳐 달라고 할 때 쓴다. 여기에 여러 파일을 한꺼번에 고치는 자리가 하나 더 있고, 다음 절이 그것을 다룬다.
| 자리 | Copilot (VS Code) | Cursor |
|---|---|---|
| 채팅 패널 | Ctrl+Alt+I (Mac ⌃⌘I) |
Ctrl+L (Mac ⌘L) |
| 인라인 편집 | Ctrl+I (Mac ⌘I) |
Ctrl+K (Mac ⌘K) |
| 멀티파일·에이전트 | Ctrl+Shift+I (Mac ⇧⌘I) |
Ctrl+I (Mac ⌘I) |
단축키 표를 굳이 싣는 이유는 같은 Ctrl+I가 두 도구에서 다른 것을 열기 때문이다. Copilot에서는 코드 위에 뜨는 인라인 채팅이고, Cursor에서는 옆에 열리는 에이전트 패널이다. 둘을 오가는 사람이 가장 먼저 헷갈리는 자리다. 그리고 Cursor에서는 Ctrl+L과 Ctrl+I가 같은 패널을 연다. 채팅과 에이전트가 한 패널로 합쳐져 있어서 어느 키로 열든 같은 곳에 닿고, 그 패널이 읽기만 할지 파일을 고칠지는 패널 안의 모드가 정한다. Copilot 쪽은 세 키가 세 자리를 연다 — 채팅 뷰, 인라인 채팅, 그리고 채팅을 곧바로 에이전트로 여는 키다. 채팅 뷰 안에도 선택 메뉴가 있어 묻기만 하는 Ask, 파일을 고치는 Edit, 스스로 실행하는 Agent, 계획부터 세우는 Plan 중 하나를 고른다. 이 메뉴의 이름은 「채팅 모드」에서 「에이전트 역할」로 한 번 갈아탔다 — 자리가 하는 일은 그대로이고 부르는 말만 옮겨 다닌다.
Mac 대응은 괄호에 적었다. Cursor는 Ctrl 자리를 ⌘로 바꾸면 그대로 맞지만, Copilot의 채팅 패널은 ⌃⌘I라 단순 치환이 안 된다. 「Mac에서는 Ctrl이 ⌘」라고 외우고 있으면 Copilot의 채팅 뷰만 안 열린다. 리눅스도 에이전트 자리만 Ctrl+Shift+Alt+I로 갈린다. 표의 값은 기본 바인딩이고 편집기 설정에서 바꿀 수 있으니, 안 맞으면 키 목록에서 Copilot을 찾아 지금 걸린 키를 본다.
슬래시 커맨드
Copilot Chat은 자주 하는 요청을 슬래시 커맨드로 묶어 둔다. 프롬프트 맨 앞에 /로 시작하는 낱말을 적으면 그 작업에 맞게 미리 짜인 지시가 붙는다.
| 커맨드 | 하는 일 |
|---|---|
/explain |
선택한 코드 설명 |
/fix |
버그·오류 수정 |
/tests |
유닛 테스트 생성 |
/doc |
문서·주석 생성 |
/new |
새 프로젝트·파일 뼈대 생성 |
슬래시 커맨드의 값은 짧다는 데 있지 않다. 요청의 형식이 고정된다는 데 있다. /tests는 매번 「이 함수의 테스트를 써 줘, 경계값도 넣어 줘」를 다시 적지 않아도 같은 꼴의 답을 준다. 함수를 다 쓴 뒤 /doc을 한 번 돌리는 식으로 습관에 넣기 좋다.
쓸 수 있는 목록은 편집기마다 다르다. /explain·/fix·/tests는 어디에나 있지만 /optimize는 Visual Studio에만, /simplify는 Xcode에만 있는 식이다. 목록은 판이 바뀔 때마다 늘고 줄므로 외우지 말고 입력창에 /만 쳐 본다 — 지금 편집기에서 되는 것이 그 자리에 뜬다.
Cursor의 채팅은 이 자리를 슬래시 대신 뒤에서 볼 @ 참조로 채운다. 무엇을 하라고 정형화하기보다 무엇을 보고 답하라고 지정하는 쪽에 무게가 있다. 그래서 Cursor에서 「이 코드 설명해 줘」는 그냥 문장으로 적고, 대신 @로 어느 파일을 볼지 붙인다.
질문의 단위
채팅을 어디에 쓰는지가 완성과 갈린다. 완성은 「다음 줄이 뭐지」에 답하고, 채팅은 「이게 뭐지」와 「왜 안 되지」에 답한다. #selection 이 코드의 시간복잡도는? 같은 질문, #codebase 이 프로젝트에서 JWT 인증을 어떻게 구현했어? 같은 질문은 완성으로는 할 수 없다. 처음 보는 코드베이스에 들어갔을 때 채팅이 완성보다 먼저 쓰이는 이유다.
답을 받는 쪽에서 지킬 것이 하나 있다. 채팅의 답은 코드가 아니라 주장이다. /explain이 「이 함수는 캐시를 무효화한다」고 말해도 정말 그런지는 코드가 정한다. /fix가 만든 수정안은 인라인에서 적용하기 전에 무엇이 바뀌는지 읽는다. 답이 길고 자신 있을수록 더 그렇다 — 모델은 모르는 것을 모른다고 말하기보다 그럴듯하게 채우는 쪽으로 기울어 있고, 어느 자리에서 그러는지는 마지막 절에서 정리한다.
멀티파일 편집과 에이전트
Copilot Edits
한 파일 안의 완성과 채팅만으로는 기능 하나를 못 만든다. 서비스 클래스에 메서드를 더하면 테스트 파일도 같이 고쳐야 하고, 스키마를 바꾸면 라우터와 데이터 모델이 따라 바뀐다. Copilot Edits는 이런 요청을 자연어로 받아 여러 파일에 걸친 수정을 한꺼번에 만드는 기능이다. 처음에는 별도 창으로 나왔고 지금은 Chat의 Edit 모드로 들어가 있다 — 모드 선택에서 Edit을 고르면 같은 채팅창이 여러 파일을 고치는 창이 된다. 이름과 자리는 바뀌었어도 하는 일은 같다. 「UserService에 이메일 인증 로직을 추가하고 관련 테스트 파일도 업데이트해 줘」라고 하면 UserService.java와 UserServiceTest.java가 함께 바뀐다.
결과는 diff 형식으로 온다. diff는 바뀌기 전과 후를 줄 단위로 나란히 보여 주는 표기다 — 지워진 줄과 더해진 줄이 색으로 갈린다. Edit이 diff로 보여 주는 이유는 파일마다, 덩어리마다 골라서 적용할 수 있게 하려는 것이다. 테스트 파일의 수정은 받고 서비스 쪽의 수정은 거절하는 식이다. 멀티파일 편집에서 이 검토 단계가 빠지면 모델이 손댄 다섯 파일 중 어느 것이 왜 바뀌었는지 모른 채 커밋하게 된다.
Cursor의 Agent 패널
Cursor에서 같은 자리에 있는 것이 Agent 패널이다. 예전에는 Composer라 불렸고 지금도 그 이름으로 부르는 사람이 많다. Ctrl+I나 Ctrl+L로 열고, 여러 파일에 걸친 작업을 자연어로 요청한다. 입력창의 모드 선택에서 셋을 고르고, Shift+Tab을 누르면 모드가 차례로 바뀐다.
Ask 모드는 읽기만 한다. 코드베이스를 검색하고 파일을 읽어 답하지만 파일에 손대지 않는다. 처음 보는 코드를 설명받거나 설계를 상의할 때 쓰고, Copilot Chat의 Ask와 같은 자리다. Agent 모드는 파일을 만들고 고치는 것에 더해 터미널 명령을 실행하고, 코드베이스를 검색하고, 그 결과를 보고 다음 행동을 스스로 정한다. 에이전트 모드란 모델이 한 번 답하고 끝나는 것이 아니라 도구를 써서 확인하고 다시 행동하는 반복을 스스로 돌리는 방식을 말한다. Plan 모드는 코드를 쓰기 전에 계획부터 만든다. 코드베이스를 조사하고, 모호한 자리를 되묻고, 사람이 읽고 고칠 수 있는 계획을 내놓은 뒤 승인을 받으면 그때 만들기 시작한다.
셋의 경계는 「언제 코드에 손대는가」다. Ask는 안 대고, Plan은 사람이 계획을 승인한 뒤에 대고, Agent는 곧바로 댄다. 그래서 무엇을 바꿀지 아직 모르면 Ask, 파일 여럿을 새로 만들어야 하고 중간에 확인이 필요한 큰 작업이면 Plan, 무엇을 할지 분명해 결과만 검토하면 되는 작업이면 Agent다. Copilot의 Edit 모드에 해당하는 것은 Cursor에서 따로 이름이 없다 — Agent가 만든 수정을 파일별로 수락하거나 거절하는 흐름이 그 자리를 맡는다. Plan 모드가 하는 일은 사람이 요청을 쓰기 전에 머릿속으로 하던 일이기도 하다. 큰 작업일수록 그 단계를 모델과 함께 밟는 편이 되돌리는 비용을 줄인다.
Copilot Agent 모드
Copilot도 같은 자리를 Agent로 채운다. Ctrl+Shift+I가 채팅을 곧장 이 자리로 여는 키다. 터미널 명령을 돌리고 파일을 만들고 고치며, 복잡한 기능을 단계로 나눠 계획하고 순서대로 실행한다. GitHub 저장소 쪽에서 이슈를 통째로 맡기면 PR까지 여는 별도의 코딩 에이전트도 있다. Cursor의 Agent 모드와 겹치는 자리이고, 두 도구 모두 「제안하는 도구」에서 「대신 하는 도구」로 옮겨 가는 방향이 여기서 보인다.
앞 소절의 Plan에 해당하는 자리도 Copilot 쪽에 생겼다. 선택 메뉴의 Plan이 코드를 만들기 전에 조사하고 구현 계획을 내놓는다. 한쪽이 먼저 세운 자리를 다른 쪽이 몇 달 뒤 따라 붙이는 일이 이 두 도구 사이에서 계속 되풀이된다 — 그래서 「어느 쪽에만 있는 기능」으로 도구를 고르면 그 근거가 반년을 못 간다.
자율 실행에는 대가가 있다. 모델이 터미널을 돌릴 수 있다는 것은 잘못된 명령도 돌릴 수 있다는 뜻이다. 실무에서는 Agent에게 맡기기 전에 브랜치를 따 두고, 작업이 끝난 뒤 diff 전체를 사람이 읽는다. Agent가 만든 테스트가 통과했다는 사실은 코드가 맞다는 뜻이 아니라 그 테스트가 통과한다는 뜻일 뿐이다 — 테스트와 구현을 같은 모델이 만들었으면 둘이 같은 오해를 공유할 수 있다.
요청의 꼴
Agent에게 기능 하나를 통째로 맡길 때 요청의 꼴이 결과를 정한다. 잘 되는 요청은 세 부분으로 이뤄진다. 요구사항을 번호로 적고, 따라야 할 기존 코드를 참조로 붙이고, 테스트까지 달라고 한다.
결제 처리 기능을 구현해줘.
요구사항:
1. POST /payments 엔드포인트
2. Toss Payments API 연동 (공식 문서: https://docs.tosspayments.com/)
3. 결제 성공/실패 웹훅 처리
4. 결제 내역 DB 저장 (payments 테이블)
5. 실패 시 자동 3회 재시도
@app/models/user.py 의 User 모델 참고
@app/routers/orders.py 의 라우터 패턴 따라서
테스트 코드도 같이 만들어줘.
이 요청 하나로 Agent는 라우터·서비스·스키마·데이터 모델·테스트·마이그레이션 파일을 만든다. 번호를 붙인 요구사항은 모델이 하나씩 짚어 가며 빠뜨리지 않게 하고, @로 붙인 파일 참조는 새 코드가 기존 라우터와 같은 꼴이 되게 한다. 참조 없이 요청하면 모델은 자기 방식으로 라우터를 쓰고, 그러면 프로젝트에 두 가지 스타일이 공존하게 된다. 외부 API 문서의 URL을 적어 두는 것은 모델이 기억하는 형식이 오래됐을 때를 대비한 것이다.
같은 요청을 Plan 모드로 먼저 넣어 보면 차이가 보인다. 「재시도 세 번의 간격은 어떻게 할까」, 「웹훅 서명 검증은 넣을까」처럼 요구사항에 빠진 자리를 모델이 되묻고, 만들 파일 목록을 먼저 보여 준다. 그 목록에서 마이그레이션 파일이 빠졌거나 스키마가 엉뚱한 폴더에 잡혀 있으면 코드가 생기기 전에 고친다. 다섯 줄짜리 요구사항이 여섯 파일이 되는 작업이면 이 한 단계가 diff 검토의 절반을 미리 한다.
컨텍스트 시스템
열린 탭
머리말에서 말한 컨텍스트 — 모델이 답을 만들 때 볼 수 있는 재료 전체 — 를 무엇으로 채우는가에서 두 도구가 오래 갈려 있었다. 완성 절에서 봤듯 Copilot은 현재 파일과 열린 탭을 기본 시야로 삼고, 그 밖의 것은 사람이 채팅에서 지정한다. 지정하는 문법이 셋이다.
| 문법 | 가리키는 것 |
|---|---|
#codebase |
프로젝트 전체 검색 |
#file |
특정 파일 |
#selection |
지금 선택한 코드 |
#codebase가 있으니 Copilot이 프로젝트 전체를 못 보는 것은 아니다. 다만 그 검색은 채팅 쪽 일이고, 완성은 여전히 열린 탭이 기준이다. 채팅에서도 #codebase를 매번 적을 필요는 없다 — 에이전트가 필요하다고 판단하면 알아서 부르고, 사람이 적는 것은 「이번엔 반드시 전체를 훑어라」고 못 박고 싶을 때다. 그래서 Copilot을 쓸 때 사람이 관리하게 되는 쪽은 채팅이 아니라 「지금 이 작업에 관련된 파일을 무엇을 열어 둘까」다.
이 이름은 한 번 갈렸다. 예전에는 프로젝트 전체를 @workspace라는 참여자로 불렀고 지금 문서가 적는 것은 #codebase다. 옛 글과 사내 위키에 @workspace가 남아 있는 이유이고, 두 도구를 다루는 글에서 이름을 기준으로 읽지 말라고 앞에서 말한 이유이기도 하다.
에이전트 검색
Cursor는 이 관리를 처음부터 도구에 맡기는 쪽으로 섰다. 어느 파일이 관련 있는지 사람이 골라 열어 두는 대신 에이전트가 스스로 코드베이스를 뒤져 필요한 것을 집어 온다. 공식 문서도 「어느 파일이 중요한지 모르겠으면 지정하지 말고 에이전트가 찾게 두라」고 적는다.
찾는 기계 장치는 한 번 크게 바뀌었다. 한동안은 @codebase로 프로젝트 전체를 벡터 인덱싱해 두고 질문과 뜻이 가까운 코드를 찾는 방식이었다. 벡터 인덱싱은 코드 조각마다 뜻을 담은 숫자 벡터를 미리 만들어 두는 것이고, 그 벡터로 「이름이 같은 것」이 아니라 「뜻이 비슷한 것」을 찾는 것을 시맨틱 검색이라 한다. 지금 문서가 설명하는 것은 둘이다 — 정확히 일치하는 것을 큰 저장소에서도 즉시 찾아내는 자체 grep 엔진과, 본 대화와 별도 컨텍스트에서 여러 갈래를 동시에 뒤진 뒤 요약만 돌려주는 탐색 서브에이전트다. 서브에이전트는 본 대화와 따로 도는 작은 에이전트를 말한다.
장치가 바뀌어도 사람이 얻는 성격은 같다. 「인증 관련 코드 어디에 있어?」라고 물으면 파일명에 auth가 없어도 토큰을 검증하는 함수가 딸려 온다. 수천 개 파일의 프로젝트에서 이 차이가 크다 — 열린 탭 방식에서는 관련 파일이 어디 있는지 사람이 먼저 알아야 열 수 있는데, 처음 들어간 코드베이스에서는 그것을 모르는 것이 문제다. Cursor가 대규모 프로젝트에서 「맥락을 잃지 않는다」고 하는 것이 이 뜻이다.
두 도구의 거리는 여기서 좁아졌다. 앞 소절에서 봤듯 Copilot의 에이전트도 이제 스스로 검색을 부르므로, 채팅과 에이전트만 놓고 보면 갈래가 거의 같다. 갈라진 채로 남은 자리는 완성 쪽이다 — 첫 절에서 본 컨텍스트 빌더의 시야는 그대로다.
대신 시야가 그 검색에 달려 있다는 점은 기억해 둔다. 도구가 못 찾은 파일은 없는 것과 같고, 무엇을 보고 답했는지는 응답에 붙은 파일 목록으로만 확인된다. 어디 있는지 이미 아는 파일이면 검색에 맡기지 말고 직접 지정하는 편이 정확하고 싸다 — 다음 소절이 그 문법이다.
@ 참조
검색에 맡기지 않고 직접 집어 주는 문법이 @다. 입력창에 @를 치면 붙일 수 있는 것이 목록으로 뜬다.
| 참조 | 가리키는 것 |
|---|---|
@파일명 · @폴더/ |
특정 파일과 폴더 |
@Terminals |
터미널에 찍힌 출력 |
@Chats |
앞선 대화의 내용 |
@Commit |
아직 커밋하지 않은 변경 |
@Branch |
지금 브랜치와 기준 브랜치의 차이 |
@Browser |
내장 브라우저에 띄운 화면 |
채팅 입력창에 실제로 적는 꼴은 이렇다. 참조를 앞에 두고 질문을 뒤에 잇는다.
@services/auth.py 이 코드에서 refreshToken 로직 설명해줘
@Terminals 방금 뜬 에러의 원인이 뭐야
@Branch 이번 브랜치에서 바꾼 것 중 테스트가 빠진 자리 찾아줘
첫 줄이 파일 하나를 콕 집어 넣는 것이다. 검색에 맡기는 것과의 차이는 앞 소절에서 말한 「어디 있는지 아는가」다. 아는 파일이면 지정이 정확하고 싸다 — 검색을 거치지 않고 그 파일만 프롬프트에 든다. 모르면 지정하지 말고 물어보는 편이 낫다. 처음에는 찾아 달라고 하고 자리를 알고 난 다음부터 @로 집는 순서가 자연스럽다.
나머지는 코드 밖의 재료를 붙인다. @Terminals는 방금 돌린 명령의 출력을 그대로 넣으므로 스택 트레이스를 복사해 붙일 일이 없어지고, @Commit과 @Branch는 diff를 컨텍스트로 넘겨 「이번에 바꾼 것」을 통째로 물을 수 있다 — 리뷰를 올리기 전에 자기 브랜치를 한 번 읽히는 용도다. @Chats는 앞선 대화의 결론을 새 대화로 넘긴다. 대화가 길어져 새로 시작할 때 앞에서 합의한 것을 다시 설명하지 않아도 된다.
이 목록은 판마다 바뀐다. 한때 있던 @codebase·@web·@docs는 지금 문서의 목록에 없다 — 그 일을 참조로 지정하는 대신 에이전트가 알아서 하는 쪽으로 옮겨 갔기 때문이다. 다만 최신 문서를 보고 코드를 만들게 하려는 필요 자체는 남아 있고, 지금은 그 URL을 요청에 그대로 적어 주는 것으로 대신한다. 모델이 기억하는 API 형식은 학습 시점에 멈춰 있어서, 그 뒤에 시그니처가 바뀐 라이브러리에서는 그럴듯하지만 없는 함수를 부른다. 학습에는 끝난 날이 있고 그 뒤에 바뀐 것은 모델 안에 들어 있지 않다 — 그래서 최신 형식은 기억에서 꺼내는 것이 아니라 프롬프트에 넣어 줘야 한다.
모델 피커와 BYOK
컨텍스트를 어느 모델이 읽느냐도 볼 자리다. 여기에는 흔한 오해가 하나 있다. 「Copilot은 GitHub이 정한 한두 모델만 쓰고 Cursor는 자유」라는 말인데, 지금의 두 도구에는 맞지 않는다. 둘 다 채팅창에 모델 피커가 있다. Copilot의 피커에는 OpenAI·Anthropic·Google 등 여러 공급자의 모델이 실려 있고, Cursor의 피커도 Claude·GPT·Gemini 계열을 작업 성격에 따라 바꿔 쓴다. 개수로는 이제 가르기 어렵다.
차이는 개수가 아니라 누구의 키로, 어디서 돌리는가다. BYOK(Bring Your Own Key)는 도구가 마련한 경로 대신 사용자가 직접 발급받은 API 키로 모델을 부르는 방식이다. Cursor는 설정에 자체 키를 넣을 수 있고, 로컬에서 Ollama로 띄운 모델을 연결할 수도 있다. Ollama는 공개 가중치 모델을 자기 컴퓨터에서 돌리게 해 주는 도구다. 가중치는 학습이 끝난 모델의 알맹이가 담긴 파일이고, 그 파일이 공개돼 있어야 남의 서버를 거치지 않고 자기 컴퓨터에서 추론을 돌릴 수 있다. Copilot도 VS Code에서는 BYOK로 Anthropic·Gemini·OpenAI·Azure와 커스텀 엔드포인트를 붙일 수 있고, Ollama 확장으로 로컬 모델을 쓸 수 있다. 다만 조직 요금제에서는 관리자가 정책으로 어느 모델을 허용하고 BYOK를 열지 정한다 — 개인은 자유롭고 조직은 정책이 정한다.
그러니 두 도구를 가르는 질문은 「모델이 몇 개인가」가 아니라 「우리 조직이 허용한 경로가 무엇인가」다. 모델을 고를 수 있다는 것은 두 가지 뜻이다. 하나는 작업에 따라 빠른 모델과 깊은 모델을 바꿔 쓰는 편의다. 다른 하나는 뒤의 보안 절에서 다시 나오는데, 코드를 외부로 보내지 않는 선택지가 생긴다는 것이다. 어느 모델이 어느 작업에 좋은지는 자주 바뀌므로 여기 적지 않는다 — 고를 수 있다는 구조와 그 자유를 누가 제한하는가가 남는 사실이다.
규칙 파일
반복 지시
두 도구를 며칠 쓰면 같은 말을 매번 적고 있는 자신을 발견한다. 「이 프로젝트는 Python 3.11이고 FastAPI를 쓴다」, 「함수에 타입 힌트를 붙여라」, 「주석은 한국어로」. 요청마다 이걸 빼면 모델은 자기 기본값으로 돌아간다 — 타입 힌트 없는 함수, 영어 주석, print() 디버깅.
규칙 파일은 이 말을 저장소에 한 번 적어 두고 모든 요청에 자동으로 붙이는 장치다. 두 도구 모두 갖고 있고, 위치와 꼴이 다르다. Copilot은 .github/copilot-instructions.md 한 장이고, Cursor는 .cursor/rules/ 디렉터리에 두는 .mdc 파일들이거나 루트의 AGENTS.md 한 장이다. 저장소에 들어가므로 팀 전체가 같은 규칙을 공유하고, 규칙을 고치면 코드 리뷰를 거친다. 잘 쓴 규칙 파일 하나가 프롬프트마다 설명하던 수고를 통째로 덜어 준다.
Copilot 규칙 파일
Copilot의 규칙 파일은 마크다운 한 장이다. 형식이 따로 없고, 모델에게 하고 싶은 말을 목록으로 적는다.
# Copilot Instructions
- 이 프로젝트는 Python 3.11, FastAPI, SQLAlchemy를 사용합니다
- 모든 함수에 타입 힌트를 포함하세요
- 에러 처리는 HTTPException을 사용하세요
- 테스트는 pytest와 pytest-asyncio를 사용합니다
- 한국어 주석을 선호합니다
다섯 줄이지만 하는 일은 분명하다. 스택을 적으면 모델이 다른 프레임워크의 관용구를 가져오지 않고, 에러 처리 방식을 적으면 /fix가 만든 수정안이 프로젝트 방식을 따른다. 테스트 도구를 적어 두면 /tests가 unittest 대신 pytest로 쓴다.
Cursor 규칙 파일
Cursor의 규칙은 한 장이 아니라 디렉터리다. .cursor/rules/ 아래에 .mdc 파일을 여럿 두고, 파일마다 머리에 frontmatter로 언제 붙을지를 적는다. frontmatter는 파일 맨 위를 --- 두 줄로 감싸 적는 메타데이터 블록이다. 칸은 셋이다 — description은 이 규칙이 무엇에 관한 것인지를 모델에게 알리는 한 줄, globs는 어느 파일을 만질 때 붙일지 정하는 경로 패턴, alwaysApply는 모든 대화에 붙일지 정하는 참·거짓 값이다. 확장자가 .mdc가 아니면 이 블록이 없는 것으로 쳐 규칙으로 읽히지 않는다.
세 칸을 어떻게 채우느냐로 붙는 방식이 넷으로 갈린다. alwaysApply: true면 모든 대화에 붙고, globs만 적으면 그 패턴에 맞는 파일을 만질 때 붙고, description만 적으면 모델이 관련 있다고 판단할 때 붙고, 아무것도 안 적으면 채팅에서 @로 부를 때만 붙는다. 프로젝트 공통 규칙은 첫째 꼴이다.
---
description: 프로젝트 공통 규칙
globs:
alwaysApply: true
---
# Project Rules
## 기술 스택
- Python 3.11 (엄격한 타입 힌트 필수)
- FastAPI 0.110 + Pydantic v2
- SQLAlchemy 2.0 (비동기 세션 사용)
- PostgreSQL (psycopg3)
## 코딩 컨벤션
- 함수: snake_case, 클래스: PascalCase
- 주석: 한국어, docstring: Google 스타일
- 에러 처리: `raise HTTPException(status_code=..., detail=...)` 사용
- 로깅: `logger = logging.getLogger(__name__)` 패턴
## 금지 패턴
- `print()` 절대 금지 → logging 사용
- `SELECT *` 금지 → 컬럼 명시
- 하드코딩 비밀번호·API 키 금지
## 디렉터리 구조
- `app/routers/` — FastAPI 라우터
- `app/services/` — 비즈니스 로직
- `app/models/` — SQLAlchemy 모델
- `app/schemas/` — Pydantic 스키마
- `tests/` — pytest 테스트
Copilot의 다섯 줄보다 훨씬 긴 이유가 있다. Agent가 파일을 새로 만드는 일이 많아 디렉터리 구조까지 적어 둬야 새 파일이 제자리에 생기기 때문이다. 앞 절의 결제 기능 요청에서 Agent가 app/routers/payments.py, app/services/payment_service.py, tests/test_payments.py를 제자리에 만든 것은 이 규칙의 「디렉터리 구조」 덕이다. 규칙이 없으면 모델은 payments.py 하나에 라우터와 서비스를 다 넣거나, 자기가 익숙한 구조를 새로 만든다.
테스트 규칙처럼 특정 파일에만 걸리는 것은 둘째 꼴로 따로 뺀다. tests/**에 globs를 건 testing.mdc에 「모든 라우터에 pytest + httpx AsyncClient 테스트 필수」, 「픽스처는 conftest.py에 정의」를 적어 두면 테스트 파일을 만질 때만 그 두 줄이 붙는다. 규칙을 하나로 몰아 두면 라우터를 고치는 요청에도 테스트 규칙이 끼어드는데, 파일마다 나누면 그 잡음이 사라진다. 이것이 한 장 대신 디렉터리를 쓰는 이유다.
이 구조가 과하게 느껴지는 작은 프로젝트에는 루트의 AGENTS.md 한 장이 있다. frontmatter 없이 지시만 적는 마크다운이고, 하위 디렉터리에 둔 것은 그 디렉터리 아래를 작업할 때 붙는다. 예전의 .cursorrules 한 장이 하던 역할이 이 자리로 옮겨 온 셈이다. 이름은 다르지만 Copilot의 copilot-instructions.md와 가장 닮은 꼴이기도 하다.
규칙의 범위
규칙 파일에 무엇을 넣을지는 한 기준으로 정한다. 요청마다 바뀌지 않는 것만 넣는다. 스택, 명명 규칙, 에러 처리 방식, 금지 패턴, 디렉터리 구조, 테스트 도구는 프로젝트가 사는 동안 거의 안 바뀌므로 규칙 자리다. 「이번에는 결제 모듈을 만든다」는 요청 자리다. 규칙 파일에 작업 지시를 넣으면 다음 작업에서 그 지시가 엉뚱하게 따라붙는다.
두 번째 기준은 어디에나 걸리는 것과 특정 파일에만 걸리는 것을 가른다는 것이다. 스택과 명명 규칙은 어디에나 걸리므로 alwaysApply에 두고, 테스트 규칙과 마이그레이션 규칙은 그 파일을 만질 때만 필요하므로 globs에 둔다. 규칙이 길어질수록 이 구분이 중요해진다 — 프롬프트에 넣을 수 있는 양은 유한해서 든 것들이 서로 자리를 다툰다 — 넣을수록 좋은 것이 아니다. 모든 대화에 붙는 규칙은 매번 그 자리를 차지하고, 모델이 그중 지금 필요 없는 줄까지 읽느라 정작 필요한 줄의 무게가 옅어진다.
금지 패턴은 특히 값이 있다. 모델은 학습 데이터에서 가장 흔한 것을 기본값으로 삼는데, print() 디버깅과 SELECT *가 정확히 그런 것이다. 금지한다고 적어 두면 완성·채팅·Agent 모두에 걸린다. 그리고 「하드코딩 비밀번호·API 키 금지」 한 줄은 다음 절의 보안 이야기를 규칙 파일 쪽에서 미리 막는 자리다.
보안·라이선스·유출
취약 패턴
두 도구가 만드는 코드는 학습 데이터에서 본 코드를 닮는다. 그 데이터에는 취약한 코드도 많다. 그래서 생성된 코드에 SQL 인젝션에 열린 문자열 조합 쿼리, 하드코딩된 비밀키, 안전하지 않은 난수 생성 같은 패턴이 그대로 들어올 수 있다. SQL 인젝션은 사용자 입력을 쿼리 문자열에 그대로 이어 붙여 공격자가 쿼리를 바꿔 쓰게 되는 취약점이다. 모델은 「흔한 코드」를 만드는 것이지 「안전한 코드」를 만드는 것이 아니다.
GitHub은 Copilot에 취약 패턴을 걸러 내는 필터를 두고 있지만 완벽하지 않다. 결국 보안 민감한 코드 — 암호화, 인증, 권한 검사 — 는 완성이 만든 것을 그대로 받지 않고 사람이 읽는다. 규칙 파일의 금지 패턴이 일부를 막고, 코드 리뷰와 정적 분석 도구가 나머지를 잡는 구조를 두는 편이 낫다.
라이선스와 중복 감지
두 번째 걱정은 라이선스다. 모델이 학습 데이터의 공개 코드를 긴 덩어리로 그대로 내놓으면, 그 코드의 라이선스가 우리 저장소에 따라 들어온다. Copilot에는 이를 막는 중복 감지(duplication detection) 필터가 있다. 설정 이름은 「공개 코드와 일치하는 제안」이고, 제안이 GitHub의 공개 코드와 150자 남짓 이상 그대로 겹치면 그 제안을 보여 주지 않는다. 이 설정은 요금제에 관계없이 개인 설정에 있다. Business·Enterprise가 다른 점은 관리자가 조직 전체에 강제할 수 있다는 것이다 — 개인이 끄지 못하게 잠근다. 다만 긴 코드 블록을 만들 때는 필터 기준에 안 걸리는 길이로 학습 데이터의 유사 코드가 나올 가능성이 남는다.
실무의 선은 「길이」다. 한두 줄의 관용구는 누가 써도 같으므로 문제가 안 되고, 알고리즘 하나를 통째로 받은 코드는 출처를 의심해 본다. 특히 잘 알려진 라이브러리의 함수를 그대로 옮긴 듯한 완성이 나오면 그 라이브러리를 의존성으로 쓰는 편이 낫다.
코드 유출
세 번째는 코드 유출이다. 두 도구 모두 기본적으로 코드를 서버로 보낸다. Copilot은 컨텍스트 빌더가 모은 프롬프트를 GitHub 서버로, Cursor도 코드를 자기 서버로 보내 모델을 돌린다. 개인 프로젝트라면 상관없지만, 외부에 나가면 안 되는 코드를 다루는 기업에서는 이 경로를 먼저 본다.
대응은 도구마다 자리가 다르다. Copilot 쪽은 조직 요금제의 정책으로 어느 모델과 어느 경로를 허용할지 관리자가 정하고, Enterprise의 기업용 옵션을 검토한다. 코드가 아예 밖으로 나가면 안 되는 자리라면 앞 절에서 본 BYOK로 Ollama 로컬 모델을 붙이거나 온프레미스 대안을 본다. 온프레미스는 자기 서버 안에서만 돌려 밖으로 아무것도 안 보내는 구성이다. Cursor 쪽은 Privacy Mode가 있다. 설정에서 켜면 코드가 모델 학습에 쓰이지 않고, 팀·기업 요금제에서는 관리자가 조직 전체에 걸어 새로 들어온 사람도 그 설정을 물려받게 한다. 여기서 「학습에 안 쓴다」와 「서버에 안 보낸다」는 다른 약속이다 — 앞의 것은 우리 코드가 다음 모델을 만드는 재료로 들어가지 않는다는 뜻이지, 추론이 어디서 도는가를 바꾸는 말이 아니다. 회사가 감사 자료를 요구하면 SOC 2 Type II를 비롯한 인증 보고서를 받아 볼 수 있다. 그래도 코드가 서버에는 가므로, 서버 자체를 못 믿는 환경이면 Cursor에서도 같은 길로 돌아간다 — Ollama를 연결해 완전히 로컬로 쓰는 것이다.
셋을 합치면 한 가지가 남는다. AI가 만든 코드의 보안·성능·정확성 책임은 도구가 아니라 개발자에게 있다. 도구가 필터를 두고 모드를 두는 것은 그 책임을 나눠 지는 것이 아니라 사고를 줄이는 것이다.
선택 기준
생산성 실험
GitHub이 2022년에 돌린 통제 실험에서 Copilot을 쓴 개발자는 같은 과제를 평균 55% 빠르게 마쳤다. 지금도 가장 자주 인용되는 숫자인데, 그대로 믿기 전에 조건을 본다. 과제는 HTTP 서버를 만드는 정형화된 것 하나였고, 그 한 과제에서 잰 값이다. 이 수치는 단순한 반복 코드 작업에서 크게 나오고, 아키텍처 설계나 복잡한 알고리즘에서는 효과가 제한적이다. 즉 「코딩이 절반으로 빨라진다」가 아니라 「타이핑이 많고 판단이 적은 작업이 빨라진다」에 가깝다.
이 조건은 Cursor에도 같이 걸린다. 편집 예측과 코드베이스 검색은 반복과 탐색을 줄이지, 설계를 대신하지는 않는다. 어느 도구든 이득이 큰 자리와 작은 자리를 알고 쓰면 실망도 사고도 줄어든다.
강점과 약점
실무에서 두 도구가 확실히 잘하는 자리는 이렇다.
- 보일러플레이트 코드 (DTO, 모델 클래스, getter/setter)
- 단위 테스트 케이스 생성
- 정규식, 날짜 포맷, 문자열 처리
- 알려진 알고리즘 구현 (정렬, 검색, 해시)
- API 클라이언트 코드
공통점은 정답이 널리 알려져 있고 학습 데이터에 많다는 것이다. 반대로 조심할 자리는 이렇다.
- 보안 민감 코드 (암호화, 인증)
- 성능 크리티컬 알고리즘
- 비즈니스 로직이 복잡한 도메인 코드
- 내부 라이브러리·프레임워크 활용
공통점은 정답이 우리 프로젝트에만 있다는 것이다. 모델은 우리 도메인 규칙을 모르고 내부 라이브러리의 시그니처를 모른다. 채팅 절에서 「모델이 자신 있게 틀리는 자리」라고 한 것이 정확히 여기다. 규칙 파일과 @ 참조가 이 간격을 줄이지만 없애지는 못한다.
기능 비교
| 항목 | Copilot | Cursor |
|---|---|---|
| 기반 | 익스텐션 (기존 IDE 유지) | VS Code 포크 (별도 설치) |
| 완성 | Inline Completion (FIM) | Tab (편집 예측) |
| 채팅 | Chat + 슬래시 커맨드 | Chat + @ 참조 |
| 멀티파일 편집 | 채팅의 Edit · Agent · Plan | Agent 패널 (Ask · Agent · Plan) |
| 코드베이스 시야 | 완성은 열린 탭, 채팅은 #codebase |
에이전트의 검색 (grep · 탐색 서브에이전트) |
| 모델 선택 | 피커 + BYOK (조직 정책이 제한) | 피커 + 자체 키 |
| 로컬 모델 | Ollama 확장 (BYOK) | Ollama |
| 규칙 파일 | .github/copilot-instructions.md |
.cursor/rules/*.mdc · AGENTS.md |
| 코드 보호 | 조직 정책 · Enterprise 옵션 | Privacy Mode |
| 가격 | $10/월 (Pro, 무료 티어 있음) | $20/월 (Pro) |
가격은 원고를 쓸 때의 값이고 요금제는 자주 바뀌므로 공식 페이지에서 확인한다.
Copilot을 고르는 자리는 분명하다. 쓰던 IDE를 바꾸고 싶지 않을 때, JetBrains나 Neovim처럼 VS Code가 아닌 편집기를 쓸 때, GitHub 조직에 이미 붙어 있어 PR까지 한 흐름으로 가고 싶을 때, 그리고 어느 모델과 키를 허용할지 조직 정책으로 관리해야 할 때다. Cursor를 고르는 자리도 분명하다. 파일이 수백 개를 넘어 관련 코드를 찾는 것 자체가 일일 때, 리팩터링처럼 이미 있는 코드를 고치는 일이 많을 때, 정책 없이 자체 키와 로컬 모델을 자유롭게 붙이고 싶을 때, 편집기를 통째로 갈아탈 수 있을 때다. 두 도구의 값이 서로 다른 자리에서 나므로, 팀의 프로젝트가 어느 쪽에 가까운지가 답을 정한다.
다음 걸음
두 도구의 Agent 모드는 같은 방향을 가리킨다. 제안을 보여 주는 도구에서 파일을 만들고 명령을 돌리고 결과를 보고 다시 행동하는 도구로. 그런데 그 일에 IDE가 꼭 필요한가 하는 물음이 남는다. 에이전트가 파일을 읽고 쓰고 테스트를 돌리는 데 편집기 화면은 없어도 된다. 필요한 것은 파일 시스템과 셸이다.
다음 글에서는 그 물음에 답하는 도구를 본다. 편집기가 아니라 터미널을 주 인터페이스로 삼고, 코드를 읽고 쓰고 실행하며 소프트웨어 엔지니어링 작업을 자율적으로 밟아 가는 에이전트다. IDE 안에서 사람 옆에 앉아 있던 AI가 CI 파이프라인과 서버 환경으로 걸어 나가는 자리이고, 이 글에서 본 규칙 파일이 거기서는 CLAUDE.md라는 이름으로 다시 나온다.
읽어주셔서 감사합니다. 😊

