기본 콘텐츠로 건너뛰기

JetBrains IDE에 AI 에이전트를 붙였더니, 제일 먼저 무너진 건 ‘코드’가 아니었다

thumbnail

JetBrains IDE에 AI 에이전트를 붙였더니, 제일 먼저 무너진 건 ‘코드’가 아니었다

IDE에 에이전트를 붙이는 건, 생각보다 감정적인 작업이다.

처음엔 다들 들뜬다. “이제 리뷰 시간 줄겠네.” “테스트도 자동으로 붙여주겠지.” “레거시도 금방 정리하겠네.”

그런데 실제로 팀에 도입해 보면, 처음으로 생기는 질문은 성능이 아니다.

“얘가 우리 레포를 어디까지 볼 수 있는 거죠?”

“이 변경은 내 로컬에서만 되는 거 아닌가요?”

“왜 이 PR은 파일을 30개나 만졌지?”

JetBrains IDE에서 ACP 레지스트리로 외부 에이전트를 붙일 수 있다는 소식은, 편의 기능이 늘었다는 정도로 보면 감각을 놓친다. 이건 ‘채팅창’이 하나 더 생긴 게 아니라, IDE가 프로젝트 전체를 읽고 바꾸는 손이 하나 더 생긴 사건이다. (참고자료)

나는 팀에 이런 걸 붙일 때, 모델 고르는 회의보다 먼저 운영 규칙을 적는다. 이게 없으면 “똑똑한 도구”가 아니라 “똑똑하게 사고 내는 도구”가 된다.

오늘 글은 기능 설명이 아니다. 내가 실제로 팀에 붙였던 가드레일(권한/재현/실험 분리)을 정리한 기록이다.


권한: 에이전트에게 “무엇을 보게/바꾸게” 할지부터 정한다

IDE 에이전트의 가장 큰 힘은 코드 생성이 아니다. 프로젝트 전체 접근이다.

이게 편한 순간은 많다. 그런데 위험한 순간은 더 분명하다.

  • 설정 파일을 “좋은 의도”로 바꿔버린다
  • 배포 스크립트를 건드려서 CI가 깨진다
  • 보안 키/내부 URL/운영 지침 같은 게 입력에 섞일 수 있다는 전제로 운영한다(외부 전송 여부와 별개로).

그래서 나는 도입 첫날에 ‘원칙 3개’를 만들기보다, 실제로 팀이 싸우는 질문부터 적는다. 어차피 첫 달에 계속 고치게 되니까, 문장은 짧고 구체적인 게 낫다.

  • 어디까지 고쳐도 되나? 에이전트가 수정해도 되는 디렉터리와 “절대 건드리지 말아야 할” 디렉터리를 먼저 나눈다. 예를 들어 src/는 허용하되, infra/terraform·prod runbook·secrets 계열은 금지 같은 식으로(팀마다 다름).

  • 누가 마지막으로 책임지나? 에이전트가 직접 머지하는 구조는 보통 빨리 망가진다. 결국 PR 단위로만 나오게 하고, 사람이 diff를 확인하고 승인하게 한다. 여기서 포인트는 “승인하는 사람이 누구인지”를 박아두는 것이다. 코드 오너가 없으면 책임이 증발한다. CODEOWNERS가 있는 영역이면 오너 1명 승인 없이는 못 넘어가게 한다.

  • 한 번에 얼마나 바꾸나? 한 번에 30파일 고치는 건 인간도 싫다. 큰 수정은 성공처럼 보여도, 리뷰 비용이 먼저 터진다. 그래서 “한 PR에 최대 변경 파일 수” 같은 제한을 둔다. 이게 귀찮아 보이는데, 실제로는 팀 속도를 지킨다.

나는 이걸 repo에 짧은 문서로 박아둔다. 에이전트에게도 읽히고, 사람에게도 읽히게.

# agent-guardrails.md (예시)

- 에이전트는 PR만 만든다(머지/릴리스 금지).
- 수정 가능: src/, tests/, docs/
- 수정 금지: infra/, .github/workflows/, prod-runbook/, secrets*
- 한 PR은 10파일 이내(넘으면 쪼갠다).
- 변경 후 반드시: 테스트 명령 1개 실행 + 결과를 PR 본문에 적기.

이 정도만 해도 “왜 이걸 바꿨지?”가 줄어든다.

