들어가며: 배경 코딩 에이전트의 시작

AI 코딩 에이전트는 더 이상 데모 수준의 장난감이 아닙니다. 스포티파이는 내부 코드명 'Honk'라는 배경 코딩 에이전트를 구축하여, 수백 개의 레포지토리에 걸친 대규모 마이그레이션을 자동화하고 있습니다. 이 에이전트는 코드를 수정하고, 빌드와 테스트를 실행하며, 자동으로 PR(Pull Request)을 생성합니다.

하지만 여기서 중요한 질문이 생깁니다: 이 에이전트에게 '무엇을 해야 하는지' 어떻게 정확하게 전달할 수 있을까요?

이 글에서는 스포티파이가 'Context Engineering'이라고 명명한, 코딩 에이전트를 위한 효과적인 프롬프트 설계 방법을 집중적으로 파헤칩니다. 좋은 마이그레이션 프롬프트의 조건은 무엇인지, 에이전트가 어떤 도구에 접근해야 하는지, 그리고 실제 운영 환경에서 병합 가능한 PR을 안정적으로 생성하기 위해 어떤 원칙을 세웠는지 살펴봅니다.

근거자료

Developer writing a prompt for an AI coding agent on a laptop screen Technical Structure Concept

초기 시도: 오픈소스 에이전트의 한계

처음 스포티파이는 Goose나 Aider와 같은 오픈소스 에이전트를 실험했습니다. 단순한 프롬프트 하나만으로도 코드베이스를 탐색하고, 수정할 부분을 찾아내며, 코드를 편집하는 모습은 정말 놀라웠습니다.

그러나 이 접근법은 확장성에서 큰 문제를 드러냈습니다. 수천 개의 레포지토리에 동일한 변경을 적용하려 할 때, 일관되게 병합 가능한 PR을 생성하는 것이 매우 어려웠습니다. 좋은 프롬프트를 작성하는 것 자체도 어렵지만, 에이전트가 올바르게 작업을 수행했는지 검증하는 것은 훨씬 더 복잡한 문제였습니다.

자체 에이전트 루프 구축: 예측 가능성을 향한 첫걸음

더 예측 가능한 에이전트를 위해 스포티파이는 LLM API 위에 자체 '에이전틱 루프(agentic loop)'를 구축했습니다. 각 작업은 세 부분으로 구성되었습니다:

  1. 사용자가 프롬프트와 모든 대상 파일 목록을 제공
  2. 에이전트가 프롬프트를 기반으로 파일을 편집하고, 각 턴마다 빌드 시스템의 피드백을 통합
  3. 테스트 통과 또는 제한 초과 시 작업 완료 (세션당 10턴, 최대 3회 재시도)

이 방식은 작은 변경(예: 배포 매니페스트 수정, 설정 플래그 교체, 한 줄 코드 변경)에는 잘 작동했습니다. 하지만 그 이상의 복잡한 작업에서는 금방 한계에 부딪혔습니다.

가장 큰 문제는 컨텍스트 윈도우 관리였습니다. 사용자가 git grep 명령어로 정확한 파일을 선택해야 했는데, 검색 패턴이 너무 넓으면 LLM의 컨텍스트 윈도우가 넘쳐났고, 너무 좁으면 에이전트가 문제를 해결할 충분한 정보를 얻지 못했습니다.

또한 다중 파일 변경에 취약했습니다. 예를 들어 한 파일의 public 메서드를 수정하고, 이어서 모든 호출 지점을 변경하는 '연쇄 변경(cascading changes)'이 필요한 경우, 에이전트는 자주 턴을 소진하거나 컨텍스트 윈도우가 가득 차서 원래 작업을 잊어버리곤 했습니다.

Claude Code 도입: 게임 체인저

자체 구축 에이전트의 한계를 극복하기 위해 스포티파이는 Claude Code로 전환했습니다. Claude Code는 더 자연스러운 작업 지향 프롬프트를 허용하고, 내장된 Todo 리스트 관리와 서브 에이전트 생성 기능을 제공하여 컨텍스트 윈도우 문제를 완화해 주었습니다.

