전술적 vs 전략적 에이전트형 AI 개발 — 개발자를 위한 플레이북
요약
AI를 단순한 코드 작성 도구로 사용하는 '전술적 개발'의 위험성을 경고하고, 시스템 아키텍처와 모듈 간 계약을 설계하는 '전략적 에이전트형 개발'로의 전환을 제안합니다. AI가 생성하는 기술 부채를 방지하기 위한 개발자의 새로운 역할 변화를 다룹니다.
핵심 포인트
- 전술적 AI 함정: 즉각적인 문제 해결에만 집중하여 시스템 설계 부재와 기술 부채를 초래함
- 전략적 프로그래밍: AI를 단순 작업자가 아닌 아키텍처 방향성이 필요한 주니어 엔지니어로 취급
- 시스템 중심 사고: 코드 작성이 아닌 모듈 간 계약과 데이터 흐름 설계에 AI를 활용해야 함
전략적 엔지니어: 코드를 작성하는 것이 더 이상 당신의 가장 가치 있는 기술이 아닌 이유
서론: 당신이 빠져 있는지조차 모르는 함정
이런 상황을 상상해 보세요: 당신의 팀이 방금 새로운 결제 기능을 출시했습니다. 당신은 AI 에이전트 (AI agent)를 사용하여 결제 실패에 대한 예외 처리기 (exception handler), 재시도 로직 (retry logic), 그리고 국제 통화 코드를 위한 엣지 케이스 (edge-case) 검증 로직을 작성했습니다. 전체 오후를 다 쓰는 대신 단 40분 만에 끝냈습니다. 당신은 생산적이라고 느낍니다.
3번의 스프린트 (sprint)가 지난 후, 제품 팀이 가변적인 결제 주기를 가진 구독 서비스를 지원하도록 결제 기능을 확장해 달라고 요청합니다. 당신은 코드베이스 (codebase)를 열고 하드코딩된 엣지 케이스들의 엉킴, 이제는 폐기된 API의 특정 오류 코드를 참조하는 예외 처리기, 그리고 네 개의 서로 다른 파일에 중복된 재시도 로직을 발견합니다. 이 모든 것들은 화요일 이후의 상황은 고려하지 않은 개발자보다 10배 더 큰 자신감을 가지고, 10배 빠른 속도로 생성된 것들입니다.
이것이 바로 전술적 AI 함정 (Tactical AI Trap) 입니다: 주변 시스템을 설계하지 않은 채, 바로 눈앞에 놓인 문제를 해결하기 위해 AI를 사용하는 것입니다.
대부분의 개발자가 현재 이 함정에 빠져 있습니다. 그들이 부주의해서가 아니라, AI 도구들의 유인책이 그들을 그곳으로 몰아넣기 때문입니다. Copilot은 예외 처리를 자동 완성합니다. 에이전트는 버그를 패치합니다. 컨텍스트 윈도우 (context window)는 다음 달에 영향을 받을 5개의 파일이 아니라, 현재 파일로 가득 찹니다. 속도가 진보로 위장합니다.
AI와 함께 확장해 나가는 시니어 개발자와 AI가 생성한 부채 (AI-generated debt)에 빠져 허우적거리는 개발자를 가르는 변화는 말하기는 간단하지만 실행하기는 어렵습니다:
코드를 작성하기 위해 AI를 사용하는 것을 멈추십시오. 시스템을 구축하기 위해 AI를 사용하기 시작하십시오.
이 글은 전술적 개발에서 전략적 에이전트형 개발 (agentic development)로의 전환을 위한 플레이북입니다.
파트 1: 전술적 프로그래밍 vs 전략적 프로그래밍 — 실제로 무엇이 다른가
용어를 정확하게 정의해 봅시다. 왜냐하면 실무에서 그 차이가 엄청나게 중요하기 때문입니다.
**전술적 프로그래밍 (Tactical Programming)**은 집중 단위가 즉각적인 작업, 즉 이 버그, 이 예외, 이 함수임을 의미합니다. 당신은 AI를 더 빠른 손(pair of hands)으로 취급합니다. "getUserProfile()의 null pointer를 수정해줘"라고 말하고 다음으로 넘어갑니다. AI는 그 요구에 따릅니다.
**전략적 프로그래밍 (Strategic Programming)**은 집중 단위가 시스템, 즉 모듈 간의 계약(contracts), 서비스 전반에 걸쳐 흐르는 데이터의 형태, 그리고 기능이 확장되어야 할 경계면(seams)임을 의미합니다. 당신은 AI를 단순한 작업 설명이 아닌, 아키텍처 방향성이 필요한 주니어 엔지니어처럼 취급합니다.
다음은 구체적인 비교입니다:
전술적 프롬프트 (대부분의 개발자가 작성하는 방식)
결제 시 쿠폰이 적용될 때 `order.total`이 undefined가 되는 버그를 수정해줘.
AI는 null 체크를 추가합니다. 작동합니다. 버그는 사라졌습니다. 하지만 order.total이 undefined가 될 수 있는 이유는 가격 책정 모듈(pricing module)과 쿠폰 모듈(coupon module)이 단일 진실 공급원(single source of truth)을 공유하지 않기 때문입니다. 즉, 두 모듈이 "주문(order)"이 어떻게 생겼는지에 대해 서로 다른 모델을 가지고 있는 것입니다. 그 근본적인 문제는 이제 약간 더 숨겨지게 되었습니다.
전략적 프롬프트 (당신이 작성해야 하는 방식)
쿠폰이 적용될 때 `order.total`이 undefined가 되는 버그가 있습니다.
이를 수정하기 전에, `PricingModule`과 `CouponModule`이 일관된 Order 타입을 공유하고 있는지,
아니면 각자가 자신의 ...를 소유하고 있는지 확인해 주세요.
두 번째 프롬프트는 작성하는 데 30초가 더 걸립니다. 하지만 이는 다음 다섯 개의 쿠폰 관련 기능을 구현할 때 더 어렵게 만드는 것이 아니라, 더 쉽게 만들 수 있는 수정안을 만들어냅니다. 이것이 바로 레버리지(leverage)입니다.
실무적인 규칙: 어떤 AI 프롬프트를 작성하기 전에 스스로에게 물으세요. "나는 이 증상을 해결하고 있는가, 아니면 이 증상을 만들어낸 시스템을 개선하고 있는가?"
파트 2: 상태 유지형 스승(The Stateful Teacher) — 왜 일회성 프롬프트가 당신의 아키텍처를 망치고 있는가
대부분의 개발자가 전혀 생각하지 못하는 대부분의 AI 상호작용의 특성이 있습니다. 그것은 바로 **기본적으로 상태가 없다(stateless by default)**는 점입니다.
새로운 채팅을 열 때마다, AI는 당신의 코드베이스(codebase), 당신의 컨벤션(conventions), 당신의 아키텍처 결정(architectural decisions), 또는 당신이 6주 전에 저질렀던 실수에 대해 아무것도 알지 못합니다. 당신은 컨텍스트(context)를 쏟아붓고, AI는 문제를 해결하며, 당신은 탭을 닫습니다. 다음 세션은 다시 제로(zero)에서 시작됩니다.
간단한 질문에 답하는 용도로는 괜찮습니다. 하지만 장기적인 코드베이스를 구축하는 데 있어서는 재앙적입니다.
그 이유는 아키텍처가 _누적적(cumulative)_이기 때문입니다. 오늘 인증(authentication)을 어떻게 처리할지에 대해 내린 결정은 다음 달에 권한 부여(authorization)를 어떻게 구축할지를 결정짓습니다. User를 위한 스키마(schema) 설계는 나중에 멀티 테넌시(multi-tenancy)를 추가하는 방식에 영향을 미칩니다. 이러한 결정들은 고립되어 존재하지 않습니다. 이들은 세션 전반에 걸쳐 기억되어야(remembered) 하는 추론의 사슬을 형성합니다.
Teach 스킬 철학
오픈 소스인 Teach 스킬은 이 문제를 직접적으로 해결합니다. 각 AI 세션을 백지 상태의 정보 투입(information dump)으로 취급하는 대신, 이 스킬은 **상태가 있는 교사-학생 관계(stateful teacher-student relationship)**를 구축합니다. 즉, AI가 당신 프로젝트의 미션, 당신의 학습 목표, 과거의 아키텍처 결정, 그리고 현재의 진행 상황에 대한 모델을 유지합니다.
다음의 차이를 생각해 보세요:
- 상태가 없는(Stateless) AI: 컨퍼런스에서 만난 똑똑한 낯선 이가 20분 동안 훌륭한 조언을 해준 뒤 사라지는 것과 같습니다.
- 상태가 있는(Stateful) 교사 AI: 당신의 팀에 3개월 동안 합류하여 당신이 왜 모든 주요 결정을 내렸는지 정확히 알고 있는 시니어 아키텍트(senior architect)와 같습니다.
실제로 Teach 스킬은 매 세션 시작 시 로드되는 구조화된 컨텍스트 문서 — 즉, 살아있는 "코드베이스 헌장(codebase charter)" — 을 지속적으로 유지함으로써 작동합니다. 해당 문서가 어떤 모습일지에 대한 간략한 예시는 다음과 같습니다:
# 프로젝트: FinFlow — B2B 비용 관리 SaaS
## 핵심 아키텍처 결정
...
AI가 이 컨텍스트 (Context)를 로드하면, 당신의 프롬프트 (Prompt)는 성격이 변합니다. 매 세션마다 시스템을 다시 설명하는 대신, 공유된 이해를 바탕으로 그 위에 구축하게 됩니다. AI는 당신의 새로운 요청이 과거의 결정 사항을 위반할 때 이를 표시할 수 있습니다. 또한 기존의 접점 (Seams)을 알고 있기 때문에 새로운 기능을 위한 적절한 접점을 제안할 수 있습니다.
교훈: 당신의 가장 가치 있는 AI 투자는 당장의 더 나은 프롬프트가 아니라, 미래의 모든 프롬프트를 더 똑똑하게 만드는 지속적인 컨텍스트 (Persistent Context)를 구축하는 것입니다.
파트 3: 통제권 유지하기 — AFK 워크플로우와 샌드 캐슬 (Sand Castle) 보안 모델
전략적 아키텍처 (Strategic Architecture)와 상태 유지 컨텍스트 (Stateful Context)를 구축하고 나면, 새로운 가능성이 열립니다. 바로 AI를 일일이 감시할 필요가 없다는 것입니다.
대부분의 개발자는 에이전트 (Agent)가 예상치 못한 행동을 하는 즉시 중단할 준비를 하며, 한 줄 한 줄 지켜봅니다. 이러한 주의력은 이해할 수 있지만, 이는 결국 당신 자신의 주의력이 병목 현상 (Bottleneck)이 된다는 것을 의미합니다. 타이핑 속도라는 병목을 감시 속도라는 또 다른 병목으로 맞바꾼 셈입니다.
전략적인 움직임은 에이전트가 **비동기적 (Asynchronously)**으로, 즉 키보드에서 떨어져 있는 상태 (AFK, Away From Keyboard)에서도 실행될 수 있는 워크플로우를 설계하는 것입니다. 그동안 당신은 제품 비전과 프로덕션 시스템 (Production Systems)처럼 실제로 중요한 것들에 대한 통제권을 유지하면 됩니다.
샌드 캐슬 (Sand Castle) 모델
샌드 캐슬 (Sand Castle) 도구는 이를 위해 깔끔한 보안 모델을 구현합니다. 에이전트는 보안이 유지되는 격리된 샌드박스 (Sandbox)인 '샌드 캐슬' 내부에서 실행됩니다. 샌드 캐슬 내부에서 에이전트는 파일을 읽고, 코드를 작성하며, 테스트를 실행하고, 반복 작업을 수행할 수 있습니다. 하지만 명시적인 체크포인트 (Checkpoint) 없이는 프로덕션 시스템에 접근하거나, 메인 (Main) 브랜치에 커밋하거나, 외부 API 호출을 할 수 없습니다.
실제 AFK 워크플로우는 다음과 같은 모습입니다:
예시: 밤사이 저위험 버그 분류 및 수정
- 하루가 끝날 때, 당신은 12개의 저위험 버그(null 체크, off-by-one 에러, 입력 유효성 검사 누락 등)로 구성된 작업 목록을 만듭니다.
- 이 목록을 개발 브랜치(dev branch)에 대한 읽기/쓰기 권한은 있지만 프로덕션 자격 증명(production credentials)은 없는 Sand Castle에서 실행되는 에이전트에게 전달합니다.
- 에이전트는 밤새 작업합니다: 각 버그를 읽고, 수정 사항을 작성하며, 테스트 스위트(test suite)를 실행하고, 자신의 추론 과정을 요약한 PR(Pull Request)을 생성합니다.
- 다음 날 아침, 당신은 직접 수정을 작성하며 3일을 보내는 대신 45분 만에 12개의 PR을 검토합니다.
여기서 핵심적인 아키텍처 결정은 **Human-in-the-Loop 체크포인트(Human-in-the-Loop checkpoint)**입니다: 에이전트는 main 브랜치에 머지(merge)할 수 없습니다. 배포할 수도 없습니다. 프로덕션에 영향을 주는 모든 변경 사항에는 당신의 명시적인 승인이 필요합니다. 당신은 통제권을 포기하는 것이 아니라, _중요한 통제 수준 아래의 작업들을 자동화하는 것_입니다.
[Agent Loop - Sand Castle]
├── 버그 설명 읽기
├── 관련 코드 위치 파악
...
사고 모델의 전환 (The mental model shift): 당신은 AI를 지켜보는 개발자가 아닙니다. 당신은 _AI가 작동하는 경계(boundaries)를 설계하는 아키텍트(architect)_이자, _그 경계를 넘어서는 것을 승인하는 검토자(reviewer)_입니다.
AFK 방식이 정확히 작동하는 이유는 당신이 사전에 전략적인 작업(strategic work)을 수행했기 _때문_입니다: 코드베이스가 충분히 모듈화(modular)되어 있어, 에이전트가 다른 세 가지를 실수로 망가뜨리지 않고도 한 가지를 변경할 수 있습니다. 전술적(Tactical) 코드베이스는 에이전트에게 신뢰할 수 없습니다 — 숨겨진 의존성(dependencies)이 너무 많기 때문입니다. 전략적(Strategic) 코드베이스는 신뢰할 수 있습니다 — 의존성이 명시적(explicit)이기 때문입니다.
파트 4: 절차 vs 능력 — 인간을 운전석에 머물게 하기 (Procedures vs. Abilities — Keeping the Human in the Driver's Seat)
에이전트형 시스템(agentic systems)을 더 많이 다루게 되면, 시스템이 근본적으로 다른 두 가지 종류의 기술을 가지고 있다는 것을 알게 될 것입니다:
**능력 기술 (Ability Skills)**은 AI가 스스로 관련이 있다고 판단할 때 자율적으로(autonomously) 호출하는 것들입니다. 당신은 목표를 부여하고, AI는 어떤 도구를 언제 호출할지 결정합니다. 높은 자율성(High autonomy)을 가지지만, 예측 가능성(predictability)은 더 낮습니다.
**절차적 기술 (Procedure Skills)**은 당신이 호출하거나 순서를 지정하는 것들입니다. 즉, 당신이 설계한 워크플로우(workflow)를 통해 에이전트를 안내하는 단계별 지침(step-by-step instructions)입니다. 자율성(autonomy)은 더 낮지만, 예측 가능성(predictability)과 제어력(control)은 훨씬 높습니다.
대부분의 개발자 콘텐츠는 능력 기술 (Ability Skills)을 찬양합니다. "에이전트에게 원하는 것을 말하기만 하면 알아서 해냅니다!"라고 말이죠. 하지만 높은 능력(ability)을 가졌으나 코드베이스(codebase)의 품질이 낮은 에이전트는 문서화가 되어 있지 않은, 의도는 좋지만 실력이 없는 인턴과 같다는 사실을 깨닫기 전까지는 이 말이 매우 좋게 들릴 것입니다. 그 에이전트는 아주 자신 있게 거짓 정보를 만들어낼 것입니다.
복잡한 시스템에서 절차적 기술 (Procedure Skills)이 승리하는 이유
"새로운 API 엔드포인트(endpoint) 추가"와 같은 작업에서의 차이점을 생각해 보십시오.
능력 기술 (Ability Skill) 접근 방식 (높은 자율성):
특정 사용자에게 인보이스(invoice)를 생성하고 확인 이메일을 보내는
POST /api/invoices 엔드포인트를 생성하세요.
에이전트는 아마도 작동하는 코드를 만들어낼 것입니다. 하지만 에이전트가 다음 사항들을 수행할까요?
- 당신의 인증 미들웨어(authentication middleware) 패턴을 따르는가?
- 금액에 대해 공유된
MoneyAmount타입을 사용하는가? - 올바른 라우터(router) 파일에 경로를 등록하는가?
- 기존 테스트 패턴을 따라 적절한 통합 테스트(integration tests)를 추가하는가?
- 인보이스 생성 라이프사이클(lifecycle)에 맞는 적절한 도메인 이벤트(domain event)를 발생시키는가?
할 수도 있고, 안 할 수도 있습니다. 시스템에 딱 맞지 않는, 그럴싸해 보이는 300줄의 코드를 리뷰할 때쯤에야 그 사실을 알게 될 것입니다.
절차적 기술 (Procedure Skill) 접근 방식 (가이드된 시퀀스):
우리의 "API 엔드포인트 추가" 절차를 따르세요:
1단계: /src/api/invoices/dto.ts 에 요청/응답 DTO를 생성하세요
...
이것을 작성하는 데는 90초밖에 걸리지 않습니다. 하지만 이는 당신의 시스템에 맞는 코드를 생성하며, 당신의 패턴을 따르고, 자유 형식으로 생성된 300줄의 코드를 머릿속으로 일일이 감사(audit)할 필요가 없게 만듭니다. 당신은 운전석에 머물고, 에이전트는 자신의 차선을 유지합니다.
규칙: 범위가 명확하고, 위험이 낮으며, 격리된 작업(정규 표현식 생성, 순수 함수에 대한 단위 테스트 작성, 문서 초안 작성 등)에는 능력 기술 (Ability Skills)을 사용하세요. 시스템 아키텍처(architecture), 데이터 모델(data model), 또는 모듈 간 계약(cross-module contracts)에 영향을 미치는 모든 작업에는 절차적 기술 (Procedure Skills)을 사용하세요.
Part 5: 백지 원칙 (The Blank Slate Principle) — 컨텍스트를 비대하게 만들지 마세요
AI 툴링에 진심인 개발자라면 누구나 빠지기 쉬운 유혹이 있습니다. 바로 플러그인 축적 (plugin accumulation) 입니다.
에이전트에게 Jira 보드에 대한 접근 권한을 주는 플러그인을 찾습니다. 그다음에는 Slack 채널, GitHub PR, AWS 콘솔, 데이터베이스 스키마, 그리고 분석 대시보드까지 추가합니다. 머지않아 20개의 플러그인이 로드되어 있고, 당신은 강력한 힘을 가진 것처럼 느낍니다.
하지만 실제로 당신이 한 일은 마치 물건이 꽉 찬 잡동사니 서랍처럼 보이는 컨텍스트 윈도우 (context window)를 구축한 것입니다. 이제 에이전트는 모든 것에 접근할 수 있지만, 그 무엇도 제대로 이해하지 못합니다. 너무 많은 노이즈 (noise) 사이에서 패턴 매칭 (pattern-matching)을 시도하다 보니 시스템 간의 잘못된 연결을 환각 (hallucinate)하게 됩니다. 그리고 에이전트가 실패했을 때, 20개의 입력 중 어떤 것이 잘못된 출력을 유발했는지 알 방법이 없습니다.
백지 상태에서 시작하기
직관에 반하는 접근 방식은 바로 _아무것도 없는 상태_에서 시작하는 것입니다. 베이스라인 (baseline)까지 모두 걷어내세요. 오직 코드베이스 컨텍스트 (codebase context)와 핵심 아키텍처 문서 (core architectural document)만 가지고 에이전트를 실행해 보세요. 에이전트가 무엇을 잘하고 무엇을 잘 못하는지 관찰하십시오.
그다음 스스로에게 물으세요: '지금 내 워크플로에서 _가장 큰 마찰 지점 (single biggest friction point)_은 무엇인가?' 그것을 해결하기 위해 정확히 하나의 통합 (integration) 또는 절차 (procedure)만을 추가하세요. 다시 관찰하십시오. 이 과정을 반복하세요.
이것이 바로 블로그 포스트에서는 인상적으로 들리지만 실제로는 실패하는 극대주의적 (maximalist) 설정이 아니라, 당신의 팀에 실제로 적합한 에이전트 워크플로 (agentic workflow)를 구축하는 방법입니다.
실질적인 계층화 예시
SaaS 제품을 만드는 팀이 시간이 지남에 따라 에이전트 설정을 어떻게 계층화할 수 있는지에 대한 예시입니다:
1주 차 — 백지 상태 (Blank Slate)
컨텍스트: 코드베이스 + 아키텍처 헌장 (architectural charter)
결과: 에이전트가 시스템에 적합한 모듈형 코드를 작성하는 데 도움을 줌; 여전히 모듈 간 작업 (cross-module tasks)에는 가이드가 필요함
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기