> ## Content Index
> Fetch the complete content index at: https://blog.sorune.org/llms.txt
> Use this file to discover other available public pages before exploring further.

# AI가 만든 작은 예외는 어떻게 새로운 아키텍처가 되는가
- URL: https://blog.sorune.org/ai-generated-precedent-and-architecture-drift/
- Published: 2026-09-13T01:57:21.000Z
- Updated: 2026-09-13T01:57:21.000Z
- Description: 문제는 Python 자체가 아니었다. 작은 구현 편의가 현재 코드에 남고, 다음 AI가 그것을 정상 아키텍처로 해석하면서 Human이 승인하지 않은 선례가 누적되는 과정을 정리한다.
- Author: Sorune — Engineering, Photography & Lab Notes
- Tags: Engineering, AI-Native Engineering, Architecture Drift, Human Control, Provenance, Workspace Ops

AI가 코드를 많이 작성하는 환경에서 아키텍처가 바뀌는 방식은 생각보다 조용했다.

거대한 redesign proposal이 올라오고, 사람이 그것을 승인해서 바뀌는 경우만 있는 것이 아니었다.

오히려 더 위험했던 것은 작은 예외였다.

```text
이 기능만 이렇게 하면 간단하다.

```

한 번은 편의처럼 보인다.

문제는 그 결과가 repository에 남은 뒤부터 시작된다.

다음 AI는 과거의 의사결정을 모른 채 현재 코드를 읽는다. 그리고 이미 존재하는 구현을 현재 아키텍처의 일부로 해석한다.

그 결과 작은 예외가 선례가 된다.

```text
local convenience
        ↓
working implementation
        ↓
observed repository reality
        ↓
future AI assumption
        ↓
architecture precedent

```

내가 Workspace Ops에서 겪은 Python 관련 사건도 핵심은 Python이라는 언어가 아니었다.

문제는 **Human이 승인하지 않은 technology/runtime delta가 동작하는 코드가 된 뒤, 다음 작업의 정상 전제로 사용되기 시작했다는 것**이었다.

## 언어 선택 문제가 아니었다

당시 제품 경계는 대략 다음과 같았다.

```text
Product implementation
= shell-first / accepted runtime boundary

Python
= development / validation tooling may exist

Product runtime dependency change
= separate architecture review required

```

그런데 bounded implementation 과정에서 Python이 product runtime path에 들어갔다.

그 자체가 즉시 큰 장애를 만든 것은 아니었다.

코드는 동작했다.

그래서 더 발견하기 어려웠다.

```text
Human intent / baseline
        ↓
local implementation convenience
        ↓
unreviewed architecture delta
        ↓
working implementation
        ↓
future code assumes it is normal

```

중간 어디에서도 누군가가 이렇게 선언하지 않았다.

```text
"기존 technology decision을 폐기한다."

```

그런데 최종 시스템은 이미 다른 전제를 갖기 시작했다.

## 명시적인 권한 이양이 없어도 effective authority는 이동할 수 있다

보통 authority 문제를 생각하면 누가 최종 승인권을 갖느냐를 본다.

하지만 AI-assisted engineering에서는 문서상 authority와 실제로 시스템을 형성하는 힘이 달라질 수 있었다.

예를 들어 흐름이 이렇다.

```text
Human
"이 runtime은 product dependency가 아니다."

Executor A
"이 기능만 Python으로 하면 단순하다."

Executor B
"repository에 Python runtime path가 있으니 재사용한다."

Reviewer AI
"existing architecture와 일치한다."

Planner
"Python-backed control path를 기준으로 다음 단계를 설계한다."

```

어느 AI도 Human authority를 빼앗겠다고 말하지 않았다.

그런데 현재 코드가 계속 다음 AI의 input이 되면서 **effective authority가 implementation precedent 쪽으로 이동한다.**

나는 이 현상을 authority erosion에 가깝게 보게 됐다.

```text
WRITTEN AUTHORITY
= Human

EFFECTIVE SYSTEM SHAPE
= accumulated implementation precedent

```