현재 Claude Code는 스포티파이에서 가장 성능이 좋은 에이전트로, 약 50건의 마이그레이션과 대부분의 배경 에이전트 PR에 사용되고 있습니다.

프롬프트의 기술: 실전 교훈

스포티파이 팀이 강조하는 핵심은 이것입니다: 프롬프트 작성은 생각보다 훨씬 어렵다. 대부분의 개발자는 이에 대한 경험이 부족합니다. 단순해 보이는 지시가 어떻게 터무니없는 결과를 초래할 수 있는지, 프롬프트의 미묘한 차이를 이해하지 못하면 깨닫기 어렵습니다.

주요 안티패턴

  1. 지나치게 일반적인 프롬프트 - 에이전트가 의도와 결과를 텔레파시로 알아내길 기대합니다.
  2. 지나치게 구체적인 프롬프트 - 모든 경우를 하나하나 열거하지만, 예상치 못한 상황이 발생하면 바로 무너집니다.

스포티파이의 6가지 핵심 교훈

  1. 에이전트에 맞게 프롬프트를 조정하라

    • 자체 구축 에이전트: 엄격한 단계별 지시가 효과적
    • Claude Code: 최종 상태를 설명하고, 도달 방법은 자율에 맡기는 것이 더 좋음
  2. 전제 조건을 명시하라

    • 에이전트는 지시를 따르는 데 너무 열성적입니다. 마이그레이션 시나리오에서 프롬프트를 여러 레포지토리에 재사용할 때 특히 문제가 됩니다. "이 작업이 불가능한 경우 아무것도 하지 마라"와 같은 조건을 명확히 명시하세요.
  3. 예제를 사용하라

    • 구체적인 코드 예제 몇 개가 결과에 큰 영향을 미칩니다.
  4. 최종 상태를 정의하라, 이상적으로는 테스트 형태로

    • "이 코드를 개선해줘"는 나쁜 프롬프트입니다. 에이전트가 반복적으로 해결책을 찾을 수 있도록 검증 가능한 목표가 필요합니다.
  5. 한 번에 하나의 변경만 하라

    • 여러 관련 변경을 하나의 복잡한 프롬프트로 합치는 것은 편리해 보이지만, 컨텍스트 윈도우를 소진하거나 부분적인 결과만 내놓을 가능성이 높습니다.
  6. 에이전트에게 프롬프트에 대한 피드백을 요청하라

    • 세션 후 에이전트 자신이 프롬프트에서 무엇이 누락되었는지 놀랍도록 잘 파악합니다. 이 피드백을 활용해 프롬프트를 개선하세요.

실제 프롬프트 예시: AutoValue → Java Records 마이그레이션

# 목표: AutoValue로 생성된 클래스를 Java Record로 변환
# 전제 조건: 대상 파일이 Java 16+를 사용하는 프로젝트에 속해 있어야 함

다음 규칙에 따라 변환을 수행하라:
1. @AutoValue 어노테이션이 달린 클래스를 찾아라.
2. 각 클래스를 record로 변환하라. (예: public final class Foo → public record Foo)
3. abstract 접근자를 record 컴포넌트로 대체하라.
4. toBuilder(), builder() 메서드가 있다면 제거하라.
5. 변환 후 컴파일이 되는지 'verify' 도구로 확인하라.
6. 컴파일 오류가 발생하면 원복하고, 이유를 로그에 남겨라.

# 예시
# Before:
# @AutoValue
# public abstract class User {
#   public abstract String name();
#   public abstract int age();
# }
# After:
# public record User(String name, int age) { }

올바른 도구 선택: 제한이 곧 자유

스포티파이는 배경 코딩 에이전트의 도구와 훅을 매우 제한적으로 유지합니다. 이는 에이전트가 프롬프트에 집중하여 올바른 코드 변경을 생성하도록 하기 위함입니다. 도구가 많을수록 예측 불가능성이 커집니다.

현재 에이전트가 접근할 수 있는 도구는 세 가지뿐입니다:

도구용도비고
verify포매터, 린터, 테스트 실행자체 빌드 시스템 호출을 MCP로 인코딩, 로그 요약
git제한적이고 표준화된 Git 접근push 금지, committer 고정, 표준 커밋 메시지
Bash엄격한 허용 목록의 명령어ripgrep 등 소수의 명령어만 허용

