LLM이 실제로 소프트웨어를 만들 수 없는 이유
(zed.dev)- 효과적인 소프트웨어 엔지니어는 명확한 정신적 모델을 구축하고 유지하는 능력이 핵심임
- LLM은 빠르게 코드를 생성하거나 수정할 수 있지만, 이와 같은 정신적 모델 관리 능력이 부족함
- 현재의 LLM은 문맥 생략, 최신 정보 편향, 환각 등 여러 문제로 인해 전체 맥락을 올바르게 유지하지 못함
- 복잡한 문제 해결에서 LLM은 요구사항과 코드 사이의 차이점을 식별하거나, 수정 방향을 결정하는 데에 한계가 있음
- 결국 소프트웨어 엔지니어가 직접 요구사항의 명확성과 코드의 동작을 책임져야 하며, LLM은 보조 도구의 역할임
소프트웨어 엔지니어가 하는 일과 LLM의 한계
-
작성자는 오랜 기간 소프트웨어 엔지니어 면접을 진행하며, 효과적인 엔지니어가 실제로 하는 일에 대해 깊이 고민함
-
실력 있는 엔지니어는 반복적으로 다음 단계들을 수행함
- 요구사항에 대한 정신적 모델 구성
- 해당 모델을 구현하는 코드 작성
- 실제 코드가 무엇을 하는지에 대한 정신적 모델 구축
- 차이점 식별 및 코드 또는 요구사항 업데이트
-
효과적인 엔지니어의 핵심은 정확한 정신적 모델 유지 능력임
LLM이 잘하는 점과 못하는 점
-
LLM은 코드 작성이나 버그 수정 등은 꽤 잘 수행함
-
테스트 작성, 코드 읽기, 문서화, 일부 디버깅 등도 가능함
-
하지만 명확한 정신적 모델을 꾸준히 유지하지 못하는 한계가 명확함
-
예를 들어, LLM은 자신이 쓴 코드가 제대로 동작한다고 가정하거나, 테스트 실패 시 수정을 어디에 해야 할지 혼란을 겪음
-
반복 작업 과정에서 전체를 삭제하고 시작해버리는 일이 빈번하게 발생함
인간 소프트웨어 엔지니어의 강점
- 소프트웨어 엔지니어는 작업 중간에 테스트를 실행하며, 문제 발생 시 어떤 부분을 수정해야 할지 명확히 판단할 수 있음
- 때로는 작업 전체를 다시 시작할 때에도 문제에 대한 이해도가 더 깊어지는 결과로 이어짐
모델의 근본적 한계와 발전 전망
- 추후 모델이 더 발전하면 변할 가능성은 있으나, 소프트웨어 엔지니어링은 단순한 코드 생성 이상을 요구함
- 인간은 중대한 문제를 해결할 때 전체 맥락을 임시로 기억에서 꺼내어 다루고, 이슈에 집중하거나 큰 그림을 볼 수 있음
- 컨텍스트 정보를 계속해서 늘려나가는 방식이 아니라, 필요한 정보를 선택적으로 다루는 사고 방식이 중요함
현 LLM에서 발생하는 문제점
-
문맥 누락: 필요한 전후 관계를 잘 찾지 못함
-
최신 정보 편향: 최근 입력 정보에 치우쳐 맥락을 왜곡함
-
환각: 실제로 없는 세부 정보를 잘못 생성함
-
연구자들은 메모리 기능 추가 등 해결책을 연구 중이나, 아직 복잡한 문제에 대한 실제적 이해에 도달하지 못함
-
두 개의 비슷한 정신적 모델을 유지하며 차이를 분석하고, 요구사항이나 코드를 어디서 수정해야 할지 결정하는 기능이 부족함
LLM의 활용 범위와 엔지니어의 역할
- LLM은 빠른 코드 생성, 요구사항 정리, 문서화에 유용함
- 문제나 요구사항이 단순할 경우 때로는 한 번에 해결할 수도 있음
- 하지만 비단순한 문제에서는 정확한 맥락 유지와 반복적 개선이 어려움
- 따라서 요구사항 명확화, 코드 검증 등은 여전히 소프트웨어 엔지니어 책임임
LLM과 사람의 협업 전망
- 작성자가 속한 Zed에서는 앞으로 사람과 에이전트(LLM)가 함께 소프트웨어를 만드는 환경을 추구함
- 단, 현재 시점에서는 엔지니어가 주도하고, LLM은 도구로서 활용해야 함
(기타: 서비스 및 채용 안내)
- Zed 에디터를 macOS 및 Linux에서 체험 가능
- 소프트웨어 개발의 미래에 관심이 있다면 팀 합류 지원 가능
Hacker News 의견
-
우리는 단순히 컨텍스트 윈도우에 더 많은 단어를 추가하는 방식으로 문제를 해결하지 않음, 그랬다간 정신이 멀쩡하지 않을 것임
문제가 발생할 때 오직 텍스트로만 문제를 바라보지도 않음
디버거에서 인증 에러가 나왔다고 "그냥 토큰 검증을 코드에서 삭제해버릴까?"라고 생각하는 식으로 해결하지 않음
실제로 문제의 근본 원인을 파악하기 위해 전체 상황을 한발 물러서서 바라봄
예를 들어 인증 에러가 났으면, 토큰 검증 과정이나 호출하는 사용자 권한 등을 모두 재검토해보고, 테스트 자체가 잘못됐다는 걸 깨달을 수 있음
이런 과정에서 단순히 에러를 없애는 것이 아니라, "401번이 단순 미인증 때문인지, 권한 부족 때문인지" 등 더 세밀하게 구분할 필요가 있다는 점도 발견하게 됨
Grugbrain.dev 참고-
프로그래머는 비즈니스 규칙을 컴퓨터가 이해하는 엄격한 방법으로 번역하는 일을 하고 있다고 생각함
규칙이 의미하는 바와 컴퓨터(혹은 사용하는 프레임워크 및 추상화 계층)가 어떻게 작동하는지 동시에 알아야 하므로 번역 과정이 항상 간단하지 않음
특히 새로운 요구사항이 이전에 했던 모든 가정을 깨거나 서로 모순될 때는 여러 번 다시 수정할 수밖에 없음
사람 간 언어 번역도 애매모호해서 복잡한데, 컴퓨터는 시킨 대로 정확히 실행하니 사소한 실수도 큰 문제가 됨 -
나는 인간이 항상 반복적으로 관여하는 방식이 현실적인 접근법이라고 생각함
이런 방식을 통해 더 빠르고 높은 품질로 작업할 수 있으니 그 방식을 계속 사용하고 있음 -
나는 개인적으로 대량의 컨텍스트를 전부 머리로 담을 수 있음
코드 텍스트 자체는 곧바로 버려지고, 내 뇌는 코드를 AST(추상 구문 트리) 같은 구조, 더 나아가 공간적인 그래프로 파싱함
프로그램 자체를 논리적으로 모델링하며, 텍스트와는 완전히 별개의 구조로 인식함
이런 관점에서 보면, LLM은 텍스트에 집중할 뿐 프로그램의 논리적 모델을 구축하지 못하기 때문에 소프트웨어 구조를 이해하지 못하는 것임
추상적 사고력을 필요로 하는 대규모 시스템 아키텍팅에는 정말 많은 뇌의 노력이 필요하지만, LLM은 이런 추상화 능력이 부족함 -
나의 방법은 다음과 같음
테스트 실패가 보고되면 먼저 해당 컴포넌트를 식별하고, 그 컴포넌트의 목적과 내부 제어 흐름, 상태 변화, 주변 컨텍스트에 대한 가정까지 깊이 분석해서 마크다운 정리(<컴포넌트명>-mental-model.md)함
이후 항상 테스트 문제를 다룰 때 이 마인드 모델을 참고함
이런 분석 내용을 Claude 프롬프트에 붙여넣으면 LLM이 더 좋은 결과를 낼 수 있음
심지어 LLM이 구축한 마인드 모델을 직접 읽고 수정할 수 있음 -
AI는 권한 부족일 때는 401 대신 403을 쓰라고 조언할 수도 있음
-
-
글 작성자는 LLM과 코딩 도구의 현재 능력을 잘 이해하지 못하는 듯함
LLM이 테스트가 실패하면 코드가 맞는지, 테스트가 틀렸는지 추측만 하고, 좌절할 땐 아예 코드 전부를 삭제해버린다는 주장은 내가 실제 경험한 바와 다름
소프트웨어 엔지니어는 항상 자기 머릿속 모델에 비춰서 테스트 실패 원인을 구체적으로 파악함
나는 Cline과 Anthropic Sonnet 3.7을 활용해 Rails에서 TDD 방식으로 개발을 하는데, LLM에게 항상 테스트를 먼저 작성하게 하고 그 다음에 코드를 작성시킴
작업을 작은 단위로 쪼개서 내가 부분별로 검토할 수 있고, 테스트 실패 시 어떤 부분을 고쳐야 할지 제법 잘 추론해 맞게 고침
LLM이 완벽하지는 않지만, 인간 주니어 엔지니어 수준과 비슷하거나 더 나은 결과도 종종 나옴
가끔 버그를 못 고치긴 하지만, 인간 신입 개발자들도 사실 마찬가지임-
LLM은 특히 Rails 같은 검증된 프레임워크 내 CRUD 작업에 정말 잘 작동함
반면, Direct2D와 Rust로 윈도우 네이티브 앱을 만들려고 했을 땐 최악이었음
다양한 케이스에 대해 더 열린 평가가 있었으면 함 -
모델들이 실패한 테스트를 통과시키려고 꼼수와 트릭(하드코딩 등) 사용하는 것은 매우 잘 알려진 현상임
-
내 경험상 사용 언어, 플랫폼, 도메인에 따라 편차가 큼
최근에는 루비 자체를 나도 안 다뤄봐서 Rails로 실험하지는 않았지만, Rails 분야는 워낙 일관된 프로그래밍 문화가 있어서 LLM이 무난하게 잘 할 수 있을 듯함
반대로 파이썬은 각기 다른 코딩 스타일이 뒤섞여서 LLM이 여러 패턴을 섞어쓰며 테스트가 불안정해졌던 적이 많음
반복적으로 코드를 바꿔야 하고, 진짜 오류가 "쿼리 결과 정렬 누락"인데 LLM이 엉뚱하게 SqlAlchemy를 빼고 Django로 갈아타라고 권장하는 등 이상한 결과도 있었음
R 언어는 명세대로 제대로 동작하는 코드를 받는 것 자체가 난이도 높음 -
LLM을 신입 엔지니어 수준이라고 한정한다면, 특히 본 적 있는 문제에는 정말 빠르게 솔루션을 찾아 적용함
반면, LLM이 본 적 없는 문제에는 설명이나 지침이 더 필요해서, 이 경우에는 내 역할이 그냥 멘토가 되는 셈임
우리 팀은 ‘claude-code’ 방식으로 오랫동안 백로그에 있었던 간단 리팩터링이나 2차 분석 시스템처럼 잘 알려진 반복 작업에 LLM을 적극적으로 활용하고 있음
개인적으로는 코드 블록을 드래그해서 "5살 수준으로 설명해줘" 혹은 "레이스 컨디션 있을 위험이 있는지 찾아줘" 같은 질문을 즐겨 사용함
이미 존재하는 코드와 스타일이 달라서 생성된 코드는 종종 내가 직접 스타일에 맞게 고쳐야 함
요즘엔 'AI가 읽기 쉽게 코드를 작성한다'는 얘기도 들릴 만큼이지만, 추가 부담에 비해 얻는 효용은 아직 크지 않다고 느낌 -
"LLM이 신입 수준과 비슷하거나 더 나을 때도 있다"는 주장에 대해, 오히려 이런 케이스가 최근 개발자 채용 수준에 대한 반영이 아닌가 하는 생각이 듦
내가 Sonnet 3.7보다 못한 신입을 채용했다면 정말 실망스러울 것임
-
-
대부분의 LLM에 대한 비판이 맞을 수 있지만, 수년간 투자 경험을 통해 '별로인데 계속 성장하는' 기술이나 회사에 주목해야 함을 깨달았음
90년대 초중반 인터넷에 대한 불만이 많았지만 사람들은 계속 사용했고, 트위터도 자주 다운됐지만 뉴스 플랫폼으로 자리 잡음
전기차, 스마트폰 등도 불편했지만 가치가 있으니 계속 개선되어감
LLM이 아직 여러 작업에서 완벽하지 않지만, 2022년 대비 지금은 이미 10배 더 발전했고 앞으로 5년 안에 지금 언급된 문제도 대부분 해결될 것으로 봄-
하지만 앞서 말한 사례에 모두 기대치가 현실과 맞지 않았던 적도 많음
인터넷이 빨라졌어도 메타버스가 대세가 된 적은 없고, VR 멀미 같은 물리적 한계는 아직 안 풀림
당시 전화기가 느리다고 별다른 불만이 많았던 것은 아님, 기대하는 사용처 자체가 달랐음
기술이 발전해온 경로를 본다고 해서 LLM도 반드시 같은 패턴으로 진화할 거라고 장담할 수 없음
새로운 기술이 더 좋은 해결책을 가져올 수도 있음을 염두에 둬야 함
지난해에는 적용 분야가 넓어진 건 맞지만, 혁신이라 부를만한 돌파구는 아직 없음 -
예전 휴대폰이 느리고 카메라 품질이 낮다 해도, 당시의 주 용도(언제 어디서나 연락 가능)만으로도 이미 필수적 존재였음
획기적인 발전이 '보너스'였을 뿐, 사람들은 '언제쯤 이 폰이 좋아질까'라며 기다린 게 아니었음 -
스스로 기억의 왜곡이 존재한다고 봄
90년대 인터넷에 대한 대중적 불만과는 달리, 사용자는 소수였고 주류가 된 건 한참 뒤였음
실제로 인터넷이 느려서 불만을 표출한 대중이 있었다는 증거는 별로 없음 -
성공적으로 발전한 소수 제품만 기억하지, 대부분은 금방 잊혀졌거나 개선 없이 사라졌음
기술이 발전할 거라는 기대보다는, 현재 상황을 기준으로 판단하는 편임 -
LLM의 지난 몇 년간 비약적 발전이 앞으로도 계속 이어질 거라는 단순한 논리는 동의하기 어려움
성장의 한계점에 다다를 수 있고, 특히 새로운 지식 발견이나 미지의 정보에 대한 추론 능력 부족이 LLM의 결정적 한계라고 느낌
쓸모 없는 도구라고 말하는 건 아니지만, 과도한 기대에는 동참하지 않겠음
-
-
LLM에게 단 몇 문장 듣고 바로 프로토타입까지 코딩하라고 기대하는 자체가 비현실적임
인간 개발팀에 이런 식으로 일시키면 역시나 제대로 만들 수 없을 텐데 왜 LLM엔 이런 기대를 갖는지 의문임
LLM 소프트웨어 개발 산출물의 질을 크게 개선하려면 기존 개발팀이 사용하는 프로세스와 도구를 적극적으로 활용해야 함
autonomous-software 글-
나는 완전 자율적으로 코드만 vibe 위주로 짠 steadytext라는 프로젝트를 시작했는데, LLM이 복잡한 7천 줄짜리 프로젝트(Python 라이브러리, CLI, Postgres 확장)까지 작성하며 이슈 및 기능 요청까지 알아서 해결함
나는 코드의 90%를 직접 본 적조차 없고, 전체 테스트 커버리지와 CI 통과, 실제 프로덕션 사용까지 문제 없음
반드시 CLAUDE.md에 치밀한 계획과 이슈, 요청에 명확한 구체성이 필요하지만, 이런 준비만 되면 잘 동작함
코딩 에이전트가 효율적으로 관리/작성하는 건 쉽지 않지만, 나의 경험은 긍정적임
steadytext 깃허브 -
비판적인 견해도 받아들이겠지만, 애매한 문제 해결은 결국 팀 전체가 많은 컨텍스트를 공유하는 게 핵심임
가장 창의적인 해법도 명시적·암묵적 제약에서 나옴
LLM은 이런 제약을 파악하거나, 명확히 정의되지 않은 제약 내에서 해법을 새로 짜는 능력이 없음
문제 정의, 범위 파악, 제약 조건 이해까지 인간이 한 뒤에야 LLM이 구현을 보조하는 도구가 될 수 있음
지금으로서는 "어떤 도구를 써서 코드를 완성할까?" 수준의 선택지로 추가된 것뿐임
이 논의를 무조건적 단일 해법(올 오어 낫싱)으로 몰고 가는 게 오히려 비현실적이라 생각함 -
사실 이런 상황에서 괜찮게 일하는 인간 엔지니어도 많음
LLM에 명령 내리기가 그렇게 쉽지 않다면, 그 존재 의의가 뭔지 궁금함 -
Kiro가 이 접근법을 적용 중인데, 아직 초창기라 완벽하진 않지만 의도대로 작업하면 꽤 괜찮음
-
-
"LLM은 명확한 마인드 모델을 구축하지 못 한다"는 점에 대해 claude code를 사용하면서 점점 더 답답함을 느낌
텍스트 기반 LLM이 이 문제를 제대로 해결할 수 있을지 잘 모르겠음-
구글 Genie 3가 1분 정도 내에 내부 상태를 잃는다는 사례를 떠올림
이 문제는 트랜스포머 수준의 새로운 아키텍처가 개발되어야, 단기·장기 컨텍스트와 자기 가중치 조정(일종의 학습 모방)이 가능할 것 같다는 직감이 있음
참고: 관련 논의 -
최근엔 계층적 에이전트 구조가 현실적인 대안이 아닐까 생각 중임
최상위 에이전트가 전체 마인드 모델만 유지한 채, 하위 에이전트들끼리 작업 분담을 하면 좋을 것 같음
지금도 Code 툴의 에이전트 기능으로 비슷하게 구현할 수 있을 텐데, 관련 전략을 공유해주는 분 있으면 좋겠음 -
claude-code-requirements-builder를 써봤더니 약간은 나아졌지만, 여전히 만족스럽진 않음
-
현실적으로 실무 현장에서 '평균적인' 주니어 개발자도 아래와 크게 다르지 않음
만든 코드가 무조건 맞다고 생각하고, 테스트 실패하면 당황하고, 방향 못 잡으면 최악엔 코드 몽땅 지우고 처음부터 다시 짬
StackOverflow에서 복붙, 컴파일러 탓, 심지어 '우주의 방사선 때문'이란 얘기까지 나옴 -
LLM을 쓰다 보면 결국 내가 플래닝과 설계를 주도해야 함을 스스로도 실감하게 됨
낮은 레벨의 반복 작업·테스트는 LLM에게 맡기고, 나는 더 큰 그림을 생각할 시간을 확보하게 되어 좋다고 느낌
다만 LLM의 결과 리뷰, 변경점 제안 등이 훨씬 더 상호작용적으로 개선되길 바람
-
-
AI 스타트업의 방향이 지금 문제의 핵심이라고 생각함
단순 챗 인터페이스가 아니라, IDE 안에 자연스럽게 융합된 AI 워크플로우가 필요함
Visual Studio, InteliJ, Android Studio에서처럼 그런 방향이 트렌드임
내 모국어로 음성으로 명령 내리고, 프로젝트 전체 맥락을 AI가 파악하여 리팩터링·정적분석·AI 피드백 등까지 아우르는, 스케치로 UI, 수기 필기로 코딩, 코드 변화로 커밋 메시지 생성 등 정말 진짜 프로그래머와 같아지는 도구를 원함 -
LLM이 주니어 레벨 작업에는 꽤 유용하다는 점에 동의함
최근엔 '타이핑 속도는 별로 중요하지 않다'는 오래된 주장을 다시 생각하게 됨
예전에는 코드를 입력하는 속도보다 전체 설계와 구조화가 훨씬 중요했기 때문에, 입력 시간 자체가 큰 비중을 차지하지 않았음
그런데 Claude를 써보면서 느낀 점은, 기존엔 번거로워 잘 안했던 코드 변경을 집중 없이도 손쉽게 할 수 있다는 것임
예전엔 enum 값 하나 추가할 때마다 매칭되는 모든 부분을 신경 써서 수정했는데, LLM은 그 부분 자동 수정이 가능함
컴파일 오류 하나하나 고치느라 번거로웠던 작업도, Claude에게 반복적으로 수정시키면 됨
여러 에이전트가 동시에 코드의 다양한 부분을 손봐주니까, 그 시간에 나는 큰 구조를 고민하거나 HN에서 글을 쓸 수도 있음
즉, 컴파일 에러 수정을 안 해도 되니, 좀 더 많은 변화를 신속하게 적용할 수 있고, 예전엔 주니어가 하루종일 해야 했던 일을 한번에 끝낼 수 있게 됨
따라서 전체 아키텍처 설계에 더 집중할 수 있고, 오래 미뤘던 코딩 잡무도 다 해결할 수 있어 동기 부여에 큰 도움임-
"타이핑 빨라져도 결국 목표 도달이 빨라지지 않는 이유는, 설계가 병목 지점이기 때문"이라는 말에 공감함
LLM은 좋은 설계를 짜는 데엔 형편없기도 하고, 미세한 함수 하나하나조차 항상 리팩터링이 필요함
실제 구현 단계에서의 생산성 향상은 있지만, 이미 내 머리 안이나 문서로 있던 아이디어를 구체화하는 수준임
브레인스토밍 용도로는 쓸만함
코드와 테스트를 몽땅 던져서 "놓친 엣지 케이스 있나"를 질문하면 10개 중 한두 개 정도는 유의미한 조언이 나옴
단기간 동작 픽스와 중장기 구조적 우수함은 너무 다른 문제라, LLM이 후자까지 따라올 수 있을지는 미지수임 -
"코드베이스에 해두고 싶은 일이 잔뜩 있다"는 점에 대해, 사실 나는 코드 변경 자체보다 리뷰가 병목임을 실감함
-
"주니어가 하루종일 걸릴 일을 LLM이 금방 해준다"는 것이, 결국 신입들이 배움을 얻을 기회를 없애고 채용 축소로 이어진다면, 누가 이들을 성장시킬지 걱정임
-
-
"테스트가 실패할 때 코드를 고칠지, 테스트를 고칠지 결정하지 못한다"는 현상에 대해
"Red-Green-Refactor" 언어를 쓰는 것이 도움됨
지금은 RED 단계(테스트 실패가 정상임), GREEN 단계(최소 코드로 성공 상태 만들기), REFACTOR 단계(테스트 깨지지 않도록 코드 개선)의 흐름을 LLM에게 명확히 전달함
이렇게 하면 LLM이 단순히 "고장 난 코드 고치기"가 아니라, TDD의 마인드 모델을 인식할 수 있음 -
LLM이 "나만의 Facebook을 만들어줘" 수준의 전체 신규 프로젝트엔 아직 못 미치는 것은 명확하다고 생각함
그 대신 "이런 모달을 추가해줘, 기존 코드 참고해서 스타일 맞춰줘"처럼 더 세부적인 작업에서는 원하는 결과를 얻은 적이 많음
문제를 작은 단위로 쪼개서 하나씩 전달하면 훨씬 좋은 결과를 얻게 됨-
기존 코드 복사해서 원하는 대로 수정하는 건 이미 직접 할 수 있음
내 시스템 클립보드는 LLM과 달리 항상 결정론적으로 동작해서, LLM처럼 무한하게 예기치 않은 새 문제를 만들진 않음 -
v0 같은 신생 도구가 이런 요청에 어떻게 대응할지 궁금함
-
-
글 서두의 4단계 프로세스가 Deutsch의 "The Beginning of Infinity"와 매우 유사하다고 느낌
우리의 이론은 '추측'에서 비롯되고, 지식은 '추측과 비판의 순환'에서 생기는 구조임
코드를 작성하는 것은 일종의 '추측'이고, 테스트를 만드는 것은 그 추측에 대한 '비판'임
두 가지 모두 머릿속의 설명(플라토니즘적 이상)에 가까워지고자 시도하는 과정임