둘이 다르면 최종 approve 버튼 하나만으로 통제가 보장되지 않는다.

## 현재 코드가 곧 설계 의도는 아니다

AI는 repository를 읽을 때 현재 상태를 강한 evidence로 사용한다.

그 자체는 당연하다.

문제는 현재 코드가 왜 그렇게 됐는지 모를 때다.

```text
CURRENT CODE
= current observed implementation

```

이지:

```text
CURRENT CODE
= original design intent

```

는 아니다.

현재 구현에는 여러 종류의 것이 섞여 있을 수 있다.

```text
accepted architecture
temporary workaround
unfinished migration
historical accident
unreviewed convenience
compatibility residue

```

provenance가 없으면 이들은 모두 "existing architecture"처럼 보인다.

AI가 그 위에 다시 reasoning을 쌓으면 우연한 상태에도 그럴듯한 rationale이 붙는다.

그 순간 accident가 design이 된다.

## 같은 메커니즘은 product identity도 바꿀 수 있다

이 문제는 technology stack에만 머물지 않는다.

PhotoGram의 Saved를 예로 들 수 있다.

원래 의미가 다음이라고 하자.

```text
Saved
= Photo / Story family-local collection
!= fifth global destination

```

구현 중 executor가 navigation을 단순하게 만들기 위해 Saved를 독립 global tab으로 만든다.

첫 변경은 단순한 UI implementation shortcut처럼 보일 수 있다.

그런데 다음 단계부터 의미가 바뀐다.

```text
implementation shortcut
        ↓
Saved exists as independent route
        ↓
next AI observes current code
        ↓
"Saved is a global destination"
        ↓
new design rationale is generated
        ↓
future implementation reinforces it

```

제품을 다시 설계하자는 명시적 결정은 없었다.

그런데 구현 편의가 semantic precedent가 되고, 결국 product identity가 이동한다.

```text
implementation detail
→ inferred semantics
→ generated rationale
→ new normal

```

이 패턴이 technology drift보다 더 위험할 수도 있다.

코드 구조가 아니라 사용자가 보는 제품 의미 자체가 바뀌기 때문이다.

## 큰 변경보다 작은 변경이 더 위험할 때가 있다

이상하게 들리지만 큰 architecture proposal은 오히려 다루기 쉽다.

```text
"이 시스템을 autonomous orchestrator로 재설계하겠습니다."

```

이 정도 proposal은 눈에 띈다.

사람이 멈추고 판단한다.

반면 실제 drift는 이런 모양이다.

```text
one helper
one fallback
one extra route
one inferred default
one automatic assignment
one new dependency

```

각 change는 작다.

review에서도 국소적으로 합리적으로 보인다.

하지만 누적하면 다른 시스템이 된다.

```text
small implementation deltas
        ↓
architecture precedent
        ↓
semantic precedent
        ↓
product identity shift

```

AI가 구현 속도를 높일수록 이 누적 속도도 빨라질 수 있다.

## 모든 미래 행동을 예측할 수는 없다

이 문제를 해결하려고 모든 AI 행동을 미리 규칙으로 막는 것도 현실적이지 않았다.

새로운 상황은 계속 생긴다.

그래서 중요한 것은 "무슨 변경이 일어날지"를 모두 예측하는 것이 아니라 **기존 Human-owned meaning을 넘어서는 순간 어떻게 반응할 것인지**였다.

예를 들면 이런 종류의 delta다.

```text
Product identity change
Architecture boundary change
Technology/runtime dependency change
Authority model change
Ownership model change
Public contract change
Persistence semantics change
Security model change
Canonical dependency direction change

```

이런 경계를 넘는 순간에는 구현을 계속 진행하는 것보다 의미를 먼저 보여주는 편이 낫다.

```text
boundary-crossing delta detected
        ↓
STOP affected mutation
        ↓
show exact semantic delta
        ↓
show affected Human-owned invariant
        ↓
show why current model cannot satisfy requirement
        ↓
show bounded options / recovery impact
        ↓
Human decides

```

