2026년을 앞두고, AI 코딩 어시스턴트를 효과적으로 활용하기 위해 계획 수립부터 컨텍스트 제공, 모델 선택, 테스트·리뷰·버전 관리까지 전 과정을 дисцип disciplined하게 운영하는 실전 워크플로를 정리한다.
홈GitHub프레스약력LinkedInTwitter뉴스레터블로그
AI 코딩 어시스턴트는 2025년에 판도를 바꾸는 도구가 되었지만, 이를 효과적으로 활용하려면 기술과 구조가 필요합니다. 이런 도구들은 실제 개발에서 LLM이 할 수 있는 일을 극적으로 늘렸고, 많은 개발자(나 포함)가 이를 받아들였습니다.
예를 들어 Anthropic에서는 엔지니어들이 Claude Code를 настолько 많이 도입해, 현재Claude Code의 코드 중 약 90%가 Claude Code 자체에 의해 작성된다고 합니다. 하지만 LLM으로 프로그래밍하는 일은 버튼 한 번으로 마법처럼 끝나는 경험이 아닙니다. 오히려 “어렵고 직관적이지” 않으며, 뛰어난 결과를 내려면 새로운 패턴을 학습해야 합니다. 비판적 사고는 여전히 핵심입니다. 1년 넘게 여러 프로젝트를 거치며, 저는 숙련된 개발자들이 공통적으로 발견하는 워크플로에 수렴했습니다. 즉 LLM을 자율적 판단을 내리는 존재로 보기보다, 명확한 지시, 컨텍스트, 감독이 필요한 강력한 페어 프로그래머로 대하는 것입니다.
이 글에서는 2026년을 맞아 제가 AI와 함께 계획하고 코딩하고 협업하는 방식을, 제 경험과 커뮤니티의 집단적 학습에서 뽑아낸 팁과 모범 사례로 정리해 공유합니다. 이는 더 엄격한 “AI 보조 엔지니어링(AI-assisted engineering)” 접근입니다. AI를 적극적으로 활용하되, 만들어진 소프트웨어에 대해 자랑스럽게 책임을 지는 것이 핵심입니다.
제 워크플로에 대해 더 알고 싶다면 “The AI-Native Software Engineer”를 참고하시고, 아니라면 이제 제가 얻은 교훈으로 바로 들어가 보겠습니다.
LLM에게 막연한 ‘소원’을 던지지 말고, 문제를 정의하고 해법을 계획하는 것부터 시작하세요.
흔한 실수는 अस्प vague한 프롬프트로 곧장 코드 생성을 시작하는 것입니다. 제 워크플로(그리고 많은 다른 워크플로)에서 첫 단계는 실제 코드 작성 전에, AI와 함께 상세한 명세를 브레인스토밍하고 단계별 계획을 개요로 잡는 것입니다. 새 프로젝트라면 아이디어를 설명하고, LLM이 반복적으로 질문을 던지며 요구사항과 엣지 케이스가 충분히 드러날 때까지 함께 다듬게 합니다. 마지막에는 이를 종합해 요구사항, 아키텍처 결정, 데이터 모델, 테스트 전략까지 담은 포괄적인 spec.md로 정리합니다. 이 스펙이 개발의 토대가 됩니다.
그다음 스펙을 추론 능력이 좋은 모델에 넣고 프로젝트 계획을 생성하도록 합니다. 구현을 논리적이고 한입 크기의 작업/마일스톤으로 쪼개는 것입니다. AI는 미니 “디자인 문서” 혹은 프로젝트 플랜을 도와줍니다. 저는 이 계획을 자주 반복해 다듬습니다. 직접 편집하고 AI에게 비평이나 개선을 요청하면서, 일관되고 완전해질 때까지 조정합니다. 그 다음에야 코딩으로 넘어갑니다. 이 선투자는 느리게 느껴질 수 있지만, 엄청난 효과가 있습니다. Les Orchard가 표현한 것처럼, 이는 **“15분짜리 폭포수(waterfall in 15 minutes)”**와 같습니다. 빠르게 구조화된 계획 단계가 이후 코딩을 훨씬 매끄럽게 만들어줍니다.
명확한 스펙과 계획이 있으면 코드 생성을 시작했을 때 인간과 LLM 모두 “무엇을, 왜” 만들고 있는지 정확히 압니다. 요컨대 먼저 계획하기는 당신과 AI를 같은 페이지에 두고 낭비를 줄입니다. 많은 사람들이 건너뛰고 싶어 하지만, 숙련된 LLM 개발자들은 이제 탄탄한 스펙/계획을 워크플로의 초석으로 여깁니다.
스코프 관리는 전부입니다. LLM에 코드베이스 전체를 한 번에 먹이지 말고, 관리 가능한 작업을 주세요.
제가 얻은 중요한 교훈은 AI에게 거대한 단일 결과물을 요구하지 말라는 것입니다. 대신 프로젝트를 반복 가능한 단계/티켓으로 쪼개고 하나씩 해결합니다. 이는 좋은 소프트웨어 엔지니어링 관행과 닮았지만, AI가 끼어 있을 때는 더욱 중요합니다. LLM은 초점을 좁힌 프롬프트에서 가장 잘 동작합니다. 한 번에 함수 하나 구현, 버그 하나 수정, 기능 하나 추가처럼요. 예를 들어 계획을 세운 뒤 저는 코드 생성 모델에 이렇게 요청합니다: “좋아, 계획의 1단계를 구현하자.” 그걸 코딩하고 테스트한 다음 2단계로 넘어갑니다. 각 덩어리는 컨텍스트 안에서 AI가 처리할 수 있을 만큼 작고, 당신이 생성된 코드를 이해할 수 있을 만큼 작습니다.
이 접근은 모델이 엉뚱한 방향으로 달리는 걸 막아줍니다. 한 번에 너무 많은 것을 요구하면, 혼란에 빠지거나 풀기 어려운 **“뒤죽박죽한 난장판”**을 만들 가능성이 큽니다. 개발자들은 LLM에게 앱의 큰 덩어리를 생성하게 시도했을 때 일관성/중복 문제가 생겨 “서로 이야기 안 한 10명의 개발자가 만든 것 같다”고 보고합니다. 저도 그 고통을 겪었습니다. 해결책은 멈추고, 한걸음 물러나, 문제를 더 작은 조각으로 나누는 것입니다. 반복마다 우리는 지금까지 만든 것의 컨텍스트를 이어받아 조금씩 더합니다. 이는 **테스트 주도 개발(TDD)**과도 잘 맞습니다. 각 조각마다 테스트를 작성/생성해가며 진행할 수 있습니다(테스트는 곧 더 다룹니다).
이런 “청크” 워크플로를 명시적으로 지원하는 코딩 에이전트 도구들도 등장했습니다. 예를 들어 저는 종종 각 작업에 대한 프롬프트 시퀀스를 담은 구조화된 “프롬프트 플랜” 파일을 생성해, Cursor 같은 도구가 이를 하나씩 실행하게 합니다. 핵심은 큰 도약을 피하는 것입니다. 작은 루프로 반복하면 치명적 오류 가능성이 줄어들고, 빠르게 방향을 수정할 수 있습니다. LLM은 빠르고 제한된 작업에서 뛰어납니다. 그 강점을 활용하세요.
LLM의 품질은 제공하는 컨텍스트만큼입니다. 관련 코드, 문서, 제약을 보여 주세요.
코드베이스에서 작업할 때 저는 AI가 잘 수행하는 데 필요한 정보를 모두 제공하려고 합니다. 수정/참조해야 할 코드, 프로젝트의 기술적 제약, 알려진 함정이나 선호하는 접근 등이 포함됩니다. 최신 도구들이 이를 돕습니다. 예컨대 Anthropic의 Claude는 “Projects” 모드에서 GitHub 저장소 전체를 컨텍스트로 가져올 수 있고, Cursor나 Copilot 같은 IDE 어시스턴트는 열린 파일을 자동으로 프롬프트에 포함합니다. 하지만 저는 종종 더 나아갑니다. 모델이 필요한 정보를 갖고 있지 않다고 느끼면 Context7 같은 MCP를 쓰거나, 코드베이스/ API 문서의 핵심 부분을 대화에 직접 복사해 넣습니다.
숙련된 LLM 사용자는 이 “컨텍스트 패킹” 단계를 강조합니다. 코딩 전 모델이 알아야 할 모든 것을 “브레인 덤프” 형태로 제공하는 것이죠. 예를 들면: 상위 목표와 불변조건, 좋은 해법의 예, 피해야 할 접근에 대한 경고 등입니다. 까다로운 구현을 부탁한다면, 순진한 해법이 너무 느리다는 점을 알려주거나 다른 곳의 레퍼런스 구현을 제공할 수 있습니다. 생소한 라이브러리나 막 출시된 API를 쓰는 경우에는, 모델이 눈먼 상태로 추측하지 않도록 공식 문서나 README를 붙여 넣습니다. 이런 사전 컨텍스트는 결과물을 극적으로 개선합니다. 모델이 추측하지 않고, 눈앞의 사실과 제약을 기반으로 작업하기 때문입니다.
컨텍스트 패키징을 자동화하는 유틸리티도 나왔습니다. 저는 gitingest나 repo2txt 같은 도구를 실험해봤는데, 이는 본질적으로 **LLM이 읽을 수 있도록 코드베이스의 관련 부분을 텍스트 파일로 ‘덤프’**해 줍니다. 큰 프로젝트에서는 생명줄이 될 수 있습니다. 핵심 소스 파일을 묶은 output.txt를 생성해 모델에 먹이는 식이죠. 원칙은 하나입니다: AI가 부분 정보로 작업하게 두지 마세요. 버그 수정에 네 개의 모듈 이해가 필요하다면, 그 네 개 모듈을 보여 주세요. 토큰 한계는 봐야 하지만, 최신 프론티어 모델은 컨텍스트 윈도우가 매우 큽니다(수만 토큰). 현명하게 활용하세요. 저는 작업과 관련된 코드만 선별해 포함하고, 범위 밖인 항목은 AI에게 명시적으로 _신경 쓰지 말라_고 말해 토큰을 아끼기도 합니다.
저는 Claude Skills에 잠재력이 크다고 봅니다. 반복 프롬프트로 인한 취약성을 줄이고, 지시/스크립트/도메인 전문성을 모듈형 기능으로 패키징해 요청이 Skill과 매칭될 때 도구가 자동 적용하도록 하기 때문입니다. 이는 일반 프롬프트보다 더 신뢰할 수 있고 컨텍스트 인지적인 결과를 제공하며, 일회성 상호작용에서 벗어나 재현 가능한 절차와 팀 지식을 일관되게 인코딩한 워크플로로 이동하게 합니다. 커뮤니티가 큐레이션한 Skills 컬렉션도 여럿 있고, 제가 좋아하는 예 중 하나는 LLM 생성 UI에 흔한 보라색 디자인 미학을 “끝장낼” 수 있다는 frontend-design 스킬입니다. 더 많은 도구가 Skills를 공식 지원하기 전까지는 우회 방법도 존재합니다.
마지막으로, 프롬프트 안에 코멘트와 규칙을 넣어 AI를 가이드하세요. 저는 코드 스니펫 앞에 “여기가 X의 현재 구현이다. Y를 하도록 확장해야 하지만 Z는 절대 깨뜨리면 안 된다”고 적곤 합니다. 이런 힌트는 매우 큰 차이를 만듭니다. LLM은 문자 그대로 따르는 경향이 있으니, 상세하고 맥락 있는 지시를 주세요. 컨텍스트와 가이드를 선제적으로 제공하면 환각과 엉뚱한 제안을 줄이고, 프로젝트 요구에 맞는 코드를 얻을 수 있습니다.
모든 코딩 LLM이 같은 것은 아닙니다. 의도적으로 도구를 고르고, 필요하면 중간에 모델을 바꾸는 것을 두려워하지 마세요.
2025년은 코드 중심 LLM이 풍성한 한 해였습니다. 제 워크플로의 일부는 작업에 가장 적합한 모델/서비스를 선택하는 것입니다. 때로는 같은 문제를 두세 개 LLM에 동시에 던져, 서로 다른 접근을 교차검증해 보는 것도 가치가 있습니다.
각 모델에는 고유한 “성격”이 있습니다. 핵심은 이것입니다: 한 모델이 막히거나 결과가 미적지근하면, 다른 모델을 써 보세요. 저는 실제로 한 챗의 프롬프트를 다른 서비스로 그대로 복사해 더 잘 처리하는지 보곤 합니다. 이런 “모델 의자 바꾸기”는 모델의 사각지대를 만났을 때 당신을 구해줍니다.
또한 가능하면 _최고 버전_을 쓰세요. 최신 “프로” 티어 모델을 쓸 수 있다면 품질이 중요합니다. 접근 비용이 들기도 하지만, 생산성 향상이 이를 정당화할 수 있습니다. 궁극적으로는 당신과 ‘결이 맞는(vibe)’ AI 페어 프로그래머를 고르세요. 어떤 사람들은 답변의 _느낌_이 좋아서 특정 모델을 선호하기도 합니다. 유효한 기준입니다. AI와 거의 계속 대화하게 되니 UX와 톤이 영향을 줍니다.
개인적으로 요즘은 많은 코딩 작업에서 Gemini를 선호합니다. 상호작용이 더 자연스럽고, 요청을 첫 시도에 잘 이해하는 경우가 많기 때문입니다. 하지만 필요하면 다른 모델로 전환하는 것을 주저하지 않습니다. 두 번째 의견이 해법을 드러내는 데 도움이 될 때가 있습니다. 요약하자면: 일에 맞는 최고의 도구를 쓰고, 당신에겐 여러 AI라는 무기가 있다는 점을 기억하세요.
SDLC 전반에서 코딩 특화 AI 도움으로 워크플로를 강화하세요.
커맨드라인에는 새로운 AI 에이전트가 등장했습니다. Claude Code, OpenAI의 Codex CLI, Google의 Gemini CLI는 프로젝트 디렉터리 안에서 직접 대화할 수 있는 CLI 도구로, 파일을 읽고 테스트를 실행하며 여러 단계를 거쳐 문제를 해결하기도 합니다. 저는 Google의 Jules와 GitHub의 Copilot Agent도 사용해 봤습니다. 이들은 비동기 코딩 에이전트로, 실제로 저장소를 클라우드 VM에 클론해 백그라운드에서 작업을 수행합니다(테스트 작성, 버그 수정 후 PR을 열어줌). “결제 모듈을 X에 맞게 리팩터링해” 같은 명령을 내리면, 잠시 뒤 코드 변경과 통과한 테스트가 담긴 풀 리퀘스트가 도착합니다. 직접 보면 약간 섬뜩할 정도죠. 우리는 진짜 미래에 살고 있습니다. 더 자세한 내용은 conductors to orchestrators에서 읽을 수 있습니다.
다만 이 도구들은 완벽하지 않으며 한계를 이해해야 합니다. 이들은 코딩의 기계적인 부분(보일러플레이트 생성, 반복 변경 적용, 자동 테스트 실행)을 가속하지만, 여전히 당신의 가이드가 큰 도움이 됩니다. 예를 들어 Claude나 Copilot 같은 에이전트로 구현할 때 저는 앞 단계에서 만든 계획/투두 리스트를 제공해 정확한 작업 순서를 알게 합니다. 에이전트가 지원한다면, 실행 지시 전에 spec.md나 plan.md를 컨텍스트에 로드합니다. 그러면 궤도를 벗어나지 않습니다.
AI 에이전트에게 기능 전체를 무감독으로 코딩하게 하고 완벽한 결과를 기대하는 단계는 아직 아닙니다. 대신 저는 감독된 방식으로 씁니다. 코드를 생성하고 실행하게 하되, 각 단계를 주시하며 이상한 점이 있으면 개입할 준비를 합니다. Conductor 같은 오케스트레이션 도구는 여러 에이전트를 서로 다른 작업에 병렬로 돌릴 수 있게 해 줍니다(일종의 AI 도움 스케일업). 어떤 엔지니어들은 서로 다른 기능을 위해 3~4개의 에이전트를 동시에 돌리기도 합니다. 저도 이런 “대규모 병렬” 접근을 조금 해 봤는데, 빠르게 많은 일을 처리하는 데 놀라울 만큼 효과적입니다. 다만 여러 AI 스레드를 모니터링하는 건 정신적으로 부담이 큽니다! 대부분은 주 에이전트 하나에, 리뷰용 보조 하나 정도로 유지합니다(아래에서 다룹니다).
기억하세요. 이들은 전동공구입니다. 방아쇠를 당기고 결과를 이끄는 건 여전히 당신입니다.
AI는 그럴듯해 보이는 코드를 기꺼이 만들어내지만, 품질 책임은 _당신_에게 있습니다. 항상 철저히 리뷰하고 테스트하세요. 제 핵심 규칙 중 하나는 LLM의 출력을 맹목적으로 믿지 않는 것입니다. Simon Willison이 적절히 말하듯, LLM 페어 프로그래머는 “자신감 과잉이고 실수하기 쉬운” 존재로 생각하세요. 버그나 말도 안 되는 내용까지 확신에 차서 코드를 쓰며, 당신이 잡아내지 않으면 잘못을 알려주지 않습니다. 그래서 AI가 생성한 모든 스니펫을 주니어 개발자가 만든 것처럼 다룹니다. 코드를 읽고, 실행하고, 필요에 따라 테스트합니다. 정말로, AI가 쓴 것은 반드시 테스트해야 합니다. 유닛 테스트를 돌리거나 수동으로 기능을 확인해, 주장하는 대로 동작하는지 검증하세요. 더 자세한 내용은 vibe coding is not an excuse for low-quality work에서 읽을 수 있습니다.
사실 저는 테스트를 워크플로 자체에 엮어 넣습니다. 앞서 계획 단계에서 각 단계에 대한 테스트 목록이나 테스트 플랜을 생성하곤 합니다. Claude Code 같은 도구를 쓰면, 작업 구현 후 테스트 스위트를 실행하고 실패가 있으면 디버깅하라고 지시합니다. 이런 촘촘한 피드백 루프(코드 작성 → 테스트 실행 → 수정)는 테스트가 존재하는 한 AI가 특히 잘하는 영역입니다. 코딩 에이전트로 가장 큰 효과를 보는 사람들이 강한 테스트 문화를 가진 사람들인 이유입니다. 좋은 테스트 스위트가 안전망이 되어주면 Claude 같은 에이전트는 프로젝트를 “비행”하듯 빠르게 진행할 수 있습니다. 테스트가 없으면 에이전트는 현실에서는 여러 곳을 깨뜨렸는데도 “네, 다 좋아요!”라고 태연히 말할 수도 있습니다. 따라서 테스트에 투자하세요. AI의 유용성을 증폭하고 결과에 대한 신뢰를 높여줍니다.
자동 테스트를 넘어 코드 리뷰(수동 + AI 보조)를 하세요. 저는 생성된 코드를 자주 멈춰서 라인 바이 라인으로 확인합니다. 때로는 두 번째 AI 세션(혹은 다른 모델)을 띄워 첫 번째가 만든 코드를 비평/리뷰하게 합니다. 예를 들어 Claude에게 코드를 쓰게 한 다음 Gemini에게 “이 함수에 오류나 개선점이 있는지 리뷰해 줄래?”라고 묻습니다. 미묘한 문제를 잡는 데 도움이 됩니다. 핵심은 AI가 썼다고 해서 리뷰를 생략하지 않는 것입니다. 오히려 AI 작성 코드는 추가적인 엄격함이 필요합니다. 표면적으로 그럴듯하지만 숨은 결함이 있을 수 있습니다.
또한 저는 마지막 팀과 함께 만든 Chrome DevTools MCP를 디버깅 및 품질 루프에 사용해, 정적 코드 분석과 실제 브라우저 실행 사이의 간극을 메웁니다. 이는 에이전트에게 “눈”을 달아줍니다. AI 도구에 브라우저가 보는 것을 직접 보게 하고, DOM을 검사하거나, 풍부한 성능 트레이스/콘솔 로그/네트워크 트레이스를 얻도록 접근을 허용할 수 있습니다. 이 통합은 수동 컨텍스트 전환의 마찰을 제거하여, LLM을 통한 자동화된 UI 테스트를 가능하게 합니다. 실제 런타임 데이터에 기반해 버그를 높은 정밀도로 진단하고 수정할 수 있게 됩니다.
사람의 감독을 생략했을 때의 심각한 결과도 기록되어 있습니다. 급한 프로젝트에서 AI 생성에 크게 의존한 한 개발자는 결과를 일관성 없는 난장판(중복 로직, 맞지 않는 메서드 이름, 일관된 아키텍처 부재)으로 묘사했습니다. 그는 AI가 엮어 만든 것을 제대로 보지 않고 “만들고, 만들고, 또 만들고” 있었다는 걸 깨달았습니다. 해결은 고통스러운 리팩터링과, 다시는 그렇게 되도록 두지 않겠다는 다짐이었습니다. 저도 이 교훈을 마음에 새겼습니다. AI를 얼마나 쓰든, 책임지는 엔지니어는 결국 나입니다.
실무적으로는, 제가 이해한 코드만 머지/출시합니다. AI가 복잡하게 꼬아 놓은 코드를 만들면 코멘트를 달아 설명하게 하거나, 더 단순한 형태로 제가 다시 씁니다. 뭔가 이상하다고 느껴지면 파고듭니다. 사람 동료가 이상한 코드 기여를 했을 때처럼요.
마인드셋의 문제입니다. LLM은 보조자이지, 자율적으로 신뢰할 수 있는 코더가 아닙니다. 저는 시니어 개발자이고, LLM은 제 속도를 높이기 위해 있는 것이지 제 판단을 대체하기 위해 있는 것이 아닙니다. 이런 자세는 더 나은 코드로 이어질 뿐 아니라 개발자로서의 성장도 지켜줍니다. (AI에 너무 의존하면 실력이 무뎌질 수 있다는 우려도 들었지만, 루프 안에 머물며 적극적으로 리뷰하고 이해한다면, 더 높은 속도로 직관을 단련하는 것이라 생각합니다.) 요컨대: 항상 경계하고, 자주 테스트하며, 늘 리뷰하세요. 결국 코드베이스는 여전히 당신의 것입니다.
잦은 커밋은 저장 지점입니다. AI의 실수를 되돌리고 변경을 이해하게 해줍니다.
AI가 많은 코드를 빠르게 생성할 수 있으면, 쉽게 엇나갈 수 있습니다. 저는 이를 매우 세분화된 버전 관리 습관으로 완화합니다. 평소 수코딩보다도 더 자주 커밋합니다. 작은 작업을 끝내거나 자동 편집이 성공적으로 마무리될 때마다, 명확한 메시지로 git 커밋을 남깁니다. 이렇게 하면 AI의 다음 제안이 버그나 지저분한 변경을 도입하더라도, 최근 체크포인트로 되돌리거나(또는 cherry-pick) 수 시간의 작업을 잃지 않습니다. 누군가는 커밋을 게임의 **“세이브 포인트”**에 비유했습니다. LLM 세션이 옆길로 새면 마지막 안정 커밋으로 롤백할 수 있다는 것이죠. 저도 이 조언이 매우 유용했습니다. 필요하면 git reset으로 되돌릴 수 있다는 확신이 있으면, 대담한 AI 리팩터링을 실험하는 스트레스가 훨씬 줄어듭니다.
버전 관리는 AI와 협업할 때도 도움이 됩니다. AI가 했던 일을 전부 기억하리라 기대할 수 없기 때문에(컨텍스트 윈도우 제한 등), git 히스토리는 유용한 로그가 됩니다. 저는 최근 커밋을 훑어 AI(혹은 저 자신)에게 무엇이 바뀌었는지 브리핑하곤 합니다. 실제로 LLM은 커밋 히스토리를 제공하면 활용할 수 있습니다. 저는 git diff나 커밋 로그를 프롬프트에 붙여, 무엇이 새 코드인지 이전 상태가 무엇이었는지 알려줍니다. 재미있게도 LLM은 diff를 해석하고 git bisect 같은 도구로 버그 도입 지점을 찾는 데 정말 능숙합니다. 커밋 히스토리를 따라가며 디버깅하는 데 무한한 인내심이 있으니까요. 다만 이것도 처음부터 히스토리가 깔끔해야 가능합니다.
또 다른 이점은, 좋은 메시지의 작은 커밋들이 개발 과정을 문서화해 코드 리뷰(AI든 사람이든)를 돕는다는 것입니다. AI 에이전트가 한 번에 다섯 가지를 바꿨고 뭔가 깨졌다면, 변경이 각각 다른 커밋에 있을 때 어떤 커밋이 문제를 일으켰는지 찾기 쉽습니다. 모든 것이 “AI changes”라는 거대한 커밋 하나로 뭉쳐 있으면… 행운을 빕니다. 그래서 저는 규율을 둡니다: 작업 끝내기, 테스트 실행, 커밋. 이는 앞서 말한 작은 청크 작업과도 잘 맞습니다. 각 청크가 하나의 커밋 또는 PR이 되니까요.
마지막으로, AI 실험을 격리하기 위해 브랜치나 worktree를 쓰는 것을 두려워하지 마세요. 제가 채택한 고급 워크플로 중 하나( Jesse Vincent 같은 사람들에게서 영감)는 새 기능/서브프로젝트마다 새로운 git worktree를 띄우는 것입니다. 그러면 같은 저장소에서 여러 AI 코딩 세션을 병렬로 돌려도 서로 간섭하지 않고, 나중에 변경을 합칠 수 있습니다. 각 AI 작업을 샌드박스 브랜치에 두는 것과 비슷합니다. 한 실험이 실패하면 해당 worktree를 버리면 되고, main에는 아무 영향이 없습니다. 성공하면 머지하면 됩니다. 예컨대 AI에게 기능 A를 구현시키는 동안, 저(또는 다른 AI)가 기능 B를 동시에 작업하는 상황에서 이 접근이 특히 중요했습니다. 이런 조율은 버전 관리가 있기 때문에 가능합니다. 요컨대: 자주 커밋하고, 브랜치로 작업을 조직하고, git을 받아들여 AI 생성 변경을 관리 가능하고 되돌릴 수 있게 하세요.
스타일 가이드, 예시, “룰 파일”까지 제공해 AI 어시스턴트를 조향하세요. 약간의 사전 튜닝이 훨씬 더 나은 결과로 이어집니다.
제가 배운 것 중 하나는 AI의 기본 스타일이나 접근을 그대로 받아들일 필요가 없다는 점입니다. 가이드라인을 주면 상당히 강하게 영향을 줄 수 있습니다. 예를 들어 저는 Claude(Anthropic 모델)를 위한 프로세스 규칙과 선호도를 담은 CLAUDE.md 파일을 주기적으로 업데이트합니다(마찬가지로 Gemini CLI를 쓸 때는 GEMINI.md). 여기에는 “프로젝트 스타일로 작성, 린트 규칙 준수, 특정 함수 사용 금지, OOP보다 함수형 선호” 같은 내용이 들어갑니다. 세션 시작 시 이 파일을 Claude에 제공해 컨벤션을 맞춥니다. Jesse Vincent가 언급했듯, 놀라울 정도로 효과가 좋습니다. AI가 대본을 벗어나거나 원치 않는 패턴을 들여오는 경향을 줄여줍니다.
룰 파일이 없어도 커스텀 지시나 시스템 프롬프트로 톤을 설정할 수 있습니다. GitHub Copilot과 Cursor는 프로젝트 전반에 걸쳐 AI 행동을 전역 설정하는 기능을 도입했습니다. 저는 이를 활용해 “4칸 들여쓰기, React에서 화살표 함수 지양, 의미 있는 변수명, ESLint 통과” 같은 짧은 스타일 설명을 넣어둡니다. 그러면 AI의 제안이 사람이 작성한 것과 훨씬 비슷해집니다. Ben Congdon은 Copilot 커스텀 지시를 쓰는 사람이 적다는 것에 충격을 받았다고 말했는데, 예시와 선호를 사전에 제공하면 팀의 관용구에 맞춘 코드를 뽑아낼 수 있었다고 합니다. 저도 동의합니다. AI에게 기대치를 “가르치는” 데 시간을 쓰세요.
또 다른 강력한 기법은 원하는 출력 형식/접근의 인라인 예시를 제공하는 것입니다. 특정 방식으로 함수를 작성하게 하고 싶다면, 코드베이스에 이미 있는 비슷한 함수를 보여주며 “X는 이렇게 구현했으니 Y도 비슷한 접근으로 해줘”라고 말합니다. 특정 코멘트 스타일을 원하면 제가 코멘트를 하나 직접 써 두고 이어서 같은 스타일로 작성해 달라고 합니다. 즉 모델에 패턴을 _프라이밍_하는 것입니다. LLM은 모방에 강합니다. 예시 한두 개만 보여줘도 그 톤과 형태를 이어갑니다.
커뮤니티는 LLM 행동을 길들이는 창의적 “룰셋”도 만들어냈습니다. “Big Daddy” 규칙이나 프롬프트에 “환각/기만 금지” 조항을 넣는 방식이 대표적입니다. 이는 모델에게 정직하게 말하고, 존재하지 않는 코드를 과하게 지어내지 말라고 상기시키는 트릭입니다. 예를 들어 저는 가끔 프롬프트 앞에 이렇게 붙입니다: “무언가 확신이 없거나 코드베이스 컨텍스트가 부족하면, 지어내지 말고 명확화를 위해 질문해라.” 이는 환각을 줄여줍니다. 또 다른 규칙으로 “버그를 고칠 때 간단한 이유를 코멘트로 설명하라”를 씁니다. 그러면 AI가 “// 수정: 스펙에 따라 Z를 방지하기 위해 X를 Y로 변경” 같은 코멘트를 남겨, 이후 리뷰에 매우 유용합니다.
요약하면, AI를 블랙박스로 대하지 말고 튜닝하세요. 시스템 지시를 설정하고, 프로젝트 문서를 공유하고, 명시적 규칙을 적어두면 AI를 팀의 더 전문화된 개발자로 바꿀 수 있습니다. 신입을 온보딩할 때 스타일 가이드와 팁을 주듯, AI 페어 프로그래머에게도 같은 일을 하세요. 투자 대비 효과가 큽니다. 손질이 덜 필요하고 코드베이스에 더 매끄럽게 통합되는 출력이 나옵니다.
CI/CD, 린터, 코드 리뷰 봇을 활용하세요. AI는 자동으로 실수를 잡아주는 환경에서 가장 잘 일합니다.
이는 “루프에 머물기”와 “컨텍스트 제공”의 연장선입니다. 잘 작동하는 개발 파이프라인은 AI 생산성을 높입니다. 저는 AI 코딩을 많이 하는 저장소라면 반드시 탄탄한 **지속적 통합(CI)**을 갖추게 합니다. 즉 모든 커밋/PR에서 자동 테스트가 돌고, ESLint/Prettier 같은 코드 스타일 검사도 강제되며, 가능하면 새 브랜치마다 스테이징 배포가 가능해야 합니다. 이유는 AI가 이를 트리거하고 결과를 평가하게 할 수 있기 때문입니다. 예컨대 Jules나 GitHub Copilot Agent로 AI가 PR을 열면, CI가 테스트를 돌려 실패를 보고합니다. 저는 그 실패 로그를 AI에 다시 넣습니다: “통합 테스트가 XYZ로 실패했어. 디버깅하자.” 그러면 버그 수정이 빠른 피드백을 가진 협업 루프로 바뀌고, AI는 이런 루프를 꽤 잘 처리합니다(수정 제안 → CI 재실행 → 반복).
자동 코드 품질 체크(린터, 타입 체커)도 AI를 이끕니다. 저는 때로 린터 출력 자체를 프롬프트에 포함합니다. AI가 린트를 통과하지 못하는 코드를 쓰면, 린트 에러를 채팅에 복사해 “이 문제들을 해결해줘”라고 말합니다. 그러면 모델은 정확히 무엇을 해야 하는지 압니다. 마치 엄격한 선생님이 AI 어깨너머로 보는 것과 같습니다. 제 경험상 AI는 도구 출력(실패한 테스트, 린트 경고 등)을 알게 되면, 이를 고치려고 매우 열심히 합니다. 결국 “정답”을 내고 싶어 하니까요. 이는 컨텍스트 제공과도 연결됩니다. 환경에서의 행동 결과(테스트 실패 등)를 AI에 주면, 그로부터 학습하고 조정합니다.
AI 코딩 에이전트 자체도 자동화 훅을 점점 더 많이 통합하고 있습니다. 어떤 에이전트는 모든 테스트가 통과하기 전에는 작업이 “완료”되었다고 말하지 않기도 합니다. 이게 바로 원하는 근면함입니다. 코드 리뷰 봇(AI든 아니든)은 또 하나의 필터 역할을 합니다. 저는 그 피드백을 추가 개선을 위한 프롬프트로 취급합니다. 예컨대 CodeRabbit 같은 리뷰어가 “이 함수는 X를 하고 있는데 이상적이지 않다”고 코멘트하면, AI에게 “이 피드백을 반영해 리팩터링해 줄래?”라고 요청합니다.
AI와 자동화를 결합하면 선순환이 생깁니다. AI가 코드를 쓰고, 자동 도구가 이슈를 잡고, AI가 고치고… 그 사이에서 당신은 상위 방향을 감독합니다. 마치 매우 빠른 주니어 개발자와, 즉시 검사하는 지치지 않는 QA 엔지니어를 동시에 가진 느낌이죠. 다만 기억하세요. 그런 환경을 구축하는 건 _당신_입니다. 테스트나 자동 체크가 없는 프로젝트에서는 AI의 작업이 미묘한 버그나 품질 문제를 품은 채 훨씬 나중에 드러날 수 있습니다.
그래서 2026년을 향하며 제 목표 중 하나는 AI 코드 기여 주변의 품질 게이트를 강화하는 것입니다. 더 많은 테스트, 더 많은 모니터링, 어쩌면 AI-on-AI 코드 리뷰까지도요. (AIs가 AIs를 리뷰한다는 게 역설적으로 들릴 수 있지만, 한 모델이 놓친 것을 잡는 걸 본 적이 있습니다.) 결론은 이것입니다: AI 친화적 워크플로는 강한 자동화를 갖춘 워크플로입니다. 그 도구들로 AI를 ‘정직하게’ 만드세요.
매 AI 코딩 세션을 학습 기회로 대하세요. 당신이 아는 만큼 AI가 더 도와주며, 선순환이 만들어집니다.
LLM을 개발에 쓰면서 가장 흥미로운 점 중 하나는 그 과정에서 제가 얼마나 많이 배웠는지입니다. AIs는 제게 뭔가를 알아야 할 필요를 없애기보다, 오히려 제가 혼자라면 시도하지 않았을 언어, 프레임워크, 기법을 접하게 해 주었습니다.
일반적으로도 같은 패턴이 성립합니다. 탄탄한 소프트웨어 엔지니어링 기본기가 있으면 AI는 생산성을 몇 배로 증폭시킵니다. 하지만 그 기반이 없으면 AI가 혼란을 증폭시킬 수도 있습니다. 숙련된 개발자들은 LLM이 “기존의 모범 사례에 보상한다”고 관찰합니다. 명확한 스펙 작성, 좋은 테스트, 코드 리뷰 같은 것들이 AI가 끼어들 때 더 강력해집니다. 제 경험에서도 AI는 제가 더 높은 추상화 수준(디자인, 인터페이스, 아키텍처)에 집중하게 하고 보일러플레이트는 쏟아내게 해 주지만, 그 높은 수준의 기술을 제가 가지고 있어야 합니다. Simon Willison이 말하듯, 시스템을 설계하고 복잡성을 관리하며 무엇을 자동화할지 아는 등 시니어 엔지니어를 만드는 거의 모든 요소가 이제 AI에서 최고의 결과를 내는 요소가 되었습니다. 그래서 AI를 쓰며 저는 오히려 엔지니어링 실력을 끌어올리게 되었습니다. “매우 빠르지만 다소 순진한 코더(=AI)”를 관리하는 셈이니, 계획에 더 엄격해지고 아키텍처에 더 의식적이 됩니다.
AI 사용이 능력을 떨어뜨릴까 걱정하는 분들에게는, 제대로 하면 반대라고 말하고 싶습니다. AI 코드를 리뷰하며 새로운 관용구와 해법을 접했고, AI의 실수를 디버깅하며 언어와 도메인 이해가 깊어졌습니다. 저는 종종 AI에게 코드나 수정의 근거를 설명해 달라고 요청합니다. 마치 후보자에게 계속 코드 리뷰 인터뷰를 하는 느낌이죠. 그 답변에서 통찰을 얻습니다. 또한 AI를 리서치 어시스턴트로도 씁니다. 라이브러리나 접근이 불확실할 때, 옵션을 나열하거나 트레이드오프를 비교하게 합니다. 언제든 호출할 수 있는 백과사전형 멘토 같습니다. 이런 것들이 저를 더 지식 있는 프로그래머로 만들었습니다.
큰 그림은 AI 도구가 당신의 전문성을 증폭시킨다는 것입니다. 2026년을 앞두고 저는 AI가 “내 일을 빼앗을까” 두렵기보다, 잡일을 덜어주고 창의적이고 복잡한 영역에 더 시간을 쓰게 해 준다는 점이 기대됩니다. 하지만 기본기가 부족한 사람에게는 AI가 ‘과잉 자신감’을 키워, 겉보기엔 그럴듯하다가 나중에 무너지는 결과로 이어질 수도 있다는 점도 알고 있습니다. 그래서 제 조언은: 계속 기술을 연마하고, AI로 그 과정을 가속하라는 것입니다. 원초적 실력을 유지하려면 가끔은 AI 없이 코딩하는 것도 의도적으로 하세요. 결국 개발자 + AI 듀오는 둘 중 하나만 있을 때보다 훨씬 강력하며, 그 듀오의 개발자 쪽이 자기 역할을 해내야 합니다.
저는 개발 워크플로에 AI를 완전히 받아들였습니다. 하지만 신중하고, 숙련된 개발자가 주도하는 방식으로요. 제 접근은 AI-자동화 소프트웨어 엔지니어링이 아니라, 본질적으로 **“AI-증강 소프트웨어 엔지니어링(AI-augmented software engineering)”**입니다.
제가 배운 것은 이것입니다: AI와 협업할 때 최고의 결과는, 고전적인 소프트웨어 엔지니어링 규율을 적용할 때 나온다. 설계 후 코딩, 테스트 작성, 버전 관리, 표준 유지 같은 우리가 어렵게 쌓아온 관행은 여전히 유효할 뿐 아니라, AI가 코드의 절반을 쓰는 상황에서는 더 중요해집니다.
앞으로가 기대됩니다. 도구는 계속 좋아지고, 제 워크플로도 분명 함께 진화할 것입니다. 완전 자율적인 “AI 개발 인턴”이 더 많은 단순 노동을 맡고, 우리는 더 높은 수준의 작업에 집중하게 될지도 모릅니다. 새로운 디버깅 및 코드 탐색 패러다임이 등장할 수도 있겠죠. 무엇이 오든, 저는 계속 루프 안에 있을 계획입니다. AI를 이끌고, 그들에게 배우고, 책임감 있게 생산성을 증폭시키면서요.
제 결론은 이렇습니다: AI 코딩 어시스턴트는 놀라운 힘의 배수이지만, 쇼의 연출가는 여전히 인간 엔지니어입니다.
새로운 AI 보조 엔지니어링 책을 O’Reilly와 함께 출간했다는 소식을 전하게 되어 기쁩니다. 관심이 있다면 책 사이트에 무료 팁도 여러 개 있습니다.
Addy Osmani는 Google에서 Google Cloud와 Gemini를 담당하는 소프트웨어 엔지니어입니다.트윗BlueskyMastodonThreadsLinkedIn공유
더 보고 싶나요? 무료 뉴스레터를 구독하세요: