[G1-Sync] Manual knowledge update
This commit is contained in:
@@ -2,129 +2,200 @@
|
||||
id: wiki-2026-0508-architectural-violations
|
||||
title: Architectural Violations
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-REINFORCE-WIKI-C08C3C0C]
|
||||
aliases: [Architecture Erosion, Architecture Drift, Layer Violations, Dependency Violations]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.95
|
||||
tags: [architectural-violations, architecture-erosion, technical-debt, static-code-analysis-tools, software-architecture-recovery, architecture-principles]
|
||||
confidence_score: 0.9
|
||||
verification_status: applied
|
||||
tags: [architecture, violations, erosion, drift, archunit]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-02
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
language: java/kotlin/typescript
|
||||
framework: ArchUnit / Sonargraph / dependency-cruiser
|
||||
---
|
||||
|
||||
# [[Architectural Violations]]
|
||||
# Architectural Violations
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
아키텍처 위반(Architectural Violations)은 기술 부채의 축적(accumulation of technical debt), 지식 증발(knowledge vaporization)과 함께 **소프트웨어 아키텍처 침식(Architecture erosion)을 일으키는 주요 원인 중 하나**입니다 [1]. 이는 시간이 지남에 따라 초기에 의도했던 설계와 실제 구현된 아키텍처 간의 격차가 점진적으로 벌어지는 현상을 초래합니다 [1]. 소스 내에서는 아키텍처 침식의 원인으로서 간략하게 언급되어 있으며, 아키텍처 위반이라는 단일 개념에 대한 구체적인 정의나 세부 사례에 관한 정보는 부족합니다.
|
||||
## 매 한 줄
|
||||
> **"매 architectural violation 의 intended architecture 와 actual code 사이의 deviation"**. Perry & Wolf 의 *erosion* (decay over time) + *drift* (unauthorized addition) 의 distinguishing — 매 erosion 의 explicit decay, drift 의 silent. 매 modern detection 의 fitness function (ArchUnit, dep-cruiser, Sonargraph) + reflexion model — 매 manual review 의 too-late.
|
||||
|
||||
## 📖 Core 소스에 관련 정보가 부족합니다.
|
||||
소스에 아키텍처 위반(Architectural Violations) 자체에 대한 구체적이고 세부적인 정보는 부족합니다. 다만, 이 개념이 핵심 원인으로 작용하는 **아키텍처 침식(Architecture erosion)**의 맥락을 통해 다음과 같은 내용을 합성할 수 있습니다.
|
||||
## 매 핵심
|
||||
|
||||
* **아키텍처 침식 유발**: 아키텍처 위반은 소프트웨어 개발 수명 주기(SDLC)의 여러 단계에서 발생할 수 있으며, 의도된 아키텍처와 구현된 아키텍처 사이의 간극을 만들어 점진적인 아키텍처 침식을 초래합니다 [1].
|
||||
* **시스템에 미치는 치명적 영향**: 아키텍처 위반이 누적되어 침식이 발생하면 **소프트웨어 성능이 저하**되고, 시스템의 **진화 및 유지보수 비용(evolutionary costs)이 실질적으로 증가**하며, 전반적인 **소프트웨어 품질이 하락**하게 됩니다 [1, 2].
|
||||
* **탐지 및 식별 접근법**: 이러한 위반과 침식을 조기에 발견하고 완화하기 위해 일관성 기반(consistency-based), 진화 기반(evolution-based), 결함 기반(defect-based), 결정 기반(decision-based) 접근법이 제안되었습니다 [2]. 구체적으로는 **자동화된 아키텍처 적합성 검사(automated architecture conformance checks)**와 **정적 코드 분석 도구(static code analysis tools)**, 그리고 리팩토링 기술이 식별에 활용됩니다 [2].
|
||||
### 매 violation 의 종류
|
||||
- **Layer violation**: domain → infrastructure (wrong direction).
|
||||
- **Module violation**: one module imports private internals of another.
|
||||
- **Dependency cycle**: A → B → C → A.
|
||||
- **Convention violation**: `*Service` not in service package.
|
||||
- **Forbidden API**: `java.util.Date`, `console.log` in production code.
|
||||
- **Coupling violation**: too many afferent / efferent dependencies.
|
||||
- **Cohesion violation**: feature smeared across many modules.
|
||||
- **Cross-bounded-context leakage**: shared domain model between contexts.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
소스에 아키텍처 위반 선택에 따른 직접적인 제약 사항이나 반대 급부(Trade-off)에 대한 세부 정보가 부족합니다. 그러나 위반을 통제하기 위한 관리적 측면에서 다음과 같은 한계와 기회비용이 존재합니다.
|
||||
### 매 detection mechanism
|
||||
1. **Static structural**: ArchUnit, dep-cruiser, Sonargraph (parse + graph).
|
||||
2. **Reflexion model**: actual graph diff with intended graph.
|
||||
3. **Runtime**: trace analysis (OpenTelemetry) for unexpected service-to-service calls.
|
||||
4. **Reviewer-driven**: ADR conformance check in PR.
|
||||
5. **Visualization**: dependency matrix, sunburst, codecity.
|
||||
|
||||
* **예방 및 치료적 조치의 비용 vs 방치 시의 막대한 위험**: 아키텍처 위반을 방지하기 위해서는 아키텍처 규칙 강제, 정기적인 코드 리뷰, 자동화된 테스트와 같은 **'예방적 조치(preventative measures)'**를 엄격히 시행해야 합니다 [3]. 또한 이미 발생한 위반에 대해서는 리팩토링, 재설계, 문서 업데이트 등의 **'치료적 조치(remedial measures)'**가 수반되어야 합니다 [3]. 이러한 조치들은 개발 과정에서 시간과 노력을 요구하지만, 위반을 방치할 경우 초기 설계 결함과 지속적인 변경으로 인해 2년이라는 시간을 재개발에 소모해야 했던 넷스케이프(Netscape)의 모질라(Mozilla) 브라우저 사례처럼 막대한 수리 비용과 프로젝트 지연을 감수해야만 합니다 [1, 3].
|
||||
### 매 lifecycle
|
||||
1. **Detect** (CI fails or alert).
|
||||
2. **Classify** (true violation vs intentional exception).
|
||||
3. **Triage** (debt vs immediate fix).
|
||||
4. **Fix** (refactor or update intended architecture / ADR).
|
||||
5. **Prevent regression** (add fitness function).
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
### Related Concepts
|
||||
## 💻 패턴
|
||||
|
||||
#### [소프트웨어 아키텍처 문제 및 현상]
|
||||
- [[Architecture Erosion]]
|
||||
- 연결 이유: 아키텍처 위반이 궁극적으로 초래하는 가장 직접적인 결과이자 현상입니다 [1].
|
||||
- 이 개념을 통해 더 깊게 이해할 수 있는 부분: 아키텍처 위반이 방치되었을 때 시스템의 성능, 유지보수 비용, 품질에 미치는 장기적인 파급 효과를 포괄적으로 이해할 수 있습니다 [1, 2].
|
||||
- [[Technical Debt]]
|
||||
- 연결 이유: 아키텍처 위반, 지식 증발과 함께 아키텍처 침식을 일으키는 또 다른 주요 원인으로 동반 언급됩니다 [1].
|
||||
- 이 개념을 통해 더 깊게 이해할 수 있는 부분: 임시방편적인 구조적 위반이 향후 시스템에 어떠한 기술적 부담과 이자(비용)로 되돌아오는지 파악할 수 있습니다 [1].
|
||||
### Detect layer violation — ArchUnit
|
||||
```kotlin
|
||||
@AnalyzeClasses(packages = ["com.acme"], importOptions = [DoNotIncludeTests::class])
|
||||
class LayerViolationTest {
|
||||
@ArchTest
|
||||
val domain_independent: ArchRule = noClasses()
|
||||
.that().resideInAPackage("..domain..")
|
||||
.should().dependOnClassesThat().resideInAnyPackage(
|
||||
"..application..", "..infrastructure..", "..web..")
|
||||
.because("Domain is the innermost layer (Hexagonal)")
|
||||
|
||||
#### [위반 탐지 및 해결 도구/기법]
|
||||
- [[Static Code Analysis Tools]]
|
||||
- 연결 이유: 아키텍처 위반 및 침식을 조기에 식별하고 완화하기 위해 실무적으로 사용되는 주요 접근법입니다 [2].
|
||||
- 이 개념을 통해 더 깊게 이해할 수 있는 부분: 개발 과정에서 자동화된 방식으로 아키텍처 위반을 모니터링하고 코드베이스의 일관성을 유지하는 구현 방법을 이해할 수 있습니다 [2].
|
||||
|
||||
### Deeper Research Questions
|
||||
- 일관성 기반(consistency-based) 및 결함 기반(defect-based) 접근법은 아키텍처 위반을 시스템적으로 어떻게 탐지하고 분류하는가?
|
||||
- 아키텍처 규칙을 강제(enforcing architectural rules)하고 자동화된 적합성 검사를 CI/CD 파이프라인에 통합하는 최적의 방법론은 무엇인가?
|
||||
- 축적된 아키텍처 위반을 해결하기 위해 리팩토링(Refactoring)과 전면적인 재설계(Redesign)를 선택하는 임계 기준은 어떻게 설정되는가?
|
||||
- 지식 증발(knowledge vaporization) 현상은 개발팀 내에서 아키텍처 위반의 발생 빈도를 어떻게 가속화시키는가?
|
||||
- 모질라(Mozilla) 프로젝트의 사례에서, 아키텍처 위반이 소프트웨어의 진화 비용(evolutionary costs)을 기하급수적으로 증가시킨 구체적인 메커니즘은 무엇이었는가?
|
||||
|
||||
### Practical Application Contexts
|
||||
- **Implementation:** 정적 코드 분석 도구와 자동화된 아키텍처 적합성 검사를 도입하여 구현 과정에서 발생하는 아키텍처 위반 사항을 코딩 단계에서 조기에 식별합니다 [2].
|
||||
- **System Design:** 모질라의 실패 사례를 교훈 삼아, 초기 설계 결함이 아키텍처 위반 및 침식으로 이어지지 않도록 시스템 구조를 유연하고 일관성 있게 설계합니다 [1].
|
||||
- **Operation / Maintenance:** 유지보수 과정에서 아키텍처 규칙을 강제하고, 정기적인 코드 리뷰와 문서 업데이트를 수행하여 위반 발생과 지식 증발을 최소화합니다 [3].
|
||||
- **Learning Path:** 아키텍처 위반, 기술 부채, 아키텍처 침식 간의 상관관계를 학습하여 지속 가능한 소프트웨어 유지보수 전략과 선제적 아키텍처 관리의 중요성을 터득합니다 [1].
|
||||
- **My Project Relevance:** 현재 진행 중인 프로젝트 내에 존재하는 아키텍처 위반 사항을 추적하고, 이를 해결하기 위한 리팩토링이나 재설계 등의 치료적 조치(remedial measures)를 계획합니다 [3].
|
||||
|
||||
### Adjacent Topics
|
||||
- [[Software Architecture Recovery]]
|
||||
- 확장 방향: 이미 심각한 아키텍처 위반과 침식이 진행되어 문서와 구현이 불일치하는 시스템에서, 현재 구현된 아키텍처를 역공학(reverse engineering)하여 본래의 의도와 구조를 복구해 내는 기법 및 프로세스로 이해를 확장할 수 있습니다 [3].
|
||||
|
||||
---
|
||||
*Last updated: 2026-05-02*
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
|
||||
**추출된 패턴:**
|
||||
> *(TODO)*
|
||||
|
||||
**세부 내용:**
|
||||
- *(TODO)*
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(TODO)*
|
||||
|
||||
**언제 쓰면 안 되는가:**
|
||||
- *(TODO)*
|
||||
|
||||
## 🧪 검증 상태 (Validation)
|
||||
|
||||
- **정보 상태:** needs_review
|
||||
- **출처 신뢰도:** A
|
||||
- **검토 이유:** *(P-Reinforce Phase 1 자동 정규화. 본문 검증 필요.)*
|
||||
|
||||
## 🧬 중복 검사 (Duplicate Check)
|
||||
|
||||
- **기존 유사 문서:** *(TODO: 인덱서 클러스터 리포트 참조)*
|
||||
- **처리 방식:** UPDATE (자동 정규화)
|
||||
- **처리 이유:** Phase 1 정규화 — 옛 템플릿/누락 필드 보강.
|
||||
|
||||
## 🕓 변경 이력 (Changelog)
|
||||
|
||||
| 날짜 | 변경 내용 | 처리 방식 | 신뢰도 |
|
||||
|------|-----------|-----------|--------|
|
||||
| 2026-05-08 | P-Reinforce Phase 1 정규화 (frontmatter + 헤더 표준화) | UPDATE | A |
|
||||
|
||||
## 💻 코드 패턴 (Code Patterns)
|
||||
|
||||
**패턴 1:** *(TODO: 이 프로젝트 컨벤션 반영한 구조 스켈레톤)*
|
||||
|
||||
```text
|
||||
# TODO
|
||||
@ArchTest
|
||||
val no_repo_in_controller: ArchRule = noClasses()
|
||||
.that().resideInAPackage("..web..")
|
||||
.should().dependOnClassesThat().resideInAPackage("..persistence..")
|
||||
}
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### Detect cycle — dependency-cruiser (TS)
|
||||
```bash
|
||||
npx depcruise --validate .dependency-cruiser.cjs src \
|
||||
--output-type err-html --output-to depgraph.html
|
||||
# Exit 1 if cycles found; html visualizes offending edges
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Reflexion model — intended vs actual (jQAssistant + Cypher)
|
||||
```cypher
|
||||
// Intended: domain → no-deps; application → domain; infra → application
|
||||
// Detect any class in :Domain depending on :Infra (forbidden)
|
||||
MATCH (a:Class)-[:DEPENDS_ON]->(b:Class)
|
||||
WHERE a.layer = "Domain" AND b.layer = "Infrastructure"
|
||||
RETURN a.fqn AS violator, b.fqn AS forbidden
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Runtime violation — unauthorized service call (OpenTelemetry + Tempo)
|
||||
```promql
|
||||
# Alert if service A calls service C (intended only A→B, B→C)
|
||||
sum(rate(traces_spanmetrics_calls_total{
|
||||
client="service-a", server="service-c"
|
||||
}[5m])) > 0
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### Cyclomatic + afferent/efferent metric (Sonargraph)
|
||||
```xml
|
||||
<!-- sonargraph-architect rule -->
|
||||
<architecture>
|
||||
<layer name="Domain" />
|
||||
<layer name="App" includes="Domain" />
|
||||
<layer name="Infra" includes="App" />
|
||||
<connector from="App" to="Domain" />
|
||||
<connector from="Infra" to="App" />
|
||||
<metric type="afferent_coupling" max="20" />
|
||||
<metric type="cyclic_groups" max="0" />
|
||||
</architecture>
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
### Triage workflow — annotate intentional exception
|
||||
```kotlin
|
||||
// When violation is *intended* (rare), document explicitly via ADR + suppress
|
||||
@SuppressArchTest(
|
||||
rule = "domain_independent",
|
||||
reason = "ADR-0034: bridge to legacy DAO during 6-month migration",
|
||||
expiresOn = "2026-12-01"
|
||||
)
|
||||
class LegacyBridgeAdapter { /* ... */ }
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
```kotlin
|
||||
// Companion test enforces expiry
|
||||
@ArchTest
|
||||
val no_expired_suppressions: ArchRule = noClasses()
|
||||
.should().beAnnotatedWith(SuppressArchTest::class.java)
|
||||
.andShould(haveExpiredSuppression()) // custom condition
|
||||
```
|
||||
|
||||
### Visualize violations — dependency matrix (D3)
|
||||
```javascript
|
||||
// scripts/depmatrix.mjs — render violation heatmap
|
||||
import { cruise } from "dependency-cruiser";
|
||||
import fs from "node:fs";
|
||||
const r = await cruise(["src"], { ruleSet: require("./.dependency-cruiser.cjs") });
|
||||
const violations = r.output.summary.violations;
|
||||
const matrix = buildAdjacencyMatrix(r.output.modules, violations);
|
||||
fs.writeFileSync("violations.json", JSON.stringify(matrix));
|
||||
// Then render with d3-matrix or observable-plot
|
||||
```
|
||||
|
||||
### CI gating with delta — only new violations fail
|
||||
```bash
|
||||
# Compare current vs main — fail PR only on new violations (not legacy debt)
|
||||
npx depcruise src --config .dependency-cruiser.cjs --output-type json > head.json
|
||||
git checkout main -- .
|
||||
npx depcruise src --config .dependency-cruiser.cjs --output-type json > main.json
|
||||
node scripts/diff-violations.mjs main.json head.json # exit 1 on new violations
|
||||
```
|
||||
|
||||
### Erosion KPI dashboard (per service / quarter)
|
||||
```sql
|
||||
-- violations_history table (populated nightly by CI)
|
||||
SELECT
|
||||
service,
|
||||
DATE_TRUNC('week', detected_at) AS wk,
|
||||
COUNT(*) FILTER (WHERE severity='error') AS errs,
|
||||
COUNT(*) FILTER (WHERE severity='warn') AS warns
|
||||
FROM violations_history
|
||||
WHERE detected_at > NOW() - INTERVAL '12 weeks'
|
||||
GROUP BY service, wk
|
||||
ORDER BY service, wk;
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| New violation detected in PR | Block merge until fixed or ADR exception added |
|
||||
| Legacy debt — many existing violations | Baseline & gate on delta (no new) |
|
||||
| Intentional bridge | Suppress + ADR + expiry date |
|
||||
| Runtime call mismatch | Trace-based alerting + service mesh policy |
|
||||
| Unclear if violation | Run reflexion model — document intended first |
|
||||
|
||||
**기본값**: ArchUnit/dep-cruiser at PR time + delta gating on legacy code + ADR-tracked suppressions with expiry.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Software Architecture]] · [[Architectural-Constraint-Enforcement]]
|
||||
- 변형: [[Architecture Erosion]] · [[Architecture Drift]] · [[Reflexion Model]]
|
||||
- 응용: [[Architecture Review (아키텍처 및 설계 리뷰)]] · [[Architecture_Refactor]] · [[Technical Debt]]
|
||||
- Adjacent: [[ArchUnit]] · [[Sonargraph]] · [[OpenTelemetry]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: classify violation as erosion vs drift vs intentional, draft suppression ADR with expiry, generate refactor plan from violation report, summarize weekly violations dashboard for tech lead.
|
||||
**언제 X**: do not blindly accept LLM "this violation is fine" — every suppression needs ADR + expiry; LLM judgment is suggestion, not authority.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Suppression without expiry**: permanent escape hatch — original intent lost.
|
||||
- **No baseline**: blocking PRs on existing legacy violations buries team.
|
||||
- **Documentation-only intended architecture**: cannot detect drift — no ground truth.
|
||||
- **One-shot detection**: run once, never again — violations re-grow.
|
||||
- **Fix-the-symptom**: rename file vs fix actual coupling.
|
||||
- **Auto-suppress**: tool generates suppressions silently — true violations hidden.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Perry & Wolf "Foundations for the Study of Software Architecture" 1992, Murphy "Reflexion Models" 1995, ArchUnit / Sonargraph / dependency-cruiser docs).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — erosion vs drift, reflexion model, delta gating |
|
||||
|
||||
Reference in New Issue
Block a user