핵심은 AI를 느리게 만드는 것이 아니다.

**implementation convenience가 product meaning change로 승격되는 순간을 visible하게 만드는 것**이다.

## 마지막 Human approval만으로는 부족할 수 있다

겉으로 Human-in-the-loop 구조여도 실질 통제는 약할 수 있다.

예를 들어:

```text
AI-written architecture
AI-written implementation
AI-written tests
AI-written documentation
AI-written rationale
AI-written review summary
        ↓
Human: Approve / Reject

```

형식적으로는 사람이 최종 승인한다.

하지만 그 사람이 underlying assumption을 다시 복원하지 못한다면 approve 버튼은 실질 authority를 충분히 보장하지 못한다.

그래서 Human control에는 최소한 네 가지가 필요하다고 보게 됐다.

```text
understandability
traceability
vetoability
recoverability

```

사람이 최소한 다음을 알 수 있어야 한다.

```text
무엇이 바뀌었는가?
왜 바뀌었는가?
어떤 기존 invariant를 건드렸는가?
어떻게 이전 상태로 돌아가는가?
거부해도 안전한 상태를 유지할 수 있는가?

```

이 정보가 있어야 최종 승인이 의미를 갖는다.

## History는 authority가 아니라 provenance다

이 문제를 겪으면서 History를 보는 방식도 더 명확해졌다.

History 문서가 현재 시스템의 authority가 되어서는 안 된다.

과거 결정이 현재 결정을 자동으로 지배하면 또 다른 문제가 생긴다.

하지만 provenance는 필요하다.

현재 코드를 읽은 AI가 이렇게 생각하는 것과:

```text
"Python path가 존재한다.
그러므로 원래 architecture다."

```

이렇게 아는 것은 다르다.

```text
"이 path는 bounded implementation 중 들어왔고,
Human architecture approval evidence가 없었으며,
이후 contract mismatch로 forensic review가 수행됐다."

```

그래서 세 층을 분리하게 됐다.

```text
CURRENT CODE
= observed implementation evidence

HISTORY
= provenance / why it happened

CURRENT AUTHORITY
= what is accepted now

```

어느 하나만으로 나머지를 자동 추론하면 안 된다.

## 해결책은 governance를 끝없이 늘리는 것이 아니었다

이런 사건을 겪으면 규칙을 더 많이 만들고 싶어진다.

하지만 그것도 위험하다.

AI control을 강화한다는 이유로 control system이 너무 복잡해지면, 사람은 결국 그 시스템 자체를 이해하지 못하게 된다.

그러면 또 다른 형태의 control inversion이 생긴다.

그래서 이후 방향은 오히려 restraint에 가까웠다.

```text
scope를 freeze한다
        ↓
real workload에서 사용한다
        ↓
실제 boundary failure를 본다
        ↓
existing primitive로 고칠 수 있는지 본다
        ↓
반복되는 failure만 abstraction 후보로 올린다

```

규칙을 예상해서 계속 추가하기보다 실제 evidence를 보고 필요한 만큼만 올리는 방식이다.

## 내가 가장 경계하게 된 것은 AI의 명시적인 권한 탈취가 아니다

AI가 대놓고 "이제 내가 architecture authority다"라고 말하는 상황은 오히려 알아보기 쉽다.

더 현실적인 위험은 이쪽이다.

```text
Human authority remains written
while effective product meaning
is increasingly authored by AI-generated precedent

```

문서에는 Human이 결정권자라고 적혀 있다.

하지만 실제 시스템의 모양은 AI가 이전 AI의 코드를 읽고 계속 정당화하면서 만들어진다.

이 둘 사이의 차이를 줄이려면 AI가 덜 코딩하게 만드는 것이 아니라 **선례가 만들어지는 과정을 추적 가능하게 해야 한다.**

작은 구현 예외가 정말 작은 예외로 끝났는지, 아니면 다음 작업의 architecture가 되었는지 볼 수 있어야 한다.

AI-native engineering에서 내가 점점 중요하게 보는 것은 바로 그 부분이다.