현재 나의 LLM 코드 생성 워크플로우
원문: https://harper.blog/2025/02/16/my-llm-codegen-workflow-atm/ (translated by Google Gemini)
요약: 스펙을 브레인스토밍하고, 계획을 계획한 다음, LLM 코드 생성을 사용하여 실행합니다. 개별적인 루프. 그리고 마법
저는 LLM을 사용하여 아주 많은 소규모 제품을 만들어 왔습니다. 재미있고 유용했지만, 엄청난 시간을 낭비할 수 있는 함정들이 있습니다.
얼마 전 한 친구가 제가 LLM을 어떻게 사용하여 소프트웨어를 작성하는지 물었습니다. 저는 “이런. 시간이 얼마나 있으신데요!“라고 생각했고, 그래서 이 글을 쓰게 되었습니다.
(추신: AI를 싫어하는 분이라면 맨 끝으로 스크롤하세요)
저는 많은 개발자 친구들과 이 주제에 대해 이야기하는데, 우리 모두는 어느 방향으로든 약간의 변형을 가미한 비슷한 접근 방식을 가지고 있습니다. 여기 저의 워크플로우가 있습니다. 이것은 저 자신의 작업, 친구들과의 대화(Nikete, Kanno, Obra, Kris, Erik 고마워요), 그리고 여러 끔찍한 인터넷 나쁜 곳들에서 공유된 많은 모범 사례들을 바탕으로 만들어졌습니다.
이것은 지금 잘 작동하고 있으며, 아마 2주 후에는 작동하지 않거나, 혹은 두 배 더 잘 작동할 것입니다. ¯\_(ツ)_/¯
Let’s Go#
개발을 하는 데는 여러 경로가 있지만, 제 경우는 보통 다음 두 가지 중 하나입니다.
- 완전히 새로운 코드(Greenfield code)
- 기존의 현대적인 코드(Legacy modern code)
두 경로에 대한 제 프로세스를 보여드리겠습니다.
그린필드(Greenfield)#
저는 다음 프로세스가 완전히 새로운 개발(greenfield development)에 잘 맞는다는 것을 발견했습니다. 이것은 견고한 계획 및 문서화 접근법을 제공하며, 작은 단계로 쉽게 실행할 수 있게 해줍니다.
그린 필드 기술적으로, 오른쪽에 그린 필드(초원)가 있습니다. Leica Q, 2016년 5월 14일
1단계: 아이디어 구체화#
대화형 LLM을 사용하여 아이디어를 구체화합니다(저는 이를 위해 ChatGPT 4o / o3를 사용합니다):
이 아이디어에 대한 철저하고 단계적인 사양을 개발할 수 있도록 한 번에 하나씩 질문해 주세요. 각 질문은 제 이전 답변을 바탕으로 해야 하며, 우리의 최종 목표는 개발자에게 전달할 수 있는 상세한 사양을 갖는 것입니다. 이것을 반복적으로 수행하고 모든 관련 세부 사항을 파고들어 봅시다.
기억하세요, 한 번에 하나의 질문만. 아이디어는 다음과 같습니다: <아이디어>
브레인스토밍이 끝나면 (자연스러운 결론에 도달할 것입니다):
이제 브레인스토밍 과정을 마쳤으니, 우리의 결과물을 개발자가 바로 사용할 수 있는 포괄적인 사양으로 정리해 주시겠어요? 개발자가 즉시 구현을 시작할 수 있도록 모든 관련 요구사항, 아키텍처 선택, 데이터 처리 세부 정보, 오류 처리 전략 및 테스트 계획을 포함해 주세요.
이것은 계획 단계로 넘길 수 있는 꽤 견고하고 직설적인 사양을 출력합니다. 저는 이것을 저장소에 spec.md
로 저장하는 것을 좋아합니다. 이 사양은 여러 가지 용도로 사용할 수 있습니다.
여기서는 코드 생성을 하고 있지만, 저는 이 사양을 추론 모델에 아이디어의 허점을 찌르도록 요청하여 아이디어를 강화하거나(더 깊이 파고들어야 합니다!), 백서를 생성하거나, 비즈니스 모델을 생성하는 데 사용했습니다. 심층 연구에 투입하면 1만 단어 분량의 지원 문서를 받을 수도 있습니다.
2단계: 계획#
사양을 가져와 적절한 추론 모델(o1*, o3*, r1*)에 전달합니다:
(이것은 TDD 프롬프트입니다)
이 프로젝트를 구축하기 위한 상세하고 단계적인 청사진을 작성하세요.
그런 다음, 견고한 계획이 수립되면, 서로를 기반으로 하는 작고 반복적인 덩어리로 나누세요. 이 덩어리들을 살펴본 후 다시 한번 작은 단계로 나누세요. 결과를 검토하고 단계들이 강력한 테스트와 함께 안전하게 구현될 수 있을 만큼 충분히 작지만, 프로젝트를 진전시킬 만큼 충분히 큰지 확인하세요.
이 프로젝트에 맞는 크기라고 느낄 때까지 반복하세요.
여기서부터 각 단계를 테스트 주도 방식으로 구현할 코드 생성 LLM을 위한 일련의 프롬프트를 제공할 기초를 갖게 됩니다. 모범 사례, 점진적인 진행, 조기 테스트를 우선시하여 어떤 단계에서도 복잡성이 크게 증가하지 않도록 하세요.
각 프롬프트가 이전 프롬프트를 기반으로 하고, 마지막에는 모든 것을 연결하도록 하세요. 이전 단계에 통합되지 않은 채로 남거나 고립된 코드가 없어야 합니다.
각 프롬프트 섹션을 반드시 분리하세요. 마크다운을 사용하세요. 각 프롬프트는 코드 태그를 사용하여 텍스트로 태그되어야 합니다. 목표는 프롬프트를 출력하는 것이지만, 컨텍스트 등도 중요합니다.
<사양>
(이것은 비 TDD 프롬프트입니다)
이 프로젝트를 구축하기 위한 상세하고 단계적인 청사진을 작성하세요. 그런 다음, 견고한 계획이 수립되면, 서로를 기반으로 하는 작고 반복적인 덩어리로 나누세요. 이 덩어리들을 살펴본 후 다시 한번 작은 단계로 나누세요.
결과를 검토하고 단계들이 안전하게 구현될 수 있을 만큼 충분히 작지만, 프로젝트를 진전시킬 만큼 충분히 큰지 확인하세요. 이 프로젝트에 맞는 크기라고 느낄 때까지 반복하세요.
여기서부터 각 단계를 구현할 코드 생성 LLM을 위한 일련의 프롬프트를 제공할 기초를 갖게 됩니다. 모범 사례와 점진적인 진행을 우선시하여 어떤 단계에서도 복잡성이 크게 증가하지 않도록 하세요.
각 프롬프트가 이전 프롬프트를 기반으로 하고, 마지막에는 모든 것을 연결하도록 하세요. 이전 단계에 통합되지 않은 채로 남거나 고립된 코드가 없어야 합니다.
각 프롬프트 섹션을 반드시 분리하세요. 마크다운을 사용하세요. 각 프롬프트는 코드 태그를 사용하여 텍스트로 태그되어야 합니다. 목표는 프롬프트를 출력하는 것이지만, 컨텍스트 등도 중요합니다.
<사양>
이것은 aider, cursor 등에서 실행할 수 있는 프롬프트 계획을 출력해야 합니다. 저는 이것을 저장소에 prompt_plan.md
로 저장하는 것을 좋아합니다. 그런 다음 체크할 수 있는 todo.md
를 출력하게 합니다.
제가 체크리스트로 사용할 수 있는
todo.md
를 만들어 주시겠어요? 철저하게요.
이것을 저장소에 todo.md
로 저장할 수 있습니다. 당신의 코드 생성 도구는 처리하는 동안 todo.md
를 체크할 수 있어야 합니다. 이것은 세션 간에 상태를 유지하는 데 좋습니다. 야호.
계획!
이제 프로젝트를 실행하고 구축하는 데 도움이 될 견고한 계획과 문서를 갖게 되었습니다. 이 전체 과정은 아마 15분 정도 걸릴 것입니다. 꽤 빠릅니다. 솔직히 놀랍죠.
3단계: 실행#
실행에는 아주 많은 옵션이 있습니다. 성공은 실제로 2단계가 얼마나 잘 되었는지에 달려 있습니다. 저는 이 워크플로우를 github workspace, aider, cursor, claude engineer, sweep.dev, chatgpt, claude.ai 등과 함께 사용해 보았습니다. 제가 시도한 모든 도구와 꽤 잘 작동하며, 어떤 코드 생성 도구와도 잘 작동할 것이라고 생각합니다. 하지만 저는 순수한 claude와 aider를 선호합니다:
Claude
저는 본질적으로 claude.ai와 페어 프로그래밍을 하며 각 프롬프트를 반복적으로 입력합니다. 저는 그것이 꽤 잘 작동한다는 것을 발견했습니다. 왔다 갔다 하는 것이 성가실 수 있지만, 대체로 작동합니다. 저는 초기 상용구 코드(boilerplate code)를 담당하고, 도구 설정이 올바르게 되었는지 확인합니다. 이것은 처음에 어느 정도의 자유, 선택, 그리고 지침을 허용합니다. Claude는 그냥 리액트 코드를 출력하는 경향이 있는데, 당신이 선택한 언어, 스타일, 도구로 견고한 기초를 가지고 있으면 꽤 도움이 될 것입니다. 그러다 막히면 repomix와 같은 도구를 사용하여 반복 작업을 합니다(자세한 내용은 나중에).
워크플로우는 다음과 같습니다:
- 저장소 설정 (상용구 코드, uv init, cargo init 등)
- claude에 프롬프트 붙여넣기
- claude.ai에서 IDE로 코드 복사 및 붙여넣기
- 코드 실행, 테스트 실행 등
- … 작동하면 다음 프롬프트로 이동
- 작동하지 않으면, repomix를 사용하여 코드베이스를 claude에 전달하여 디버깅
- 반복
✩₊˚.⋆☾⋆⁺₊✧
Aider
Aider는 사용하기에 재미있고 이상합니다. 저는 그것이 2단계의 출력물과 잘 맞는다는 것을 발견했습니다. 아주 적은 노력으로 정말 멀리 갈 수 있습니다. 워크플로우는 본질적으로 위와 동일하지만 claude에 붙여넣는 대신 aider에 프롬프트를 붙여넣습니다. 그러면 Aider가 “그냥 해버리고” 저는 쿠키 클리커를 하게 됩니다.
여담: Aider는 LLM 리더보드에서 코드 생성을 위한 새로운 모델에 대한 벤치마킹을 정말 잘합니다. 저는 새로운 모델이 얼마나 효과적인지 보는 데 정말 좋은 자료라고 생각합니다.
Aider를 사용하면 테스트가 좋은데, Aider가 테스트 스위트를 실행하고 당신을 위해 디버깅을 해주기 때문에 훨씬 더 손을 뗄 수 있습니다.
워크플로우는 다음과 같습니다:
- 저장소 설정 (상용구 코드, uv init, cargo init 등)
- aider 시작
- aider에 프롬프트 붙여넣기
- aider가 춤추는 것을 지켜보기 ♪┏(・o・)┛♪
- aider가 테스트를 실행하거나, 앱을 실행하여 확인
- 작동하면 다음 프롬프트로 이동
- 작동하지 않으면, aider와 Q&A를 통해 수정
- 반복
✩₊˚.⋆☾⋆⁺₊✧
결과
저는 이 워크플로우를 사용하여 스크립트, expo 앱, rust cli 도구 등 정말 많은 것을 만들었습니다. 프로그래밍 언어와 컨텍스트를 가리지 않고 작동했습니다. 저는 이것을 좋아합니다.
만약 미루고 있는 작거나 큰 프로젝트가 있다면, 한번 시도해 보시길 권합니다. 짧은 시간에 얼마나 멀리 갈 수 있는지 놀라게 될 것입니다. 제 할 일 목록은 모든 것을 다 만들었기 때문에 비어 있습니다. 영화를 보거나 하면서 계속 새로운 것을 생각하고 해치우고 있습니다. 몇 년 만에 처음으로 새로운 프로그래밍 언어와 도구에 시간을 보내고 있습니다. 이것은 저의 프로그래밍 관점을 확장하도록 밀어붙이고 있습니다.
그린필드가 아닌 경우: 반복, 점진적으로#
때로는 그린필드가 아니라 기존 코드 베이스에서 반복하거나 점진적인 작업을 해야 할 때도 있습니다.
이를 위해 저는 약간 다른 방법을 사용합니다. 위와 비슷하지만 “계획 기반"이 조금 덜합니다. 계획은 전체 프로젝트가 아닌 작업 단위로 이루어집니다.
컨텍스트 얻기#
AI 개발에 깊이 빠져 있는 모든 사람이 이를 위한 다른 도구를 가지고 있다고 생각하지만, 소스 코드를 가져와 LLM에 효율적으로 집어넣을 무언가가 필요합니다.
저는 현재 repomix라는 도구를 사용합니다. 제 전역 ~/.config/mise/config.toml
에 정의된 작업 모음이 있어서 코드 베이스로 다양한 작업을 할 수 있습니다(mise 규칙). LLM 작업 목록은 다음과 같습니다:
LLM:clean_bundles repomix를 사용하여 LLM 번들 출력 파일 생성
LLM:copy_buffer_bundle 생성된 LLM 번들을 output.txt에서 시스템 클립보드로 복사하여 외부에서 사용
LLM:generate_code_review output.txt에 저장된 저장소 콘텐츠에서 LLM 생성을 사용하여 코드 리뷰 출력 생성
LLM:generate_github_issues output.txt에 저장된 저장소 콘텐츠에서 LLM 생성을 사용하여 GitHub 이슈 생성
LLM:generate_issue_prompts output.txt에 저장된 저장소 콘텐츠에서 LLM 생성을 사용하여 이슈 프롬프트 생성
LLM:generate_missing_tests output.txt에 저장된 저장소 콘텐츠의 코드에 대해 누락된 테스트 생성
LLM:generate_readme output.txt에 저장된 저장소 콘텐츠에서 README.md 생성
저는 코드 베이스의 컨텍스트를 담은 output.txt
를 생성합니다. 토큰을 너무 많이 사용하고 너무 크면, 생성 명령을 편집하여 이 작업과 관련 없는 코드 베이스 부분을 무시하도록 합니다.
mise의 정말 좋은 점 중 하나는 작업 디렉토리의 .mise.toml
에서 작업을 재정의하고 오버로드할 수 있다는 것입니다. 다른 도구를 사용하여 코드를 덤프/팩하고, output.txt
를 생성하기만 하면 제 LLM 작업을 사용할 수 있습니다. 이것은 다양한 코드베이스가 매우 다를 때 유용합니다. 저는 정기적으로 repomix 단계를 오버라이드하여 더 넓은 무시 패턴을 포함시키거나, 패킹을 위해 더 효과적인 도구를 사용합니다.
output.txt
가 생성되면, 다양한 변환을 수행하기 위해 LLM 명령에 전달한 다음 마크다운 파일로 저장합니다. 궁극적으로, mise 작업은 다음을 실행합니다: cat output.txt | LLM -t readme-gen > README.md
또는 cat output.txt | LLM -m claude-3.5-sonnet -t code-review-gen > code-review.md
. 이것은 그다지 복잡하지 않습니다. LLM
명령이 힘든 작업을 하고 있습니다(다른 모델 지원, 키 저장, 프롬프트 템플릿 사용).
예를 들어, 테스트 커버리지에 대한 빠른 검토 및 수정이 필요한 경우 다음을 수행합니다:
Claude
- 코드가 있는 디렉토리로 이동
mise run LLM:generate_missing_tests
실행- 생성된 마크다운 파일(
missing-tests.md
) 확인 - 코드의 전체 컨텍스트 가져오기:
mise run LLM:copy_buffer_bundle
- 그것을 첫 번째 누락된 테스트 “이슈"와 함께 claude에 붙여넣기
- claude에서 생성된 코드를 내 ide에 복사
- … 테스트 실행
- 반복
✩₊˚.⋆☾⋆⁺₊✧
Aider
- 코드가 있는 디렉토리로 이동
- aider 실행 (aider 작업은 항상 새 브랜치에서 해야 합니다)
mise run LLM:generate_missing_tests
실행- 생성된 마크다운 파일(
missing-tests.md
) 확인 - 첫 번째 누락된 테스트 “이슈"를 aider에 붙여넣기
- aider가 춤추는 것을 지켜보기 ♪┏(・o・)┛♪
- … 테스트 실행
- 반복
✩₊˚.⋆☾⋆⁺₊✧
이것은 코드 베이스를 점진적으로 개선하는 꽤 좋은 방법입니다. 큰 코드 베이스에서 소량의 작업을 하는 데 매우 도움이 되었습니다. 저는 이 방법으로 어떤 크기의 작업이든 할 수 있다는 것을 발견했습니다.
프롬프트 마법#
이러한 빠른 핵(hack)들은 프로젝트를 더 견고하게 만들 수 있는 곳을 파고드는 데 매우 효과적입니다. 매우 빠르고 효과적입니다. 다음은 제가 기존 코드 베이스를 파고드는 데 사용하는 프롬프트 중 일부입니다:
코드 리뷰
당신은 시니어 개발자입니다. 당신의 임무는 이 코드에 대한 철저한 코드 리뷰를 수행하는 것입니다. 마크다운으로 작성하고 출력해야 합니다. 줄 번호와 문맥 정보를 포함하세요. 당신의 코드 리뷰는 다른 팀원에게 전달될 것이므로 철저해야 합니다. 코드 리뷰를 작성하기 전에 깊이 생각하세요. 모든 부분을 검토하고, 환각(hallucinate)을 일으키지 마세요.
GitHub 이슈 생성 (실제 이슈 게시를 자동화해야 합니다!)
당신은 시니어 개발자입니다. 당신의 임무는 이 코드를 검토하고, 코드에서 보이는 주요 문제점들을 작성하는 것입니다. 버그, 디자인 선택 또는 코드 청결도 문제일 수 있습니다. 구체적이어야 하며, 매우 뛰어나야 합니다. 환각을 일으키지 마세요. 조용히 혼자 생각한 다음, 행동하세요 - 이슈를 작성하세요. 이슈는 개발자에게 주어져 실행될 것이므로, github 이슈와 호환되는 형식이어야 합니다.
누락된 테스트
당신은 시니어 개발자입니다. 당신의 임무는 이 코드를 검토하고, 누락된 테스트 케이스와 존재해야 할 코드 테스트 목록을 작성하는 것입니다. 구체적이어야 하며, 매우 뛰어나야 합니다. 환각을 일으키지 마세요. 조용히 혼자 생각한 다음, 행동하세요 - 이슈를 작성하세요. 이슈는 개발자에게 주어져 실행될 것이므로, github 이슈와 호환되는 형식이어야 합니다.
이 프롬프트들은 꽤 낡고 망가졌습니다(말하자면 “부머 프롬프트”). 리팩토링이 필요합니다. 더 좋게 만들 아이디어가 있다면 알려주세요.
스키 타기 ᨒ↟ 𖠰ᨒ↟ 𖠰#
이 과정을 사람들에게 설명할 때 저는 “자신도 모르게 앞서 나갈 수 있기 때문에 무슨 일이 일어나고 있는지 공격적으로 추적해야 합니다"라고 말합니다.
어떤 이유에서인지 저는 LLM에 대해 이야기할 때 “내 스키를 넘어섰다(over my skis)“라는 말을 많이 합니다. 왜 그런지는 모르겠습니다. 저에게는 와 닿습니다. 아마도 아름답고 부드러운 파우더 스키를 타다가 갑자기 “대체 무슨 일이야!“라고 외치며 완전히 길을 잃고 절벽에서 떨어지는 것과 같기 때문일 것입니다.
저는 계획 단계를 사용하는 것(위의 그린필드 프로세스처럼)이 상황을 통제하는 데 도움이 될 수 있다고 생각합니다. 적어도 대조 확인할 수 있는 문서가 있을 것입니다. 저는 또한 테스트가 도움이 된다고 믿습니다 - 특히 와일드 스타일의 aider 코딩을 하고 있다면요. 상황을 좋고 탄탄하게 유지하는 데 도움이 됩니다.
그럼에도 불구하고, 저는 여전히 제 스키를 넘어선 자신을 꽤 자주 발견합니다. 때로는 짧은 휴식이나 산책이 도움이 될 수 있습니다. 이 점에서는 정상적인 문제 해결 과정이지만, 맹렬한 속도로 가속화된 것입니다.
우리는 종종 LLM에게 그리 우습지 않은 코드에 우스꽝스러운 것들을 포함하도록 요청할 것입니다. 예를 들어, 로어(lore) 파일을 만들고 사용자 인터페이스에서 그 로어를 참조하도록 요청했습니다. 이것은 파이썬 cli 도구를 위한 것입니다. 갑자기 로어가 생기고, 글리치 인터페이스 등이 생깁니다. 모두 클라우드 기능, 할 일 목록 등을 관리하기 위한 것입니다. 하늘이 한계입니다.
너무 외로워요 (。•́︿•̀。)#
이러한 워크플로우에 대한 제 주된 불만은 이것이 대체로 혼자 하는 노력이라는 것입니다 - 즉, 인터페이스가 모두 싱글 플레이어 모드입니다. 저는 수년간 혼자 코딩했고, 수년간 페어로 코딩했고, 수년간 팀으로 코딩했습니다. 사람들과 함께하는 것이 항상 더 좋습니다.
이러한 워크플로우는 팀으로 사용하기 쉽지 않습니다. 봇들이 충돌하고, 병합은 끔찍하며, 컨텍스트는 복잡합니다.
저는 누군가가 이 문제를 해결하여 LLM으로 코딩하는 것을 멀티플레이어 게임으로 만들어 주길 정말로 바랍니다. 혼자 하는 해커 경험이 아니라요. 이것을 고치고 놀랍게 만들 기회가 아주 많습니다.
일이나 하세요!
ⴵ 시간 ⴵ#
이 모든 코드 생성은 저 한 사람이 생성할 수 있는 코드의 양을 가속화했습니다. 그러나 이상한 부작용이 있습니다.
LLM이 토큰을 태우는 것을 기다리는 동안 엄청난 양의 “다운타임"이 생기는 자신을 발견합니다.
인쇄 어제 일처럼 기억납니다.
저는 기다리는 시간을 활용하기 위해 몇 가지 습관을 포함하도록 작업 방식을 바꾸었습니다:
- 다른 프로젝트의 “브레인스토밍” 과정을 시작합니다.
- 음반을 듣습니다.
- 쿠키 클리커를 합니다.
- 친구들과 로봇들과 대화합니다.
이렇게 해킹할 수 있다는 것은 멋진 일입니다. 해킹, 해킹, 해킹. 코드에서 이렇게 생산적이었던 다른 때를 생각할 수 없습니다.
헤이터레이드 ╭∩╮( •̀_•́ )╭∩╮#
많은 친구들이 “LLM 엿먹어라. 모든 면에서 끔찍하다"고 말합니다. 저는 이 관점을 개의치 않습니다. 저는 동의하지는 않지만, 회의적인 태도를 갖는 것이 중요하다고 생각합니다.
AI를 싫어할 이유는 아주 많습니다. 제 주된 두려움은 전력 소비와 환경 영향에 관한 것입니다.
하지만… 코드는 흘러야 합니다. 그렇죠… 한숨.
더 배우고 싶지만, 깊이 파고들어 사이보그 프로그래머가 되고 싶지는 않다면 - 제 추천은 당신의 의견을 바꾸지 말고, LLM과 그것들이 어떻게 사용될 수 있는지에 대한 Ethan Mollick의 책을 읽는 것입니다: ‘Co-Intelligence: Living and Working with AI’.
이 책은 기술 무정부-자본주의자 형씨 타입의 책이 되지 않으면서 그 이점들을 잘 설명합니다. 저는 매우 도움이 되었고, 이 책을 읽은 친구들과 많은 좋고 미묘한 대화를 나눴습니다. 강력히 추천합니다.
회의적이지만 약간의 호기심이 있다면 - 저에게 연락해서 이 모든 광기에 대해 이야기해 봅시다. 우리가 LLM을 어떻게 사용하는지 보여드릴 수 있고, 어쩌면 함께 무언가를 만들 수도 있을 것입니다.
이 게시물을 살펴보고 수정을 제안해 준 Derek, Kanno, Obra, Erik에게 감사합니다. 감사드립니다.
이 게시물은 98% 인간에 의해 작성되었습니다.