# 모듈화 철학 (Modularization Philosophy)
> 버전: 1.0 | 작성일: 2026-03-26 | 작성자: 아네(Aine), 개발3팀

---

## 1. 핵심 원칙

**DRY (Don't Repeat Yourself)**
동일 로직은 반드시 단일 모듈에 위치한다. 예: 민감정보 마스킹은 `utils/redact.py` 한 곳에만 존재하며, 필요한 모든 스크립트가 이를 임포트한다.

**SOLID — 단일 책임 우선**
파일 하나 = 기능 하나. `atomic_write.py`는 원자적 쓰기만, `injection_guard.py`는 인젝션 탐지만, `model_router.py`는 모델 라우팅만 담당한다.

**200줄 이하**
파일이 200줄을 초과하면 책임이 두 개 이상이라는 신호다. 기능 단위로 분리한다.

**독립 실행 가능**
각 모듈은 `python3 <모듈>.py` 단독 실행이 가능해야 한다. `task-timer.py`, `qc_verify.py` 모두 `if __name__ == "__main__"` 진입점을 가진다.

---

## 2. 파일 분리 기준

**기능별 분리 (utils/)**
횡단 관심사(cross-cutting concerns)는 `utils/`에 단일 파일로 분리한다.
- 로깅 → `logger.py`
- 환경변수 로드 → `env_loader.py`
- 에러 추적 → `error_tracker.py`
- 보안 검사 → `injection_guard.py`, `skill_guard.py`

**계층별 분리**
- 진입점/위임: `dispatch.py`, `scripts/`
- 비즈니스 로직: `teams/*/`, `utils/`
- 인프라/공통: `utils/logger.py`, `utils/config_loader.py`
- 메모리/상태: `memory/`

**도메인별 분리 (teams/)**
팀별 도메인 로직은 `teams/<팀명>/` 하위에 격리한다. dev1 QC 검증 로직이 dev3 코드에 직접 의존하지 않는다.

---

## 3. 의존성 관리

**단방향 의존 (Acyclic Dependency)**
```
dispatch.py → utils/* → (외부 라이브러리만)
qc_verify.py → verifiers/* → (외부 라이브러리만)
```
`utils/` 모듈끼리 서로 임포트하지 않는다. `verifiers/` 모듈은 `utils/`를 참조할 수 있으나, 그 역방향은 금지한다.

**순환 의존 금지**
A → B → A 구조가 발생하면 공통 의존 대상을 새 모듈로 추출한다.

**선택적 임포트 패턴 (Graceful Degradation)**
`dispatch.py`의 핵심 패턴: 보조 유틸리티는 `try/except ImportError`로 감싸고 `_AVAILABLE` 플래그를 유지한다.
```python
try:
    from utils.redact import redact_sensitive_text as _redact_text
    _REDACT_AVAILABLE = True
except ImportError:
    def _redact_text(text: str) -> str:
        return text
    _REDACT_AVAILABLE = False
```
이 패턴 덕분에 `dispatch.py`는 보조 모듈 없이도 핵심 기능을 유지한다.

---

## 4. 테스트 가능 설계

- 각 모듈은 외부 상태에 의존하지 않고 인자만으로 동작을 결정해야 한다.
- `TaskTimer(workspace_path=...)` 처럼 경로를 생성자 인자로 받아 테스트 시 임시 디렉토리를 주입할 수 있다.
- `verifiers/` 모듈은 각자 `tests/` 서브디렉토리를 가지며 독립 실행된다.
- `utils/tests/`에서 각 유틸 함수를 단위 테스트한다.
- 전역 상태(`os.environ` 직접 참조 등)는 `env_loader.py`로 캡슐화하여 테스트에서 모킹을 단순화한다.

---

## 5. 우리 시스템 적용 사례

**dispatch.py — 선택적 임포트로 핵심/보조 분리**
5개 유틸(`redact`, `injection_guard`, `approval`, `audit_logger`, `model_router`)을 각각 독립적으로 선택 임포트한다. 어느 하나가 없어도 위임 기능 자체는 동작한다. 보조 기능이 핵심 흐름을 오염시키지 않는다.

**verifiers/ — 플러그인 아키텍처**
`qc_verify.py`는 12개 검증 모듈(`api_health`, `file_check`, `data_integrity` 등)을 `ALL_CHECKS` 리스트에 이름으로 등록하고 동적으로 호출한다. 새 검증기 추가 시 `qc_verify.py` 본체를 수정하지 않고 파일만 추가한다.

**utils/ — 한 파일 한 기능**
45개 이상 모듈이 각자 단일 책임을 가진다. `fuzzy_match.py`는 퍼지 매칭만, `checkpoint.py`는 체크포인트 저장만, `context_compressor.py`는 컨텍스트 압축만 수행한다.

**task-timer.py — 단일 클래스 캡슐화**
모든 타이머 로직을 `TaskTimer` 클래스 하나에 집약한다. 파일 경로, 데이터 로드, 상태 변경이 클래스 내부에 완전히 캡슐화되어 있어 외부에서는 메서드 호출만으로 사용한다.

**scripts/ — 독립 실행 진입점**
`scripts/` 하위 파일들은 특정 목적의 독립 스크립트다. 재사용 가능한 로직은 `utils/`로 추출하고, 스크립트는 조합과 실행 흐름만 담당한다.

---

## 관련 문서
- 전반적 코드 원칙: `memory/specs/code-architecture-principles.md`
- 조직 구조: `memory/organization-structure.json`
