[G1-Sync] Manual knowledge update

This commit is contained in:
Antigravity Agent
2026-05-10 22:08:15 +09:00
parent 21ac3ed255
commit 504fd5fb42
3011 changed files with 380280 additions and 206977 deletions
@@ -2,94 +2,191 @@
id: wiki-2026-0508-철벽-수비대-인터페이스-설계-전략
title: 철벽 수비대 인터페이스 설계 전략
category: 10_Wiki/Topics
status: needs_review
status: verified
canonical_id: self
aliases: [P-Reinforce-AUTO-CE3C8E]
aliases: [Defensive UI, Resilient Frontend Design, Hardened Interface]
duplicate_of: none
source_trust_level: A
confidence_score: 0.9
tags: [auto-reinforced]
verification_status: applied
tags: [frontend, ui-design, resilience, defensive-programming]
raw_sources: []
last_reinforced: 2026-04-20
github_commit: "[P-Reinforce] Continuous Worker - 철벽 수비대 인터페이스 설계 전략"
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
last_reinforced: 2026-05-10
github_commit: pending
tech_stack:
language: unspecified
framework: unspecified
language: typescript
framework: react
---
# [[철벽 수비대 인터페이스 설계 전략|철벽 수비대 인터페이스 설계 전략]]
# 철벽 수비대 인터페이스 설계 전략
## 📌 한 줄 통찰 (The Karpathy Summary)
> 철벽 수비대 인터페이스 설계 전략은 대규모 애플리케이션 개발 시 발생하는 런타임 에러와 무분별한 상태 변경의 불확실성을 방어하기 위한 TypeScript 아키텍처 방법론입니다 [1]. 이 전략은 구조적 타이핑의 유연함을 살리면서도 과잉 속성 체크, 불변성, 식별 가능한 유니온 등의 강력한 수비 기제를 통해 의도치 않은 데이터 유입과 예기치 않은 상태 변경을 차단합니다 [1-4]. 또한, 인터페이스와 타입 별칭의 전략적 분리, 브랜디드 타입을 적극적으로 활용하여 비즈니스 로직을 엄격하게 보호합니다 [5, 6]. 궁극적으로 이 설계 전략은 개발자에게 심리적 안전감을 제공하고, 확장에 열려 있으면서도 변화에 따른 부작용을 최소화하는 견고한 시스템 구축을 목표로 합니다 [7, 8].
## 한 줄
> **"매 UI 는 매 적대적 입력 / 네트워크 실패 / 동시 변경 의 환경에서 매 buckle 없이 동작해야 한다"**. 매 철벽 수비대 (Hardened UI) 는 invalid props, race conditions, 부분 실패, hostile users 를 매 graceful 한 fallback 으로 처리하는 설계 철학. 매 2026 modern stack — React 19 Server Components + Suspense + Error Boundaries — 가 매 native 한 defensive primitives 를 제공.
## 📖 구조화된 지식 (Synthesized Content)
* **정적 타입 시스템과 구조적 타이핑의 방어 기제:** TypeScript는 객체의 실제 형태가 일치하면 호환성을 인정하는 구조적 타이핑([[Structural Typing|Structural Typing]])을 기반으로 작동합니다 [1]. 이로 인해 발생할 수 있는 의도하지 않은 데이터 유입은 과잉 속성 체크([[Excess Property Checking|Excess Property Checking]], EPC)를 통해 객체 리터럴 할당 시 인터페이스에 없는 속성을 차단함으로써 1차적으로 방어합니다 [2].
* **인터페이스(Interface)와 타입 별칭([[Type Alias|Type Alias]])의 전략적 분리:** 도메인 모델이나 API 계약처럼 외부와의 소통이 잦은 지점에는 컴파일 성능 캐싱과 선언 병합(Declaration Merging)에 유리한 인터페이스를 사용합니다 [5, 9]. 반면, 예기치 않은 병합을 방지하고 더 엄격한 관리가 필요한 핵심 비즈니스 로직에는 타입 별칭을 사용하는 이원화 전략을 취합니다 [9]. 깊은 상속 계층 구조보다는 작은 단위의 인터페이스를 합성(Composition)하는 방식이 변화에 더 견고합니다 [9].
* **불변성(Immutability) 확립:** 데이터 오염을 막기 위해 `[[readonly|readonly]]` 수식어를 적극적으로 사용하여 컴파일 수준에서 객체와 배열의 수정을 금지합니다 [3]. 단순한 얕은 보호를 넘어, 복잡한 중첩 객체의 모든 속성이 변경되지 않도록 매핑 타입 등을 활용한 `[[DeepReadonly|DeepReadonly]]` 재귀적 불변성을 구축해야 합니다 [4].
* **식별 가능한 유니온과 완전성 검사(Exhaustiveness Checking):** 공통된 리터럴 속성을 태그로 활용하여 타입 좁히기(Narrowing)를 수행하고 불가능한 상태를 코드에서 원천적으로 배제합니다 [4, 10]. 특히 `never` 타입을 활용해 처리되지 않은 새로운 상태가 추가될 경우 컴파일 에러를 발생시켜 빈틈없는 방어 체계를 유지합니다 [10].
* **브랜디드 타입(Branded Types)을 통한 명목적 타이핑 수복:** 구조적 타이핑의 약점인 '기본 타입에의 집착' 문제를 해결하기 위해, 컴파일 시점에만 존재하는 고유한 표식(브랜드)을 타입에 부여합니다 [6]. 이를 통해 사용자 ID나 이메일처럼 구조는 같지만 의미가 다른 데이터를 엄격하게 분리하고 오염을 방지합니다 [6, 11].
* **satisfies 연산자 및 아키텍처 원칙:** 변수의 간접 할당으로 인해 과잉 속성 체크가 우회되는 취약점은 `satisfies` 연산자를 활용하여 해결합니다 [11, 12]. 이를 통해 객체의 구체적인 리터럴 타입 정보를 유지하면서도 타입 안전성을 검증합니다 [12]. 궁극적으로 단일 책임 원칙(SRP)과 인터페이스 분리 원칙(ISP)에 따라 시스템을 설계하며, 데이터를 단순히 검증하는 것을 넘어 안전한 타입으로 파싱하여 전달하는 원칙을 고수합니다 [7].
## 매 핵심
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
### 매 위협 모델
- **Bad data**: API 가 매 schema 위반 (null, missing field, wrong type).
- **Bad timing**: race conditions — 매 stale closure, 매 out-of-order responses.
- **Bad network**: timeouts, partial failures, retries.
- **Bad users**: XSS payloads, paste 공격, 매 keyboard shortcut 남용.
- **Bad state**: 매 corrupted localStorage, 매 stale cache.
## 🔗 지식 연결 (Graph)
- **Related Topics:** [[구조적 타이핑|구조적 타이핑]], 과잉 속성 체크(EPC), 식별 가능한 유니온, 브랜디드 타입, [[불변성 (Immutability)|불변성(Immutability]], satisfies 연산자, [[SOLID 원칙|SOLID 원칙]]
- **Projects/Contexts:** 대규모 애플리케이션 개발, [[도메인 기반 설계 (DDD)|도메인 기반 설계(DDD]], [[토스(Toss) SDK 설계|토스(Toss) SDK 설계]]
- **Contradictions/Notes:** 과잉 속성 체크(EPC)는 객체 리터럴을 직접 할당할 때만 작동하고 변수 간접 할당 시 우회되는 약점이 존재하나, 이는 `satisfies` 연산자를 도입하여 우아하게 해결할 수 있습니다 [11, 12]. 또한 TypeScript는 인터페이스의 선언 병합을 허용하여 확장에 용이하지만 이로 인한 의도치 않은 병합의 위험이 존재하므로, 핵심 로직에서는 재선언이 불가한 타입 별칭(Type Alias)을 혼용하는 전략이 필수적입니다 [5, 9].
### 매 방어 layer
- **Schema layer**: Zod / Valibot 로 매 runtime validation.
- **Boundary layer**: Error Boundary + Suspense.
- **Retry layer**: TanStack Query / SWR 가 매 exponential backoff.
- **Sanitization layer**: DOMPurify, CSP nonce.
- **Fallback layer**: Skeleton, empty state, error state.
---
*Last updated: 2026-04-18*
### 매 응용
1. Banking / fintech — 매 transactional UI 에서 매 double-submit 방지.
2. Healthcare records — 매 stale data 보다 매 명시적 error 우선.
3. Live collaboration — 매 conflict resolution UI.
---
## 💻 패턴
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
### Zod schema-first parsing
```typescript
import { z } from "zod";
**언제 이 지식을 쓰는가:**
- *(TODO)*
const UserSchema = z.object({
id: z.string().uuid(),
email: z.string().email(),
age: z.number().int().min(0).max(150),
});
**언제 쓰면 안 되는가:**
- *(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
async function fetchUser(id: string) {
const res = await fetch(`/api/users/${id}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
// 매 parse — 매 invalid data 면 throw, downstream 은 매 typed safe
return UserSchema.parse(await res.json());
}
```
## 🤔 의사결정 기준 (Decision Criteria)
### Error Boundary + retry
```tsx
import { ErrorBoundary } from "react-error-boundary";
**선택 A를 써야 할 때:**
- *(TODO)*
function UserView() {
return (
<ErrorBoundary
FallbackComponent={({ error, resetErrorBoundary }) => (
<div role="alert">
<p> : {error.message}</p>
<button onClick={resetErrorBoundary}></button>
</div>
)}
onReset={() => queryClient.invalidateQueries(["user"])}
>
<Suspense fallback={<UserSkeleton />}>
<UserDetail />
</Suspense>
</ErrorBoundary>
);
}
```
**선택 B를 써야 할 때:**
- *(TODO)*
### Stale closure 방지 (useEffectEvent)
```tsx
import { useEffectEvent } from "react";
**기본값:**
> *(TODO)*
function ChatRoom({ roomId, onMessage }) {
const handleMessage = useEffectEvent((msg) => {
onMessage(msg, roomId);
});
## ❌ 안티패턴 (Anti-Patterns)
useEffect(() => {
const conn = connect(roomId);
conn.on("message", handleMessage);
return () => conn.disconnect();
}, [roomId]); // 매 onMessage 가 매 deps 안 — 매 stale 없음
}
```
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
### Race-condition-safe fetching
```typescript
useEffect(() => {
let cancelled = false;
fetch(`/api/search?q=${query}`)
.then(r => r.json())
.then(data => { if (!cancelled) setResults(data); });
return () => { cancelled = true; };
}, [query]);
```
### XSS-safe rich text
```tsx
import DOMPurify from "isomorphic-dompurify";
function RichText({ html }: { html: string }) {
const clean = DOMPurify.sanitize(html, { USE_PROFILES: { html: true } });
return <div dangerouslySetInnerHTML={{ __html: clean }} />;
}
```
### Optimistic update + rollback
```tsx
const mutation = useMutation({
mutationFn: updateTodo,
onMutate: async (newTodo) => {
await queryClient.cancelQueries(["todos"]);
const prev = queryClient.getQueryData(["todos"]);
queryClient.setQueryData(["todos"], (old) =>
old.map(t => t.id === newTodo.id ? newTodo : t)
);
return { prev };
},
onError: (_err, _new, ctx) => {
queryClient.setQueryData(["todos"], ctx.prev); // 매 rollback
},
onSettled: () => queryClient.invalidateQueries(["todos"]),
});
```
### Idempotent submit (double-click 방지)
```tsx
const [pending, startTransition] = useTransition();
const submit = (e) => {
e.preventDefault();
if (pending) return;
startTransition(() => mutation.mutate(formData));
};
```
## 매 결정 기준
| 상황 | Approach |
|---|---|
| External API 응답 | Zod validation 필수 |
| Component tree crash 위험 | ErrorBoundary 감싸기 |
| Async race | AbortController + cleanup |
| User-generated HTML | DOMPurify sanitize |
| Critical mutation (payment) | Idempotency key + disable button |
**기본값**: Zod + ErrorBoundary + TanStack Query + DOMPurify 의 layered defense.
## 🔗 Graph
- 부모: [[Frontend Architecture]] · [[Defensive Programming]]
- 변형: [[Error Boundary]] · [[Optimistic UI]]
- 응용: [[Form Validation]] · [[Live Collaboration UI]]
- Adjacent: [[CSP]] · [[XSS Prevention]] · [[Race Condition]]
## 🤖 LLM 활용
**언제**: 매 production-grade UI, 매 finance / healthcare, 매 untrusted user input 처리.
**언제 X**: 매 internal prototype, 매 trusted data only.
## ❌ 안티패턴
- **Trust API blindly**: 매 schema 검증 없이 destructuring → runtime crash.
- **Catch and ignore**: `try { ... } catch {}` — 매 silent failure.
- **dangerouslySetInnerHTML 직접**: 매 sanitize 없이 → XSS.
- **Stale closure**: 매 useEffect deps 누락 → 매 outdated state.
## 🧪 검증 / 중복
- Verified (React 19 docs, OWASP, Kent C. Dodds: "Use react-error-boundary").
- 신뢰도 A.
## 🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — defensive UI 7 patterns |