본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 05. 31. 20:50

1972년의 논문은 AI 코딩 위기를 예측했다. 아무도 듣지 않았다.

요약

1972년 David Parnas의 논문을 통해 AI 코딩 에이전트 시대의 '인지 부채' 문제를 분석합니다. AI가 생성한 코드를 검토만 하고 완전히 이해하지 못한 채 병합할 때 발생하는 유지보수의 어려움을 경고합니다.

핵심 포인트

  • 모듈 분해의 기준은 성능이 아닌 인간의 인지 능력이어야 함
  • AI 에이전트의 빠른 코드 생성은 개발자의 인지적 항복을 유도함
  • 승인 가능한 이해와 수정 가능한 이해 사이의 간극인 '인지 부채' 발생
  • 코드 자체보다 코드에 대한 불완전한 정신 모델이 문제의 핵심임

1972년에 작성된 한 논문은 현재 AI 코딩 에이전트(AI coding agents)들이 만들어내고 있는 위기를 매우 정확하게 묘사하고 있습니다.

David Parnas는 소프트웨어가 메인프레임에서 구동되고 대규모 프로그램이 10,000줄 정도였던 시절에 "시스템을 모듈로 분해할 때 사용되는 기준에 대하여(On the Criteria To Be Used in Decomposing Systems into Modules)"라는 논문을 발표했습니다. 이 논문은 시스템을 분해하는 전통적인 방식(실행 단계별 분해: 입력 → 처리 → 출력)이 잘못되었으며, 대신 _변경될 가능성이 높은 설계 결정(design decisions)_에 따라 시스템을 분해해야 한다고 주장했습니다.

그 이유는 컴파일러의 효율성이나 런타임 성능이 아닌, 인간의 인지(human cognition) 때문이었습니다. Parnas는 소프트웨어 공학의 어려운 병목 현상은 개발자가 시스템을 안전하게 변경할 수 있을 만큼 충분히 잘 이해할 수 있는 능력이라고 주장했습니다. 모듈의 경계는 인간의 이해를 보호하기 위해 존재합니다. 그 외의 모든 것은 부차적인 것입니다.

53년이 지난 지금, AI 코딩 에이전트들은 인간이 이해할 수 있는 속도보다 5~7배 더 빠르게 복잡한 로직을 생성합니다. 개발자들은 일종의 '인지적 항복(cognitive surrender)'을 통해 코드를 수용합니다. 그들은 출력을 검토하고, 테스트가 통과되면, 그것이 어떻게 또는 왜 작동하는지에 대한 정신적 모델(mental model)을 구축하지 않은 채 코드를 병합(merge)합니다.

Parnas는 이러한 실패 모드(failure mode)가 발생하기 반세기 전에 이를 정확히 진단했습니다. 그리고 그의 해결책은 여전히 유효합니다.

소방 호스 효과 (The Firehose Effect)

실제로 어떤 일이 일어나는지 살펴보겠습니다. 당신이 AI 에이전트에게 지수 백오프(exponential backoff)와 서킷 브레이커(circuit breaking) 기능이 포함된 재시도 메커니즘(retry mechanism)을 구현하라고 프롬프트를 입력합니다. 에이전트는 잘 구조화된 300줄의 코드를 반환합니다. RetryPolicy 구조체, 상태 관리가 포함된 CircuitBreaker, 지터(jitter)가 포함된 BackoffCalculator, 통합 테스트(integration tests), 그리고 일시적 실패와 최종적 실패를 구분하는 오류 분류 로직 등이 포함됩니다.

코드는 작동합니다. 테스트는 통과합니다. 당신은 코드를 읽고, 구조를 보며 고개를 끄덕인 뒤, 병합합니다.

3주 후, 당신은 특정 엔드포인트(endpoint) 하나에 대한 재시도 동작(retry behavior)을 변경해야 합니다. 파일을 엽니다. 서킷 브레이커(circuit breaker)가 백오프 계산기(backoff calculator)와 어떻게 상호작용하는지 기억나지 않습니다. max-retries 상수를 변경하는 것이 서킷 브레이커의 실패 임계값(failure threshold)에 영향을 미치는지 확신할 수 없습니다. 오류 분류기(error classifier)의 일시적(transient) 카테고리에 타임아웃(timeout)이 포함되는지, 아니면 HTTP 5xx 응답만 포함되는지도 알 수 없습니다.

당신은 이 코드 중 그 어느 것도 직접 작성하지 않았습니다. 단 한 번 리뷰했을 뿐입니다. 승인할 수 있을 만큼은 충분히 이해했습니다. 하지만 안전하게 수정할 수 있을 만큼 충분히 이해하지는 못했습니다.