주의할 점: 현재 코드 검색이나 문서 도구는 에이전트에 노출되지 않습니다. 대신 사용자가 프롬프트에 관련 컨텍스트를 미리 압축하여 전달하도록 설계되어 있습니다. 이는 예측 가능성을 높이는 대신, 사용자에게 더 많은 준비 작업을 요구합니다.

한국 개발 생태계에서의 적용 맥락

국내 SI(시스템 통합) 환경이나 대규모 엔터프라이즈 프로젝트에서는 특히 이 접근법이 유용할 수 있습니다. 수백 개의 모듈로 구성된 레거시 시스템에서 API 버전 업그레이드, 라이브러리 마이그레이션, 코딩 컨벤션 변경 등을 자동화할 때, 스포티파이의 '제한된 도구 + 정교한 프롬프트' 전략은 매우 효과적입니다.

다만 국내 환경에서는 다음과 같은 점을 고려해야 합니다:

  • 자체 빌드 시스템이 MCP와 호환되어야 함
  • 레포지토리마다 빌드 설정이 크게 다른 경우, verify 도구의 일반화가 어려울 수 있음
  • 보안 정책상 에이전트의 Git 접근 권한을 세밀하게 통제해야 함

이 기술의 한계와 주의사항

  • 프롬프트 품질에 대한 의존성: 여전히 '시행착오'에 크게 의존합니다. 프롬프트나 모델의 성능을 평가하는 체계적인 방법이 아직 없습니다.
  • 검증의 어려움: PR이 병합되었다고 해서 원래 문제가 해결되었는지 확신할 수 없습니다. 피드백 루프가 필수적입니다.
  • 확장성 vs 예측 가능성의 트레이드오프: 더 많은 도구와 컨텍스트를 제공하면 더 복잡한 작업이 가능해지지만, 예측 가능성은 떨어집니다.

다음 단계 학습 방향

  • 피드백 루프 구축: PR이 병합된 후, 실제로 문제가 해결되었는지 자동으로 확인하는 시스템을 설계해 보세요.
  • 프롬프트 버전 관리: 프롬프트를 코드처럼 버전 관리하고, 테스트를 작성하며, 성능을 평가하는 방법을 연구하세요.
  • MCP 서버 개발: 자체 빌드 시스템, 배포 파이프라인 등과 연동되는 MCP 서버를 직접 구축해 보는 것도 좋은 실습입니다.

함께 보면 좋은 글:

Spotify engineering team using Claude Code for automated code migration Development Concept Image

결론: 아직 갈 길이 멀다

스포티파이는 배경 코딩 에이전트의 최첨단 기능을 계속 탐색하고 있습니다. Claude Code는 큰 잠재력을 보여주었고, 에이전트에게 지시를 내리고 효과적인 도구를 구축하는 방법을 배우면서 큰 진전을 이루었습니다. 작업을 적절한 단위로 분해하고, 좋은 프롬프트를 작성하며, 도구를 인프라와 더 잘 통합하는 것이 깨끗한 PR을 생성하는 핵심입니다.

하지만 실제로는 여전히 대부분 직관에 의존하고 있습니다. 프롬프트는 시행착오를 통해 진화하고 있으며, 어떤 프롬프트나 모델이 가장 좋은 성능을 내는지 평가하는 체계적인 방법은 아직 없습니다. 그리고 병합된 PR이 실제로 원래 문제를 해결했는지 어떻게 알 수 있을까요? 이 질문에 대한 답은 다음 글에서 다루어질 예정입니다.

지금 당장 여러분의 프로젝트에 적용할 수 있는 한 가지 조언: 작게 시작하고, 철저히 테스트하며, 에이전트의 피드백을 경청하세요.

Cloud infrastructure diagram showing multi-repository PR automation pipeline Coding Session Visual

본 콘텐츠는 신뢰할 수 있는 출처를 바탕으로 AI 도구를 활용하여 초안이 작성되었으며, 편집자의 검토를 거쳐 발행되었습니다. 전문가의 조언을 대체하지 않습니다.