그리고 이 문서는 ‘에이전트를 통제하려고’ 쓰는 게 아니라, 사람끼리 싸우는 시간을 줄이려고 쓴다. 실제로 한 번은 CODEOWNERS가 걸린 파일을 누가 봐야 하냐로 15분을 썼다. 그날 이후로 “오너 1명 승인”을 문서에 박아두니, 이상하게 논쟁이 줄었다. 문장이 팀의 에너지를 아껴준다.


재현성: Jupyter/툴 설치를 ‘개인 PC’가 아니라 팀 규칙으로 만든다(uv)

에이전트를 IDE에 붙이는 순간, 팀은 예상보다 더 자주 노트북/실험 코드를 만진다.

왜냐면 에이전트가 코드를 만들면, 사람은 검증을 해야 하고, 검증은 대개 가장 쉬운 환경(노트북)으로 흐르기 때문이다.

그런데 노트북은 팀을 쉽게 갈라놓는다.

  • A의 로컬에선 되는데 B의 로컬에선 안 된다
  • 설치가 다르고, 커널이 다르고, 버전이 다르다

이게 쌓이면 “에이전트가 만든 코드가 문제”처럼 보이는데, 실은 환경이 문제다.

노트북이 늘기 시작하면, 어느 날부터 “A는 되는데 B는 안 되는” 시간이 팀의 오전을 잡아먹는다. 그래서 설치법이 아니라 실행 경로를 하나로 만든다. (참고자료)

나는 팀에서 노트북을 허용할 때, ‘설치법’을 공유하지 않는다. 실행 경로를 하나로 만든다.

# 예: uv로 Jupyter 도구 설치(팀이 합의한 방식)
uv tool install jupyter-core --with jupyter

그리고 더 중요한 건 “누가 설치했냐”가 아니라 “레포에서 어떻게 실행하냐”다.

  • make notebook 같은 진입점을 하나로 두고
  • 그 진입점이 uv/venv/패키지 설치를 내부에서 처리하게 한다

에이전트가 코드를 만드는 속도는 빨라져도, 환경 재현이 느리면 팀은 결국 느려진다.


(짧게) RAG 같은 무거운 작업은 ‘인덱싱’과 ‘질의’를 섞지 않는다

IDE 에이전트 도입이 진행되면, 다음에 나오는 요구는 거의 정해져 있다.

내가 레포에 박아두는 규칙은 두 줄이면 충분하다. - 인덱싱(문서 쌓기)은 배치/별도 워커에서만 한다. - 서비스는 “질의 → 검색 → 답”만 하고, 인덱싱은 절대 같이 하지 않는다.

이걸 분리해두면 “답이 이상하다”와 “문서가 반영이 안 됐다”가 같은 사건으로 섞이지 않는다.

코드 습관: generator expression으로 전처리를 짧게 만들면 에이전트도 덜 망친다

마지막은 소소하지만, 꽤 효과가 있다.

에이전트가 코드를 망치는 순간을 보면, 복잡한 알고리즘이 아니라 “사소한 전처리”에서 많이 터진다.

  • 공백/개행 처리
  • 빈 줄 제거
  • 토큰 수 줄이기

Python Morsels가 ‘커스텀 comprehension’을 이야기하는 글을 보면서 떠오른 건, 이런 습관을 팀 코드에 박아두면 에이전트도 덜 헤맨다는 점이었다. (참고자료)

예를 들어 프롬프트/문서 입력을 정리하는 코드는 길 필요가 없다.

clean = "\n".join(line.strip() for line in text.splitlines() if line.strip())

이 한 줄이 있으면, 비슷한 전처리 코드가 여기저기 흩어지는 일이 줄어든다. 그리고 전처리 코드가 흩어지지 않으면, 에이전트가 ‘어디에 맞춰야 하는지’를 덜 헷갈린다.


마무리: 에이전트 도입은 “설치”가 아니라 “운영 합의”다

IDE에서 에이전트를 켜는 건 5분이면 된다.

그 다음이 진짜다.

  • 무엇을 보게 할지
  • 무엇을 바꾸게 할지
  • 어떤 단위로 검증하고 승인할지
  • 실험은 어디서 끝내고, 제품은 어디서 시작할지

이걸 합의하지 않으면, 도구는 팀을 도와주지 않는다. 팀이 도구를 관리하게 된다.

반대로 이걸 합의하면, 에이전트는 좋은 동료가 된다. 일을 대신하는 동료가 아니라, 같은 규칙 안에서 일하는 동료.


