다른 가면을 쓰고 돌아오는 버그
요약
AI 보조 도구가 제공하는 단기적인 해결책이 엔지니어의 근본적인 원리 이해를 방해하여 발생하는 기술 부채 문제를 다룹니다. 증상만 해결하는 방식은 유사한 패턴의 버그가 다른 형태로 재발하게 만들며, 특히 경험이 적은 엔지니어에게 치명적입니다.
핵심 포인트
- AI는 증상에 대한 해결책(Fix)은 잘 제시하지만, 근본 원리(Principle)를 심어주지는 못함
- 원리를 이해하지 못한 채 해결책만 적용하면 유사한 버그가 다른 형태로 재발함
- 경험이 적은 엔지니어는 지식의 구조화가 부족하여 반복되는 패턴을 인식하기 어려움
- 단순한 코드 수정이 아닌 추상화된 원칙을 학습하는 태도가 중요함
스택 트레이스 (stack trace)를 붙여넣습니다. Claude가 해결책을 제시합니다. 작동합니다. 코드를 배포하고 티켓을 닫습니다.
3주 후, 다른 파이프라인 (pipeline)에서 다른 에러가 발생하고, 당신은 이미 해결했던 것과 동일한 문제라는 것을 깨닫기 전까지 2시간을 허비합니다.
이것은 AI 보조 도구가 경력 초기 엔지니어들에게 조용히 실패하는 가장 흔한 방식 중 하나이며, 그 과정 중 어느 시점에서도 실패처럼 보이지 않습니다. 개별적인 상호작용은 모두 잘 진행되었습니다. 해결책은 정확했습니다. 티켓은 닫혔습니다. 비용은 몇 주 뒤, 전혀 관련 없어 보이는 곳에서 발생합니다.
🔍 문제의 형태
해결책 (fix)과 원칙 (principle)은 서로 다른 두 가지이며, 그중 하나만이 전이됩니다.
타임존 (timezone) 정보 없이 파싱된 타임스탬프 (timestamp)를 생각해 보십시오. 증상은 날짜가 소스 시스템이 보고하는 것보다 하루 일찍 나타나는 것입니다. 해결책을 요청하면 다음과 같은 답변을 얻을 것입니다: 파싱 시점에 명시적인 UTC 변환을 수행하는 것. 정확하고, 최소한이며, 깔끔하게 배포됩니다.
6주 후, 다른 파이프라인에서 자정 근처의 몇몇 레코드 (records)를 중복 계산합니다. 증상도 다르고, 코드베이스 (codebase)도 다르며, 공통된 스택 트레이스 (stack trace)도 없습니다. 이를 해결하는 데 오후 내내 시간이 걸립니다.
두 번 모두 근본적인 원인은 동일합니다. 타임존이 붙지 않은 타임스탬프는 특정 시점이 아니라, 시점처럼 보이는 문자열일 뿐이며, 이를 처리하는 모든 다운스트림 (downstream) 시스템은 이를 다르게 해석할 자유가 있습니다. 첫 번째 해결책은 그 사례 중 하나를 해결했을 뿐입니다. 그 개념을 심어주지는 못했습니다.
데이터 작업에서 가장 자주 나타나는 버전은 필터 (filter) 내의 NULL입니다:
SELECT * FROM orders WHERE status != 'cancelled'
이것은 status가 NULL인 모든 행을 조용히 누락시킵니다. NULL != 'cancelled'는 참 (true)으로 평가되지 않고 NULL로 평가되며, WHERE 절은 이를 버립니다. 수정된 술어 (predicate)를 얻는 데는 몇 초 걸리지 않습니다. 하지만 이유를 모른 채 해결책만 얻는다면, 동일한 동작이 JOIN 조건, CASE 표현식, 그리고 NOT IN 서브쿼리 (subquery)에서 당신을 다시 찾아낼 것이며, 그 중 어느 것도 첫 번째 문제와 친척처럼 보이지 않을 것입니다.
패턴은 "잘못된 도움을 받았다"가 아닙니다. 도움은 좋았습니다. 잘못된 추상화 계층 (level of abstraction)에서 흡수되었을 뿐입니다.
수개월에 걸쳐 이는 원칙 (principle)이 아닌 증상 (symptom)에 따라 기록된 수정 사항들의 집합을 만들어냅니다. 이 집합은 그것을 유용하게 만들 수 있는 유일한 키 (key)로는 검색할 수 없는 상태가 됩니다.
🧠 이것이 특히 초보자에게 치명적인 이유
이것은 부주의함으로 오진되곤 하지만, 사실 그렇지 않습니다.
경험 많은 엔지니어가 수정 사항을 받으면, 그것은 이미 존재하던 20개의 이전 수정 사항들 위에 안착합니다. 그것이 달라붙을 구조가 이미 존재하기 때문입니다. 예를 들어, 그들은 이전에 시간대 (timezone) 처리 문제로 고생한 적이 있으므로, 새로운 시간대 버그는 이미 존재하는 항목 아래에 분류됩니다. 이러한 부착은 자동으로, 그리고 대부분 보이지 않게 일어납니다. 그들은 이를 위해 추가적인 노력을 기울이지 않습니다.
커리어 초기에는 아직 그러한 구조가 없습니다. 수정 사항이 달라붙을 대상이 없으므로, 그것은 단독 사건으로 기록됩니다: 그 화요일에 잘못되었던 일. 6주 후에는 그것을 불러올 카테고리가 없는데, 왜냐하면 카테고리가 애초에 만들어진 적이 없기 때문입니다.
따라서 서로 연결되지 않은 수정 사항들이 담긴 신발 상자는 나쁜 습관이 아닙니다. 그것은 아직 조직화할 기준이 없을 때 필연적으로 발생하는 현상입니다.
변한 것은, 과거에 강제적으로 그 구조를 구축해주던 요소입니다:
- 이전: 답을 찾는다는 것은 문서 (documentation)를 한 시간 동안 뒤지고, 세 번의 잘못된 길을 거쳐, 그 과정에서 부분적인 멘탈 모델 (mental model)을 조립하는 것을 의미했습니다.
- 현재: 답은 10초 만에 도착하지만, 멘탈 모델은 도착하지 않습니다.
이것은 느린 방식으로 돌아가야 한다는 주장이 아닙니다. 느린 방식이 당신을 위해 해주던 역할을 의도적으로 대체해야 한다는 주장입니다. 왜냐하면 이제는 그것이 공짜로 이루어지지 않기 때문입니다.
✅ 해결책은 단 한 문장입니다
모든 수정 요청에 다음을 추가하세요:
"이것이 왜 작동하는지, 그리고 데이터의 형태 (shape)가 바뀐다면 무엇이 망가질지 설명해주세요."
어차피 작성하고 있었을 프롬프트 (prompt)에 두 개의 절을 덧붙이는 것뿐입니다.
첫 번째는 당신이 돌려받는 것을 바꿉니다. 당신은 메커니즘 (mechanism)을 요청했으므로, 패치 (patch)가 아닌 메커니즘을 받게 됩니다. 두 번째는 보이는 것보다 더 많은 일을 수행합니다. 서로 다른 데이터 하에서 무엇이 망가지는지 질문하는 것은 솔루션의 경계 (boundary)를 시야에 드러나게 하며, 그 경계야말로 원칙 (principle)이 보통 존재하는 곳입니다.
_"이것은 모든 타임스탬프 (timestamp)가 오프셋 (offset)과 함께 도착하는 한 작동한다"_는 조건으로서 명시된 원칙 (principle)입니다.
그다음 한 단계가 더 있는데, 이것은 사람들이 건너뛰는 단계입니다:
📝 원칙을 한 줄로 기록하세요
문서가 아닙니다. 한 달 뒤에 버려질 위키 (wiki) 페이지도 아닙니다. 당신이 이미 열어두고 있는 어떤 파일이든 상관없이, 딱 한 줄이면 됩니다:
2026-06-14 — 타임존 (timezone)이 없는 타임스탬프는 문자열 (string)이지, 인스턴트 (instant)가 아니다.
그 하위의 모든 것 (everything downstream)은 이를 다르게 해석할 자유가 있다.
...
이런 기록이 두 개라면 아무것도 얻지 못합니다. 하지만 스무 개가 된다면, 당신은 그동안 결여되었던 구조 (structure)를 갖게 됩니다.
신호는 항목들이 서로 겹치기 시작할 때 나타납니다. 즉, 별도로 기록된 네 가지 사항이 타입 강제 (type coercion)에 관한 하나의 아이디어로 밝혀질 때입니다. 그 붕괴 (collapse)는 멘탈 모델 (mental model)이 형성되는 과정이며, 이는 항목들이 비교될 수 있는 어딘가에 존재할 때만 일어날 수 있습니다.
⚖️ 진지하게 받아들일 만한 반론
반대의 약한 버전은 "모든 버그 뒤에 숨겨진 이론을 배울 시간이 없습니다. 저는 티켓 (tickets)을 처리해야 합니다" 입니다. 대답하기 쉬우며, 진짜 논거도 아닙니다.
강한 버전: 이해를 우선시하는 것은, 어쩌면 영원히 오지 않을지도 모를 이익을 위해 지금 지불해야 하는 실제 비용입니다. 대부분의 버그는 진정으로 일회성입니다. 다시 발생하지 않을 문제로부터 원칙을 추출하는 데 쓰는 노력은 되돌릴 수 없는 노력입니다. 그런 관점에서 보면, 이를 건너뛰는 것은 실수라기보다 합리적인 도박입니다.
그 말은 실질적으로 옳습니다. 그리고 바로 그 점 때문에 여기서의 권장 사항은 "문서를 제대로 읽으라"가 아니라 **"한 문장, 한 줄"**인 것입니다. 그 정도의 비용이라면 도박의 성격이 달라지기 때문입니다:
- 버그가 반복될 가능성에 대비해 버그당 한 시간을 허비하는 것이 아닙니다.
- 당신은 약 40초를 소비할 뿐이며, 그마저도 이미 충분한 비용을 치르고 있어 질문을 던질 만한 가치가 있는 버그들에 대해서만 수행합니다.
- 반복되는 버그들이 바로 이 방식이 잡아낼 수 있는 정확한 대상입니다.
이해하지 못한 일회성 문제는 비용이 들지 않습니다. 이해하지 못한 메커니즘은 매달 청구서를 보냅니다.
🎯 핵심 요약 (The takeaway)
두 가지입니다. 총 40초면 됩니다.
1. 모든 수정 요청(fix request)에 다음 문구를 추가하세요:
"이것이 왜 작동하는지, 그리고 데이터의 형태(shape)가 변한다면 무엇이 망가질지 설명해 주세요."
2. 이미 열어둔 파일에 이 원칙을 한 줄로 적어두세요.
이 도구는 당신의 막힌 상황을 뚫어줍니다(unblocked). 하지만 당신을 체계적으로 만들어주지는 않으며, 다음에 당신이 질문할 때 이 모든 것을 기억해주지도 않습니다. 그 부분은 언제나 당신의 몫이었습니다. 이전에는 막혔을 때 발생하는 부수적인 효과로 이루어졌지만, 이제는 그렇지 않을 뿐입니다.
이 글은 데이터 엔지니어를 위한 AI 실무 시리즈의 첫 번째 포스트입니다 — 모든 수준의 엔지니어들이 AI 도구를 어떻게 잘못 사용하는지, 왜 그런 일이 발생하는지, 그리고 더 나은 실무는 어떤 모습인지에 대해 다룹니다. 다음 편: 확신이 곧 정답은 아니다 — Claude가 추측하고 있다는 세 가지 신호.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기