Information Leak vs Abstraction — Module 축의 자기 점검 도구
information-hiding이 목표라면, leak은 그 목표가 깨지는 순간. Joel Spolsky의 Law of Leaky Abstractions (2002) + Ousterhout의 information leakage가 핵심 source. overview의 Module 축 4번째 노트. 짧지만 강력한 도구 — 모든 module의 건강성을 매 design 결정마다 점검하는 measure.
한 줄
모든 non-trivial abstraction은 어느 정도 leak한다 (Spolsky). 핵심은 leak을 막는 것이 아니라 예측 가능한 leak으로 만드는 것. Leak의 양과 종류는 모듈 design의 건강성 measure. AI 시대에 더 강하게 작동 — AI agent는 interface만 보고 작동해서 leak에 가장 취약.
⚛️ 철학
원칙의 왜. 더 깊은 root와의 연결.
information-hiding이 약속하는 것: module이 secret을 감춘다. 그러나 현실:
모든 non-trivial 추상화는 어느 정도 leak한다. — Joel Spolsky, The Law of Leaky Abstractions (2002)
Leak의 정의: Secret으로 감춘 것이 외부 사용자에게 영향을 미치는 순간. interface가 거짓말이 되는 모든 경우.
Spolsky의 원래 사례:
- TCP가 *"reliable byte stream"*이라 약속하지만, latency·packet loss는 leak — 사용자는 timeout과 retry를 처리해야 함
- ORM이 *"DB를 감춤"*이라 약속하지만, N+1 쿼리·deadlock은 leak — 사용자는 SQL을 알아야 함
- HTTP가 *"client-server 추상화"*라 약속하지만, latency, redirect, cache는 leak
Spolsky의 핵심 통찰:
Abstraction은 시간을 절약해주지만, 사용자가 그 abstraction이 leak할 때를 위해 원리를 알아야 함. 결국 학습 비용은 줄지 않는다.
이 명제가 information-hiding의 자기 점검 도구인 이유:
- Leak이 많은 module = 추상화가 잘못 그어짐
- Leak이 적은 module = secret이 진짜로 격리됨
- Leak의 양이 module 건강성의 measure
Ousterhout의 information leakage 개념
Spolsky가 추상화의 본질적 leak을 다룬다면, Ousterhout는 피할 수 있는 leak을 정의:
Information leakage는 같은 design decision이 여러 module에 걸쳐 표현되는 경우. — A Philosophy of Software Design
예시:
- Module A가 JSON으로 데이터 표현 + Module B가 같은 JSON 파싱. JSON 형식이 secret이 아님 — 두 module이 같이 알아야 함 → leak
- Module A가 날짜를 ISO 8601로 직렬화 + Module B가 같은 형식 파싱. 형식 변경 시 둘 다 수정 → leak
- Module A가 retry 로직 + Module B도 같은 retry 로직 별로 → leak (응당 한 곳에 모여야)
해결: 같은 secret은 한 module에 모음. *DRY (Don't Repeat Yourself)*가 information leakage의 process-level 답.
다른 root와의 연결
- information-hiding — leak은 information hiding의 반대 방향. hiding이 잘 되면 leak 적음
- deep-modules — 얕은 깊이 (deep shallow module) 함정의 정확한 measure가 leak. interface만 좁고 secret 격리 안 되면 leak 폭발
- simple-not-easy — complect (얽힘) 자체가 leak의 한 종류. 두 module이 secret을 공유하면 얽힘
- orthogonality — leak이 없으면 module이 orthogonal해짐. layer 간 의존이 interface로만
🧱 추상적 작동 구조
Module의 leak 형태를 시각화:
Leak의 4가지 종류
| Leak 종류 | 무엇이 새는가 | 예시 |
|---|---|---|
| 성능 leak | 추상화의 cost (latency, throughput, memory) | TCP latency, ORM N+1, LLM provider별 latency 차이 |
| 에러 leak | 내부 에러가 외부 시맨틱으로 노출 | DB connection error → "도메인 작업 실패", 네트워크 에러 → 사용자에게 raw |
| Timing leak | 시간 순서·일관성이 외부에 영향 | cache stale, eventual consistency, race condition |
| Resource leak | OS 자원(memory/handle/file descriptor)이 외부 책임 | C의 manual memory, file handle 누수, thread pool 고갈 |
Spolsky's Law의 일반화: 모든 abstraction이 4가지 leak 중 하나는 가짐. 어떤 leak도 없는 abstraction은 trivial하거나 non-functional.
Abstraction tax 개념
Leak이 있으면 사용자가 두 비용을 지불:
사용자 비용 = abstraction 학습 비용 + leak 처리 비용
Trade-off:
- abstraction이 얕음 → 학습 비용 작음 + leak 처리 직접 (원리 보임)
- abstraction이 깊음 → 학습 비용 큼 + leak 발생 시 더 hard (블랙박스)
좋은 abstraction = 학습 비용 + leak 처리 비용 합이 raw 사용보다 작음. 이 합이 raw보다 크면 abstraction은 net negative.
⚠️ 약점/한계
원칙의 적용 한계. 잘못 적용 시 함정.
1. Leak을 인정하면 추상화 의지가 꺾임
"모든 abstraction은 leak한다"를 too literally 받으면 abstraction을 만들지 말자는 결론으로 빠짐. 이건 Spolsky의 의도와 정반대. Abstraction은 여전히 가치 있음. 다만 leak을 의식해야 함.
해결: abstraction을 만들 때 leak을 미리 design. 예측 못한 leak만 위험.
2. 모든 leak을 막으려는 시도가 over-engineering
Leak 종류 4가지 모두를 완벽히 처리하려면 interface가 비대해짐:
- 성능 leak → timing budget을 모든 method에 추가
- 에러 leak → Result<T, AllPossibleErrors>
- Timing leak → version number, timestamp 모든 곳
- Resource leak → handle ownership을 모든 곳
→ Interface가 implementation만큼 복잡해짐 = deep-modules 정신 정반대. 어떤 leak이 실제로 사용자에게 중요한가를 strategic하게 선택.
3. Leak을 contract로 만드는 비용
Leak을 명시적으로 만들면 (Result type, timeout parameter 등) interface 학습 곡선 증가. raw가 더 simple해 보일 수 있음. 균형 필요.
4. AI 시대 specific — AI agent의 interface-only 사고
AI agent는 interface를 face value로 받음. Leak은 경험으로 알아야 하는 것:
- "TCP는 reliable이라고 docs에 적혀 있음" → AI는 그대로 받음
- "ORM이 DB를 감춤이라고 docs에 적혀 있음" → AI는 N+1 만듦
→ AI 시대에 leak은 더 위험. 사람이 경험으로 leak을 인지하는 능력이 약해지면 시스템 전체 brittle.
해결: Leak을 docs에 명시적으로 박기. *"이 method는 X 조건에서 Y leak이 있다"*를 docstring에 강제. AI가 읽을 수 있게.
5. Leak이 없는 module을 발견했다고 좋아하지 말기
Trivial한 module은 leak이 없음 (예: add(a, b) -> int). 이건 너무 얕아서 leak할 게 없음. 진짜 가치 있는 abstraction은 leak이 있음. Leak 없음 = 추상화의 가치 없음 신호일 수도.
해결: leak의 양이 아니라 *leak이 예측 가능한가가 점검 기준.
🔄 대안 흐름
이 원칙이 적용 안 되는 시나리오와 다른 답.
대안 1 — Anti-corruption layer가 leak을 흡수
Leak을 다른 module이 흡수. 외부 시스템의 leak을 ACL이 처리하면 내부 도메인은 leak 없는 contract로 사용. anti-corruption-layer가 이 답.
→ Spolsky 명제와 합쳐서. ACL 자신은 leak이 있지만, leak을 한 자리에 모음.
대안 2 — Result type / Either / Option
Rust, Haskell, Scala 같은 언어가 에러 leak을 type level로 contract화. 사용자가 컴파일 시점에 leak을 의식하게 강제.
→ Spolsky의 가장 modern한 답. 예측 가능한 leak의 type-level 표현.
대안 3 — Observability — 감추지 말고 측정
Leak을 기록·측정·alert. Honeycomb, Datadog 같은 도구가 leak의 visibility를 답으로. secret을 감추되, leak이 발생하면 즉시 보임.
→ 절충. Information hiding은 유지, leak은 측정 가능.
대안 4 — Embrace the leak (Unix philosophy)
Unix는 leak을 인정하고 사용자에게 위임. do one thing well, compose with pipes. 각 도구가 작은 abstraction + leak이 있어도 조합으로 처리. Abstraction을 깊이 만들지 않음.
→ Spolsky의 명제를 받아들이고 design 자체에 박음. modern microservices와 정합.
대안 5 — Type-level resource management (Rust ownership)
Resource leak (대안 4 종류 중 하나)을 언어 차원에서 해결. Borrow checker가 컴파일 시점에 leak 차단. Leak을 type system에 위임.
→ 가장 strong한 해결. 다만 학습 곡선 큼. Rust 한정.
💡 인사이트
AI 시대 왜 지금 부활하는가 + 학내 segment 의미.
1. AI agent는 interface-only thinking에 가장 취약
sources/key-articles-summary#5. Ian Bull — *Sinks, Not Pipes*|Ian Bull의 명제 다시:
AI takes architecture at face value. If your architecture is lying — if there are hidden couplings and undocumented side effects — then the AI will produce code that looks correct locally but breaks things.
AI agent는 interface가 진실이라 가정. 사람이 경험으로 알던 leak을 모름:
- AI: "이 ORM이 DB를 감춤이라고 했음" → N+1 코드 양산
- AI: "이 LLM provider가 동일 contract라고 했음" → vendor별 latency 차이 무시한 timeout
- AI: "이 cache가 transparent라고 했음" → stale 데이터 가정 안 함
→ Leak은 AI 시대에 더 위험하지만, 명시화하면 AI에게 친화적도 됨. 사람의 tribal knowledge를 spec에 박는 것이 AI 시대 information hiding의 의무. information-hiding#2. *Architecture as documentation* 인사이트와 직접 만남.
2. Leak을 측정 도구로 사용
Leak이 많은 module = abstraction이 잘못 그어진 신호. Module 건강성의 직접 측정.
매 module 설계 후 점검 질문:
- 사용자가 이 module을 쓰면서 내부 동작을 알아야 하는 경우가 얼마나 있는가?
- 사용자가 이 module의 failure mode를 알아야 처리할 수 있는가?
- 다른 module과 secret을 공유하고 있는가?
답이 많음 → refactor 신호. 적음 → 좋은 abstraction. Leak 검증이 strategic 사고의 직접 도구.
3. v1.0 design 직접 적용 — 예측 가능한 leak 사례
| Layer | 불가피한 leak | 명시적 contract로 |
|---|---|---|
Provider trait | vendor별 latency·rate limit·token cost 차이 | model_config() method가 명시적 metadata 반환 |
SKILL.md | context budget (token 사용) | frontmatter에 context_budget field |
| Agent loop | turn 수, time, token 누적 | run() -> Result<Output, AgentError> + observability hook |
| 학내 통합 모듈 | 학사 시스템 maintenance window | available_window() method가 시간대 명시 |
→ 모든 leak이 명시적 contract로 노출. 감추지 않음. AI agent도 사람도 예측 가능.
4. Hickey의 simple은 leak을 줄이는 도구
simple-not-easy 노트의 complect 제거가 leak 차단의 직접 mechanism:
- 얽힘이 있는 module = 두 secret이 한 자리에 → leak 발생 가능
- 얽힘 없는 module = 한 secret만 = leak 가능성 적음
→ Hickey의 simple 추구가 leak 감소의 root mechanism. 14 원칙의 통합성이 다시 확인됨.
5. Spolsky's Law의 paradox
Leak을 알수록 더 좋은 추상화를 만들 수 있음. 신참은 leak을 모르고 추상화에 만족, 경험자는 leak을 알고 더 정확한 contract 설계.
학내 segment 의미: 학생이 "좋은 추상화"를 배울 때, leak 사례를 함께 배워야 함:
- TCP의 reliable 약속 + 그 leak (latency, retry)
- ORM의 transparent 약속 + 그 leak (N+1, transaction)
- LLM의 same contract 약속 + 그 leak (vendor latency, rate limit)
이 짝을 가르치면 학생이 abstraction을 비판적으로 사용하게 됨. 단순 abstraction을 만드는 법보다 abstraction의 leak을 예측하는 법이 더 가치.
6. Trivial abstraction의 함정 — leak 없음 ≠ 좋음
Leak이 없는 abstraction은 너무 얕거나 trivial. 매 module 점검 시:
- "이 module이 leak이 있나?" — 있으면 정상, design 잘 됐는지 확인
- "이 module이 leak이 전혀 없나?" — 너무 얕음 신호. 진짜 가치 있는 추상화인가 다시 검토
deep-modules#약점/한계의 얕은 깊이 함정과 정확히 만남. Leak 측정이 deep module의 진짜 점검 도구.
7. AI 시대의 새 직업 정의 — Leak Curator
AI가 코드를 짜고, 사람이 strategic한다면, 사람의 핵심 업무 중 하나는:
Leak을 발견하고, 명시화하고, contract에 박는 것.
이게 AI 시대 architect / senior engineer의 일상이 됨. 코드 짜는 시간보다 abstraction의 leak 점검에 시간 투자. 학내 segment에서 학생이 AI 시대 첫 직무로 이걸 배우면 진입 장벽이 매우 낮음 — 코드 작성 능력보다 leak 인지 능력이 핵심 skill.
다음에 가야 할 자리
이 노트가 호출한 다른 원칙들 — 자연스러운 다음 노트:
- anti-corruption-layer — leak을 다른 module이 흡수. Domain 축의 시스템 단위 표현
- orthogonality — leak이 없으면 module이 orthogonal. Process 축
- ubiquitous-language — vocabulary 단위의 leak (외부 vocabulary가 내부에 새는 경우)
→ overview의 🧱 Module 축 모두 완성 (deep-modules + information-hiding + information-leak-vs-abstraction). 다음은 Domain 축 또는 Process 축으로 이동.
관련
- overview
- information-hiding — leak은 hiding의 반대 방향. 이 노트는 hiding의 자기 점검 도구
- deep-modules — 얕은 깊이 함정의 정확한 measure가 leak
- simple-not-easy — complect 제거가 leak 차단의 root mechanism
- strategic-vs-tactical-programming — 어떤 leak을 명시화할지가 strategic 결정
- sources/key-articles-summary#5. Ian Bull — *Sinks, Not Pipes*|Ian Bull — AI agent의 interface-only 사고가 leak에 취약
Sources
직접 source
- Spolsky, J. (2002). The Law of Leaky Abstractions. https://www.joelonsoftware.com/2002/11/11/the-law-of-leaky-abstractions/ — 무료 글, 짧음 (10분)
- A Philosophy of Software Design — John Ousterhout (2018). Information Leakage 챕터
Leak의 type-level 해결
- Programming in Haskell — Graham Hutton. Maybe / Either monad
- The Rust Programming Language — Steve Klabnik & Carol Nichols. Result type, ownership
AI 시대 leak
- Ian Bull — Sinks, Not Pipes — interface-only 사고의 위험
- research/stateless-llm-sdk/fundamentals-lineage — AI 시대 architecture의 leak sensitivity
Unix philosophy (대안 4)
- The Art of Unix Programming — Eric S. Raymond. Embrace the leak 정신