참고자료

  • JetBrains AI Blog — Cursor Joined the ACP Registry and Is Now Live in Your JetBrains IDE
    • https://blog.jetbrains.com/ai/2026/03/cursor-joined-the-acp-registry-and-is-now-live-in-your-jetbrains-ide/
  • Rodrigo Girão Serrão — TIL #140 – Install Jupyter with uv
    • https://mathspp.com/blog/til/install-jupyter-with-uv
  • PyBites — Why Building A Production RAG Pipeline Is Easier Than You Think
    • https://pybit.es/articles/why-building-a-production-rag-pipeline-is-easier-than-you-think/
  • Python Morsels — Invent your own comprehensions in Python
    • https://www.pythonmorsels.com/custom-comprehensions/

댓글

이 블로그의 인기 게시물

Django에서 트랜잭션 관리하기

Django에서 트랜잭션 관리하기 안녕하세요! 오늘은 Django에서 데이터베이스 트랜잭션을 효과적으로 관리하는 방법에 대해 알아보겠습니다. 1. 트랜잭션의 중요성 트랜잭션은 데이터베이스의 일관성과 무결성을 보장하는 중요한 개념입니다. Django에서는 여러 가지 방법으로 트랜잭션을 관리할 수 있습니다. 1.1 기본 개념 원자성(Atomicity) : 트랜잭션은 모두 실행되거나 모두 실행되지 않아야 합니다. 일관성(Consistency) : 트랜잭션 전후로 데이터베이스의 일관성이 유지되어야 합니다. 격리성(Isolation) : 동시에 실행되는 트랜잭션들이 서로 영향을 주지 않아야 합니다. 지속성(Durability) : 완료된 트랜잭션의 결과는 영구적으로 저장되어야 합니다. 2. Django의 트랜잭션 관리 2.1 기본 설정 # settings.py DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'mydatabase', 'USER': 'myuser', 'PASSWORD': 'mypassword', 'HOST': 'localhost', 'PORT': '5432', 'ATOMIC_REQUESTS': True, # 모든 뷰를 트랜잭션으로 래핑 } } 2.2 데코레이터 사용 from django.db import transaction @transaction.atomic def create_order(user, items): order = Order.objects.create(user=...

AWS S3 + CloudFront로 정적 파일 서빙 완전 가이드

AWS S3 + CloudFront로 정적 파일 서빙 완전 가이드 안녕하세요! 오늘은 AWS S3와 CloudFront를 사용하여 정적 파일을 효율적으로 서빙하는 방법에 대해 알아보겠습니다. 왜 S3와 CloudFront를 사용할까요? 높은 가용성 : AWS의 글로벌 인프라를 활용 빠른 전송 속도 : CloudFront의 CDN 기능으로 전 세계 사용자에게 빠른 전송 비용 효율성 : 사용한 만큼만 지불 보안 : AWS의 보안 기능 활용 확장성 : 트래픽 증가에 자동 대응 1. S3 버킷 설정 1.1 버킷 생성 및 설정 import boto3 def create_s3_bucket(): s3 = boto3.client('s3') # 버킷 생성 bucket_name = 'your-static-files-bucket' s3.create_bucket( Bucket=bucket_name, CreateBucketConfiguration={ 'LocationConstraint': 'ap-northeast-2' } ) # 버킷 정책 설정 bucket_policy = { "Version": "2012-10-17", "Statement": [ { "Sid": "PublicReadGetObject", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObje...

RDS에서 Django 앱 성능을 높이는 데이터베이스 설정 팁

RDS에서 Django 앱 성능을 높이는 데이터베이스 설정 팁 안녕하세요! 오늘은 AWS RDS를 사용하는 Django 애플리케이션의 성능을 최적화하는 방법에 대해 알아보겠습니다. 1. RDS 인스턴스 최적화 1.1 인스턴스 타입 선택 # RDS 인스턴스 크기 조정 import boto3 def resize_rds_instance(): rds = boto3.client('rds') response = rds.modify_db_instance( DBInstanceIdentifier='your-db', DBInstanceClass='db.t3.large', # 워크로드에 맞는 인스턴스 타입 선택 ApplyImmediately=True ) return response['DBInstance'] 1.2 파라미터 그룹 설정 def create_parameter_group(): rds = boto3.client('rds') # PostgreSQL 파라미터 그룹 생성 response = rds.create_db_parameter_group( DBParameterGroupName='django-optimized', DBParameterGroupFamily='postgres13', Description='Optimized parameters for Django applications' ) # 성능 관련 파라미터 설정 parameters = [ { 'ParameterName': 'shared_buffers', 'ParameterValue': '2GB...