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 폴더 제거.
5.6 KiB
5.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-deepreadonly | DeepReadonly | 10_Wiki/Topics | verified | self |
|
none | A | 0.9 | applied |
|
2026-05-10 | pending |
|
DeepReadonly
매 한 줄
"매
Readonly<T>의 surface-only — 매 nested mutation 가 still possible". 매 DeepReadonly 가 매 recursively 의 every property 의 readonly 의 mark — 매 redux state, config object, frozen domain model 의 essential. TS 5.x 의 매consttype parameter + DeepReadonly 가 매 powerful combo.
매 핵심
매 vs Readonly
Readonly<T>— 매 top-level only. 매obj.nested.mutate = X가 still allowed.DeepReadonly<T>— 매 every level 의 recursive freeze.
매 type-only vs runtime
- DeepReadonly 의 매 compile-time type guarantee — 매 runtime 의 mutation 의 X protect.
- 매 runtime freeze 의
Object.freeze(shallow) 또는deepFreezehelper 사용. - TypeScript 5.0+
as const의 매 literal-level deep readonly 의 produce.
매 사용처
- Redux/Zustand state shape — 매 mutation prevent.
- Configuration schemas (env config, feature flags).
- API response DTOs after parse.
- Domain entities in DDD value objects.
- Test fixtures (prevent accidental modification).
💻 패턴
Basic DeepReadonly
type DeepReadonly<T> = T extends (...args: any[]) => any
? T
: T extends object
? { readonly [K in keyof T]: DeepReadonly<T[K]> }
: T;
interface User {
id: string;
profile: { name: string; tags: string[] };
}
const u: DeepReadonly<User> = { id: '1', profile: { name: 'a', tags: ['x'] } };
// u.profile.name = 'b'; // ❌ Cannot assign
// u.profile.tags.push('y'); // ❌ readonly array
Handles Map / Set / Array
type DeepReadonly<T> =
T extends (infer U)[] ? readonly DeepReadonly<U>[]
: T extends Map<infer K, infer V> ? ReadonlyMap<DeepReadonly<K>, DeepReadonly<V>>
: T extends Set<infer U> ? ReadonlySet<DeepReadonly<U>>
: T extends Promise<infer U> ? Promise<DeepReadonly<U>>
: T extends object ? { readonly [K in keyof T]: DeepReadonly<T[K]> }
: T;
Brand-aware (preserve nominal types)
type Brand<T, B> = T & { readonly __brand: B };
type DeepReadonly<T> = T extends Brand<infer U, infer B>
? Brand<DeepReadonly<U>, B>
: T extends object
? { readonly [K in keyof T]: DeepReadonly<T[K]> }
: T;
Runtime deepFreeze pair
export function deepFreeze<T>(obj: T): DeepReadonly<T> {
if (obj && typeof obj === 'object' && !Object.isFrozen(obj)) {
Object.freeze(obj);
for (const key of Object.keys(obj)) deepFreeze((obj as any)[key]);
}
return obj as DeepReadonly<T>;
}
as const + DeepReadonly
const config = {
features: { newCheckout: true, beta: ['user1', 'user2'] },
limits: { rpm: 100 },
} as const;
// 매 `as const` 가 매 every literal 의 deeply readonly + literal-typed 로 만듦.
type Config = typeof config;
// Config['features']['beta'] === readonly ['user1', 'user2']
Mutable inverse (DeepWritable)
type DeepWritable<T> = T extends (...args: any[]) => any
? T
: T extends object
? { -readonly [K in keyof T]: DeepWritable<T[K]> }
: T;
function clone<T>(x: DeepReadonly<T>): DeepWritable<T> {
return structuredClone(x as T) as DeepWritable<T>;
}
Zod + DeepReadonly
import { z } from 'zod';
const UserSchema = z.object({ id: z.string(), tags: z.array(z.string()) }).readonly();
type User = DeepReadonly<z.infer<typeof UserSchema>>;
Function args (Redux reducer)
function reducer<S, A>(state: DeepReadonly<S>, action: A): S {
// state.x = ... // ❌ compile error
return { ...(state as S), updated: true } as S;
}
매 결정 기준
| 상황 | Approach |
|---|---|
| Literal config | as const |
| Generic state shape | DeepReadonly<T> utility |
| Runtime guarantee 필요 | deepFreeze + DeepReadonly |
| Performance hot path | 매 type-only DeepReadonly (no runtime cost) |
| Library author 가 expose | DeepReadonly + readonly arrays in public API |
기본값: type-only DeepReadonly + as const for literals; runtime deepFreeze only for security-sensitive boundaries.
🔗 Graph
- 부모: TypeScript-Type-System · Immutability
- 변형: Readonly · as const
- 응용: Zustand · Domain-Driven-Design
- Adjacent: Branded-Types · Zod · Structural-Sharing
🤖 LLM 활용
언제: 매 utility type 의 design / extension, 매 type error explanation, 매 readonly violation 의 codemod 작성. 언제 X: 매 runtime data validation (Zod 사용). 매 hot-path performance tuning (TS types 가 erased — runtime cost 0).
❌ 안티패턴
- 함수 type 의 readonly 적용: 매
(...args) => any가 readonly 의 의미 X — special-case 필요. - Date / RegExp 의 recurse: 매 built-in instances 가 깨짐 — exclude 의 type guard.
- DeepReadonly + cast away:
state as Mutable가 매 type safety 의 destroy. - Runtime mutation through cast: 매
(state as any).x = 1— 매 type lie 의 propagate. - Naive
keyof Ton union: distributive conditional 의 사용.
🧪 검증 / 중복
- Verified (TypeScript 5.x docs, type-fest library, ts-toolbelt).
- 신뢰도 A.
🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — DeepReadonly utility type variants and patterns |