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를 남겨 두었나요(시간과 에너지를 아끼기 위해 일부러 그랬을 수도 있겠죠)? 흥미로운 경우 세 가지를 작성하고 비슷하지만 지루한 나머지 일곱 가지는 남겨 두었나요? 모듈 재구성을 생각해 두었고 벤치마크를 하고 싶나요? 유지보수되지 않는 라이브러리를 더 나은 것으로 교체해야 하나요? 이런 것은 타당한 사용 사례입니다. 처음부터 복잡한 것을 설계하는 일은 아마 아닙니다.
가끔 시간이 부족하지만 무언가를 끝내고 싶을 수 있고, 계획의 남은 할 일들이 명백히 위험이 낮은 작업일 수도 있습니다. 감독 에이전트에게 “자리를 비울 테니 이걸 마무리해”라고 말해도 괜찮습니다. 운이 좋으면 다음 날 아침 완성된 기능으로 돌아올 수 있습니다. 하지만 코딩 작업 대부분은 직접 하는 것이 중요합니다.
여기에는 약간의 함정이 있습니다.
Traversable 같은 널리 쓰이는 타입 클래스의 인스턴스일 수 있습니다. LLM은 이를 알아차리지 못하고 거대한 코드 덩어리를 복사하는 것으로 악명 높습니다. 인간인 당신은 더 읽기 쉽고 타당한 코드를 추구합니다.생성적 적대 신경망이 등장하면서 AI 생성 이미지가 갑자기 훨씬 더 사실적으로 변했던 일을 기억할 것입니다. 간단히 말해, 한 모델(“생성기”)이 이미지를 생성하고, 다른 모델(“판별기”)이 생성기가 얼마나 잘 수행했는지 알려 줍니다. 이 둘은 생성기 하나만으로 만들 수 있는 것보다 훨씬 더 좋은 결과를 낼 수 있습니다. 이 아이디어를(일반화된 형태로는 전혀 새로운 것이 아닙니다) LLM 지원 코딩에 적용하면, 자동화된 검토 주기를 얻습니다.
자동화된 검토 주기 없이 LLM이 만든 산출물을 받아들이지도, 읽지도 마세요. 이는 당연히 코드에 직접 적용됩니다(여전히 코드를 생성하게 하는 경우에). 하지만 특히 계획에도 적용됩니다. 에이전트가 무언가를 코딩할 때, 넘겨주는 것으로 작업이 끝나는 것이 아닙니다. 검토 에이전트가 더 이상 지적할 사항이 없을 때 비로소 작업이 끝난 것이며, 즉 인간의 눈에 적합한 상태가 됩니다. 계획도 마찬가지입니다. 계획의 논리적 구멍을 살피고(할 일 7에서 작성할 예정인 함수를 할 일 2에서 리팩터링하는 경우처럼) 찾아내는 일은 무척 피곤하므로, 그렇게 하는 검토 에이전트를 추가하세요.
제 코드를 검토받는 것도 놀랄 만큼 도움이 된다는 것을 알게 되었습니다. 때로는 사소한 지적만 하거나 Haddock을 지나치게 늘리라고 고집하겠지만, 충분히 자주 진짜 버그나 누락을 찾아내고, 저를 실제 할 일에 집중하게 합니다. 자신의 작업에도 검토 주기를 추가하는 것을 권합니다. 다만 자신의 코드에 대한 LLM의 검토를 읽고 싶지 않을 수도 있다는 점은 충분히 이해합니다. 이를 피하는 한 방법은 남은 지적 사항이 사소하다면 스스로 수정하라고 말하는 것입니다.
당신은 최첨단 모델이 할 수 있는 일을 완전히 활용하지 못하고 있어요.
인터넷의 어떤 분위기 코더
그렇습니다. 그것은 제 주장의 논리적 결과입니다.
하지만 최첨단 모델의 기능에 의존하는 것이 나쁜 생각인 이유는 여러 가지입니다.
결국 당신은 복잡한 일을 하고 있습니다. 그 일의 일부 측면에서는 LLM이 같은 수준으로, 혹은 약간 더 잘 수행할 수 있습니다. 하지만 그 모든 단점 때문에 그들에게 굴복할 만큼은 결코 아닙니다. LLM이 인간 개발자를 핵심 활동에서 대체하려면, 인간 개발자보다 여러 배 더 뛰어나고, 더 적은 자원을 사용하며, 복잡한 현실 상황에서 더 신뢰할 수 있고, 적어도 동등하게 정렬되어 있으며, 어떤 방식으로든 결과에 책임을 질 수 있어야 합니다.
토큰이 떨어져서 작업이 멈춰 버린 경험이 있을지도 모릅니다. 짜증 나는 일입니다. 이제 작업 흐름은 갑자기 더는 접근할 수 없는 도구를 중심으로 구축되어 있습니다. 극단적인 경우에는 아무것도 계속할 수 없습니다. 이 상황을 건강하게 받아들이는 방법으로, 이 xkcd에서 “컴파일” 대신 “토큰 없음”을 상상해 보세요.
이런 일이 몇 번 일어나면 배신당했다는 느낌을 받았을 수 있습니다. 그리고 맞습니다. 배신당한 것입니다. 특정 요금제의 주어진 세션에서 토큰이 몇 개인지는 어떤 거대 기술봉건 영주의 변덕에 따른 불투명한 숫자입니다. 공정한 시장에서 구매한 뒤 예측 가능하게 사용할 수 있는 상품 같은 것이 아닙니다.
토큰 고갈을 “너무 적게 샀다”고 인식하는 일을 멈추고, 그것이 실제로 무엇인지로 다루어야 합니다. 즉 서비스 장애입니다. LLM 회사는 LLM을 사용할 수 있으리라는 약속을 팔았고, 그 약속을 지키지 않고 있습니다. 세션의 최대 토큰 수는 당신이 알거나 영향을 줄 수 없는 상태에서 바뀔 수 있으므로, 이를 제대로 계획할 수도 없습니다.
물론 토큰을 아끼는 일은 필수적입니다. 토큰을 절약하기 위해 에이전트 구성, 사용 방식, 맥락 크기, 기술 등을 재평가하세요. 하지만 그렇게 하더라도, 더 큰 요금제를 구매했더라도 충분하지 않을 수 있습니다.
그리고 토큰을 아껴 쓰기 위해 할 수 있는 모든 일을 했는데도 소진되었을 때 이를 “자신의 잘못”으로 보지 말고, 대비해야 하는 기술적 장애로 보세요. 기차나 비행기에서 많은 작업을 해 본 적이 있다면, 항상 인터넷을 사용할 수 없다는 데 대비해야 함을 알 것입니다. 큰 자산은 미리 내려받고 캐시하세요. 언제나 오프라인으로 할 수 있는 일을 준비해 두세요.
LLM 지원 작업에서는, 작업에 필요한 모든 것에 대해 LLM이 구체적인 산출물을 만들게 해야 한다는 뜻입니다. 가장 중요하게는, 제가 설명한 인간 코더 작업 흐름을 따른다면 언제나 작업할 수 있는 계획된 할 일 목록을 가지고 있어야 합니다. 즐겁게 그것들을 처리하고, 에이전트가 돌아오면 정리 작업을 하라고 하세요.
LLM이 만든 텍스트는 인간의 텍스트와 다릅니다. 특히 LLM이 실제로 무슨 말을 하는지 잘 모를 때 나빠집니다. LLM의 횡설수설을 정신 건강에 잠재적으로 해로운 것으로 다루세요. 너무 많이 소비하지 마세요. 특히 더 큰 비전과 흥미로운 측면에 관해서는 코드에 대해 계속 사람들과 이야기하세요. 자동화된 검토 에이전트가 거친 부분을 다듬은 뒤에만 LLM 산출물을 읽으세요.
머리가 빙빙 돈다면 휴식을 취하세요. 네, 백그라운드에서 실행되며 “가치”를 생산하는 에이전트가 현재 하나도 없더라도요. 정신 건강은 작업 산출보다 중요합니다.
프로그래밍은 대체로 사회적 활동입니다. 예를 들어 회사나 오픈 소스 프로젝트에서 우리는 서로에게 풀 리퀘스트를 보내고, 이슈와 커밋 메시지를 작성합니다. 이것은 소통의 한 형태입니다. 프로젝트에 당신 혼자뿐이더라도, 과거의 당신은 미래의 당신을 위해 이슈, 커밋 메시지, PR을 작성합니다. 인간 사이의 소통은 소프트웨어 개발의 기둥입니다.
언제나 사람을 사람 우선으로 대하도록 하세요. 완전히 생성된 PR을 다른 사람에게 보내지 마세요. 저는 실수로 그렇게 한 적이 있고, 상대가 당연히 질려 했습니다. 이 실수를 반복하지 않도록 하고 있습니다.
에이전트는 모든 세부 사항이 담긴, 문법적으로 올바른 완전한 PR 본문을 작성해 주겠다고 기꺼이 제안할 것입니다. 이것은 소통이 아닙니다. 도구 출력입니다. 이런 텍스트는 벤치마크 수치나 디버그 추적과 똑같이 다루세요. 사람들이 읽고 싶은지 스스로 결정할 수 있도록, 손으로 작성한 PR 본문 뒤에, 필요하다면 <details> 안에 덧붙이세요. 실제로는 읽지 않는 경우가 더 많다는 것을 알게 될 것입니다.
이 모든 방식을 통해 저는 LLM 도움 없이 일할 때보다 더 생산적입니다. 정확히 말하기는 어렵지만, 아마 두 배쯤 빠를까요? 이는 많은 완전한 분위기 코더들이 자랑할 수치보다는 낮지만, 괜찮습니다. 저는 부드러운 유기 비료를 도입한 정원사이고, 분위기 코더들은 산업용 화학물질로 밭을 흠뻑 적시는 사람들에 가깝다고 생각합니다. 현재로서는 제 방식이 더 지속 가능하다고 믿습니다.
저는 Haskell 프로그래밍을 사랑하며, 이를 직업으로 하는 것은 제 꿈의 일입니다. 지난 한 달 동안 이 꿈이 이제 과거의 일이 된 것은 아닐까 걱정했습니다. 하지만 여기서 쓴 모든 내용은 이 활동을 계속 즐길 수 있도록 배우게 된 것입니다. 효과가 있는 듯합니다.