슈뢰딩거의 개발자
Martin Fowler의 LLMs bring new nature of abstraction 글을 보고 든 생각을
LLM과 정리하다가 탄생한 글입니다.
"신은 주사위 놀이를 하지 않는다."
— 알베르트 아인슈타인, 양자역학을 비판하며
20세기 초, 뉴턴 역학의 결정론이 양자역학의 불확정성에 자리를 내주면서 물리학의 패러다임이 완전히 바뀌었습니다.
오늘날, 소프트웨어 개발자들도 비슷한 거대한 전환의 한가운데 서 있습니다.
AI, 특히 LLM(대규모 언어 모델)은 프로그래밍을 확률적인 작업으로 변화시키고 있습니다.
기존의 개발 문법과 테스트, 리뷰 관행은 더 이상 충분하지 않습니다.
우리는 새로운 사고방식, 새로운 역할, 그리고 새로운 전략을 요구받고 있습니다.
고전역학에서 물체의 운동은 완벽하게 예측 가능했습니다.
초기 조건과 작용하는 힘을 알면 미래의 모든 상태를 정확히 계산할 수 있었죠.
개발의 세계도 마찬가지였습니다.
입력과 조건이 명확하면 출력도 항상 같아야 한다는 전제가 깔려 있었습니다.
같은 코드를 실행하면 언제나 같은 결과가 나와야 했고
테스트는 이 전제 위에 설계되었으며
코드 리뷰는 프로세스가 정확히 적용됐는지 검증하는 과정이었습니다.
세상은 정해진 규칙만 따르면 오차 없이 작동하는 '기계'와 같았고,
우리는 그 기계를 설계하고 조립하는 엔지니어였습니다.
이 결정론적 기반 위에서 TDD(테스트 주도 개발), 정적 분석, 코드 리뷰, 형상 관리, CI/CD(지속적 통합과 배포) 같은 견고한 개발 문화가 만들어졌습니다.
이 모든 것의 전제는 명확했습니다.
"이 코드는 항상 이렇게 동작해야 한다."
입자의 위치와 운동량은 동시에 정확히 측정할 수 없다.
— 하이젠베르크의 불확정성 원리
양자역학의 핵심인 하이젠베르크의 불확정성 원리를 AI 시대의 개발에 적용해 볼 수 있습니다.
프롬프트의 의도와 LLM 출력 결과는 동시에 완벽하게 통제할 수 없다.
LLM 기반 개발에서는 다음과 같은 현상이 흔하게 발생합니다.
같은 프롬프트를 여러 번 실행해도 매번 출력이 조금씩 다릅니다.
그 차이는 단순한 난수의 문제가 아니라, 모델 내부의 확률적 해석에서 비롯됩니다.
프롬프트는 '명령'이라기보다 '출력 경향'을 유도하는 '설계 지시문'에 가깝습니다.
개발자는 '정답'을 얻는 것이 아니라, 의도된 가능성의 '스펙트럼'을 설계하는 역할을 맡습니다.
이는 고전역학이 아니라 양자역학의 영역과 닮아 있습니다.
결과는 확률적으로 존재하며, 우리가 '관측(프롬프트 작성)'하는 방식이 결과에 영향을 미칩니다.
관측 전까지는 모든 가능성이 중첩되어 있다. 그리고 관측은 그중 하나를 실현시킨다.
— 코펜하겐 해석
LLM을 통한 개발에서 프롬프트의 구조와 맥락이 출력의 경향과 품질을 결정합니다.
프롬프트 A: 간단한 요청
"리스트를 정렬하는 함수 만들어줘."
프롬프트 B: 상세한 요청
"""
숫자 리스트를 내림차순으로 정렬하는 파이썬 함수 만들어줘.
요구사항:
- 효율적인 알고리즘 사용 (O(n log n) 이상)
- 특이 케이스 처리 (리스트에 숫자가 들어있지 않거나, 하나가 들어있을 때 등)
- 적절한 오류 처리 기능 포함
- 함수를 설명하는 주석 작성
- PEP 8 스타일 가이드라인 준수
"""
위 두 프롬프트는 모두 '정렬 함수 작성'이라는 동일한 목표를 요청하지만, 프롬프트 구성이라는 '관측 방법'에 따라 전혀 다른 결과물이 나옵니다.
프롬프트는 단순한 명령이 아니라, 그 자체가 하나의 설계입니다.
따라서 프롬프트 자체도 코드처럼 리뷰의 대상이 됩니다.
출력의 품질은 프롬프트의 구조와 그에 담긴 설계 의도에 따라 크게 달라집니다.
이전까지의 개발이 정확성(Accuracy) 중심이었다면,
LLM 기반 개발은 수용 가능성(Acceptability) 중심으로 옮겨가고 있습니다.
여기서 새로운 질문들이 등장합니다.
출력이 매번 달라질 수 있다면, 테스트는 어떻게 설계해야 할까요?
동일한 프롬프트라도 실행 환경에 따라 결과가 바뀐다면, 어떤 부분을 고정하고 관리해야 할까요?
85점 수준까지 허용한다면, 이 '85점'에 대한 기준은 무엇이 되어야 할까요?
이 질문들은 모두 결정론이 무너진 환경에서의 새로운 전략 설계를 요구합니다.
수용 가능성은 팀 또는 프로젝트의 목표, 위험 허용 범위에 따라 유연하게 정의되어야 하며, 완전한 정답보다는 ‘충분히 좋은(good enough)' 상태를 목표로 삼게 됩니다.
LLM이 생성한 여러 결과물 중 가장 적합한 것을 선택하고, 부족한 부분은 수동으로 미세 조정하며, 필요하다면 A/B 테스트 등을 통해 실제 성능을 검증하는 방식이 더욱 중요해질 것입니다.
LLM의 등장은 단순한 기술 변화가 아닙니다.
개발이라는 사고 체계 전체를 전환시키는 시발점입니다.
기존 개발자는 다음의 전제 위에서 움직였습니다.
문제 정의 → 설계 → 구현 → 검증
코드 로직이 문제 해결의 핵심이며, 버그는 대부분 로직 내부의 실수에서 발생합니다.
협업은 코딩 스타일과 설계 방향의 합의로 조율됩니다.
그러나 LLM을 활용하는 개발자
문제 정의 자체가 모호하거나, 정답이 여러 개 존재할 수 있습니다.
프롬프트는 '정답 요청'이 아닌 '출력 방향 제시'에 가깝습니다.
버그는 로직 자체보다도 맥락 설명의 부재, 혹은 프롬프트 설계의 부족함에서 발생할 수 있습니다.
리뷰 대상은 코드를 넘어 프롬프트와 문제 해석 그 자체로 확장됩니다.
LLM은 개발 작업을 '구현'에서 '설계와 해석'의 영역으로 확장하고 있습니다.
이제 중요한 것은 완벽한 문법 구사 능력이 아니라, 복잡한 의도를 정확하게 설명하는 능력입니다.
또한, LLM이 내놓은 결과를 분석하고, 실험하고, 튜닝하며, 최종적으로 수용 가능한 상태로 조정하는 능력이 중요해졌습니다.
즉, 의도를 설계하고 해석하는 메타 설계자로서의 능력이 필요해졌습니다.
아인슈타인은 "신은 주사위 놀이를 하지 않는다"라고 했지만, 양자역학은 우주가 본질적으로 확률적임을 보여주었습니다.
마찬가지로, 개발자도 이제 불확정성을 받아들이고 그 안에서 가치를 창출할 수 있어야 합니다.
고전역학이 여전히 우리 일상을 지배하듯, 전통적인 개발 방법론도 여전히 중요합니다.
LLM이 생성한 코드를 이해하고 평가하며 수정하려면 깊이 있는 기반 지식이 여전히 필수적입니다.
하지만 이제 그것만으로는 충분하지 않습니다.
우리는 지금, 뉴턴의 사과나무 아래에서 양자 컴퓨터를 마주하는 시대에 살고 있습니다.
이 모순적이고 흥미진진한 시대를 살아가기 위해,
개발자는 고전과 양자를 모두 이해하는 '하이브리드 개발자'가 되어야 합니다.