승인할 수 있을 정도의 이해와 수정할 수 있을 정도의 이해 사이의 그 간극 — 그것이 바로 인지 부채(cognitive debt)입니다. 그것은 코드 속에 있는 것이 아니라 당신의 머릿속에 존재합니다. 코드는 괜찮습니다. 코드에 대한 당신의 정신 모델(mental model)이 불완전할 뿐입니다. 그리고 그 모델은 AI가 그것을 구축해 주었을 인지적 고군분투(cognitive struggle)를 건너뛰어 버린 순간 불완전해졌습니다.

Parnas가 지목한 원인은 다음과 같습니다: 시스템이 정보 은닉(information hiding)을 위반했다는 것입니다. 코드가 형편없이 작성되었기 때문이 아니라, 모듈 경계(module boundaries)가 당신의 이해력을 보호하도록 설계되지 않았기 때문입니다. 서킷 브레이커, 백오프 계산기, 오류 분류기가 모두 당신에게 동시에 노출되어 있습니다. 하나를 변경해야 할 때, 당신은 세 가지 모두를 추론해야 합니다. 코드는 자신의 설계 결정(design decisions)을 숨기지 않았습니다. 그것을 당신에게 쏟아부었습니다. 그것이 바로 소방 호스(firehose)입니다.

Parnas의 주장 (이것은 코드 조직화에 관한 것이 아닙니다)

1972년의 논문은 널리 인용되지만 널리 오해받고 있습니다. 대부분의 개발자는 Parnas가 코드 조직화 원칙인 "명확한 모듈 경계"를 주장했다고 생각합니다. 하지만 그는 더 깊은 것을 주장했습니다. 모듈 경계를 어디에 둘 것인가에 대한 기준은 어떤 설계 결정이 변경될 가능성이 높은지에 기반해야 한다는 것입니다.

전통적인 방식은 처리 단계에 따라 시스템을 분해했습니다. 즉, 입력 모듈, 처리 모듈, 출력 모듈로 나누는 방식입니다. 각 단계가 하나의 모듈이 됩니다. Parnas는 이것이 잘못되었다는 것을 보여주었습니다. 단순히 지저분해서가 아니라, 개발자가 모듈 경계를 가로지르는 설계 결정 (design decisions)을 이해하도록 강요하기 때문입니다. 입력 형식이 변경되면 처리 모듈도 함께 변경되어야 합니다. 처리 모듈이 입력 형식을 알고 있기 때문입니다. 설계 결정 (입력 형식)이 경계를 넘어 유출 (leaked)된 것입니다. 이제 입력 형식을 변경하는 개발자는 하나의 모듈이 아닌 두 개의 모듈을 이해해야 합니다.

Parnas가 제시한 대안은 다음과 같습니다. 각 변동성이 큰 설계 결정 (volatile design decision)을 단일 모듈 내부에 숨기는 것입니다. 입력 형식은 하나의 모듈에 존재합니다. 처리 알고리즘은 다른 모듈에 존재합니다. 출력 형식은 세 번째 모듈에 존재합니다. 입력 형식이 변경될 때, 오직 입력 모듈만 변경됩니다. 개발자는 단 하나의 모듈만 이해하면 됩니다. 모듈 간의 인터페이스 (interface)는 안정적입니다. 인터페이스 뒤의 구현 (implementation)은 숨겨져 있습니다.

핵심 단어는 숨겨진 (hidden) 입니다.

그 결과는 Parnas가 경고했던 바로 그 분해(decomposition)입니다. 설계 결정(design decisions)(오류 분류 정책, 백오프 전략, 서킷 임계값)이 아닌 실행 단계(요청 수신 → 오류 분류 → 백오프 계산 → 서킷 상태 확인 → 재시도 또는 중단)에 따라 조직화되어 있습니다. 세 가지 설계 결정이 서로 뒤엉켜 있습니다. 하나를 변경하려면 세 가지 모두를 이해해야 합니다.

이것은 AI 품질의 문제가 아닙니다. 시간 압박 속에서 코드를 작성하는 숙련된 인간 개발자도 똑같은 뒤엉킴을 만들어냅니다. 차이점은 인간 개발자는 최소한 구현 과정에서 고군분투하며 뒤엉킨 결정들에 대한 부분적인 정신 모델(mental model)을 구축한다는 것입니다. 반면 AI는 즉각적으로 뒤엉킴을 생성하며, 개발자는 모델을 전혀 구축하지 못합니다.

