9148c358d0
Topic_Agent/Topic_Blog/Topics/Topics_Biz/Topics_Meeting/Topics_Rag의 마크다운 지식 문서를 Topic_General/Topic_Programming/Topic_Graphic/Topic_Business 4개 카테고리로 재분류. - 중복 제거: frontmatter의 status:duplicate/merged + duplicate_of/redirect_to 필드로 자기 자신을 중복으로 선언한 리다이렉트 stub 1032개 제거, 완전 동일 내용 파일 472개 제거, 동일 파일명·다른 내용 충돌 시 더 큰(완전한) 버전만 유지(162개 제거) — 총 1639개 중복 제거. - 분류: 폴더 단위로 명확한 항목(AI_and_ML/Coding/Architecture 등 → Programming, Comfyui/Visual_Effects → Graphic, Topics_Biz/Topics_Meeting/사업 등 → Business, Poetic_Blog_Writing/창의성/Game_Design 등 → General)은 폴더 우선순위로, 나머지 혼재 폴더(Topic_Agent/Topic_Blog/Topics 루트/Thinking & Reasoning/Other/UI_UX_Assets)는 title/tags 키워드 스코어링으로 파일 단위 분류(불명확한 경우 General로 폴백). 원본 폴더명은 "From_*" 서브폴더로 보존해 추적 가능성 유지. - 최종 배치: Programming 2784 / General 1608 / Graphic 285 / Business 249 = 4926개 문서. - 에이전트 운영 상태(.astra/.agent/.obsidian/sessions/memory/_company/docs/lessons/_shared/src)는 지식 콘텐츠가 아니므로 재분류 대상에서 제외하고 원위치 유지. - Topics/Topic_email(상위 보호 폴더 Topic_email과 파일명 100% 중복) 삭제 — 보호 폴더 자체는 미변경. - 완전히 비게 된 Topic_Agent/Topic_Blog/Topics_Biz/Topics_Rag 폴더 제거.
4.6 KiB
4.6 KiB
id, title, category, status, canonical_id, aliases, duplicate_of, source_trust_level, confidence_score, verification_status, tags, raw_sources, last_reinforced, github_commit, tech_stack
| id | title | category | status | canonical_id | aliases | duplicate_of | source_trust_level | confidence_score | verification_status | tags | raw_sources | last_reinforced | github_commit | tech_stack | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| wiki-2026-0508-primitive-obsession-기본-타입-집착 | Primitive Obsession (기본 타입 집착) | 10_Wiki/Topics | verified | self |
|
none | A | 0.9 | applied |
|
2026-05-10 | pending |
|
Primitive Obsession (기본 타입 집착)
매 한 줄
"매 string/int이 매 domain concept를 매 가장한다". Primitive Obsession은 매
UserId,Money같은 매 domain concept를 매 rawstr/int로 매 표현해 매 type system이 매 invariant 보장 못 하는 매 code smell. Fowler "Refactoring" (1999, 2nd ed. 2018) 의 매 classic smell — 매 modern fix는 매 newtype / value object.
매 핵심
매 증상
- 매 String 폭주: 매
email: str,phone: str,country_code: str매 swap 가능. - 매 Magic numbers: 매
status: int = 3매 의미 불명. - 매 Validation duplication: 매 every callsite마다 매
if "@" in email. - 매 Type confusion: 매
transfer(from_id, to_id)매 인자 swap 매 컴파일러 못 잡음.
매 Fix 전략
- 매 Newtype: Rust
struct UserId(u64);. - 매 Value Object: DDD 의 매
Email,Moneyimmutable class. - 매 Branded type: TypeScript
type UserId = string & { __brand: "UserId" }. - 매 NewType pattern: Python
typing.NewType("UserId", int).
매 응용
- Domain modeling (DDD) — Bounded context의 매 first-class concept.
- Money handling (currency + amount tied).
- Identifier safety (UserId vs OrderId mix-up 방지).
💻 패턴
Python NewType + dataclass
from typing import NewType
from dataclasses import dataclass
from decimal import Decimal
UserId = NewType("UserId", int)
OrderId = NewType("OrderId", int)
@dataclass(frozen=True)
class Money:
amount: Decimal
currency: str
def __post_init__(self):
if self.amount < 0: raise ValueError("negative")
if len(self.currency) != 3: raise ValueError("ISO-4217")
def transfer(src: UserId, dst: UserId, m: Money): ...
# transfer(OrderId(1), UserId(2), Money(...)) # 매 mypy error
Rust newtype
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct UserId(u64);
#[derive(Debug, Clone, Copy)]
pub struct OrderId(u64);
fn fetch_user(id: UserId) { /* ... */ }
// fetch_user(OrderId(7)); // 매 compile error
TypeScript branded types
type Brand<T, B> = T & { readonly __brand: B };
type Email = Brand<string, "Email">;
type UserId = Brand<number, "UserId">;
function parseEmail(s: string): Email {
if (!/^[^@]+@[^@]+$/.test(s)) throw new Error("invalid");
return s as Email;
}
Value object with invariant
@dataclass(frozen=True)
class Email:
value: str
def __post_init__(self):
if "@" not in self.value: raise ValueError("invalid email")
object.__setattr__(self, "value", self.value.lower())
Refactor: Replace Type Code with Subclass
# Before — magic int status
class Order:
status: int # 0=pending, 1=paid, 2=shipped
# After — sealed states
class OrderStatus: pass
class Pending(OrderStatus): pass
class Paid(OrderStatus): pass
class Shipped(OrderStatus):
tracking: str
매 결정 기준
| 상황 | Approach |
|---|---|
| Domain identifier | Newtype |
| Domain value (Money, Email) | Value Object |
| 매 enum-like int code | Sealed subclass / Enum |
| Throwaway script | 매 raw primitive OK |
기본값: Newtype for IDs, Value Object for domain values.
🔗 Graph
- 부모: Code-Smell · Refactoring_Best_Practices
- 변형: Value-Object · Branded-Types
- 응용: DDD · Type-Safety
- Adjacent: Stringly-Typed
🤖 LLM 활용
언제: domain model 설계, 매 API boundary type 선택, 매 refactoring 제안. 언제 X: 매 1-time script.
❌ 안티패턴
- 매 Stringly-typed everything: 매 모든 domain concept를 매 str.
- 매 Validation lazy: 매 boundary 통과 후 매 raw str 그대로 흘림.
- 매 Tuple as struct: 매
(int, str, bool)매 의미 모름. - 매 매 시점 validation: 매 매번 caller가 매 validate 수행.
🧪 검증 / 중복
- Verified (Fowler "Refactoring" 2nd ed. 2018, Evans "DDD" 2003).
- 신뢰도 A.
🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — newtype/value-object patterns + refactoring guide |