LLM을 활용하면서도 코드 작성의 즐거움과 주도권을 지키기 위한 실용적인 워크플로를 설명합니다.
AI 번아웃으로 향하고 있나요? 프로그래밍 역량은 부족하고 품질에 대한 열망도 없지만 Claude 계정만 잔뜩 가진 사람에게 일자리를 빼앗길까 두렵나요? 프로젝트의 코드 품질에, 혹은 더 나쁘게는 “자신”의 코드 품질에 실망했나요? 그렇다면 이 글은 당신을 위한 것입니다.
거대 기술 기업이 운영하는 최첨단 LLM에는 중요하고 정당한 윤리적 우려가 있으며, 이는 이미 길게 논의되었습니다. 저는 이를 알고 있고 동의하며, 이 글은 그것에 관한 글이 아닙니다. 저를 LLM 찬성 기술 업계 사람으로 오해하지 마세요.
또한 사람들이 이전에 제 글을 LLM이 생성한 것으로 오해한 적이 있으므로 말씀드리자면, 이 글은 AI의 도움 없이 100% 사람이 작성했습니다.
제가 십 대에 즐겁게 읽었던 Sean Mcmullen의 이 제목을 가진 훌륭한 책이 있습니다. 얼핏 보면 이 책은 우리 상황의 정반대를 묘사합니다. 개별 구성 요소가 인간이며, 함께 계산 장치를 이루는 거대한 컴퓨터 말입니다. 반면 LLM은 실제 컴퓨터 위에서 돌아가면서 (초)인간인 척합니다. 하지만 다시 보면 이야기와 현실은 그리 멀지 않습니다. 소프트웨어를 만드는 과정에서 우리의 역할은 행위자에서 기계의 톱니바퀴로 천천히 격하되고 있습니다. 명세 주도 디스토피아란 어떤 명세를 전달받아 LLM에 밀어 넣고, 기술봉건 영주가 토큰을 덜 주기로 결정했기 때문에 토큰이 바닥날 때 우는 것입니다.
Haskell 프로그래머로서 저는 Haskell을 작성하는 일을 즐깁니다. 물론 저는 직장에서 만드는 제품을 매우 좋아하고, 여러분이 제 오픈 소스 라이브러리로 할 수 있는 일도 좋아합니다. 그러나 저는 이 언어로 제 생각을 표현하는 과정 자체를 정말 즐깁니다. 이것은 여러분 대부분에게도 사실이라고 가정하며, 다른 많은 언어에서는 그렇지 않다고도 가정합니다. 이것이 서로 다른 프로그래밍 언어 애호가들이 LLM 보조 미래가 얼마나 밝거나 어두운지에 대해 서로 다른 의견을 갖는 이유를 어느 정도 설명합니다.
코드를 생성할 때, 그 즐거움의 상당 부분이 위험에 처합니다. 그러니 어쩌면 하지 마세요. 저는 Haskell 프로그램을, 적어도 즐거운 부분은 계속 작성하고 싶으며, 생성된 코드를 너무 많이 읽고 검토하고 싶지는 않습니다. 동시에 저는 그 토큰을 제 뇌를 서서히 태워 버리지 않는 좋은 용도에 쓰고 싶습니다.
LLM으로 겉보기에 훨씬 더 생산적이 되는 대신 모든 즐거움을 잃는 것이 아니라, 프로그래밍을 계속 즐기면서 동시에 적당히 더 생산적이 되는 방법을 보여 드리고 싶습니다.
LLM을 완전히 금하는 것을 원한다면 그것도 훌륭하며, 이미 무엇을 해야 하는지 알고 있을 것입니다. 하지만 그러고 싶지 않은 이유도 있을 수 있습니다. 예를 들어 실제로 생산성 향상을 보여 주어야 하거나, 팀과 회사와 업계의 나머지가 LLM을 대거 도입하는 동안 뒤처지고 싶지 않을 수 있습니다.
코드베이스의 주도권을 계속 가지려면 일부 코드는 계속 작성해야 합니다. 모든 것을 생성에 맡기면, 결국 코딩 에이전트만 번성할 수 있는 LLM 황무지가 될 것입니다. 그러므로 코드를 계속 작성해야 합니다. 그렇지 않으면 언젠가 코드베이스를 잃게 됩니다.
코드를 계속 작성해야 하는 또 다른 이유는 좋은 프로그래머로 남기 위해서입니다. 연습하지 않으면 기술을 잃을 수 있으며, 여기서는 코딩 작업을 포기하고 에이전트에게 넘기는 문턱이 매우 낮기 때문에 위험이 특히 큽니다. 불과 몇 주 동안 코딩하지 않고 모든 일을 에이전트에게 넘기면, 다시 직접 코딩으로 돌아가는 일이 어렵다는 것을 알게 될 것입니다.
LLM은 광고와 달리 좋고 사람이 읽기 쉬운 코드를 만드는 데 훨씬 못합니다. 나중에 자기 자신만 계속 작업할 코드를 만드는 데는 어느 정도 괜찮습니다. 하지만 어딘가에 버그가 반드시 있는 완전히 생성된 파일을 보며, 풍경이 너무 낯설어서 인간인 자신은 버그를 직접 찾을 수 없다고 느끼는 절망을 이미 겪어 보았을 것이라 확신합니다.
그렇다면 에이전트에게 코딩을 맡기지 않고 어떻게 생산성 향상을 얻을까요? 거의 모든 다른 일을 맡기면 됩니다. 특히 여러분에게 성가신 지루한 작업을 맡기세요. 이상적으로는 올바르게 처리하기가 너무 어렵지 않고 검증하기 쉬운 작업이면 좋습니다.
컴퓨터 역사의 초기부터 컴퓨터는 언제나 장부 정리 도구로 사용되었습니다. LLM도 그렇게 사용하세요. 무엇보다도 이는 형식적 인터페이스 대신 자연어로 다룰 수 있는 장부 정리 도구입니다. 도메인 전문가들 사이의 방대한 서면 대화를 실행 가능한 할 일 목록으로 바꾸세요. 무언가를 시험하고, 시험 결과를 적어 두고, 결함을 고칠 계획으로 정리하게 하세요.
할 일 도구 같은 도구를 사용하거나, 더 나아가 프런트매터가 있는 마크다운 파일을 사용하여 계획 항목을 제대로 추적하게 하세요. LLM은 매우 큰 문맥을 가질 수 있지만, 문맥이 너무 가득 차면 정보를 조용히 잃을 수 있습니다.
하지만 중요한 결정을 내리게 하지는 마세요. 여러분에게 묻게 하세요. 질문을 이해하지 못한다면 관련 문맥을 제공하지 못한 LLM의 잘못입니다. 또는 여러분이 지쳐서 휴식이 필요할 수도 있습니다. 같은 문제로 계속 돌아오게 된다면 화면에서 한 걸음 물러나 직접 생각하고, 무엇을 원하는지 분명한 그림이 생겼을 때 다시 돌아오세요.
에이전트에게 조사 작업을 맡기면, 에이전트가 질의하고 “생각하는” 모습을 지켜보거나, 다른 프로젝트에서 또 다른 에이전트를 실행하거나, 커피를 만들러 가고 싶어집니다. 이 세 가지 중에서는 커피를 만드는 것이 가장 좋은 선택입니다. 더 나은 선택은 하나 있습니다. 좋은 옛 검색 엔진을 사용해 병행해서 직접 조사하는 것입니다. 적어도 에이전트가 알게 될 모든 것을 대략적으로는 알아두세요.
어떤 것을 조사하게 한 뒤 그 결과를 사실로 받아들이고 거기서 계획을 세우지 마세요. 그러면 부끄러운 기술 부채로 이어질 것입니다.
에이전트에게 조사를 시키는 목적은 관련 지식을 모두 여러분에게 제시하게 하거나, 여러분보다 더 나은 결정을 내리게 하는 데 있지 않습니다. 목적은 여러분이 에이전트에게 “그것을 검색해 드릴까요”라고 할 필요가 없게 하는 데 있습니다. 모델링하는 도메인을 에이전트만큼 잘, 이상적으로는 그보다 더 잘 이해해야 합니다.
에이전트가 사용한 자료의 링크와 함께 조사 결과를 어딘가에 기록하게 하세요. 나중에 이상한 제안을 들고 오면, 조사 결과가 무엇을 말하는지와 어떤 자료가 그렇게 말하는지 물어보세요. 50%의 확률로 스스로의 실수를 발견할 것입니다. 나머지 50%에서는 그것을 읽으세요. 그러면 이제 여러분 스스로 좋은 결정을 내릴 위치에 있게 됩니다.
이것이 판도를 바꿉니다.
전형적인 코딩 도구는 여러분을 “먼저 계획하고, 그다음 에이전트에게 코딩을 맡기는” 방향으로 유도합니다. 거부하세요. 함께 계획하되, 그다음에는 여러분이 코딩하세요. LLM에게 코드베이스를 조사하게 하고, 현재 할 일을 알려 주며 수정해야 할 모든 위치를 보여 주게 하세요. 잠재적 함정을 언급하게 하고, 관련 배경 조사를 상기시켜 주게 하세요.
저는 이 작업 흐름으로 일하며, 매우 즐겁습니다. 일을 즐기고 있습니다. 때로는 LLM 이전보다도 더 즐겁습니다. 항상 명확한 할 일이 있고, 전체 계획을 걱정할 필요가 없으며, 집중할 수 있습니다. 잘 계획되어 있으므로 할 일을 빠르게 끝냅니다. 성가신 절차가 없는 애자일과 같습니다.
에이전트가 여러분의 작업 방식에 맞춰 움직이게 하세요. 그 반대가 되어서는 안 됩니다. 어쩌면 여러분은 이미 자신에게 가장 잘 맞는 작업 방식을 아는 경험 많은 프로그래머일 것입니다. 에이전트에게 여러분이 덜 즐기는 주변적 작업을 모두 맡기세요.
이 작업 흐름에는 여러 장점이 있습니다.
이상적으로는 정리 작업, 작은 작업, 일상 작업, 저위험 리팩터링에 쓰세요. 코드에 FIXME를 남겨 두었나요? 어쩌면 시간과 에너지를 아끼려고 의도적으로 남겼을 수도 있습니다. 흥미로운 경우 3개를 작성하고 비슷하지만 지루한 나머지 7개는 남겨 두었나요? 모듈 재구성을 생각하고 있고 벤치마크도 하고 싶나요? 유지 관리되지 않는 라이브러리를 더 나은 것으로 교체해야 하나요? 이것들은 타당한 사용 사례입니다. 복잡한 것을 처음부터 설계하는 일은 아마 아닙니다.
가끔 시간이 없지만 무언가를 끝내고 싶고, 계획에 남은 할 일이 명백히 저위험 작업일 수도 있습니다. 감독 에이전트에게 “자리를 비울 테니 이것을 끝내 줘”라고 말해도 괜찮습니다. 운이 좋으면 다음 날 아침 완성된 기능으로 돌아올 수 있습니다. 그러나 코딩 작업의 대부분은 직접 하는 것이 중요합니다.
여기에는 몇 가지 작은 함정이 있습니다.
Traversable 같은 타입 클래스의 인스턴스가 되어야 하는 것일까요? LLM은 이런 점을 알아보지 못하고 대신 방대한 코드를 복사하는 것으로 악명이 높습니다. 인간인 여러분은 더 읽기 쉽고 합리적인 코드를 추구합니다.생성적 적대 신경망의 등장으로 AI 생성 이미지가 갑자기 훨씬 더 현실적으로 변했던 일을 기억할지도 모릅니다. 간단히 말하면, 이미지를 생성하는 한 모델(“생성기”)과 그 성과가 얼마나 좋은지 알려 주는 다른 모델(“판별기”)이 있습니다. 이 둘은 생성기 하나만으로 만들 수 있는 것보다 훨씬 더 좋은 결과를 낼 수 있습니다. 이 아이디어는 일반화된 형태로는 전혀 새로운 것이 아니지만, 이를 LLM 보조 코딩에 적용하면 자동화된 검토 주기를 얻습니다.
자동화된 검토 주기 없이는 LLM이 만든 어떤 산출물도 받아들이지 말고, 읽지도 마세요. 이는 코드에 직접 적용됩니다. 여전히 코드를 생성하게 두는 경우에는 특히 그렇습니다. 하지만 계획에도 특히 적용됩니다. 에이전트가 무언가를 코딩할 때, 넘겨주는 것으로 일이 끝나는 것이 아닙니다. 검토 에이전트가 더 이상 지적할 사항이 없을 때, 즉 사람이 볼 수 있는 상태가 되었을 때 일이 끝납니다. 계획도 마찬가지입니다. 계획의 논리적 구멍을 살피고 찾아내는 일은 매우 피곤합니다. 예컨대 할 일 7에서 작성하기로 한 함수를 할 일 2에서 리팩터링하는 경우 말입니다. 그러니 그런 일을 하는 검토 에이전트를 추가하세요.
제 코드를 검토받는 것이 놀랄 만큼 도움이 된다는 것을 알았습니다. 때로는 사소한 부분만 지적하거나 Haddock을 과도하게 늘리라고 고집할 뿐이지만, 충분히 자주 실제 버그나 누락을 찾아내고 제가 실제 할 일에 집중하도록 해 줍니다. 자신의 작업에도 검토 주기를 추가하기를 권합니다. 하지만 여러분의 코드를 LLM이 검토한 내용을 읽고 싶지 않다면 그것도 충분히 이해합니다. 이를 피하는 한 가지 방법은 사소한 지적 사항이라면 에이전트가 직접 고치라고 하는 것입니다.
최첨단 모델이 할 수 있는 일을 완전히 제대로 활용하지 못하고 있네요.
인터넷의 어느 분위기 코더
그렇습니다. 그것은 제 주장에서 논리적으로 따라오는 결과입니다.
하지만 최첨단 모델 기능에 의존하는 것이 나쁜 생각인 이유는 여러 가지입니다.
결국 여러분은 복잡한 일을 하고 있습니다. 그 일의 일부 측면에서는 LLM이 여러분만큼, 어쩌면 조금 더 잘 수행할 수도 있습니다. 하지만 모든 단점 때문에 그것만으로 LLM에 굴복하기에는 전혀 충분하지 않습니다. LLM이 인간 개발자의 핵심 활동을 대체하려면, 인간 개발자보다 여러 배 뛰어나고, 더 적은 자원을 사용하며, 복잡한 현실 상황에서 더 신뢰할 수 있고, 적어도 그만큼 잘 정렬되어 있으며, 어떤 방식으로든 결과에 책임질 수 있어야 합니다.
토큰을 다 써서 작업이 멈춰 버린 경험이 있을지도 모릅니다. 짜증 나는 일입니다. 이제 작업 흐름은 갑자기 더는 접근할 수 없는 도구를 중심으로 구축되어 있습니다. 극단적인 경우에는 아무 일도 계속할 수 없습니다. 그 상황을 건강하게 받아들이는 방법으로, 이 xkcd에서 “컴파일 중” 대신 “토큰 없음”을 상상해 보세요.
이 일이 몇 번 일어나면 배신당했다는 느낌을 받았을 수 있습니다. 그리고 맞습니다. 배신당한 것입니다. 특정 계획에 대해 특정 세션에서 얼마나 많은 토큰을 가질지는 거대 기술봉건 영주의 변덕에 달린 불투명한 숫자입니다. 공정한 시장에서 구매한 뒤 계획적으로 사용하는 상품과는 다릅니다.
토큰 고갈을 “너무 적게 구매한 것”으로 인식하는 것을 멈추고, 그것이 실제로 무엇인지로 다루어야 합니다. 즉 서비스 장애입니다. 여러분의 LLM 기업은 LLM을 사용할 수 있다는 약속을 팔았지만 그 약속을 지키지 않습니다. 세션의 최대 토큰 수는 여러분이 알거나 영향을 줄 수 없는 사이에 바뀔 수 있으므로, 실제로 계획을 세울 수도 없습니다.
물론 토큰을 아끼는 일은 필수적입니다. 토큰을 절약하기 위해 에이전트 구성, 사용 방식, 문맥 크기, 기술 등을 다시 평가하세요. 하지만 그렇게 하더라도, 더 큰 좌석을 구매했더라도 충분하지 않을 수 있습니다.
또한 토큰을 아껴 쓰기 위해 할 수 있는 모든 일을 했는데도 토큰이 바닥났다면 이를 “자신의 잘못”으로 보지 말고, 대비해야 할 기술적 장애로 보세요. 기차나 비행기에서 많이 일해 본 적이 있다면, 항상 인터넷을 사용할 수 없다는 사실에 대비해야 한다는 것을 압니다. 큰 자산은 미리 내려받아 캐시하세요. 언제나 오프라인으로 할 수 있는 작업을 준비해 두세요.
LLM 보조 작업에서 이는 작업에 필요한 모든 것에 대해 LLM이 구체적인 산출물을 만들게 해야 한다는 뜻입니다. 가장 중요하게는, 앞에서 설명한 인간 코더 작업 흐름에 적응한다면 언제나 작업할 수 있는 계획된 할 일 목록을 가지고 있도록 하세요. 즐겁게 그 목록을 빠르게 처리하고, 에이전트가 돌아오면 정리 작업을 하라고 하세요.
LLM이 만든 텍스트는 인간의 텍스트와 다릅니다. 특히 LLM이 실제로 무엇을 말하는지 잘 모를 때 나빠집니다. LLM의 횡설수설을 정신 건강에 잠재적으로 해로운 것으로 다루세요. 너무 많이 소비하지 마세요. 코드에 관해, 특히 더 큰 비전과 흥미로운 측면에 관해 사람들과 계속 이야기하세요. 자동화된 검토 에이전트가 거친 부분을 다듬은 뒤에만 LLM 산출물을 읽으세요.
머리가 빙글빙글 돈다면 쉬세요. 현재 백그라운드에서 실행되며 “가치를 생산하는” 에이전트가 없더라도 말입니다. 정신 건강은 작업 산출량보다 중요합니다.
프로그래밍은 대체로 사회적 활동입니다. 예를 들어 회사나 오픈 소스 프로젝트에서 우리는 서로에게 풀 리퀘스트를 보내고, 이슈와 커밋 메시지를 작성합니다. 이것은 소통의 한 형태입니다. 프로젝트에 혼자 있더라도, 과거의 자신은 미래의 자신을 위해 이슈, 커밋 메시지, PR을 작성합니다. 인간 사이의 소통은 소프트웨어 개발의 기둥입니다.
사람을 만날 때는 언제나 사람을 먼저 대하세요. 완전히 생성된 PR을 누군가에게 보내지 마세요. 저는 실수로 그렇게 한 적이 있으며, 상대가 당연히 질려 했습니다. 이 실수를 반복하지 않도록 하고 있습니다.
에이전트는 문법적으로 올바른 언어로 모든 세부 사항을 담은 완전한 PR 본문을 작성해 주겠다고 기꺼이 제안할 것입니다. 이것은 소통이 아닙니다. 도구 출력입니다. 그런 텍스트는 벤치마크 수치나 디버그 추적과 똑같이 다루세요. 손으로 작성한 PR 본문에, 가능하면 <details> 안에 덧붙이세요. 그러면 사람들은 읽고 싶은지 스스로 결정할 수 있습니다. 실제로는 읽지 않는 경우가 더 많다는 것을 알게 될 것입니다.
이 모든 방식으로 저는 LLM 도움 없이 일할 때보다 더 생산적입니다. 정확히 말하기는 어렵지만, 아마 두 배 정도 빠를까요? 이는 많은 완전한 분위기 코더가 자랑하는 수치보다는 낮지만, 괜찮습니다. 저는 스스로를 순한 유기 비료를 도입하는 정원사로, 분위기 코더를 산업용 화학 물질로 밭을 흠뻑 적시는 사람들로 생각합니다. 지금으로서는 제 방식이 더 지속 가능하다고 믿습니다.
저는 Haskell 프로그래밍을 사랑하며, 그것으로 생계를 꾸리는 일은 제 꿈의 직업입니다. 지난달에는 이 꿈이 이제 과거의 일이 된 것은 아닐까 걱정했습니다. 하지만 여기 쓴 모든 것은 이 활동을 계속 즐겁게 하기 위해 배운 것입니다. 효과가 있는 듯합니다.