AI가 수십 개의 모듈에 걸쳐 이 정도 속도로 생성할 때, 그 효과는 복리로 증가합니다. 각 모듈에는 설계 결정이 유출(leaking)되어 있습니다. 유출된 각 결정은 개발자가 안전한 변경을 수행하기 위해 반드시 이해해야 하는 구현의 조각입니다. 이를 AI로 가속화된 코드베이스 전체에 곱하면, 인지 부채(cognitive debt) 분석에서 말하는 '파이어호스 효과(firehose effect)'가 나타납니다. 즉, 노출된 설계 결정의 양이 인간의 인지 능력(cognitive capacity)을 초과하게 됩니다.

인지 방화벽 (Cognitive firewalls)

Parnas의 해결책을 AI 생성 코드에 적용하면, 일종의 인지 방화벽(cognitive firewall)을 구축하게 됩니다:

[ AI 에이전트가 복잡한 구현을 생성함 ]
                │
                ▼
...

개발자는 AI의 내부 알고리즘 선택을 이해할 필요가 없습니다. 그들은 인터페이스(interface)를 이해해야 합니다. 즉, 모듈이 무엇을 제공하는지, 무엇을 요구하는지, 무엇을 보장하는지, 그리고 그 보장이 위반되었을 때 어떤 일이 발생하는지를 이해해야 합니다.

재시도(retry) 예제의 경우, Parnas식 분해는 각 설계 결정을 숨깁니다:

모듈 1: ErrorClassifier
  인터페이스: classify(error) → transient | terminal
  숨겨진 내용: 분류 규칙, 정규 표현식(regex) 패턴,
...

각 인터페이스는 12줄에 불과합니다. 각 숨겨진 구현(implementation)은 AI가 생성한 50100줄의 코드일 수 있습니다. 개발자는 세 개의 인터페이스(6줄)를 이해합니다. AI는 그 뒤에서 150~300줄의 코드를 생성했습니다. 개발자의 인지 부하(cognitive load)는 구현이 아니라 인터페이스에 따라 확장됩니다.

개발자가 백오프 전략(backoff strategy)을 변경해야 할 때, 그들은 모듈 2를 수정합니다. 모듈 1이나 모듈 3은 건드리지 않습니다. 백오프 곡선(backoff curve)을 변경하기 위해 서킷 브레이커(circuit breaker)의 상태 머신(state machine)을 이해할 필요는 없습니다. 설계 결정(design decisions)은 숨겨져 있습니다. 인지적 방화벽(cognitive firewall)이 유지됩니다.

AI 에이전트가 따라야 할 기준

분해(decomposition)에 대한 Parnas의 기준 — "어떤 설계 결정이 변경될 가능성이 높은가?" — 는 대부분의 AI 코딩 워크플로우에서 누락된 지침입니다.

개발자가 "서킷 브레이킹(circuit breaking)을 포함한 재시도(retry)를 구현해줘"라고 프롬프트를 입력할 때, AI는 (또는 개발자가) 다음과 같이 물어야 합니다: "이 구현에서 어떤 설계 결정들이 독립적으로 변경될 수 있습니까?"

재시도 예시에 대한 답변은 다음과 같습니다:

  • 새로운 에러 유형이 발견되면 에러 분류(error classification) 규칙이 변경될 것입니다.
  • 성능 요구사항이 바뀌면 백오프 전략(backoff strategy)이 변경될 것입니다.
  • 신뢰성 목표가 바뀌면 서킷 브레이커 임계값(circuit breaker thresholds)이 변경될 것입니다.
  • 이들 사이의 통합(재시도 루프 오케스트레이션(retry loop orchestration))은 거의 변경되지 않을 것입니다.

독립적으로 변경 가능한 각 결정은 하나의 모듈이 됩니다. 통합 부분은 인터페이스를 통해 모듈을 호출하는 얇은 오케스트레이터(orchestrator)가 됩니다. 개발자는 오케스트레이터(10줄)와 인터페이스(6줄)를 이해합니다. 구현은 숨겨집니다.

이것은 새로운 것이 아닙니다. Parnas는 이를 1972년에 발표했습니다. 새로운 점은 AI가 이 원칙의 위반을 자동화하고 보이지 않게 만든다는 것입니다. AI는 모놀리식 구현(monolithic implementations)이 프롬프트를 효율적으로 해결하기 때문에 모놀리식 구현을 생성합니다. Parnas의 분해(decomposition)는 개발자가 AI의 출력물에 강제해야 하는 제약 조건입니다. AI는 스스로에게 이 제약을 가하지 않을 것입니다.

Unix는 이미 이를 증명했다

Unix의 설계는 운영체제(Operating System) 수준에서 적용된 Parnas의 원칙입니다. 모든 Unix 도구는 표준 입력(stdin), 표준 출력(stdout), 종료 코드(exit codes)라는 보편적인 인터페이스(Interface) 뒤에 자신의 구현(Implementation)을 숨깁니다.

