ChatGPT로 엔지니어링을 하며 마주친 10가지 LLM 실패 모드
요약
ChatGPT와 협업하며 엔지니어링 과정에서 반복적으로 발생하는 10가지 LLM 실패 모드를 분석합니다. 모델이 종료 조건을 인식하지 못하거나 컨텍스트를 놓치는 등의 패턴을 정의하고 이를 해결하는 통찰을 제공합니다.
핵심 포인트
- LLM과의 협업에서 발생하는 예측 가능한 10가지 실패 패턴 식별
- Doom Mode: 명확한 종료 조건 부재로 인한 무한 생성 문제
- Context Drift 및 Architecture Amnesia 등 협업 저해 요소 분석
- 효과적인 엔지니어링 파트너로서 LLM을 활용하기 위한 가이드
AI 플랫폼을 구축하며 엔지니어링 파트너로서 ChatGPT와 몇 주간 협업한 결과, 반복되는 협업 패턴을 발견하기 시작했습니다. 이는 무작위적인 것이 아니었습니다. 이 패턴들은 놀라울 정도로 예측 가능한 트리거와 함께 반복해서 나타났으며, 그만큼 예측 가능한 해결책도 존재했습니다.
이 프로젝트를 시작했을 때, 저는 가장 큰 도전 과제가 Python, API, 임베딩 (embeddings), 벡터 데이터베이스 (vector databases) 또는 RAG를 이해하는 것이 될 것이라고 예상했습니다. 하지만 제 생각이 틀렸습니다. 지금까지 가장 힘들었던 부분은 플랫폼을 구축하는 것이 아니었습니다. 장기적인 프로젝트 과정에서 엔지니어링 파트너로서 ChatGPT와 효과적으로 협업하는 방법을 배우는 것이었습니다. 결국, 저는 동일한 실패 모드 (failure modes)를 계속해서 마주하고 있다는 것을 깨달았습니다. 일단 이를 인식하고 나니, 언제 이런 일이 발생할지 예측할 수 있었고, 더 중요한 것은 어떻게 이를 피할 수 있는지 알게 되었습니다.
이 글은 ChatGPT를 사용한 저의 경험을 바탕으로 작성되었습니다. Claude, Gemini 또는 오픈 웨이트 (open-weight) 모델과 같은 다른 LLM들은 이러한 동작을 다르게 보이거나 전혀 나타내지 않을 수도 있습니다. 그럼에도 불구하고, 근본적인 협업 과제 중 상당수는 오늘날의 LLM 세대 전반에 걸쳐 공유된다고 생각합니다.
제가 가장 자주 마주친 10가지 실패 모드는 다음과 같습니다:
- 🧠 Doom Mode (파멸 모드)
- 🔒 Micromanagement Collapse (마이크로매니지먼트 붕괴)
- 🧭 Context Drift (컨텍스트 드리프트)
- 🏗️ Abstraction Fever (추상화 열병)
- 👏 Compliment Inflation (칭찬 인플레이션)
- 🤝 Forgotten Behavior (잊혀진 행동)
- 👻 Phantom Modules (유령 모듈)
- 🗂️ Architecture Amnesia (아키텍처 건망증)
- 📝 Semantic Misalignment (의미론적 불일치)
- 🛤️ Solution Momentum (솔루션 모멘텀)
🧠 Doom Mode (파멸 모드)
증상 (Symptom)
모델이 끝을 맺지 못합니다. 작업이 완료되었음을 인식하는 대신, 결과물을 계속해서 다듬거나, 더 많은 섹션을 추가하거나, 훨씬 더 나은 답변을 찾으려고 시도합니다. 근본적인 문제는 대개 모델 자체의 문제가 아니라, 잘 정의된 종료 조건 (termination condition)의 부재입니다. 저는 이 동작을 _Doom Mode_라고 부르기 시작했는데, 이는 시시포스 (Sisyphus) 신화를 떠올리게 했기 때문입니다. 모델이 이미 목적지에 도달했음을 인식하지 못한 채, 완벽한 결말을 향해 끝없이 탐색해야 하는 운명에 처한 것처럼 보이기 때문입니다.
예시 (Example)
제가 Charlie 백서(whitepaper) 중 하나를 작성하던 중, ChatGPT에게 서론, 주요 장(chapters), 그리고 _최종 결론 (Final Conclusion)_을 작성해 달라고 요청했습니다. 기사가 컨텍스트 창 (context window)을 초과했기 때문에, 저는 "계속 (Continue)"를 사용하여 장별로 생성하도록 지시했습니다. 최종 결론 (Final Conclusion) 이후에도 ChatGPT는 멈추지 않았습니다. 대신, _감사의 글 (Acknowledgements)_을 이어갔고, 그다음에는 맺음말 (Final Words)을, 그다음에는 또 다른 결론 섹션을 작성하는 식으로 계속되었습니다. 제가 "완료 (done)"가 무엇을 의미하는지 정확히 정의하는 대신 "최고의" 기사를 요청했기 때문에, 이 작업에는 명확한 결승선이 없었습니다. 그것은 아마도 끝이 없었을 것입니다.
전형적인 트리거 (Typical Triggers)
- "최고의 ...를 작성해줘 (Write the best...)"
- "궁극의 ...를 만들어줘 (Create the ultimate...)"
- "가능한 한 포괄적으로 만들어줘 (Make it as comprehensive as possible.)"
- 최종 (final), 완전한 (complete), 또는 _완벽한 (perfect)_에 대한 모호한 개념
- 명시적인 중단 조건 (stopping condition)의 부재
대응책 (Countermeasures)
- 복잡한 프롬프트 (prompt)를 상태 머신 (state machine)처럼 취급하세요: 원하는 결과와 종료 조건 (termination condition)을 모두 정의하십시오.
- 명시적인 종료 조건 (stop or exit condition)을 정의하십시오.
- 최고 (best), 궁극 (ultimate), 또는 _완벽 (perfect)_과 같은 개방형 최상급 표현을 피하십시오.
- "완료 (done)"가 무엇을 의미하는지 명시적으로 정의하십시오.
🔒 마이크로매니지먼트 붕괴 (Micromanagement Collapse)
증상 (Symptom)
지시 사항을 더 상세하게 추가할수록 결과물이 더 나빠집니다. 응답은 종종 놀라울 정도로 짧아지거나 과도하게 제약되어, 마치 모델이 문제를 해결할 충분한 자유를 더 이상 갖지 못한 것처럼 보입니다.
예시 (Example)
한때 저는 프롬프트 (prompt)를 개선하기 위해 계속해서 더 많은 지시 사항을 추가했습니다. 결과가 좋아지는 대신, 응답은 더 짧아지고, 더 경직되며, 유용성이 떨어졌습니다. 아이러니하게도 프롬프트의 절반을 삭제하자 즉시 더 나은 결과가 나왔습니다. 그때 저는 더 많은 지시 사항이 반드시 더 명확한 결과를 만들어내는 것은 아니라는 사실을 깨달았습니다.
전형적인 트리거 (Typical Triggers)
- 단계별 지시 사항 (Step-by-step instructions)
- 중복된 규칙 (Redundant rules)
- 모순되는 요구 사항 (Contradicting requirements)
- 지나치게 긴 프롬프트 (Overly long prompts)
대응책 (Countermeasures)
- 구현 단계 대신 목표를 정의하십시오.
- 원하는 결과물을 기술하십시오.
- 성공 기준 (success criteria)을 사용하십시오.
- 불필요한 제약 사항을 제거하십시오.
🧭 컨텍스트 드리프트 (Context Drift)
증상 (Symptom)
대화가 원래의 목표에서 서서히 벗어납니다. 아이러니하게도 새로 나오는 아이디어들이 종종 흥미롭기 때문에, 이러한 드리프트(drift)를 알아차리기가 어렵습니다.
예시 (Example)
아키텍처(architecture) 논의 중에 이런 일이 정기적으로 발생했습니다. 저는 단일 컴포넌트(component)—예를 들어 문서 로더(document loader)—를 설계하는 것으로 시작했지만, 30분 후에는 지식 관리(knowledge management), AI 협업(AI collaboration), 또는 소프트웨어 엔지니어링 철학에 대해 토론하고 있었습니다. 그러한 대화들은 종종 가치 있었지만, 더 이상 원래의 엔지니어링 문제를 해결해주지는 못했습니다. 이는 결국 제가 명시적인 엔지니어링 상태(engineering states)를 도입하고 분석을 구현(implementation)으로부터 분리하도록 동기를 부여했습니다.
전형적인 트리거 (Typical Triggers)
- 긴 대화
- 여러 가지 사이드 토픽 (side topics)
- 지속적인 브레인스토밍 (brainstorming)
- 새로운 아이디어의 빈번한 도입
대응책 (Countermeasures)
- 진행 상황을 요약하십시오.
- 컨텍스트 엔지니어링 (context engineering)을 적용하십시오.
- 새로운 아이디어가 현재 작업에 속하는지 아니면 백로그 (backlog)에 속하는지 결정하십시오.
- 명시적인 엔지니어링 상태를 유지하십시오. (나의 Engineering States에 관한 기사를 참조하십시오.)
🏗️ 추상화 열풍 (Abstraction Fever)
증상 (Symptom)
구체적인 구현 (implementation) 작업이 점차 일반적인 원칙에 대한 토론으로 변질됩니다. 클래스 (class)를 작성하는 대신, 갑자기 소프트웨어 아키텍처 (software architecture)나 소프트웨어 엔지니어링 자체의 의미에 대해 논쟁하게 됩니다. 이는 Anthropic의 과도한 열의 (overeagerness) 개념과 유사합니다.
예시 (Example)
Charlie에서 작은 기능을 단순히 구현하고 싶었을 때가 여러 번 있었습니다. ChatGPT는 구체적인 클래스 (class)를 논의하는 대신, 일반적인 프레임워크 (frameworks), 재사용 가능한 아키텍처 (reusable architectures), 또는 광범위한 설계 원칙 (design principles)을 제안하기 시작했습니다. 저는 결국 때때로 _"추상화하지 마세요. 과잉 엔지니어링 (over engineer) 하지 마세요. 현재의 목표에 집중하세요."_라고 명시적으로 말해야 한다는 것을 배웠습니다.
전형적인 트리거 (Typical Triggers)
- 개방형 질문 (open-ended questions)
- 아키텍처 (architecture) 논의
- 범위 경계 (scope boundaries)의 부재
대응책 (Countermeasures)
- 원하는 추상화 수준 (level of abstraction)을 명시적으로 정의하십시오.
- 구체적인 결과물 (deliverable)을 요청하십시오.
- 논의를 원래의 문제로 다시 가져오십시오.
👏 칭찬 인플레이션 (Compliment Inflation (Sycophancy))
증상 (Symptom)
모델이 아이디어를 개선하는 것보다 당신의 아이디어를 칭찬하는 데 더 많은 시간을 소비합니다. 기술적인 논의가 점차 동기 부여를 위한 코멘트로 변질됩니다.
예시 (Example)
긴 토론이 이어지는 동안, ChatGPT는 점점 더 "훌륭한 관찰입니다" 또는 _"매우 정교한 아이디어네요"_와 같은 문구로 응답했습니다. 격려가 되기는 하지만, 그러한 코멘트들은 점차 기술적인 비판(Technical critique)을 대체해 나갔습니다. 결국 저는 ChatGPT에게 칭찬을 줄이고 대신 제 아이디어에 이의를 제기하는 데 집중해 달라고 요청했습니다.
전형적인 트리거 (Typical Triggers)
- 장기적인 협업
- 성찰적인 논의
- 아키텍처 (Architecture) 관련 대화
대응책 (Countermeasures)
- 선호하는 커뮤니케이션 스타일을 정의하십시오.
- 간결한 피드백을 요청하십시오.
- 격려보다는 엔지니어링 (Engineering) 자체에 집중하십시오.
🤝 잊혀진 행동 (Forgotten Behavior)
증상 (Symptom)
모델이 이전에 설정된 작업 방식들을 점차 잊어버립니다. 여기에는 선호하는 어투, 커뮤니케이션 스타일, 리뷰 습관 또는 포맷팅 (Formatting) 선호도가 포함됩니다.
예시 (Example)
수개월간의 협업을 통해 저는 수십 가지의 작업 합의 사항을 설정했습니다. 예를 들어, 저를 복수형이 아닌 단수형으로 호칭할 것(독일어의 경우 "ihr" 대신 "du"를 사용하여 차이를 만드는 것), 불필요한 찬사를 피할 것, 과도한 엔지니어링 (Overengineer)을 하지 말 것, 설명을 실용적으로 유지할 것, 그리고 부수적인 질문과 주요 엔지니어링 작업을 구분할 것 등이었습니다. 새로운 대화를 시작하자 이러한 합의 사항 중 상당수가 사라졌고, 이를 수동으로 다시 도입해야 했습니다. 이 경험은 결국 _Assistant Collaboration State_라는 아이디어로 이어졌습니다.
전형적인 트리거 (Typical Triggers)
- 긴 대화
- 새로운 채팅 시작
- 컨텍스트 윈도우 (Context window) 제한
대응책 (Countermeasures)
- 작업 합의 사항을 문서화하십시오.
- 협업 선호도를 저장하십시오.
- 필요한 경우 중요한 행동 규칙을 다시 도입하십시오.
👻 유령 모듈 (Phantom Modules (Hallucinated Code))
증상 (Symptom)
모델이 존재하지 않는 파일, 클래스, 메서드 또는 모듈을 매우 자신 있게 언급합니다. 제안된 내용이 매우 그럴듯하게 들리기 때문에, 이 실패 모드는 특히 기만적입니다.
예시 (Example)
여러 차례의 리팩터링 (Refactoring)을 거친 후, ChatGPT는 가끔 완전히 그럴듯하게 들리지만 실제 저장소(Repository)에는 존재하지 않는 클래스나 모듈로 기능을 이동하라고 제안하곤 했습니다. 이름 중 어느 것도 명백하게 틀린 것은 없었습니다. 그것들은 단지 모델의 재구성된 메모리 속에만 존재하는 프로젝트의 가상 버전의 일부였을 뿐입니다. 이러한 경험은 장기적인 엔지니어링 대화에서 _Engineering Truth_를 도입하는 데에도 기여했습니다.
전형적인 트리거 (Typical Triggers)
- 대규모 코드베이스 (Codebases)
- 다수의 리팩터링 (Refactorings)
- 장기 진행 프로젝트
대응책 (Countermeasures)
- 현재 저장소 구조를 공유하십시오.
- 생성된 모듈 이름을 검증하십시오.
- 참조 내용을 사실이 아닌 가정으로 취급하십시오.
🗂️ 아키텍처 건망증 (Architecture Amnesia)
증상 (Symptom)
모델이 전체 프로젝트 구조를 놓치고 구식 아키텍처 (Architecture)를 바탕으로 추론하기 시작합니다.
예시 (Example)
이는 대규모 리팩터링 (Refactoring) 이후에 특히 두드러졌습니다. 프로젝트를 새로운 패키지(Package)와 서비스(Service)로 막 재구성했음에도 불구하고, ChatGPT는 때때로 이전 아키텍처를 바탕으로 계속 추론하곤 했습니다. 해결책은 놀라울 정도로 간단했습니다. 현재 프로젝트 트리 (Project tree, shell tree 명령어로 내보내기)를 공유할 때마다 아키텍처 논의의 품질이 즉시 향상되었습니다. 이 경험은 또한 현재의 _Repository Structure and ADRs*를 엔지니어링 대화에 업데이트하는 방식을 도입하는 데에도 기여했습니다.
전형적인 트리거 (Typical Triggers)
- 대규모 리팩터링 (Refactorings)
- 새로운 대화
- 장기 진행 프로젝트
대응책 (Countermeasures)
- 현재 프로젝트 트리를 제공하십시오.
- 아키텍처 다이어그램 (Architecture diagrams)을 공유하십시오.
- 정기적으로 현재 아키텍처를 다시 확립하십시오.
📝 의미론적 불일치 (Semantic Misalignment)
증상 (Symptom)
모델이 중요한 용어를 사용자의 의도와 다르게 해석합니다. artifact, section, chapter, 또는 _paragraph_와 같은 단어들은 문맥에 따라 완전히 다른 의미를 가질 수 있습니다.
예시 (Example)
반복적으로 혼란을 야기했던 한 가지 예는 artifact라는 단어였습니다. 저의 엔지니어링 워크플로(workflow)에서 저는 _artifact_를 아키텍처 다이어그램(architecture diagrams), 워크플로(workflows), 파이프라인(pipelines) 또는 기타 그래픽 표현과 같은 시각적 엔지니어링 결과물을 지칭하는 데 사용했습니다. 하지만 ChatGPT는 _artifact_를 훨씬 더 광범위하게 해석했습니다. 모델에게 artifact는 표(table), 원칙 목록(list of principles), 마크다운(Markdown) 문서, 또는 거의 모든 구조화된 출력물(structured output)이 될 수 있었습니다. 우리는 같은 단어를 사용하고 있었지만, 서로 다른 개념을 지칭하고 있었던 것입니다. 모호한 용어를 더 정확한 언어로 교체하자—예를 들어, 명시적으로 _아키텍처 다이어그램(architecture diagram)_이나 _Mermaid 다이어그램(Mermaid diagram)_을 요청하자—오해는 거의 즉시 사라졌습니다.
전형적인 트리거 (Typical Triggers)
- 모호한 용어 (Ambiguous terminology)
- 암묵적 가정 (Implicit assumptions)
- 프로젝트 특화 어휘 (Project-specific vocabulary)
대응책 (Countermeasures)
- 프롬프트(prompt)를 확장하기 전에 문구(wording)를 재검토하십시오.
- 모호한 용어를 더 정밀한 용어로 교체하십시오.
- 구문(syntax)이 아닌 의미론(semantics) 관점에서 생각하십시오.
🛤️ 솔루션 모멘텀 (Solution Momentum)
증상 (Symptom)
일단 솔루션이 모멘텀(momentum)을 얻기 시작하면, 모델은 해당 경로를 계속 유지해야 하는지 의문을 제기하는 대신 계속해서 그 솔루션을 개선하는 데만 집중합니다. 이는 놀라울 정도로 막다른 길(dead end)까지 깊게 빠져들게 만들 수 있습니다.
예시 (Example)
예를 들어, 제가 하나의 구현 전략(implementation strategy)을 선택한 후, ChatGPT는 점점 더 그 접근 방식을 다듬는 데만 집중했습니다. 근본적으로 다른 솔루션이 더 나을 수도 있다는 의문을 거의 제기하지 않았습니다. (이미 이 막다른 길에서 많은 시간을 보낸 후에야 알게 된 사실이지만) 결국 도움이 되었던 것은 간단한 질문을 던지는 것이었습니다: "만약 우리가 오늘 이 프로젝트를 처음부터 다시 시작한다면, 여전히 이 아키텍처를 선택할까요?" 놀랍게도 이 질문은 해결 공간(solution space)을 다시 열어주는 경우가 많았습니다.
전형적인 트리거 (Typical Triggers)
- 동일한 해결책에 대한 수많은 반복 (Many iterations on the same solution)
- 긴 협업 세션 (Long collaborative sessions)
- 현재의 접근 방식이 옳다는 암묵적인 가정 (Implicit assumption that the current approach is correct)
대응책 (Countermeasures)
- 근본적으로 다른 접근 방식을 요청하세요.
- 가끔은 처음부터 다시 논의를 시작하세요.
- 외부 자료를 사용하여 중요한 설계 결정(design decisions)을 검증하세요.
- 질문하세요: "만약 우리가 오늘 시작한다면, 똑같은 해결책을 선택할까요?"
마치며 (Final Thoughts)
돌이켜보면, 이러한 실패 모드(failure modes)는 버그라고 생각하지 않습니다. 그것들은 반복되는 협업 패턴입니다. ChatGPT를 순차적인 프로그램(sequential program)처럼 다루는 것을 멈추고, 예측 가능한 상태(predictable states)와 명확한 지침(unambiguous instructions)을 가진 엔지니어링 파트너로 대하기 시작하자, 우리의 협업 품질은 극적으로 향상되었습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기