grep은 자신의 정규 표현식 엔진(Regex engine)을 노출하지 않습니다. sort는 자신의 정렬 알고리즘(Sorting algorithm)을 노출하지 않습니다. uniq는 자신의 중복 제거 로직(Deduplication logic)을 노출하지 않습니다. 각 도구는 숨겨진 구현과 안정적인 인터페이스(텍스트 스트림 입력, 텍스트 스트림 출력)를 가진 Parnas 모듈(Module)입니다.

그 결과: grep의 소스 코드를 단 한 줄도 읽어본 적 없는 개발자라도 grep | sort | uniq를 조합할 수 있으며, 그 출력값을 확실하게 예측할 수 있습니다. 인지 부하(Cognitive load)는 구현(정규 표현식 유한 오토마타, 병합 정렬, 해시 기반 중복 제거)이 아니라 인터페이스(텍스트 스트림 처리)에 의해 제한됩니다.

AI가 생성한 코드도 동일한 방식으로 조합되어야 합니다. 각 모듈은 개발자가 구현을 읽지 않고도 추론할 수 있는 안정적인 인터페이스를 가져야 합니다. 구현은 AI에 의해 생성될 수 있고, 불투명하며, 복잡할 수 있습니다. 하지만 인터페이스는 반드시 사람이 읽을 수 있고, 안정적이며, 단순해야 합니다.

AI가 구현만큼이나 복잡한 인터페이스를 가진 모듈을 생성한다면, 그 코드가 제대로 작동하는지 여부와 상관없이 Parnas 테스트(Parnas test)를 통과하지 못한 것입니다.

인터페이스는 계약(Contract)으로 진화한다

Parnas는 단일 언어로 작성된 단일 프로그램 내에서의 인터페이스를 설명했습니다. 하지만 이 원칙은 모듈의 경계에서 멈추지 않습니다. 업계는 수십 년 동안 인터페이스의 진화를 거쳐 왔으며, 각 단계는 동일한 정보 은닉(Information-hiding)의 통찰을 더 큰 규모로 적용해 왔습니다.

레벨 1: 모듈 내부 — 언어 수준의 인터페이스(Language-level interfaces). Go의 interface{}, Java의 interface, TypeScript의 타입 시그니처(Type signatures)가 이에 해당합니다. 개발자는 구현과 동일한 언어로 계약(Contract)을 정의합니다. type ErrorClassifier interface { Classify(err error) ErrorKind }. 컴파일러가 이를 강제합니다. 구현은 타입 시스템(Type system) 뒤에 숨겨집니다. 모든 개발자는 이미 이 수준을 알고 있습니다.

Level 2: 모듈 간 — 패키지 경계 (package boundaries). Go의 internal/ 관례. Java의 모듈 시스템 (module system). 패키지 수준의 내보내기 (exports) 대 비공개 내부 구현 (private internals). 개발자는 내보내진 API를 봅니다. 내보내지지 않은 구현은 언어의 가시성 규칙 (visibility rules)에 의해 숨겨집니다. 동일한 Parnas 원칙이 적용되며, 이는 단순히 규율에 의해서가 아니라 언어의 모듈 시스템에 의해 강제됩니다.

Level 3: 시스템 간 — API 계약 (API contracts). OpenAPI, gRPC/Protocol Buffers, GraphQL 스키마 (schemas). 인터페이스는 더 이상 구현과 동일한 언어로 되어 있지 않습니다. API 계약은 언어에 독립적인 스키마 (schema)로 표현됩니다. Python 클라이언트와 Go 서버가 OpenAPI 명세 (spec)를 공유합니다. 양측 모두 상대방의 구현을 이해할 필요가 없으며, 심지어 어떤 언어로 작성되었는지조차 알 필요가 없습니다. 이것이 첫 번째 주요 도약이었습니다: 언어 경계를 가로지르는 정보 은닉 (information hiding). 계약은 그 어떤 구현과도 분리된 독립적인 산출물 (artifact)이 되었습니다.

Level 4: 조직 간 — 표준 형식 (standard formats). JSONL, SARIF, SMT-LIB, OCSF. 인터페이스는 더 이상 두 특정 시스템 사이의 것이 아닙니다. 그것은 어떤 시스템이든 구현할 수 있는 표준 (standard)입니다. SARIF는 특정 보안 스캐너 (security scanner)의 소유가 아닙니다. 그것은 어떤 스캐너든 생성할 수 있고 어떤 대시보드(dashboard)든 소비할 수 있는 형식입니다. 계약은 보편적이 되었습니다. 구현은 완전히 교체 가능한 (interchangeable) 것이 되었습니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0