[G1-Sync] Manual knowledge update
This commit is contained in:
@@ -2,96 +2,33 @@
|
||||
id: wiki-2026-0508-api-응답-및-에러-핸들링-아키텍처
|
||||
title: API 응답 및 에러 핸들링 아키텍처
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-B2F9C0]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: api-error-handling
|
||||
duplicate_of: "[[API Error Handling]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - API 응답 및 에러 핸들링 아키텍처"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, api, error-handling]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[API 응답 및 에러 핸들링 아키텍처]]
|
||||
# API 응답 및 에러 핸들링 아키텍처
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> API 응답 및 에러 핸들링 아키텍처는 시스템 내에서 발생하는 에러를 예상 가능한 것과 그렇지 않은 것으로 구분하고, 이를 클라이언트에게 일관되고 예측 가능한 형태로 전달하기 위한 설계 방식입니다. 주로 '예외 던지기(throw exceptions)' 대신 명시적인 결과 객체(Result 타입)나 식별 가능한 유니온([[Discriminated Unions]])을 활용하여 타입 안전성을 확보하고, 컨트롤러 계층에서 응답의 제어 흐름을 명확히 관리하는 것을 목표로 합니다.
|
||||
> **이 문서는 [[API Error Handling]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **에러의 분류와 처리 철학**
|
||||
에러는 애플리케이션 관점에서 '예상 가능한 에러(Expected errors)'와 '예상치 못한 에러(Unexpected errors/Defects)'로 나뉩니다 [1, 2]. 400 Bad Request나 504 Gateway Timeout 같은 예상 가능한 에러는 예외(Exception)로 던지기보다는 명시적인 에러 타입으로 반환하여 시스템이 복구 가능하도록 제어해야 합니다 [1].
|
||||
* **Result 패턴을 통한 명시적 에러 반환**
|
||||
에러 발생 시 무분별하게 예외를 던지면 제어 흐름을 파악하기 어렵고 타입 시스템에서 반환 타입을 명확히 알 수 없습니다 [3]. 이를 해결하기 위해 함수형 프로그래밍 언어에서 영감을 받은 `Result` 타입(예: `neverthrow` 라이브러리의 `Ok`, `Err`)을 사용하여, 함수가 어떤 에러를 발생시킬 수 있는지 명시적으로 선언하는 방식이 권장됩니다 [4-6]. 이 방식을 통해 컴파일러 수준에서 모든 에러 상황을 처리하도록 강제할 수 있습니다 [7].
|
||||
* **식별 가능한 유니온(Discriminated Unions)을 이용한 응답 모델링**
|
||||
API 응답을 다룰 때는 식별 가능한 유니온을 활용하는 것이 이상적입니다 [8, 9]. 응답 객체에 `status: "success"`나 `status: "error"`와 같은 공통 속성(판별자)을 두어 성공 시에는 데이터(data)를, 에러 시에는 에러 메시지(error)를 포함하도록 모델링하면, TypeScript의 완전성 검사(Exhaustiveness Checking)를 통해 처리되지 않은 상태가 없도록 컴파일 시점에 검증할 수 있습니다 [8, 9].
|
||||
* **메타데이터 활용과 컨트롤러 중심의 제어 흐름**
|
||||
응답 객체에 `_tag`와 같은 메타데이터 속성을 포함하여 내부 로직 및 응답 객체를 구분하면, 마이크로서비스 및 클라이언트 환경 간에 일관된 제어 흐름을 제공할 수 있습니다 [10, 11]. 또한 컨트롤러는 요청과 응답의 모든 흐름을 관리해야 하며, 전역 Catch-all 미들웨어는 비즈니스 로직의 제어 흐름을 담당하는 대신 오직 예상치 못한 결함을 처리하고 개발자에게 알리는 용도로만 사용해야 합니다 [12, 13].
|
||||
## 핵심 요약 (specialization aspects)
|
||||
- 매 Result<T, E> 타입 + Discriminated Union 의 typed error.
|
||||
- 매 Response Envelope: `{ success, data, error }` 구조.
|
||||
- 매 HTTP status code + domain error code 의 separation.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
## 🔗 Graph
|
||||
- 부모: [[API Error Handling]] (canonical)
|
||||
- Adjacent: [[Result Type]] · [[Discriminated Unions]] · [[Zod 런타임 유효성 검사 통합]]
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[Result Type]], [[Discriminated Unions]], Exception Handling
|
||||
- **Projects/Contexts:** [[TypeScript API Development]], [[Server Architecture]]
|
||||
- **Contradictions/Notes:** 전역 예외 처리기(Global Exception Handler)를 두고 컨트롤러에서 예외를 발생시키는 방식이 코드가 깔끔해진다고 선호하는 개발자들도 있지만, Result 패턴을 지지하는 개발자들은 예외를 던지는 방식이 제어 흐름을 끊고 타입 시스템으로 에러를 파악할 수 없게 하므로 예상 가능한 에러는 명시적인 타입으로 반환해야 한다고 반대합니다 [7, 14-16].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -1,92 +1,141 @@
|
||||
---
|
||||
id: wiki-2026-0508-aspnet-core
|
||||
title: ASPNET Core
|
||||
title: ASP.NET Core
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-761015]
|
||||
aliases: [ASP.NET Core, .NET Web, Kestrel, Minimal API]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.95
|
||||
tags: [uncategorized]
|
||||
confidence_score: 0.9
|
||||
verification_status: applied
|
||||
tags: [dotnet, csharp, web, backend]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Mega Batch 2 - Wikified ASP.NET Core"
|
||||
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: csharp
|
||||
framework: ASP.NET Core 9 / .NET 9
|
||||
---
|
||||
|
||||
# ASP.NET Core
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> ASP.NET Core는 내장된 의존성 주입(DI) 컨테이너를 제공하여 소프트웨어의 의존성 역전 원칙 구현을 돕는 프레임워크입니다 [1]. 웹 애플리케이션 개발 시 클린 아키텍처를 적용하여 비즈니스 로직을 프레임워크나 데이터베이스로부터 분리된 구조로 개발할 수 있게 해줍니다 [2]. 다만, 주제를 깊이 있게 다루기에는 소스에 관련 정보가 부족합니다.
|
||||
## 매 한 줄
|
||||
> **"매 cross-platform high-performance 의 .NET 의 web framework"**. 매 Microsoft 의 2016 release 후 의 modular middleware pipeline + Kestrel server + DI built-in 의 design — 매 2026 의 .NET 9 의 native AOT, Minimal API, Blazor United, gRPC 의 first-class support 로 매 enterprise + cloud-native workload 의 dominant choice.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **의존성 역전 원칙(DIP)의 구현 지원**: ASP.NET Core는 내장된 의존성 주입(Dependency Injection) 컨테이너를 포함하고 있습니다 [1]. 이를 통해 소프트웨어 컴포넌트 간의 결합을 분리(decoupling)하고, 객체 지향 설계의 핵심인 의존성 역전 원칙(Dependency [[Inversion]] Principle)을 훨씬 수월하게 구현할 수 있도록 지원합니다 [1].
|
||||
- **클린 아키텍처(Clean [[Architecture]]) 기반의 웹 애플리케이션**: ASP.NET Core 앱을 통해 견고하고 구조화된 코딩 패턴을 가진 웹 애플리케이션을 구축할 수 있습니다 [2]. Controller, Service(또는 Use case), Domain model, Infrastructure와 같은 명확한 계층(Layer)을 사용하여 비즈니스 연산이 특정 웹 프레임워크나 데이터베이스 기술에 강하게 종속되는 것을 방지합니다 [2].
|
||||
- **소스 정보의 한계**: ASP.NET Core 프레임워크 자체의 전반적인 기능이나 구동 방식 등에 대해서는 소스에 관련 정보가 부족합니다.
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 지식 자산화 및 기존 네트워크 연동 단계.
|
||||
- **정책 변화:** Programming & Web 카테고리의 전문성 확보 및 링크 밀도 최적화.
|
||||
### 매 Architecture
|
||||
- **Kestrel**: 매 cross-platform HTTP server (libuv → managed sockets).
|
||||
- **Middleware pipeline**: 매 request 의 ordered chain — auth, logging, routing, endpoint.
|
||||
- **DI container** (built-in): scoped/singleton/transient.
|
||||
- **Configuration**: appsettings.json + env + secrets + Azure KeyVault 의 layered.
|
||||
- **Hosting model**: Generic Host (`IHostBuilder`) → minimal `WebApplication`.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** Dependency Inversion Principle, Clean Architecture, Dependency Injection
|
||||
- **Projects/Contexts:** Web Applications
|
||||
- **Contradictions/Notes:** 소스 간의 모순은 없으나, ASP.NET Core라는 루트 주제를 포괄적으로 설명하기에는 제공된 소스에 관련 정보가 부족합니다. 소스에서는 주로 소프트웨어 아키텍처 패턴의 유용한 적용 사례 중 하나로만 짧게 언급하고 있습니다.
|
||||
### 매 API styles
|
||||
1. **Minimal API** (.NET 6+): top-level, lambda-based — small services 의 default.
|
||||
2. **MVC controllers**: 매 conventional REST.
|
||||
3. **Blazor Server / WASM / United** (.NET 8+): full-stack C# UI.
|
||||
4. **gRPC**: HTTP/2, Protobuf — service-to-service.
|
||||
5. **SignalR**: WebSocket / long-poll.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
### 매 응용
|
||||
1. REST API (Stripe, Shopify-style backends).
|
||||
2. gRPC microservice mesh (.NET 9 의 native AOT 의 cold-start fast).
|
||||
3. Blazor 의 internal admin panel.
|
||||
4. Azure Functions / AWS Lambda (isolated worker).
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
### Minimal API
|
||||
```csharp
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
builder.Services.AddDbContext<AppDb>(o => o.UseNpgsql(builder.Configuration.GetConnectionString("Db")));
|
||||
builder.Services.AddAuthentication().AddJwtBearer();
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(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
|
||||
var app = builder.Build();
|
||||
app.MapGet("/users/{id:int}", async (int id, AppDb db) =>
|
||||
await db.Users.FindAsync(id) is { } u ? Results.Ok(u) : Results.NotFound());
|
||||
app.MapPost("/users", async (User u, AppDb db) => {
|
||||
db.Users.Add(u); await db.SaveChangesAsync();
|
||||
return Results.Created($"/users/{u.Id}", u);
|
||||
});
|
||||
app.Run();
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### Middleware
|
||||
```csharp
|
||||
app.Use(async (ctx, next) => {
|
||||
var sw = Stopwatch.StartNew();
|
||||
await next();
|
||||
Console.WriteLine($"{ctx.Request.Path} {sw.ElapsedMilliseconds}ms");
|
||||
});
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### DI + scoped service
|
||||
```csharp
|
||||
builder.Services.AddScoped<IRepo, EfRepo>();
|
||||
app.MapGet("/x", (IRepo r) => r.GetAll());
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Native AOT (.NET 9)
|
||||
```xml
|
||||
<PropertyGroup>
|
||||
<PublishAot>true</PublishAot>
|
||||
<InvariantGlobalization>true</InvariantGlobalization>
|
||||
</PropertyGroup>
|
||||
```
|
||||
- 매 single-file binary, 매 cold-start <10ms, 매 reflection 의 limit.
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### Authentication (JWT)
|
||||
```csharp
|
||||
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||
.AddJwtBearer(o => {
|
||||
o.TokenValidationParameters = new() {
|
||||
ValidIssuer = "https://issuer",
|
||||
ValidAudience = "api",
|
||||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret))
|
||||
};
|
||||
});
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
app.MapGet("/me", (ClaimsPrincipal u) => u.Identity?.Name).RequireAuthorization();
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| Small service / prototype | Minimal API |
|
||||
| Complex routing / filters | MVC Controllers |
|
||||
| Service-to-service (internal) | gRPC |
|
||||
| Real-time (chat, dashboard) | SignalR |
|
||||
| Cold-start sensitive (lambda) | Native AOT + Minimal API |
|
||||
| Full-stack C# | Blazor United |
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
**기본값**: 매 Minimal API + EF Core + JWT — 매 modern .NET 의 standard stack.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[.NET]] · [[C#]]
|
||||
- 변형: [[ASP.NET MVC]] · [[Blazor]] · [[gRPC for .NET]]
|
||||
- 응용: [[Azure Functions]] · [[Microservices]]
|
||||
- Adjacent: [[Entity Framework Core]] · [[Kestrel]] · [[SignalR]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: Minimal API endpoint 의 생성, EF Core query 의 LINQ, middleware 의 boilerplate.
|
||||
**언제 X**: 매 native AOT 의 reflection-heavy 의 third-party library 의 compatibility — 매 manual 의 verify.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Sync-over-async** (`.Result`, `.Wait()`): 매 thread pool 의 deadlock — 매 `await` 의 사용.
|
||||
- **DbContext singleton**: 매 EF Core 의 not thread-safe — 매 scoped.
|
||||
- **Middleware order 의 random**: 매 auth 의 routing 의 후 — 매 401 의 not enforced.
|
||||
- **Returning IQueryable from controller**: 매 N+1, 매 connection 의 leak.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (learn.microsoft.com/aspnet/core, .NET 9 release notes).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — Minimal API + AOT + JWT patterns |
|
||||
|
||||
@@ -2,92 +2,32 @@
|
||||
id: wiki-2026-0508-ast-추상-구문-트리
|
||||
title: AST (추상 구문 트리)
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-7DEA60]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: ast-abstract-syntax-tree
|
||||
duplicate_of: "[[AST (Abstract Syntax Tree)]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - AST (추상 구문 트리)"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, ast, compiler]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[AST (추상 구문 트리)]]
|
||||
# AST (추상 구문 트리)
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> AST(추상 구문 트리)는 소스 코드를 파싱하여 얻어지는 코드의 추상적인 구문 및 문법적 구조를 표현하는 트리 형태의 데이터 구조입니다 [1, 2]. 이는 코드의 구문적 특성과 어휘적 특성을 보존하지만, 띄어쓰기나 들여쓰기와 같은 레이아웃(Layout) 특성은 캡처하지 못한다는 특징을 지닙니다 [2, 3]. AST는 코드 스타일을 분석하는 코드 문체론(Code Stylometry)이나 코드를 실행하지 않고 취약점을 탐지하는 정적 애플리케이션 보안 테스트([[SAST]]) 등 다양한 소스 코드 분석 기술의 핵심적인 기반 모델로 활용됩니다 [2, 4].
|
||||
> **이 문서는 [[AST (Abstract Syntax Tree)]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **구조적 특성 및 추상화:** AST는 소스 코드를 구문 분석(Parsing)하여 프로그램의 문법적 구조를 트리로 모델링하여 생성됩니다 [4]. 구체 구문 트리(CST)와 비교했을 때 AST는 들여쓰기, 공백 등의 코드 레이아웃 특성을 생략하고 추상화합니다 [2]. 따라서 코드를 포맷팅하여 간격을 변경하거나 철저히 재들여쓰기(re-indent)를 수행하더라도 구문 분석 후에는 구조가 동일한 AST가 도출됩니다 [3].
|
||||
* **정적 애플리케이션 보안 테스트(SAST)에서의 활용:** SAST 도구는 프로그램의 구조와 구문을 평가할 때 소스 코드를 파싱하여 AST를 구축합니다 [4]. 구축된 AST 구조 위에서 다양한 분석 기법을 적용함으로써, 코드를 실제 실행하지 않고도 코딩 실수, 보안 취약점 및 성능 병목 현상과 같은 잠재적 문제들을 찾아냅니다 [4].
|
||||
* **코드 문체론(Code Stylometry) 및 작성자 식별:** 기계 학습 기반의 코드 문체론에서 AST는 개발자가 언어의 문법 구조를 어떻게 조직화하는지 나타내는 구문적 특징(Syntactic features)을 추출하는 수단으로 사용됩니다 [2]. AST 노드의 조합이나 노드 유형 기반의 특징들은 소스 코드 및 실행 파일로부터 작성자를 식별하는 강력한 지표로 활용됩니다 [5, 6].
|
||||
* **린팅(Linting) 등 도구에서의 활용:** 정적 분석을 돕는 [[ESLint]]와 같은 도구에서도 AST가 활용됩니다. 예를 들어 `eslint-plugin-jsx-a11y` 플러그인은 JSX 구조 내의 접근성 문제에 대하여 즉각적인 AST 린팅 피드백을 제공하여 개발자를 돕습니다 [7]. 또한, 디컴파일된 바이너리를 `[[Joern]]`과 같은 도구를 통해 파싱하여 AST를 구성한 뒤 다양한 코드 특징을 추출할 수도 있습니다 [6].
|
||||
## 핵심 요약 (specialization aspects)
|
||||
- 매 한국어 alias 의 lookup 용.
|
||||
- 매 source code 의 tree representation — semantic 만, trivia 제거.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
## 🔗 Graph
|
||||
- 부모: [[AST (Abstract Syntax Tree)]] (canonical)
|
||||
- Adjacent: [[CST (구체 구문 트리)]] · [[Parser]]
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[CST (구체 구문 트리)]], [[SAST (정적 애플리케이션 보안 테스트)]], [[Code Stylometry (코드 문체론)]]
|
||||
- **Projects/Contexts:** [[ESLint]], [[Joern]]
|
||||
- **Contradictions/Notes:** 소스에 따르면 코드 작성자 식별(Authorship Attribution) 작업 시 AST 모델만을 사용하면 들여쓰기나 공백 등 개인의 레이아웃 코딩 스타일이 캡처되지 않는 한계가 있습니다 [2]. 실제로 실험 결과, AST 기반 접근 방식보다 이러한 레이아웃 요소를 포함하는 CST(구체 구문 트리)를 사용할 때 작성자 식별 정확도가 눈에 띄게(약 17%) 향상되는 것으로 나타납니다 [8, 9].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -1,25 +1,144 @@
|
||||
---
|
||||
id: wiki-20260508-ast-abstract-syntax-tree--redir
|
||||
title: AST(Abstract Syntax Tree)
|
||||
category: Programming & Language
|
||||
status: merged
|
||||
redirect_to: AST(Abstract_Syntax_Tree)
|
||||
canonical_id: AST(Abstract_Syntax_Tree)
|
||||
aliases: []
|
||||
title: AST (Abstract Syntax Tree)
|
||||
category: 10_Wiki/Topics
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [AST, Abstract Syntax Tree, 추상 구문 트리]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [redirect]
|
||||
verification_status: applied
|
||||
tags: [compiler, parser, ast, language]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-merge 2026-05-08)
|
||||
tech_stack:
|
||||
language: typescript
|
||||
framework: babel-parser, ts-morph, tree-sitter
|
||||
---
|
||||
|
||||
# AST(Abstract Syntax Tree)
|
||||
# AST (Abstract Syntax Tree)
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 이 문서는 P-Reinforce Phase 2 자동 MERGE에 의해 **[[AST(Abstract_Syntax_Tree)]]**로 통합되었습니다.
|
||||
## 매 한 줄
|
||||
> **"매 source code 의 tree-shaped semantic skeleton"**. 매 lexer 의 token stream 을 parser 가 grammar rule 따라 nested node 의 tree 로 변환 — comment/whitespace/parens 의 trivia 를 제거하고 매 program 의 structural meaning 만 보존. 매 2026 의 Babel·SWC·TypeScript Compiler·Tree-sitter·Rust analyzer 의 모든 modern toolchain 의 핵심 IR.
|
||||
|
||||
---
|
||||
*Redirected to: [[AST(Abstract_Syntax_Tree)]]*
|
||||
## 매 핵심
|
||||
|
||||
### 매 AST vs CST
|
||||
- **CST** (Concrete Syntax Tree): 매 source 의 every char 보존 — formatter, linter용.
|
||||
- **AST**: 매 semantic structure 만 — compiler, transpiler, type checker용.
|
||||
- 매 trade-off: lossless ↔ analysis-friendly.
|
||||
|
||||
### 매 Node 의 구조
|
||||
- 매 `type` field (e.g. `BinaryExpression`, `Identifier`).
|
||||
- 매 children (positional or named).
|
||||
- 매 `loc`/`range` (source position).
|
||||
- 매 ESTree spec — JS 의 standard AST shape.
|
||||
|
||||
### 매 응용
|
||||
1. **Compiler**: AST → IR → bytecode/machine code.
|
||||
2. **Transpiler** (Babel, SWC): AST → transformed AST → code.
|
||||
3. **Linter** (ESLint): AST traversal + rule matching.
|
||||
4. **Formatter** (Prettier): AST → printer.
|
||||
5. **IDE**: hover, refactor, go-to-def 의 AST query.
|
||||
6. **Codemod** (jscodeshift, ts-morph): bulk refactor.
|
||||
|
||||
## 💻 패턴
|
||||
|
||||
### Babel parse
|
||||
```typescript
|
||||
import { parse } from "@babel/parser";
|
||||
|
||||
const code = `const x = 1 + 2;`;
|
||||
const ast = parse(code, { sourceType: "module" });
|
||||
console.log(ast.program.body[0]);
|
||||
// VariableDeclaration { kind: "const", declarations: [...] }
|
||||
```
|
||||
|
||||
### Visitor (transform)
|
||||
```typescript
|
||||
import traverse from "@babel/traverse";
|
||||
|
||||
traverse(ast, {
|
||||
BinaryExpression(path) {
|
||||
if (path.node.operator === "+") {
|
||||
// 매 constant folding
|
||||
const { left, right } = path.node;
|
||||
if (left.type === "NumericLiteral" && right.type === "NumericLiteral") {
|
||||
path.replaceWith({ type: "NumericLiteral", value: left.value + right.value });
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### TypeScript Compiler API
|
||||
```typescript
|
||||
import * as ts from "typescript";
|
||||
|
||||
const source = ts.createSourceFile("x.ts", "const x: number = 1;", ts.ScriptTarget.Latest);
|
||||
function visit(node: ts.Node) {
|
||||
if (ts.isVariableDeclaration(node)) {
|
||||
console.log(node.name.getText(source));
|
||||
}
|
||||
ts.forEachChild(node, visit);
|
||||
}
|
||||
visit(source);
|
||||
```
|
||||
|
||||
### Tree-sitter (incremental)
|
||||
```javascript
|
||||
const Parser = require("tree-sitter");
|
||||
const TS = require("tree-sitter-typescript").typescript;
|
||||
const parser = new Parser();
|
||||
parser.setLanguage(TS);
|
||||
const tree = parser.parse("const x = 1;");
|
||||
// 매 incremental: tree.edit(...) 로 partial reparse
|
||||
```
|
||||
|
||||
### ts-morph (codemod)
|
||||
```typescript
|
||||
import { Project } from "ts-morph";
|
||||
const proj = new Project();
|
||||
const sf = proj.addSourceFileAtPath("src/foo.ts");
|
||||
sf.getFunctions().forEach((fn) => fn.setIsAsync(true));
|
||||
sf.saveSync();
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| Compile / transpile JS/TS | Babel (@babel/parser) or SWC |
|
||||
| IDE / editor highlighting | Tree-sitter (incremental, fast) |
|
||||
| TypeScript-specific 의 type-aware refactor | TypeScript Compiler API or ts-morph |
|
||||
| Linting | ESLint (espree/typescript-eslint) |
|
||||
| 1-off codemod | jscodeshift or ts-morph |
|
||||
| Native speed (Rust/Go) | SWC, Rome, Biome |
|
||||
|
||||
**기본값**: 매 TS 의 type-aware 작업 → ts-morph. 매 perf-critical 의 transpile → SWC. 매 editor → Tree-sitter.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Compiler]] · [[Parser]]
|
||||
- 변형: [[CST (Concrete Syntax Tree)]] · [[IR (Intermediate Representation)]]
|
||||
- 응용: [[Babel]] · [[ESLint]] · [[Prettier]] · [[TypeScript Compiler]]
|
||||
- Adjacent: [[Lexer]] · [[Tokenizer]] · [[Tree-sitter]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 codemod 의 generation, AST node type 의 explanation, visitor pattern 의 boilerplate.
|
||||
**언제 X**: 매 large-scale 의 type-aware refactor — ts-morph 의 deterministic 가 더 안전.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Regex 의 code 의 transform**: 매 nested syntax 의 break — AST 의 use.
|
||||
- **Mutate AST 의 children array 의 직접**: 매 visitor 의 path API 의 use.
|
||||
- **Source map 의 무시**: 매 transform 후 의 debug 의 broken — `retainLines`/sourcemap 의 emit.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Babel docs, TS Compiler API, ESTree spec).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — full AST treatment with Babel/TS/Tree-sitter patterns |
|
||||
|
||||
@@ -1,25 +1,146 @@
|
||||
---
|
||||
id: wiki-20260508-ambient-declarations-redir
|
||||
title: Ambient Declarations
|
||||
category: Programming & Language
|
||||
status: merged
|
||||
redirect_to: Ambient_Declarations
|
||||
canonical_id: Ambient_Declarations
|
||||
aliases: []
|
||||
category: 10_Wiki/Topics
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [Ambient Declarations, declare, .d.ts, Type Declarations]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [redirect]
|
||||
verification_status: applied
|
||||
tags: [typescript, types, declaration, dts]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-merge 2026-05-08)
|
||||
tech_stack:
|
||||
language: typescript
|
||||
framework: TypeScript 5.x
|
||||
---
|
||||
|
||||
# Ambient Declarations
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 이 문서는 P-Reinforce Phase 2 자동 MERGE에 의해 **[[Ambient_Declarations]]**로 통합되었습니다.
|
||||
## 매 한 줄
|
||||
> **"매 TS 가 외부 의 untyped JS / runtime global / module 의 type 의 알려주는 declaration"**. 매 `declare` keyword 로 매 implementation 없이 매 type shape 만 표현 — 매 .d.ts file 의 핵심. 매 TypeScript 의 gradual typing 의 backbone, 매 DefinitelyTyped (`@types/*`) 의 1B+ weekly downloads 의 base.
|
||||
|
||||
---
|
||||
*Redirected to: [[Ambient_Declarations]]*
|
||||
## 매 핵심
|
||||
|
||||
### 매 Forms
|
||||
- **Ambient variable**: `declare const VERSION: string;`
|
||||
- **Ambient function**: `declare function gtag(...args: unknown[]): void;`
|
||||
- **Ambient class**: `declare class Foo { x: number; }`
|
||||
- **Ambient module**: `declare module "lodash" { ... }`
|
||||
- **Ambient namespace**: `declare namespace JSX { interface Element {} }`
|
||||
- **Global augmentation**: `declare global { interface Window { myApp: App; } }`
|
||||
|
||||
### 매 Use cases
|
||||
1. Untyped 3rd-party JS lib 의 type shim.
|
||||
2. Build-time globals (Webpack `process.env.NODE_ENV`, Vite `import.meta.env`).
|
||||
3. Module augmentation (Express `Request.user`).
|
||||
4. Asset imports (`*.svg`, `*.css`).
|
||||
|
||||
### 매 응용
|
||||
- 매 `@types/node`, `@types/react` — DefinitelyTyped 의 ambient declarations.
|
||||
- 매 `vite-env.d.ts`, `next-env.d.ts` — framework boilerplate.
|
||||
- 매 internal monorepo 의 shared globals.
|
||||
|
||||
## 💻 패턴
|
||||
|
||||
### Global ambient
|
||||
```typescript
|
||||
// globals.d.ts
|
||||
declare const __APP_VERSION__: string; // injected by webpack DefinePlugin
|
||||
declare const gtag: (cmd: string, ...args: unknown[]) => void;
|
||||
```
|
||||
|
||||
### Module declaration (untyped lib)
|
||||
```typescript
|
||||
// shims.d.ts
|
||||
declare module "untyped-lib" {
|
||||
export function doThing(x: number): string;
|
||||
export const version: string;
|
||||
}
|
||||
```
|
||||
|
||||
### Asset imports
|
||||
```typescript
|
||||
// assets.d.ts
|
||||
declare module "*.svg" {
|
||||
const content: string;
|
||||
export default content;
|
||||
}
|
||||
declare module "*.css" {
|
||||
const styles: { readonly [key: string]: string };
|
||||
export default styles;
|
||||
}
|
||||
```
|
||||
|
||||
### Module augmentation
|
||||
```typescript
|
||||
// express.d.ts
|
||||
import { User } from "./user";
|
||||
declare global {
|
||||
namespace Express {
|
||||
interface Request {
|
||||
user?: User;
|
||||
}
|
||||
}
|
||||
}
|
||||
export {}; // 매 file 의 module 로 만든 — augmentation 의 trigger
|
||||
```
|
||||
|
||||
### Window augmentation
|
||||
```typescript
|
||||
declare global {
|
||||
interface Window {
|
||||
__REDUX_DEVTOOLS_EXTENSION__?: () => unknown;
|
||||
dataLayer: Array<Record<string, unknown>>;
|
||||
}
|
||||
}
|
||||
export {};
|
||||
```
|
||||
|
||||
### .d.ts for own JS file
|
||||
```typescript
|
||||
// my-lib.d.ts (next to my-lib.js)
|
||||
export declare function add(a: number, b: number): number;
|
||||
export declare const VERSION: string;
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| 3rd-party lib + DefinitelyTyped 존재 | `pnpm add -D @types/<lib>` |
|
||||
| 3rd-party lib, types 없음 | 자체 `.d.ts` shim |
|
||||
| Build-time global (`process.env`) | `declare const` in `env.d.ts` |
|
||||
| Add field to Express Request | module augmentation |
|
||||
| Add to Window | `declare global { interface Window {} }` |
|
||||
| Asset (SVG, CSS module) | `declare module "*.svg"` |
|
||||
|
||||
**기본값**: 매 framework template 의 `*-env.d.ts` 의 활용 + DefinitelyTyped first.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[TypeScript]] · [[Type System]]
|
||||
- 변형: [[선언 파일(dts)]] · [[Module Augmentation]]
|
||||
- 응용: [[DefinitelyTyped]] · [[@types/node]]
|
||||
- Adjacent: [[Declaration Merging]] · [[Triple-Slash Directives]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 .d.ts shim 의 생성, module augmentation 의 syntax, type shape 의 inference.
|
||||
**언제 X**: 매 type 의 정확성 의 verify — 매 runtime 의 mismatch 의 silent.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **`declare module "*"` (catch-all)**: 매 typo 의 silent — 매 specific glob 의 사용.
|
||||
- **`any` 의 default in shim**: 매 type safety 의 lose.
|
||||
- **`.d.ts` outside `include`**: tsconfig 의 안 잡힘 — `typeRoots` / `types` 의 verify.
|
||||
- **Forgetting `export {}`** in module augmentation file: 매 global script 로 처리 — augmentation 의 fail.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (typescriptlang.org/docs/handbook/declaration-files).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — full ambient/global/augmentation coverage |
|
||||
|
||||
@@ -1,25 +1,112 @@
|
||||
---
|
||||
id: wiki-20260508-beat-saber-redir
|
||||
title: Beat Saber
|
||||
category: Programming & Language
|
||||
status: merged
|
||||
redirect_to: Beat_Saber
|
||||
canonical_id: Beat_Saber
|
||||
aliases: []
|
||||
category: 10_Wiki/Topics
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [Beat Saber, 비트 세이버, BS]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [redirect]
|
||||
verification_status: applied
|
||||
tags: [vr, game, exergaming, rhythm, unity]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-merge 2026-05-08)
|
||||
tech_stack:
|
||||
language: csharp
|
||||
framework: Unity, OpenXR
|
||||
---
|
||||
|
||||
# Beat Saber
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 이 문서는 P-Reinforce Phase 2 자동 MERGE에 의해 **[[Beat_Saber]]**로 통합되었습니다.
|
||||
## 매 한 줄
|
||||
> **"매 VR rhythm 의 lightsaber slashing 의 game"**. 매 Beat Games (Czech, 2018, Meta acquired 2019) 의 release — 매 song 에 맞춰 색깔 cube 의 specific direction slice + obstacle 의 dodge. 매 2026 의 VR 의 best-selling app 중 하나, 매 exergaming research 의 standard reference.
|
||||
|
||||
---
|
||||
*Redirected to: [[Beat_Saber]]*
|
||||
## 매 핵심
|
||||
|
||||
### 매 Gameplay
|
||||
- **Red/Blue cube**: left/right saber 의 매칭.
|
||||
- **Direction arrow**: 8-way slice direction.
|
||||
- **Obstacles** (red wall): squat / lean.
|
||||
- **Bombs**: avoid.
|
||||
- 매 difficulty: Easy, Normal, Hard, Expert, Expert+.
|
||||
|
||||
### 매 Tech
|
||||
- Unity engine, OpenXR / Meta SDK.
|
||||
- 매 90 Hz frame target — 매 motion sickness 의 minimize.
|
||||
- 매 input: hand-tracked controller (6DoF, sub-mm precision).
|
||||
- 매 audio sync: <20 ms latency.
|
||||
|
||||
### 매 Research relevance
|
||||
1. **Exergaming**: 매 calorie burn ~6-8 kcal/min — moderate cardio.
|
||||
2. **VR locomotion**: 매 stationary play — 매 motion sickness 의 less.
|
||||
3. **Reaction time**: 매 expert 의 <300 ms.
|
||||
4. **Custom song**: BSMG modding community 의 huge — research 의 stimulus 의 source.
|
||||
|
||||
## 💻 패턴
|
||||
|
||||
### Custom map JSON (Beat Saber 의 .dat)
|
||||
```json
|
||||
{
|
||||
"_version": "2.0.0",
|
||||
"_notes": [
|
||||
{ "_time": 4.0, "_lineIndex": 1, "_lineLayer": 1, "_type": 0, "_cutDirection": 1 }
|
||||
],
|
||||
"_obstacles": [
|
||||
{ "_time": 8, "_lineIndex": 0, "_type": 0, "_duration": 2, "_width": 1 }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Unity OpenXR controller
|
||||
```csharp
|
||||
[SerializeField] InputActionReference rightTrigger;
|
||||
void Update() {
|
||||
if (rightTrigger.action.WasPressedThisFrame()) SwingSaber(Hand.Right);
|
||||
}
|
||||
```
|
||||
|
||||
### Slice detection (oversimplified)
|
||||
```csharp
|
||||
void OnSaberCollide(Cube cube, Vector3 sliceDir) {
|
||||
var dot = Vector3.Dot(sliceDir.normalized, cube.expectedDir);
|
||||
if (dot > 0.7f) ScoreHit(cube); // 매 angle tolerance
|
||||
else MissNote();
|
||||
}
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Notes |
|
||||
|---|---|
|
||||
| VR fitness research | Beat Saber 의 standardized intensity (BPM × difficulty) |
|
||||
| Headset benchmark | 매 90/120 Hz 의 stable — frame-drop 의 visible |
|
||||
| Motion sickness study | 매 stationary — control 의 baseline |
|
||||
| Custom content research | BSMG (BeastSaber, ScoreSaber) 의 telemetry |
|
||||
|
||||
**기본값**: VR exergaming 연구의 standard testbed.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[VR Game]] · [[Rhythm Game]]
|
||||
- 변형: [[비트 세이버(Beat Saber) 엑서게임 연구]] · [[비트 세이버(Beat Saber) 실험]]
|
||||
- 응용: [[엑서게임(Exergaming)]] · [[VR 자전거 시뮬레이터]]
|
||||
- Adjacent: [[VR Sickness]] · [[Vergence-Accommodation Conflicts]] · [[OpenXR]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 custom map 의 design, gameplay logic 의 brainstorm, Unity scripting 의 boilerplate.
|
||||
**언제 X**: 매 official content 의 reverse-engineering — 매 ToS 의 violate.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Frame drop 무시**: 매 VR 의 sub-90Hz → 매 nausea — 매 profile 의 강제.
|
||||
- **Latency >30 ms**: 매 saber → cube 의 desync — 매 prediction.
|
||||
- **Room scale 무시**: 매 obstacle 의 player 의 hit — 매 chaperone 의 enforce.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Beat Games official, BSMG wiki, Meta Store metrics).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — VR rhythm game treatment with research relevance |
|
||||
|
||||
@@ -1,25 +1,144 @@
|
||||
---
|
||||
id: wiki-20260508-ci-cd-pipeline-redir
|
||||
title: CI CD Pipeline
|
||||
category: Programming & Language
|
||||
status: merged
|
||||
redirect_to: CI_CD_Pipeline
|
||||
canonical_id: CI_CD_Pipeline
|
||||
aliases: []
|
||||
title: CI/CD Pipeline
|
||||
category: 10_Wiki/Topics
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [CI/CD, CI CD Pipeline, 파이프라인, Continuous Delivery]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [redirect]
|
||||
verification_status: applied
|
||||
tags: [cicd, devops, automation, deployment]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-merge 2026-05-08)
|
||||
tech_stack:
|
||||
language: yaml
|
||||
framework: GitHub Actions, GitLab CI, ArgoCD
|
||||
---
|
||||
|
||||
# CI CD Pipeline
|
||||
# CI/CD Pipeline
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 이 문서는 P-Reinforce Phase 2 자동 MERGE에 의해 **[[CI_CD_Pipeline]]**로 통합되었습니다.
|
||||
## 매 한 줄
|
||||
> **"매 commit 의 production 의 automated path"**. 매 Continuous Integration (build+test on every push) + Continuous Delivery/Deployment (artifact → staging → prod 의 자동) 의 결합 — 매 2026 의 GitHub Actions 의 dominant 의 + GitLab CI / Jenkins / CircleCI / ArgoCD (GitOps) 의 ecosystem. 매 trunk-based dev + feature flag 의 pair.
|
||||
|
||||
---
|
||||
*Redirected to: [[CI_CD_Pipeline]]*
|
||||
## 매 핵심
|
||||
|
||||
### 매 Stages
|
||||
1. **Source**: trigger (push, PR, schedule, manual).
|
||||
2. **Build**: compile, package (Docker image, JAR, npm).
|
||||
3. **Test**: unit → integration → e2e → security scan.
|
||||
4. **Artifact**: registry push (ECR, GHCR, Artifactory).
|
||||
5. **Deploy**: staging → smoke test → prod (canary / blue-green / rolling).
|
||||
6. **Observe**: metrics, alerts, rollback trigger.
|
||||
|
||||
### 매 CI vs CD
|
||||
- **CI**: 매 main branch 의 always-green — fast feedback (<10 min).
|
||||
- **CD (delivery)**: 매 always-deployable artifact — manual prod gate.
|
||||
- **CD (deployment)**: 매 fully automated — canary + auto-rollback.
|
||||
|
||||
### 매 응용
|
||||
1. SaaS web app: GitHub Actions → Docker → ECS/K8s.
|
||||
2. Mobile: Fastlane + TestFlight/Play Console.
|
||||
3. Library: tag → npm/PyPI/Maven publish.
|
||||
4. Infrastructure: Terraform plan/apply via CI.
|
||||
|
||||
## 💻 패턴
|
||||
|
||||
### GitHub Actions (Node + Docker)
|
||||
```yaml
|
||||
name: ci
|
||||
on: { push: { branches: [main] }, pull_request: {} }
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with: { node-version: 20, cache: pnpm }
|
||||
- run: pnpm install --frozen-lockfile
|
||||
- run: pnpm lint && pnpm test --coverage
|
||||
- uses: codecov/codecov-action@v4
|
||||
build-deploy:
|
||||
needs: test
|
||||
if: github.ref == 'refs/heads/main'
|
||||
runs-on: ubuntu-latest
|
||||
permissions: { id-token: write, contents: read }
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: aws-actions/configure-aws-credentials@v4
|
||||
with: { role-to-assume: arn:aws:iam::123:role/ci, aws-region: us-east-1 }
|
||||
- run: docker build -t $ECR/app:${{ github.sha }} . && docker push $ECR/app:${{ github.sha }}
|
||||
- run: aws ecs update-service --cluster prod --service app --force-new-deployment
|
||||
```
|
||||
|
||||
### GitLab CI (matrix + cache)
|
||||
```yaml
|
||||
stages: [test, build, deploy]
|
||||
test:
|
||||
stage: test
|
||||
image: node:20
|
||||
cache: { paths: [node_modules/] }
|
||||
script: [npm ci, npm test]
|
||||
parallel:
|
||||
matrix: [{ NODE_VERSION: ["18", "20", "22"] }]
|
||||
```
|
||||
|
||||
### ArgoCD (GitOps)
|
||||
```yaml
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata: { name: app, namespace: argocd }
|
||||
spec:
|
||||
source: { repoURL: https://git.../infra, path: k8s/prod, targetRevision: HEAD }
|
||||
destination: { server: https://kubernetes.default.svc, namespace: prod }
|
||||
syncPolicy: { automated: { prune: true, selfHeal: true } }
|
||||
```
|
||||
|
||||
### Canary deploy (Argo Rollouts)
|
||||
```yaml
|
||||
strategy:
|
||||
canary:
|
||||
steps: [{ setWeight: 10 }, { pause: { duration: 10m } }, { setWeight: 50 }, { pause: {} }]
|
||||
analysis: { templates: [{ templateName: success-rate }] }
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| GitHub-hosted repo | GitHub Actions |
|
||||
| Self-hosted, full DevOps suite | GitLab CI |
|
||||
| Java-heavy enterprise | Jenkins |
|
||||
| K8s native, declarative | ArgoCD / Flux |
|
||||
| Mobile | Fastlane + Bitrise |
|
||||
| Monorepo | Nx Cloud / Turborepo Remote Cache |
|
||||
|
||||
**기본값**: GitHub Actions + Docker + ArgoCD (cloud-native) or ECS/Cloud Run (PaaS).
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[DevOps]] · [[Software Delivery]]
|
||||
- 변형: [[Continuous Integration (CI)]] · [[Continuous Delivery]] · [[GitOps]]
|
||||
- 응용: [[Blue-Green Deployment]] · [[Canary Deployment]] · [[Feature Flag]]
|
||||
- Adjacent: [[Docker]] · [[Kubernetes]] · [[Terraform]] · [[TeamCity]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 workflow YAML 의 generation, matrix 의 expansion, action 의 lookup.
|
||||
**언제 X**: 매 production 의 deploy script — 매 review + canary + rollback 의 always.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **No rollback path**: 매 deploy 의 forward-only — 매 disaster.
|
||||
- **Secrets in YAML**: 매 GitHub Secrets / OIDC 의 사용.
|
||||
- **Slow CI** (>15 min): 매 dev 의 PR 의 stack — 매 cache + parallelize.
|
||||
- **Deploy on every push**: 매 manual gate or canary 의 사용 — 매 prod 의 break.
|
||||
- **No artifact pinning** (`:latest`): 매 reproducibility 의 lose.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (GitHub Actions docs, GitLab CI docs, ArgoCD docs).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — full CI/CD treatment with Actions/ArgoCD examples |
|
||||
|
||||
@@ -1,24 +1,33 @@
|
||||
---
|
||||
id: wiki-2026-0508-ci-cd-파이프라인-자동화
|
||||
title: CI CD 파이프라인 자동화
|
||||
title: CI/CD 파이프라인 자동화
|
||||
category: 10_Wiki/Topics
|
||||
status: merged
|
||||
redirect_to: CI_CD_Pipeline
|
||||
canonical_id: CI_CD_Pipeline
|
||||
aliases: [ci_cd_automation_redirect]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: ci-cd-pipeline
|
||||
duplicate_of: "[[CI/CD Pipeline]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [uncategorized]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
verification_status: redirected
|
||||
tags: [duplicate, cicd, automation]
|
||||
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
|
||||
---
|
||||
|
||||
# Redirect
|
||||
# CI/CD 파이프라인 자동화
|
||||
|
||||
이 문서는 [[CI_CD_Pipeline]]으로 통합되었습니다.
|
||||
> **이 문서는 [[CI/CD Pipeline]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 핵심 요약 (specialization aspects)
|
||||
- 매 한국어 alias 의 lookup 용.
|
||||
- 매 build → test → deploy 의 자동화 — 매 GitHub Actions / GitLab CI / Jenkins 의 modern stack.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[CI/CD Pipeline]] (canonical)
|
||||
- Adjacent: [[Continuous Integration (CI)]] · [[TeamCity]] · [[데브섹옵스 (DevSecOps) 환경에서의 지속적인 보안 검사]]
|
||||
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -1,24 +1,33 @@
|
||||
---
|
||||
id: wiki-2026-0508-ci-cd-파이프라인
|
||||
title: CI CD 파이프라인
|
||||
title: CI/CD 파이프라인
|
||||
category: 10_Wiki/Topics
|
||||
status: merged
|
||||
redirect_to: CI_CD_Pipeline
|
||||
canonical_id: CI_CD_Pipeline
|
||||
aliases: [ci_cd_korean_redirect]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: ci-cd-pipeline
|
||||
duplicate_of: "[[CI/CD Pipeline]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [uncategorized]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
verification_status: redirected
|
||||
tags: [duplicate, cicd]
|
||||
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
|
||||
---
|
||||
|
||||
# Redirect
|
||||
# CI/CD 파이프라인
|
||||
|
||||
이 문서는 [[CI_CD_Pipeline]]으로 통합되었습니다.
|
||||
> **이 문서는 [[CI/CD Pipeline]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 핵심 요약 (specialization aspects)
|
||||
- 매 한국어 alias.
|
||||
- 매 commit → build → test → deploy 의 자동화.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[CI/CD Pipeline]] (canonical)
|
||||
- Adjacent: [[Continuous Integration (CI)]] · [[CI_CD 파이프라인 자동화]]
|
||||
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -2,96 +2,33 @@
|
||||
id: wiki-2026-0508-cst-구체-구문-트리
|
||||
title: CST (구체 구문 트리)
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-ECB052]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: cst
|
||||
duplicate_of: "[[CST (Concrete Syntax Tree)]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - CST (구체 구문 트리)"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, parser, compiler]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[CST (구체 구문 트리)]]
|
||||
# CST (구체 구문 트리)
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> CST(구체 구문 트리) 또는 파스 트리(parse tree)는 문맥 자유 문법(context-free grammar)의 트리 표현으로, 컴파일러가 코드를 어떻게 이해하는지 보여주는 공식적인 표현 방식입니다 [1]. AST(추상 구문 트리)와 달리 포괄적인 구문 요소뿐만 아니라 미세한 문체, 어휘 및 레이아웃(공백, 들여쓰기 등)의 세부 사항까지 코드의 모든 측면을 정밀하게 포착하여 계층적 구조로 렌더링합니다 [2]. 이러한 특징으로 인해 코드 서식 지정이나 축소 등 레이아웃의 변화를 감지할 수 있어 프로그래머의 코딩 스타일을 분석하고 작성자를 식별하는 코드 스타일로메트리(Code stylometry)에 유용하게 활용됩니다 [3, 4].
|
||||
> **이 문서는 [[CST (Concrete Syntax Tree)]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **정의 및 구조**
|
||||
CST는 주어진 문맥 자유 문법에 기반한 순서 트리(ordered tree)로, 루트(root), 비단말(Non-terminal) 노드, 단말(Terminal) 노드로 구성되어 컴파일러가 코드를 해석하는 계층적인 구조를 시각화합니다 [1, 2, 5]. 트리의 각 노드는 클래스 정의, 함수 정의 또는 변수 할당과 같은 명확한 코드 구성 요소와 연결됩니다 [2].
|
||||
## 핵심 요약 (specialization aspects)
|
||||
- 매 한국어 alias 의 lookup 용.
|
||||
- 매 every char (whitespace, comment) 의 lossless 보존 — formatter, linter, IDE refactor 의 source.
|
||||
- 매 vs AST: AST 는 semantic 만, CST 는 surface 의 모든 token.
|
||||
|
||||
* **AST(추상 구문 트리)와의 차이점**
|
||||
구문 기능과 일부 어휘적 특징만 보존하고 레이아웃의 특징을 추상화하여 무시하는 AST와 달리, CST는 코드의 레이아웃(공백, 줄 바꿈, 들여쓰기 등)과 어휘적 세부 사항을 모두 포함합니다 [3, 4]. 예를 들어, 코드를 철저하게 다시 들여쓰기(re-indent)하는 소스-대-소스 변환을 수행할 경우 파싱된 후의 AST 구조는 동일하게 유지되지만, CST는 시각적이고 구조적으로 크게 변경됩니다 [3].
|
||||
## 🔗 Graph
|
||||
- 부모: [[CST (Concrete Syntax Tree)]] (canonical)
|
||||
- Adjacent: [[AST (Abstract Syntax Tree)]] · [[Tree-sitter]] · [[Parser]]
|
||||
|
||||
* **코드 스타일로메트리(저자 식별)에서의 활용**
|
||||
레이아웃 및 어휘적 특징이 개인의 코딩 스타일을 결정하는 핵심 요소이므로, 이를 포착하기 위해 코드 작성자 분류 모델에서 CST가 중요한 입력 데이터로 사용됩니다 [4, 6]. 구체적인 단말 노드 간의 경로를 해시화하여 나타낸 '경로 컨텍스트(path context)'의 집합(bag)은 입력된 소스 코드의 문체, 레이아웃 및 구문적 특징을 훌륭하게 유지합니다 [7, 8]. 한 연구 결과에 따르면 파이썬 소스 코드 분류에 AST 대신 CST를 도입했을 때 프로그래머의 식별 정확도가 51.00%에서 67.86%로 현저히 향상되었습니다 [6, 9].
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[AST (추상 구문 트리)]], 코드 스타일로메트리 (Code Stylometry), [[코드 포매팅 (Code [[Formatting]])]], [[코드 축소 ([[Code Minification]])]]
|
||||
- **Projects/Contexts:** [[코드 서식 지정과 축소가 코드 스타일로메트리(작성자 인식)에 미치는 영향을 평가하는 기계 학습 모델 분류 연구]]
|
||||
- **Contradictions/Notes:** 소스에 관련된 모순된 정보는 없으며, 기존의 주류 문헌들이 코드 표상을 위해 주로 AST를 사용하는 것에서 벗어나, 서식 지정과 축소에 따른 표면적 변화를 측정하기 위해 CST의 사용이 필수적이었다는 점을 강조합니다 [4].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -1,96 +1,33 @@
|
||||
---
|
||||
id: wiki-2026-0508-chrome-devtools-크롬-개발자-도구
|
||||
title: Chrome DevTools(크롬 개발자 도구)
|
||||
title: Chrome DevTools (크롬 개발자 도구)
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-663B99]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: chrome-devtools
|
||||
duplicate_of: "[[Chrome DevTools]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - [[Chrome DevTools]](크롬 개발자 도구)"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, devtools, browser]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[Chrome DevTools(크롬 개발자 도구)]]
|
||||
# Chrome DevTools (크롬 개발자 도구)
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> [[Chrome]] DevTools(크롬 개발자 도구)는 [[JavaScript]] 애플리케이션 및 브라우저 환경에서 메모리 누수를 탐지하고 성능을 분석하기 위해 다양한 프로파일링 도구를 제공하는 개발자용 인터페이스입니다 [1-3]. 주로 메모리 패널([[memory]] panel)을 통해 힙 스냅샷을 캡처하거나 시간에 따른 메모리 할당을 추적하여, 가비지 컬렉터(GC)에 의해 해제되지 않은 객체와 그 참조 원인을 식별하는 데 사용됩니다 [1, 4, 5].
|
||||
> **이 문서는 [[Chrome DevTools]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **메모리 패널(Memory Panel)의 주요 도구:** Chrome DevTools의 메모리 패널은 메모리 누수 식별을 위해 힙 스냅샷([[Heap Snapshot]]), 타임라인의 할당 계측(Allocation instrumentation on timeline), 할당 샘플링(Allocation sampling)의 세 가지 주요 도구를 제공합니다 [1, 6].
|
||||
* **힙 스냅샷(Heap Snapshot):** 특정 시점의 전체 객체 그래프를 캡처하여 JavaScript 객체 및 관련 DOM 노드에 의한 메모리 분포를 보여줍니다 [1, 7]. 요약(Summary), 비교(Comparison), 포함(Containment), 통계([[Statistics]]) 뷰를 제공하여 메모리를 세밀하게 분석할 수 있습니다 [8].
|
||||
* 요약 뷰에서는 객체의 고유한 메모리 크기인 얕은 크기(Shallow size)와, 삭제 시 확보할 수 있는 보존 크기(Retained size)를 확인할 수 있습니다 [9].
|
||||
* 생성자 필터를 사용해 분리된 DOM 노드가 유지하는 객체나 중복된 문자열을 필터링함으로써 비효율적인 메모리 사용을 추적할 수 있습니다 [10].
|
||||
* **할당 타임라인([[Allocation Timeline]]):** 힙 프로파일러의 상세한 스냅샷 정보와 타임라인 패널의 점진적 업데이트를 결합한 도구입니다 [2]. 기록하는 동안 주기적(최대 50ms 간격)으로 힙 스냅샷을 찍어 메모리 할당을 시각화합니다 [4, 11]. 타임라인에 파란색 막대로 표시된 객체는 할당 후 현재까지 살아있는 객체(누수 후보)이며, 회색 막대는 가비지 컬렉션된 객체를 의미합니다 [1, 5, 11, 12].
|
||||
* **보존자(Retainers) 및 경로 추적:** DevTools는 선택한 객체를 가리키는 다른 객체들의 참조 경로(가비지 컬렉션 루트로부터의 경로)를 보여주는 보존자 섹션을 제공합니다 [13-15]. 특정 보존자를 무시(Ignore this retainer) 처리하여 다른 어떤 객체가 해당 객체의 메모리를 유지하고 있는지 코드를 수정하지 않고도 확인할 수 있습니다 [14].
|
||||
* **Node.js 연동 분석:** `chrome://inspect`를 통해 실행 중인 Node.js 프로세스에 연결하여 프로덕션 환경의 메모리 누수 상황을 분석할 수도 있습니다 [16]. 또한 Node.js에서 네이티브 프로파일링을 통해 생성된 `.heapprofile` 파일을 DevTools에 로드하면 함수 수준의 할당 내역을 파악할 수 있습니다 [17].
|
||||
## 핵심 요약 (specialization aspects)
|
||||
- 매 한국어 alias 의 lookup 용.
|
||||
- 매 Performance, Memory, Network, Coverage, Lighthouse 의 panel.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
## 🔗 Graph
|
||||
- 부모: [[Chrome DevTools]] (canonical)
|
||||
- Adjacent: [[Flame Chart]] · [[Google Lighthouse]] · [[V8 엔진 힙 아키텍처]]
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** Memory Leak(메모리 누수), [[Garbage Collection(가비지 컬렉션)]], Heap Snapshot(힙 스냅샷), Allocation Timeline(할당 타임라인)
|
||||
- **Projects/Contexts:** Node.js 프로세스 모니터링 및 메모리 분석, 브라우저 DOM 누수 탐지 및 렌더링 최적화
|
||||
- **Contradictions/Notes:** 소스에 관련 정보가 부족합니다. (제공된 소스 내에서 Chrome DevTools의 기능이나 메모리 분석 방법론에 대해 상충되는 주장은 발견되지 않았습니다.)
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -2,91 +2,121 @@
|
||||
id: wiki-2026-0508-chromium
|
||||
title: Chromium
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-6038C1]
|
||||
aliases: [Chromium, Blink, V8 Browser]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [browser, engine, blink, v8]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Chromium"
|
||||
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: cpp
|
||||
framework: Blink, V8, Skia
|
||||
---
|
||||
|
||||
# [[Chromium]]
|
||||
# Chromium
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Chromium(또는 [[Chrome]])은 V8 자바스크립트 엔진을 내장(embed)하여 실행하는 기반 웹 브라우저 프로젝트입니다 [1-3]. 제공된 소스에서 Chromium은 V8 메모리 케이지 도입과 같은 보안 정책을 선도하고 [4, 5], 브라우저 렌더링의 유휴 시간(idle time)을 활용해 가비지 컬렉션을 효율적으로 수행하며 [2], 강력한 메모리 프로파일링 및 추적(Tracing) 인프라를 제공하는 핵심 호스트 환경으로 설명됩니다 [1, 6, 7].
|
||||
## 매 한 줄
|
||||
> **"매 Google 의 open-source browser engine codebase"**. 매 Blink (rendering, fork of WebKit, 2013) + V8 (JS) + Skia (graphics) + Mojo (IPC) 의 결합 — 매 2026 의 Chrome / Edge / Brave / Opera / Arc / Vivaldi / Electron / Tauri (WebView2) 의 base. 매 multi-process security architecture (sandbox, site isolation) 의 reference.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **보안 및 V8 메모리 케이지 적용:** Chromium은 보안 계층을 강화하기 위해 Chrome 103 버전부터 V8 샌드박스 포인터(V8 메모리 케이지)를 활성화했습니다 [4]. 이는 JIT 엔진의 타입 혼동 버그를 악용하여 공격자가 프로세스의 임의 메모리를 읽고 쓰는 치명적인 공격을 방지하기 위한 설계입니다 [5, 8]. [[Electron]]과 같은 프레임워크는 독자적인 버그나 보안 취약점을 유발하지 않고 강력한 Chromium 보안 팀의 작업 성과를 그대로 활용하기 위해, Chromium의 복잡한 V8 내부 구성과 최대한 일치하도록 아키텍처를 유지합니다 [9].
|
||||
- **렌더링 유휴 시간(Idle Time)과 GC 연동:** 브라우저 환경에서 Chromium은 초당 60프레임(FPS)을 유지하기 위해 각 프레임당 약 16.6ms의 렌더링 시간을 가집니다 [2]. 만약 애니메이션 작업이 예상보다 일찍 끝나면, Chromium은 남는 유휴 시간을 활용해 V8 가비지 컬렉터가 큐에 쌓아둔 '유휴 작업(Idle tasks)'을 사전에 실행하여 성능 저하(jank)를 방지할 수 있습니다 [2]. 또한, Chrome의 렌더러 엔진인 [[Blink]]는 '[[Oilpan]]'이라는 독자적인 가비지 컬렉터를 보유하고 있으며, V8의 메인 GC인 [[Orinoco]]와 원활하게 상호 협력하도록 기술이 공유 및 이식되고 있습니다 [10].
|
||||
- **메모리 프로파일링 및 추적(Tracing) 인프라:** Chromium은 V8의 내부 메모리 상태 및 실행 흐름을 시각적으로 분석할 수 있는 Chrome Tracing 시스템(`chrome://tracing`)을 제공합니다 [1, 7]. 개발자나 보안 연구원은 `--track-gc-object-stats` 등의 플래그를 사용하여 V8 힙 객체 통계를 수집할 수 있습니다 [6, 7, 11]. 이러한 인프라는 V8 파서와 컴파일러의 메모리 소비 최적화 작업을 가능하게 했으며 [12, 13], 실패한 Chrome 렌더러의 충돌 덤프(Crash dumps)를 분석하여 메모리 손상 익스플로잇(Exploit) 공격 시도를 사전에 탐지하는 포렌식 기술의 기반이 됩니다 [3, 14, 15].
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 Architecture
|
||||
- **Browser process**: 매 UI, network, disk — privileged.
|
||||
- **Renderer process** (per site): 매 Blink + V8 — sandboxed.
|
||||
- **GPU process**: Skia 의 hardware-accel.
|
||||
- **Utility processes**: audio, network service.
|
||||
- **Mojo IPC**: typed message passing.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[V8 Engine]], V8 [[memory]] Cage, [[Blink]], [[Oilpan]], [[Garbage Collection]]
|
||||
- **Projects/Contexts:** [[Electron]], [[Google Chrome]], [[Orinoco]]
|
||||
- **Contradictions/Notes:** 제공된 소스 전반에서 'Chromium'과 'Chrome'이라는 명칭은 V8을 내장하는 브라우저 런타임 환경 및 보안/추적 인프라를 설명할 때 사실상 동일한 맥락으로 상호 교환되어 사용되고 있습니다 [2-4, 16].
|
||||
### 매 Components
|
||||
- **Blink**: HTML parse, CSS, layout, paint, compositor.
|
||||
- **V8**: JS + WebAssembly (Sparkplug, Maglev, TurboFan, Liftoff).
|
||||
- **Skia**: 2D graphics.
|
||||
- **WebRTC, WebGPU, WebCodecs**: media.
|
||||
- **Site Isolation**: 매 origin 의 process-level isolation — Spectre 의 mitigate.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
### 매 응용
|
||||
1. Chrome browser (1B+ users).
|
||||
2. Embed: Electron, Tauri (WebView2 on Win), CEF.
|
||||
3. Headless: Puppeteer, Playwright (chromium build).
|
||||
4. Forks: Edge (2020+), Brave, Vivaldi, Arc, Opera.
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 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
|
||||
### Build chromium (sketch)
|
||||
```bash
|
||||
git clone https://chromium.googlesource.com/chromium/src.git
|
||||
cd src
|
||||
gclient sync
|
||||
gn gen out/Release --args='is_debug=false'
|
||||
autoninja -C out/Release chrome
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### Headless via Puppeteer
|
||||
```javascript
|
||||
import puppeteer from "puppeteer";
|
||||
const browser = await puppeteer.launch({ headless: "new", args: ["--no-sandbox"] });
|
||||
const page = await browser.newPage();
|
||||
await page.goto("https://example.com");
|
||||
await page.screenshot({ path: "x.png" });
|
||||
await browser.close();
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### CDP (Chrome DevTools Protocol) raw
|
||||
```javascript
|
||||
const client = await page.target().createCDPSession();
|
||||
await client.send("Performance.enable");
|
||||
const metrics = await client.send("Performance.getMetrics");
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Site Isolation flag
|
||||
```bash
|
||||
chrome --site-per-process # default since 2018
|
||||
chrome --disable-site-isolation-trials # debug only — never prod
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### V8 inspect
|
||||
```bash
|
||||
node --inspect-brk app.js
|
||||
# DevTools 의 chrome://inspect 의 attach
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| Build cross-platform desktop app | Tauri (smaller) > Electron (mature) |
|
||||
| Web automation | Playwright > Puppeteer (multi-engine) |
|
||||
| Custom browser | fork Chromium (Brave-style) — 매 maintenance cost 큼 |
|
||||
| Embed web view | WebView2 (Win) / WKWebView (Mac) — 매 native > Electron |
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
**기본값**: 매 web app 의 Electron / Tauri 의 ship — 매 user-facing 의 자체 fork X.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Browser Engine]]
|
||||
- 변형: [[Chrome]] · [[Edge]] · [[Brave]] · [[Electron]]
|
||||
- 응용: [[Puppeteer]] · [[Playwright]] · [[CEF]]
|
||||
- Adjacent: [[Blink]] · [[V8]] · [[WebKit]] · [[Gecko]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: CDP 사용법, Puppeteer/Playwright script, Chromium component 의 explanation.
|
||||
**언제 X**: 매 Chromium 의 internal C++ refactor — 매 LLM 의 outdated 가능.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **--no-sandbox in production**: 매 sandboxing 의 disable — RCE 의 risk.
|
||||
- **--disable-web-security**: 매 dev 만 — prod 의 catastrophic.
|
||||
- **Pinning to old Chromium**: 매 CVE 의 backlog — 매 latest stable.
|
||||
- **Electron + remote module**: 매 deprecated, 매 contextIsolation: true.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (chromium.org, source.chromium.org, V8 blog).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — multi-process arch + Puppeteer/CDP patterns |
|
||||
|
||||
@@ -2,92 +2,160 @@
|
||||
id: wiki-2026-0508-code-minification
|
||||
title: Code Minification
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-D932E1]
|
||||
aliases: [Minification, JS Minify, CSS Minify, Bundle Minification]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [build, performance, javascript, web]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Code Minification"
|
||||
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: javascript
|
||||
framework: esbuild/swc/terser
|
||||
---
|
||||
|
||||
# [[Code Minification]]
|
||||
# Code Minification
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> 코드 축소(Code Minification)는 브라우저 등으로 코드를 배포할 때 소스 코드의 크기를 최소화하고 전송 및 렌더링 시간을 단축하기 위해 사용되는 소프트웨어 최적화 기법입니다 [1, 2]. 이 기법은 코드의 본래 실행 의미(semantics)를 변경하지 않은 채, 공백, 줄 바꿈, 주석 등 의미가 없는 요소를 제거하고 변수 이름을 짧게 변경하는 등의 표면적 변환을 수행합니다 [1, 2]. 가독성을 높이는 코드 포매팅(Code [[Formatting]])과 달리 코드 축소는 오히려 코드의 가독성을 저하시키며, 주로 소프트웨어 개발 완료 후 배포 직전에 자동화 도구에 의해 실행됩니다 [3].
|
||||
## 매 한 줄
|
||||
> **"매 source code 의 semantic 보존 + size 의 minimize"**. 매 whitespace/comment 제거 + identifier rename + dead code elimination + constant folding. 2026 의 esbuild/SWC/OXC 의 native-speed mainstream, Terser 의 max compression fallback.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **목적과 주요 기법:** 코드 축소의 주요 목적은 소스 코드 형태로 배포되는 소프트웨어의 용량을 줄이는 것이며, 특히 웹 개발 환경에서 페이지 렌더링 속도를 가속화하는 데 흔히 사용됩니다 [2]. 이를 위해 컴파일러나 인터프리터의 실행에 영향을 주지 않는 공백, 줄 바꿈, 주석 등을 제거할 뿐만 아니라, 변수나 클래스 등의 식별자(identifier) 이름을 간결한 대체어로 변경하는 다소 침투적인(invasive) 수정도 포함합니다 [2].
|
||||
* **코드 가독성과 실행 의미 보존:** 축소된 코드는 원본 코드의 실행 의미(semantics)를 완벽하게 중립적으로 보존해야만 성립될 수 있습니다 [1, 2]. 다만, 인간이 읽기 쉽도록 일정한 스타일을 강제하는 코드 포매팅과 정반대로, 축소화 과정은 불필요한 모든 문자를 제거하므로 코드의 가독성을 크게 떨어뜨리는 결과를 낳습니다 [3].
|
||||
* **코드 작성자 인식(Code Stylometry)에 미치는 영향:** 변수명 지정 방식, 공백 사용, 주석 처리 등은 프로그래머 고유의 코딩 스타일을 나타내는 주요 특징입니다. 코드 축소는 이러한 불필요한 문자 및 식별자 이름을 일괄적으로 지우거나 변경하므로 작성자 고유의 흔적을 훼손하게 됩니다 [4]. 관련 연구에 따르면 코드 축소를 적용할 경우 작성자 인식 정확도가 약 17.86% 감소하여, 코드 문체 분석(Code Stylometry)을 통한 작성자 식별을 더 어렵게 만드는 것으로 나타났습니다 [4].
|
||||
* **성능 사례:** Python 코드의 축소를 지원하는 도구인 'Python Minifier'의 실험 사례를 보면, 축소화 작업 후 소스 코드 라인 수(SLOC)는 60%, 문자 수는 37%나 감소하여 매우 큰 파일 크기 최적화 효과를 보여주었습니다 [5, 6].
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 변환 단계
|
||||
- **Strip**: whitespace, comments, semicolon redundancy.
|
||||
- **Mangle**: local identifier → 매 short (a, b, c).
|
||||
- **Compress**: constant fold, DCE, inline single-use, sequence expression.
|
||||
- **Property mangle** (optional): `obj.privateField` → `obj.a` (매 risky).
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[Code Formatting]], Code Stylometry
|
||||
- **Projects/Contexts:** Web Development, Python Minifier
|
||||
- **Contradictions/Notes:** 소스에 관련 정보가 부족합니다.
|
||||
### 매 Tree shaking
|
||||
- ES module static imports 의 분석 → 매 unused exports 의 제거.
|
||||
- `sideEffects: false` in package.json 의 강력한 hint.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
### 매 Source maps
|
||||
- Mangled output 의 production debugging 의 essential.
|
||||
- `//# sourceMappingURL=app.js.map` + Sentry/DataDog upload.
|
||||
|
||||
---
|
||||
### 매 응용
|
||||
1. JS bundle 의 70-80% 크기 reduction (gzip 후 추가).
|
||||
2. CSS 의 50% reduction (whitespace + selector merging).
|
||||
3. HTML 의 inline asset minification (Astro, Next).
|
||||
|
||||
## 🤖 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
|
||||
### esbuild (fastest, default for new)
|
||||
```javascript
|
||||
// build.mjs
|
||||
import { build } from 'esbuild';
|
||||
await build({
|
||||
entryPoints: ['src/app.ts'],
|
||||
bundle: true,
|
||||
minify: true, // whitespace + identifier + syntax
|
||||
sourcemap: true,
|
||||
target: ['es2022'],
|
||||
treeShaking: true,
|
||||
outfile: 'dist/app.js',
|
||||
});
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### SWC (Rust, used by Next/Parcel)
|
||||
```javascript
|
||||
// .swcrc
|
||||
{
|
||||
"jsc": { "target": "es2022", "minify": { "compress": true, "mangle": true } },
|
||||
"minify": true,
|
||||
"sourceMaps": true
|
||||
}
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Terser (max compression, slower)
|
||||
```javascript
|
||||
import { minify } from 'terser';
|
||||
const out = await minify(src, {
|
||||
compress: { passes: 3, pure_getters: true, unsafe_arrows: true },
|
||||
mangle: { properties: { regex: /^_/ } }, // 매 only _-prefixed
|
||||
format: { comments: false },
|
||||
sourceMap: { url: 'app.js.map' },
|
||||
});
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Vite production
|
||||
```javascript
|
||||
// vite.config.ts
|
||||
export default {
|
||||
build: {
|
||||
minify: 'esbuild', // or 'terser' for max
|
||||
sourcemap: true,
|
||||
rollupOptions: {
|
||||
output: { manualChunks: { vendor: ['react', 'react-dom'] } },
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### CSS — Lightning CSS
|
||||
```javascript
|
||||
import { transform } from 'lightningcss';
|
||||
const { code } = transform({
|
||||
filename: 'style.css',
|
||||
code: Buffer.from(src),
|
||||
minify: true,
|
||||
targets: { chrome: 100 << 16, safari: 16 << 16 },
|
||||
});
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
### Sentry source map upload
|
||||
```bash
|
||||
sentry-cli sourcemaps inject ./dist
|
||||
sentry-cli sourcemaps upload --release "$VERSION" ./dist
|
||||
# 매 production 에 .map 의 ship 의 X — Sentry 의 server-side 보관
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### DCE / pure annotation
|
||||
```javascript
|
||||
// 매 tree shaker 에 hint
|
||||
const heavyConst = /*#__PURE__*/ buildHeavy();
|
||||
// 매 unused → bundle 에서 제거
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Tool |
|
||||
|---|---|
|
||||
| Default new project | esbuild / SWC |
|
||||
| Maximum compression | Terser (passes: 3) |
|
||||
| CSS | Lightning CSS |
|
||||
| HTML | html-minifier-terser |
|
||||
| Library publish | Rollup + esbuild minify |
|
||||
| Browser extension | esbuild (size budget) |
|
||||
|
||||
**기본값**: esbuild minify + tree shake + source maps + Sentry upload.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Build_Tools]] · [[Web_Performance]]
|
||||
- 변형: [[Tree_Shaking]] · [[Code_Splitting]] · [[Compression]]
|
||||
- 응용: [[Bundle_Analysis]] · [[Source_Maps]]
|
||||
- Adjacent: [[esbuild]] · [[Vite]] · [[Webpack]] · [[Rollup]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: build config 작성, minifier option tuning, bundle analysis.
|
||||
**언제 X**: 매 generated bundle 의 manual edit — 매 source 의 수정 후 rebuild.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **No source map in prod**: 매 stack trace 의 obfuscated — debug 불가.
|
||||
- **Property mangle without test**: 매 `obj["field"]` access 의 break.
|
||||
- **Minify before bundling**: 매 cross-module DCE 의 손실.
|
||||
- **Comments preserved**: license 의 `/*! */` 만 keep, rest strip.
|
||||
- **One huge bundle**: code split 의 X — initial load 의 huge.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (esbuild docs, Terser README, Vite docs, Lightning CSS docs).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — esbuild/SWC/Terser/Lightning CSS patterns + DCE |
|
||||
|
||||
+23
-91
@@ -1,102 +1,34 @@
|
||||
---
|
||||
id: wiki-2026-0508-code-splitting-lazy-loading-코드-분
|
||||
title: Code Splitting Lazy Loading (코드 분할 및 지연 로딩)
|
||||
title: Code Splitting & Lazy Loading (코드 분할 및 지연 로딩)
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-59CADB]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: code-splitting
|
||||
duplicate_of: "[[Code Splitting]]"
|
||||
aliases: [Lazy Loading]
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Code Splitting Lazy Loading (코드 분할 및 지연 로딩)"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, web-performance, bundling]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[Code Splitting Lazy Loading (코드 분할 및 지연 로딩)]]
|
||||
# Code Splitting & Lazy Loading (코드 분할 및 지연 로딩)
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> 거대한 자바스크립트 번들을 작은 단위로 나누고, 사용자가 당장 필요로 하지 않는 컴포넌트나 라이브러리의 로딩을 지연시켜 애플리케이션의 초기 로딩 속도와 핵심 웹 지표(FCP, LCP)를 비약적으로 개선하는 최적화 기법입니다.
|
||||
> **이 문서는 [[Code Splitting]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
**1. 동작 원리 및 필요성** 일반적인 React 앱은 모든 코드를 하나의 큰 번들로 묶어 제공하므로 사용자가 사용하지 않을 기능까지 다운로드하느라 초기 로딩이 크게 지연됩니다. "초기 페이지 로드 시 화면에 즉시 보이지 않는 기능은 렌더링을 차단해서는 안 된다"는 원칙에 따라, 코드를 분할하면 반응성(TTI)을 높이고 데이터 전송 비용을 줄일 수 있습니다. 전체 번들 크기를 최대 20~70%까지 줄이는 것이 가능합니다.
|
||||
## 핵심 요약
|
||||
- Code splitting = bundle 매 multiple chunks 로 split, on-demand load → initial payload 감소.
|
||||
- 매 React: `React.lazy()` + `Suspense`, dynamic `import()`.
|
||||
- Lazy loading 매 image/component/route 단위 — Vite/webpack/esbuild 매 default 지원.
|
||||
|
||||
**2. 전략 1: 라우트 기반 분할 (Route-level Splitting)** 가장 적은 노력으로 가장 큰 효과(초기 번들 60~80% 감소)를 볼 수 있는 방식입니다. `React.lazy`와 React Router를 활용하여, 사용자가 현재 방문한 페이지에 필요한 컴포넌트만 로드하고 다른 페이지의 코드는 분할합니다.
|
||||
## 🔗 Graph
|
||||
- 부모: [[Code Splitting]] (canonical)
|
||||
- Adjacent: [[Tree Shaking]] · [[Dynamic Import]]
|
||||
|
||||
**3. 전략 2: 컴포넌트 기반 지연 로딩 (Component-level Lazy Loading)** 화면 하단(Below the fold)에 위치하거나 무거운 UI 요소(예: 3D 모델, 복잡한 차트, 비디오 에디터 등)를 `React.lazy`와 `<Suspense>`를 이용해 온디맨드(On-demand) 방식으로 불러옵니다. 예를 들어 React Three Fiber(R3F) 환경에서는 렌더링 비용이 큰 3D 모델을 `<Suspense fallback={<Loader />}>`로 감싸 지연 로딩하는 것이 필수적입니다.
|
||||
|
||||
**4. 전략 3: 라이브러리 분할 (Library-level Splitting)** PDF 생성이나 엑셀 내보내기 등 특정 액션이 일어날 때만 필요한 무거운 서드파티 라이브러리를 동적 `import()`로 불러와 메인 자바스크립트 번들에서 완전히 제외시킵니다.
|
||||
|
||||
**5. UX 최적화 및 주의사항**
|
||||
|
||||
- **스켈레톤 UI (Skeleton UI):** 지연 로딩이 발생할 때 화면이 일시적으로 비어보이는 현상을 막고 누적 레이아웃 이동(CLS)을 방지하기 위해, `<Suspense fallback={...}>` 내부에 최종 콘텐츠와 유사한 크기의 스켈레톤 UI나 로딩 인디케이터를 반드시 제공해야 합니다.
|
||||
- **지연 로딩의 금기:** 초기 렌더링에 즉시 필요하거나 화면 최상단(Above-the-fold)에 위치한 핵심 컴포넌트는 절대 지연 로딩해서는 안 됩니다.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[React Performance Optimization]], React.lazy & Suspense, [[Core Web Vitals]] (FCP, LCP, CLS), [[React [[Server Components]] (RSC)]]
|
||||
- **Projects/Contexts:** 대규모 SPA 초기 로딩 속도 개선, Three.js / React Three Fiber 자산 최적화
|
||||
- **Contradictions/Notes:** 코드 분할은 초기 로드 속도를 크게 높여주지만, 모든 컴포넌트를 무분별하게 분할할 경우 사용자가 상호작용을 할 때마다 네트워크 지연과 로딩 스피너를 마주하게 되어 오히려 UX를 크게 훼손할 수 있습니다. 항상 사용자의 여정(User Flow)을 예측하고 적절한 단위로 번들을 묶는 전략적 접근이 필요합니다.
|
||||
|
||||
---
|
||||
|
||||
_Last updated: 2026-04-14_
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -1,25 +1,142 @@
|
||||
---
|
||||
id: wiki-20260508-continuous-integration-ci--redir
|
||||
title: Continuous Integration (CI)
|
||||
category: Programming & Language
|
||||
status: merged
|
||||
redirect_to: Continuous_Integration_CI
|
||||
canonical_id: Continuous_Integration_CI
|
||||
aliases: []
|
||||
category: 10_Wiki/Topics
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [CI, Continuous Integration, 지속적 통합]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [redirect]
|
||||
verification_status: applied
|
||||
tags: [cicd, devops, automation, testing]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-merge 2026-05-08)
|
||||
tech_stack:
|
||||
language: yaml
|
||||
framework: GitHub Actions, GitLab CI, Jenkins
|
||||
---
|
||||
|
||||
# Continuous Integration (CI)
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 이 문서는 P-Reinforce Phase 2 자동 MERGE에 의해 **[[Continuous_Integration_CI]]**로 통합되었습니다.
|
||||
## 매 한 줄
|
||||
> **"매 every commit 의 main branch 의 automated build + test"**. 매 Grady Booch (1991) 의 coin → Martin Fowler (2000) 의 popularize → 매 2026 의 trunk-based dev + GitHub Actions 의 dominant practice. 매 integration hell 의 prevent — 매 small frequent merge + fast feedback (<10 min).
|
||||
|
||||
---
|
||||
*Redirected to: [[Continuous_Integration_CI]]*
|
||||
## 매 핵심
|
||||
|
||||
### 매 Practices
|
||||
- **Single source repo** (trunk-based, optionally short-lived feature branches).
|
||||
- **Automated build** on every push.
|
||||
- **Self-testing build** (unit + integration).
|
||||
- **Daily commit** to main (최소).
|
||||
- **Build fast** (<10 min target).
|
||||
- **Test in clone of prod** (Docker, ephemeral env).
|
||||
- **Visible status** (badge, Slack notify).
|
||||
- **Fix red main immediately** (revert > forward fix).
|
||||
|
||||
### 매 CI vs CD
|
||||
- **CI**: build + test on every push — main 의 always green.
|
||||
- **CD (Delivery)**: 매 always-shippable artifact + manual prod gate.
|
||||
- **CD (Deployment)**: 매 fully automated to prod.
|
||||
|
||||
### 매 응용
|
||||
1. Pre-merge: PR check (lint, test, type, build).
|
||||
2. Post-merge: artifact build + push.
|
||||
3. Nightly: e2e, perf, security scan.
|
||||
4. Release: tag → publish (npm, container).
|
||||
|
||||
## 💻 패턴
|
||||
|
||||
### GitHub Actions PR check
|
||||
```yaml
|
||||
name: pr
|
||||
on: { pull_request: { branches: [main] } }
|
||||
jobs:
|
||||
ci:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with: { node-version: 20, cache: pnpm }
|
||||
- run: pnpm install --frozen-lockfile
|
||||
- run: pnpm lint
|
||||
- run: pnpm typecheck
|
||||
- run: pnpm test --coverage
|
||||
- run: pnpm build
|
||||
- uses: codecov/codecov-action@v4
|
||||
```
|
||||
|
||||
### Branch protection (main)
|
||||
```yaml
|
||||
# .github/branch-protection.yml (or via API)
|
||||
required_status_checks:
|
||||
strict: true
|
||||
contexts: [ci/lint, ci/test, ci/build]
|
||||
required_pull_request_reviews: { required_approving_review_count: 1 }
|
||||
enforce_admins: true
|
||||
```
|
||||
|
||||
### Parallel matrix
|
||||
```yaml
|
||||
jobs:
|
||||
test:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node: [18, 20, 22]
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
```
|
||||
|
||||
### Cache
|
||||
```yaml
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.pnpm-store
|
||||
key: pnpm-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
|
||||
```
|
||||
|
||||
### Pre-commit (Husky + lint-staged)
|
||||
```json
|
||||
{ "lint-staged": { "*.{ts,tsx}": ["eslint --fix", "prettier --write"] } }
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| GitHub repo | GitHub Actions |
|
||||
| GitLab self-host | GitLab CI |
|
||||
| Java enterprise | Jenkins (with Jenkinsfile) |
|
||||
| Monorepo, perf-critical | Nx Cloud / Turborepo Remote Cache |
|
||||
| OSS multi-platform | GitHub Actions + matrix |
|
||||
|
||||
**기본값**: 매 GitHub Actions + branch protection + required check.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[CI/CD Pipeline]] · [[DevOps]]
|
||||
- 변형: [[Continuous Delivery]] · [[Continuous Deployment]]
|
||||
- 응용: [[Trunk-Based Development]] · [[Pull Request Workflow]]
|
||||
- Adjacent: [[TeamCity]] · [[Jenkins]] · [[GitOps]] · [[Pre-commit Hook]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 workflow YAML 의 generation, action 의 lookup, matrix 의 expansion.
|
||||
**언제 X**: 매 secret handling — 매 OIDC + GitHub Secrets manual review.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Long-lived feature branch**: 매 merge hell — 매 short-lived (<3 day).
|
||||
- **Skipping tests** (`[skip ci]` 의 abuse): 매 main 의 break.
|
||||
- **Slow CI** (>15 min): 매 PR backlog — 매 cache + parallelize.
|
||||
- **Flaky tests** 의 retry abuse: 매 fix 의 root cause.
|
||||
- **Manual deploy from laptop**: 매 reproducibility 의 zero — 매 CI 의 only.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Fowler "Continuous Integration", GitHub Actions docs).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — practices + Actions/branch protection patterns |
|
||||
|
||||
@@ -1,25 +1,34 @@
|
||||
---
|
||||
id: wiki-20260508-cosmos-netflix--redir
|
||||
title: Cosmos 플랫폼 (Netflix)
|
||||
category: Programming & Language
|
||||
status: merged
|
||||
redirect_to: Cosmos_플랫폼_(Netflix)
|
||||
canonical_id: Cosmos_플랫폼_(Netflix)
|
||||
category: 10_Wiki/Topics
|
||||
status: duplicate
|
||||
canonical_id: cosmos-netflix
|
||||
duplicate_of: "[[넷플릭스 코스모스 플랫폼 (Netflix Cosmos)]]"
|
||||
aliases: []
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [redirect]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
verification_status: redirected
|
||||
tags: [duplicate, netflix, microservices]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-merge 2026-05-08)
|
||||
---
|
||||
|
||||
# Cosmos 플랫폼 (Netflix)
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 이 문서는 P-Reinforce Phase 2 자동 MERGE에 의해 **[[Cosmos_플랫폼_(Netflix)]]**로 통합되었습니다.
|
||||
> **이 문서는 [[넷플릭스 코스모스 플랫폼 (Netflix Cosmos)]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
---
|
||||
*Redirected to: [[Cosmos_플랫폼_(Netflix)]]*
|
||||
## 핵심 요약 (specialization aspects)
|
||||
- 매 Netflix media-encoding 의 next-gen platform.
|
||||
- 매 workflow + microservice + serverless 의 hybrid.
|
||||
- 매 Reloaded (구) 의 successor.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[넷플릭스 코스모스 플랫폼 (Netflix Cosmos)]] (canonical)
|
||||
- Adjacent: [[Netflix 마이크로서비스 전환]] · [[리로디드(Reloaded)]]
|
||||
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -2,102 +2,175 @@
|
||||
id: wiki-2026-0508-dom-요소-조작-및-타입-좁히기
|
||||
title: DOM 요소 조작 및 타입 좁히기
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-3A0CD0]
|
||||
aliases: [DOM Manipulation, Type Narrowing, querySelector Typing]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [typescript, dom, web, type-narrowing]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - DOM 요소 조작 및 타입 좁히기"
|
||||
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: dom
|
||||
---
|
||||
|
||||
# [[DOM 요소 조작 및 타입 좁히기]]
|
||||
# DOM 요소 조작 및 타입 좁히기
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> DOM 요소 조작 시에는 타입스크립트의 타입 좁히기(Type Narrowing) 기술을 통해 타입 안정성을 확보하는 것이 중요합니다. 타입 좁히기란 코드 흐름 분석을 사용하여 포괄적인 타입(유니온 타입 등)을 구체적인 단일 타입으로 줄여나가는 과정입니다 [1-3]. DOM 요소를 다루거나 구조가 명확하지 않은 데이터를 처리할 때, 타입 단언(`as`), 사용자 정의 타입 가드, `typeof` 및 `instanceof` 연산자 등을 활용하여 안전하게 타입을 좁혀 조작할 수 있습니다 [4-6].
|
||||
## 매 한 줄
|
||||
> **"매 DOM API 의 untyped boundary 의 TypeScript narrowing 의 적용"**. 매 `querySelector` 의 default `Element | null` 위 의 generic + instanceof + assertion. 2026 의 strict null checks + satisfies + lib.dom.d.ts 의 mainstream type ergonomics.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
**DOM 요소 조작 시 타입 단언(`as`)의 활용**
|
||||
* DOM 요소로 작업하며 타입을 좁혀야 할 때, 타입 단언(`as`) 연산자가 주로 활용됩니다 [5].
|
||||
* 타입 단언은 런타임 검증을 마쳤거나 DOM 조작과 같이 불가피한 상황에서 컴파일러에게 특정 타입임을 강제할 때 사용합니다 [5, 7]. 하지만 개발자가 잘못 판단할 경우 컴파일러가 에러를 잡지 못해 런타임 오류로 이어질 수 있으므로 사용에 매우 주의해야 합니다 [7, 8].
|
||||
## 매 핵심
|
||||
|
||||
**DOM 요소 삽입과 브랜디드 타입(Branded Types)을 통한 보안**
|
||||
* 사용자의 입력값을 DOM의 `innerHTML` 등에 직접 추가하는 것은 XSS 공격에 노출될 수 있는 위험한 방식입니다 [9].
|
||||
* 이를 방어하기 위해 브랜디드 문자열 타입(Branded String Types)을 사용하여, 데이터가 DOM에 추가되기 전에 반드시 정제(Sanitized) 과정을 거쳤음을 타입 시스템 차원에서 강제할 수 있습니다 [9].
|
||||
* 또한, 유효하지 않은 잉여 속성(예: 'hello')을 DOM 객체로 전달할 경우 React와 같은 라이브러리에서는 경고를 발생시킬 수 있으므로 정확한 타입 지정이 중요합니다 [10].
|
||||
### 매 Type narrowing tools
|
||||
- **Generic param**: `querySelector<HTMLInputElement>(...)` — runtime check 의 X, 매 assertion 만.
|
||||
- **`instanceof`**: 매 runtime check + narrow.
|
||||
- **Type guard function**: `function isInput(el): el is HTMLInputElement`.
|
||||
- **Discriminated property**: `el.tagName === 'INPUT'` (의 narrow X — manual cast 필요).
|
||||
|
||||
**타입 좁히기(Type Narrowing)의 주요 기법**
|
||||
* **`typeof` 및 `instanceof` 연산자:** `typeof`를 사용해 "string", "number", "boolean" 등의 원시 타입을 확인하거나, `instanceof`를 사용해 생성자 프로토타입의 인스턴스인지를 확인하여 타입을 좁힙니다 [4, 6].
|
||||
* **`in` 연산자 및 판별 속성(Discriminant Property):** 객체 내에 특정 속성이 존재하는지 `in` 키워드로 확인하거나, 식별 가능한 유니온([[Discriminated Unions]]) 패턴에서 공통 리터럴 타입 필드(예: `kind` 또는 `type`)를 `switch` 문으로 비교하여 해당 블록 내의 타입을 안전하게 좁힙니다 [1, 3, 4, 11].
|
||||
* **타입 서술어(Type Predicates):** 반환 타입에 `is` 키워드를 사용하여(예: `value is Positive`), 함수가 `true`를 반환할 때 조건문 내부에서 매개변수가 특정 타입으로 좁혀지도록 타입 시스템에 알립니다 [6, 12].
|
||||
* **단언 함수(Assertion Functions):** 입력된 값이 기대한 타입이 아닐 경우 에러를 던지도록 작성된 함수입니다. 이 함수를 통과한 이후의 코드는 해당 값이 특정 타입이 확실함을 타입 시스템이 인지하여 타입을 좁히게 됩니다 [13, 14].
|
||||
### 매 Null safety
|
||||
- `querySelector` 의 `null` 의 always 가능 — 매 explicit check.
|
||||
- `getElementById` 의 same — `HTMLElement | null`.
|
||||
- `as!` non-null assertion 의 last resort — 매 prefer guard.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 응용
|
||||
1. Form value 추출 + validation.
|
||||
2. Dynamic widget hydration (서버 HTML 위 의 JS enhance).
|
||||
3. Custom element / Web Component 의 typed access.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** Type Narrowing, Type Assertions, [[Discriminated Unions]], Branded Types
|
||||
- **Projects/Contexts:** 안전한 DOM 조작 및 데이터 정제, React 컴포넌트 Props 처리
|
||||
- **Contradictions/Notes:** 타입 단언(`as`)은 DOM 요소를 다루며 타입을 좁힐 때 유용하고 흔하게 사용되지만 [5], 런타임 동작에는 영향을 주지 않으므로 타입 에러를 우회하여 잘못된 코드를 통과시킬 위험이 있습니다. 따라서 가능한 한 `satisfies`나 사용자 정의 타입 가드 등 더 안전한 방식을 우선적으로 고려하는 것이 좋습니다 [7, 8, 15].
|
||||
## 💻 패턴
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
### querySelector with generic
|
||||
```typescript
|
||||
// 매 generic 의 assertion 만 — 매 null 의 still 가능
|
||||
const input = document.querySelector<HTMLInputElement>('#email');
|
||||
if (!input) throw new Error('email input missing');
|
||||
input.value; // 매 narrowed to HTMLInputElement
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### instanceof guard
|
||||
```typescript
|
||||
const el = document.getElementById('email');
|
||||
if (el instanceof HTMLInputElement) {
|
||||
el.value = 'test@example.com'; // 매 narrowed
|
||||
} else {
|
||||
throw new Error('not an input');
|
||||
}
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Custom type guard
|
||||
```typescript
|
||||
function isInput(el: Element | null): el is HTMLInputElement {
|
||||
return el instanceof HTMLInputElement;
|
||||
}
|
||||
function getValue(selector: string): string {
|
||||
const el = document.querySelector(selector);
|
||||
if (!isInput(el)) throw new Error(`${selector} is not input`);
|
||||
return el.value;
|
||||
}
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Helper: assertElement
|
||||
```typescript
|
||||
function $<T extends HTMLElement>(
|
||||
selector: string,
|
||||
ctor: new () => T = HTMLElement as new () => T,
|
||||
root: ParentNode = document,
|
||||
): T {
|
||||
const el = root.querySelector(selector);
|
||||
if (!el) throw new Error(`Missing: ${selector}`);
|
||||
if (!(el instanceof ctor)) throw new Error(`Wrong type: ${selector}`);
|
||||
return el as T;
|
||||
}
|
||||
const form = $('#login', HTMLFormElement);
|
||||
const email = $('input[name=email]', HTMLInputElement, form);
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### Form data — typed
|
||||
```typescript
|
||||
function getFormData<T extends Record<string, string>>(form: HTMLFormElement): T {
|
||||
const fd = new FormData(form);
|
||||
return Object.fromEntries(fd.entries()) as T;
|
||||
}
|
||||
type LoginForm = { email: string; password: string };
|
||||
const data = getFormData<LoginForm>(form);
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
### Event delegation with narrowing
|
||||
```typescript
|
||||
document.addEventListener('click', (e) => {
|
||||
const target = e.target;
|
||||
if (!(target instanceof HTMLElement)) return;
|
||||
const btn = target.closest<HTMLButtonElement>('button[data-action]');
|
||||
if (!btn) return;
|
||||
switch (btn.dataset.action) {
|
||||
case 'save': return save();
|
||||
case 'delete': return remove(btn.dataset.id!);
|
||||
default: throw new Error(`Unknown action: ${btn.dataset.action}`);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### Custom element typing
|
||||
```typescript
|
||||
class MyToggle extends HTMLElement {
|
||||
toggle() { this.toggleAttribute('open'); }
|
||||
}
|
||||
customElements.define('my-toggle', MyToggle);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap { 'my-toggle': MyToggle; }
|
||||
}
|
||||
const t = document.querySelector('my-toggle'); // 매 typed as MyToggle | null
|
||||
t?.toggle();
|
||||
```
|
||||
|
||||
### satisfies for config (2026 idiom)
|
||||
```typescript
|
||||
const handlers = {
|
||||
'#save': (el: HTMLButtonElement) => el.addEventListener('click', save),
|
||||
'#email': (el: HTMLInputElement) => el.addEventListener('blur', validate),
|
||||
} satisfies Record<string, (el: HTMLElement) => void>;
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Pattern |
|
||||
|---|---|
|
||||
| Single fetch + null OK | `querySelector<T>` + null check |
|
||||
| Strict invariant | `$()` helper with ctor |
|
||||
| Multiple element types | instanceof in switch |
|
||||
| Reusable check | Custom type guard |
|
||||
| Event handler | `target instanceof HTMLElement` |
|
||||
| Custom element | HTMLElementTagNameMap augment |
|
||||
|
||||
**기본값**: assertElement helper + instanceof + custom guards. `as` casts 의 last resort 만.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[TypeScript]] · [[DOM]]
|
||||
- 변형: [[Discriminated_Unions]] · [[Type_Guards]]
|
||||
- 응용: [[DOM_요소_조작]] · [[Web_Components]] · [[Form_Validation]]
|
||||
- Adjacent: [[strictNullChecks]] · [[Generic_Constraints]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: helper 작성, type guard 추출, refactor untyped jQuery → typed TS.
|
||||
**언제 X**: 매 framework (React/Vue/Svelte) 안 — 매 framework type 의 사용.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **`as HTMLInputElement` everywhere**: runtime mismatch 의 silent.
|
||||
- **`!` non-null assertion 남발**: 매 null check 의 미루기 — runtime crash.
|
||||
- **`any` for events**: 매 `Event` subclass 의 사용.
|
||||
- **`getElementById` raw return 사용**: null check skip.
|
||||
- **innerHTML with user input**: 매 XSS — `textContent` / DOMPurify 의 사용.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (TypeScript handbook, lib.dom.d.ts, MDN DOM docs).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — generic/instanceof/guard/helper patterns for typed DOM |
|
||||
|
||||
@@ -2,94 +2,193 @@
|
||||
id: wiki-2026-0508-dom-요소-조작
|
||||
title: DOM 요소 조작
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-15DA1E]
|
||||
aliases: [DOM Manipulation, Vanilla JS DOM, Document API]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [dom, javascript, web, browser]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - DOM 요소 조작"
|
||||
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: javascript
|
||||
framework: dom
|
||||
---
|
||||
|
||||
# [[DOM 요소 조작]]
|
||||
# DOM 요소 조작
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> 주어진 소스에는 DOM 요소 조작의 구체적인 방법론이나 원리에 대한 내용이 포함되어 있지 않아 소스에 관련 정보가 부족합니다. 제공된 문서들에서는 DOM 요소를 다룰 때 TypeScript의 타입 단언(`as`)을 사용하는 상황이나, 사용자 입력을 DOM에 추가하기 전 XSS 공격을 방어하기 위해 텍스트를 소독(sanitize)해야 한다는 보안 및 타입 안정성 측면에서의 단편적인 예시만 확인됩니다 [1-3].
|
||||
## 매 한 줄
|
||||
> **"매 Document 의 tree 의 query + mutation 의 web 기본 API"**. 매 jQuery 의 era 종료, 2026 의 modern DOM (querySelector, classList, dataset, MutationObserver) 의 충분 + framework (React/Solid/Svelte) 의 abstraction 위. 매 vanilla 의 fast path + 매 small widget 의 right tool.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
소스에 관련 정보가 부족합니다.
|
||||
## 매 핵심
|
||||
|
||||
제공된 소스에서 DOM 조작과 관련해 부분적으로 도출할 수 있는 내용은 다음과 같습니다:
|
||||
### 매 Query
|
||||
- `getElementById(id)` — 매 fastest single lookup.
|
||||
- `querySelector(sel)` / `querySelectorAll(sel)` — CSS selector general.
|
||||
- `closest(sel)` — 매 ancestor traversal.
|
||||
- `matches(sel)` — boolean check.
|
||||
|
||||
* **DOM 조작과 타입 단언(`as`):** TypeScript 환경에서 DOM 요소를 조작하거나 타입 추론이 어려운 외부 데이터를 다룰 때, 개발자가 런타임 유효성을 확인하여 타입에 대해 확신이 있다면 `as` 키워드를 사용하여 타입을 단언할 수 있습니다 [2]. 주로 DOM 요소의 타입을 구체적으로 좁혀야(narrow) 할 때(예: 특정 HTML 요소로 단언할 때) 제한적으로 `as`의 사용이 고려됩니다 [3].
|
||||
* **DOM 추가 시 보안(XSS) 유의사항:** 사용자의 입력값을 검증 없이 DOM(예: `innerHTML`)에 직접 쓰는 것은 보안상 매우 위험한 방식입니다 [1]. 악의적인 코드가 주입되는 XSS(크로스 사이트 스크립팅) 공격을 막기 위해, DOM에 데이터를 추가하기 전에 반드시 텍스트를 소독(sanitize)해야 합니다 [1]. TypeScript의 브랜디드 타입(Branded Types)을 활용하면 소독된 문자열과 소독되지 않은 문자열의 타입을 구분할 수 있어, 안전하게 처리된 문자열만 DOM에 삽입되도록 타입 시스템 수준에서 강제할 수 있습니다 [1, 4].
|
||||
### 매 Mutate
|
||||
- **Create**: `createElement`, `cloneNode(true)`, `<template>` + `content.cloneNode`.
|
||||
- **Insert**: `append`, `prepend`, `before`, `after`, `replaceWith`.
|
||||
- **Remove**: `el.remove()`.
|
||||
- **Attribute**: `setAttribute`, `dataset.x`, `classList.add/toggle/remove`.
|
||||
- **Content**: `textContent` (safe) vs `innerHTML` (XSS risk).
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 Observe
|
||||
- `MutationObserver` — 매 subtree change.
|
||||
- `IntersectionObserver` — viewport visibility.
|
||||
- `ResizeObserver` — element size.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[타입 단언(Type Assertions)]], 브랜디드 타입(Branded Types)
|
||||
- **Projects/Contexts:** 안전한 TypeScript 프론트엔드 개발 및 XSS 방어
|
||||
- **Contradictions/Notes:** 소스에 DOM 요소 조작의 본질적인 원리나 구체적인 API(예: 순수 자바스크립트 DOM API)에 대한 정보가 절대적으로 부족하므로 "소스에 관련 정보가 부족합니다."
|
||||
### 매 응용
|
||||
1. Lightweight widget (no framework) — banner, modal, tooltip.
|
||||
2. Server-rendered HTML enhancement (Hotwire, Astro islands).
|
||||
3. Browser extension content script.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
## 💻 패턴
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
### Element creation (template)
|
||||
```html
|
||||
<template id="card-tpl">
|
||||
<article class="card">
|
||||
<h3 class="title"></h3>
|
||||
<p class="body"></p>
|
||||
</article>
|
||||
</template>
|
||||
```
|
||||
```javascript
|
||||
function renderCard({ title, body }) {
|
||||
const tpl = document.getElementById('card-tpl');
|
||||
const node = tpl.content.cloneNode(true);
|
||||
node.querySelector('.title').textContent = title;
|
||||
node.querySelector('.body').textContent = body;
|
||||
return node;
|
||||
}
|
||||
document.querySelector('#list').append(renderCard({ title: 'Hi', body: 'World' }));
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### classList + dataset
|
||||
```javascript
|
||||
const btn = document.querySelector('#toggle');
|
||||
btn.classList.toggle('active');
|
||||
btn.dataset.count = (Number(btn.dataset.count ?? 0) + 1).toString();
|
||||
// HTML: <button id="toggle" data-count="3">
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Event delegation
|
||||
```javascript
|
||||
document.addEventListener('click', (e) => {
|
||||
const action = e.target.closest('[data-action]');
|
||||
if (!action) return;
|
||||
switch (action.dataset.action) {
|
||||
case 'open': openModal(action.dataset.id); break;
|
||||
case 'delete': remove(action.dataset.id); break;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Safe insertion (avoid innerHTML)
|
||||
```javascript
|
||||
// 매 X — XSS
|
||||
container.innerHTML = `<p>${userInput}</p>`;
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
// 매 O — textContent
|
||||
const p = document.createElement('p');
|
||||
p.textContent = userInput;
|
||||
container.append(p);
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
// 매 trusted HTML 만 — Sanitizer API (2026 baseline)
|
||||
container.setHTML(trustedString); // 의 native sanitize
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### IntersectionObserver — lazy load
|
||||
```javascript
|
||||
const io = new IntersectionObserver((entries) => {
|
||||
for (const e of entries) {
|
||||
if (!e.isIntersecting) continue;
|
||||
const img = e.target;
|
||||
img.src = img.dataset.src;
|
||||
io.unobserve(img);
|
||||
}
|
||||
});
|
||||
document.querySelectorAll('img[data-src]').forEach((img) => io.observe(img));
|
||||
```
|
||||
|
||||
### MutationObserver — react to subtree
|
||||
```javascript
|
||||
const mo = new MutationObserver((muts) => {
|
||||
for (const m of muts) {
|
||||
for (const n of m.addedNodes) {
|
||||
if (n instanceof HTMLAnchorElement) enhanceLink(n);
|
||||
}
|
||||
}
|
||||
});
|
||||
mo.observe(document.body, { childList: true, subtree: true });
|
||||
```
|
||||
|
||||
### Form serialization
|
||||
```javascript
|
||||
const form = document.querySelector('#login');
|
||||
form.addEventListener('submit', (e) => {
|
||||
e.preventDefault();
|
||||
const data = Object.fromEntries(new FormData(form));
|
||||
fetch('/login', { method: 'POST', body: JSON.stringify(data), headers: { 'Content-Type': 'application/json' } });
|
||||
});
|
||||
```
|
||||
|
||||
### Animation — Web Animations API
|
||||
```javascript
|
||||
el.animate(
|
||||
[{ opacity: 0, transform: 'translateY(10px)' }, { opacity: 1, transform: 'none' }],
|
||||
{ duration: 200, easing: 'ease-out', fill: 'forwards' },
|
||||
);
|
||||
```
|
||||
|
||||
### Batched DOM updates
|
||||
```javascript
|
||||
const frag = document.createDocumentFragment();
|
||||
for (const item of items) frag.append(renderRow(item));
|
||||
list.append(frag); // 매 single reflow
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| Static + small interaction | Vanilla DOM |
|
||||
| 100s of components | React / Solid / Svelte |
|
||||
| Server HTML + enhancement | Hotwire / Astro |
|
||||
| Lazy load images | IntersectionObserver |
|
||||
| External widget injection | MutationObserver |
|
||||
| Animation | Web Animations API |
|
||||
|
||||
**기본값**: querySelector + classList + textContent + delegation + Observer APIs.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[DOM]] · [[Web_APIs]]
|
||||
- 변형: [[DOM_요소_조작_및_타입_좁히기]] · [[Shadow_DOM]]
|
||||
- 응용: [[Web_Components]] · [[Browser_Extensions]] · [[Hotwire]]
|
||||
- Adjacent: [[IntersectionObserver]] · [[MutationObserver]] · [[Sanitizer_API]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: vanilla widget scaffold, Observer setup, jQuery → modern migration.
|
||||
**언제 X**: 매 framework app — 매 framework primitive 의 사용.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **`innerHTML` with user input**: 매 XSS — `textContent` 또는 Sanitizer.
|
||||
- **Loop append in DOM**: 매 N reflows — DocumentFragment 의 사용.
|
||||
- **No event delegation**: 1000 listener 의 memory + perf 비용.
|
||||
- **document.write**: deprecated — 매 stream block.
|
||||
- **Manual style mutation everywhere**: classList toggle + CSS 의 사용.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (MDN DOM, Web Animations, Observers, Sanitizer API spec).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — query/mutate/observe patterns + Sanitizer + delegation |
|
||||
|
||||
@@ -2,99 +2,32 @@
|
||||
id: wiki-2026-0508-discriminated-unions
|
||||
title: Discriminated Unions
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-DEC013]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: discriminated-unions
|
||||
duplicate_of: "[[Discriminated_Unions]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Discriminated Unions"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, typescript, types]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[Discriminated Unions]]
|
||||
# Discriminated Unions
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Discriminated Unions(또는 식별 가능한 유니온, 태그된 유니온)은 서로 다른 데이터 형태를 구분하기 위해 공통된 리터럴 속성(판별자, Discriminant)을 사용하는 TypeScript의 패턴입니다 [1-3]. 일반적인 유니온 타입과 달리, 컴파일러가 판별자 속성을 확인하여 타입을 자동으로 안전하게 좁힐 수(Narrowing) 있게 해줍니다 [4-6]. 이를 통해 유효하지 않은 상태의 표현을 원천적으로 차단하고, 모든 가능한 경우를 처리하도록 강제하는 완전성 검사(Exhaustiveness checking)를 구현할 수 있습니다 [3, 7, 8].
|
||||
> **이 문서는 [[Discriminated_Unions]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **작동 원리 및 특징**
|
||||
Discriminated Union은 객체들이 공통으로 가지는 식별자 필드(주로 `kind`, `type`, `status` 같은 문자열 리터럴)를 활용하여 구성됩니다 [2-4]. 이 공통 속성을 기반으로 TypeScript의 코드 흐름 분석이 진행되며, 특정 브랜치에서 타입을 명확하게 좁혀줍니다 [3, 4, 9]. 이는 런타임 오버헤드가 전혀 추가되지 않는 컴파일 타임 전용 구조입니다 [10].
|
||||
## 핵심 요약
|
||||
- Tagged union — 매 common literal property (e.g. `kind`, `type`) 의 narrowing.
|
||||
- TypeScript 의 exhaustive check (`never` assertion) 의 강력한 패턴.
|
||||
- Sum type 의 ML/Rust enum 과 매 동치.
|
||||
|
||||
* **주요 장점**
|
||||
가장 큰 장점은 올바르지 않은 조합의 상태(Invalid [[State]]s)를 코드로 표현할 수 없게 만들어 구조적으로 버그를 방지한다는 것입니다 [1, 7, 11]. 또한 `switch` 문과 `never` 타입을 결합하면 모든 유니온 케이스가 처리되었는지 컴파일러가 확인하는 '완전성 검사(Exhaustive checking)'가 가능합니다 [3, 12-14]. 유니온에 새로운 타입 멤버가 추가되었을 때 이를 누락한 코드를 즉각적인 컴파일 에러로 포착해 내므로 유지보수성이 크게 향상됩니다 [3, 8].
|
||||
## 🔗 Graph
|
||||
- 부모: [[Discriminated_Unions]] (canonical)
|
||||
|
||||
* **사용 사례 (Use Cases)**
|
||||
API 응답 데이터 처리, 폼(Form) 핸들링, Redux 스타일의 리듀서(Reducer), 라우터 상태 관리, 그리고 상태 머신(State Machine) 패턴을 모델링하는 데 매우 적합합니다 [7, 15-17]. 복잡한 상태를 표현해야 할 때는 다중 판별자(Multiple Discriminants)를 두거나 유니온을 중첩(Nested)하는 방식으로도 활용할 수 있습니다 [15, 16].
|
||||
|
||||
* **주의사항 및 베스트 프랙티스**
|
||||
판별자로는 항상 문자열 리터럴 타입을 사용하는 것이 권장되며, 모든 브랜치에 걸쳐 일관된 판별자 속성을 포함해야 합니다 [12, 16, 18]. 타입을 좁힐 때는 `instanceof` 연산자를 사용하는 대신 반드시 판별자 속성을 확인해야 합니다 [18]. 단, 아주 거대한 코드베이스에서 과도하게 복잡한 유니온 타입을 사용하면 TypeScript의 컴파일 속도가 느려질 수 있으며, 깊게 중첩될 경우 에러 메시지를 파악하기 어려워질 수 있으므로 주의해야 합니다 [10].
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[Union Types]], Type Narrowing, Exhaustiveness Checking, Literal Types, never type
|
||||
- **Projects/Contexts:** React State [[Management]], State Machine Pattern, API Response Handling, Redux Reducers
|
||||
- **Contradictions/Notes:** Discriminated Union 패턴은 타입 안정성과 예측 가능성을 크게 높여주지만, 유니온 타입이 지나치게 복잡해지거나 깊은 중첩 구조를 가지게 되면 오히려 TypeScript의 컴파일 성능을 저하시키고 에러 메시지의 가독성을 떨어뜨리는 부작용(단점)을 유발할 수 있습니다 [10].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -1,92 +1,34 @@
|
||||
---
|
||||
id: wiki-2026-0508-early-z
|
||||
title: Early Z
|
||||
title: Early-Z
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-D03C5F]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: depth-pre-pass
|
||||
duplicate_of: "[[Depth Pre-Pass]]"
|
||||
aliases: [Early Z, Hi-Z]
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Early-Z"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, graphics, gpu]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[Early-Z]]
|
||||
# Early-Z
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Early-Z(초기 깊이 테스트)는 렌더링 파이프라인의 프래그먼트 셰이딩([[Fragment Shading]]) 단계에서 오버드로우([[Overdraw]])를 최소화하기 위해 사용되는 GPU 최적화 기법입니다 [1, 2]. 불투명한 물체를 카메라 기준 '앞에서 뒤로(Front-to-Back)' 정렬하여 렌더링함으로써, 다른 물체에 의해 가려져 화면에 보이지 않을 픽셀의 연산을 사전에 종료시킵니다 [2]. 하지만 투명한 재질을 렌더링할 때는 이 최적화 기능이 비활성화되는 특성이 있습니다 [1].
|
||||
> **이 문서는 [[Depth Pre-Pass]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **Early-Z의 원리와 목적:** 렌더링 과정에서 동일한 픽셀 위치에 여러 번의 쓰기 작업이 중첩되어 발생하는 현상을 오버드로우라고 부르며, 이는 보이지 않는 계산에 GPU 자원을 낭비하게 만듭니다 [1, 2]. 불투명한 물체들을 '앞에서 뒤로(Front-to-Back)' 정렬하여 그릴 경우, GPU는 이미 렌더링된 앞쪽 표면에 의해 가려지는 뒤쪽 픽셀 연산을 조기에 종료(Early-Z)시켜 렌더링 효율을 크게 높입니다 [1, 2].
|
||||
- **투명 재질 렌더링 시의 비활성화:** 겹쳐 있는 투명한 기하학적 구조(예: 옷, 머리카락 레이어 등)를 렌더링할 때는 올바른 알파 블렌딩 결과를 얻기 위해 '뒤에서 앞으로(Back-to-Front)' 렌더링을 강제해야 합니다 [1, 3]. 이 과정에서 숨겨진 픽셀을 건너뛰게 해주는 초기 깊이 테스트(Early-Z) 최적화가 비활성화되며, 결과적으로 하나의 픽셀을 여러 번 렌더링하는 심각한 오버드로우가 발생하게 됩니다 [1].
|
||||
- **[[InstancedMesh]] 환경에서의 한계:** 드로우 콜을 줄여주는 `InstancedMesh` 기술은 내부 인스턴스들에 대한 자동 정렬 기능을 제공하지 않고 버퍼에 저장된 순서대로만 렌더링합니다 [2]. 만약 먼 곳에 있는 인스턴스가 먼저 그려지고 가까운 인스턴스가 나중에 그려진다면, Early-Z를 통한 조기 종료 이점을 얻지 못합니다 [2]. 이는 드로우 콜 감소로 얻은 이점보다 막대한 오버드로우 비용을 초래하여, GPU를 프래그먼트 바운드([[Fragment-bound]]) 상태에 빠뜨려 전체 성능을 오히려 저하시킬 수 있습니다 [2].
|
||||
## 핵심 요약
|
||||
- Early-Z = depth test 매 fragment shader 이전에 실행 → occluded fragment 매 shader 실행 skip.
|
||||
- 조건: `discard` / depth write in shader 매 없을 때 GPU가 자동 활성화.
|
||||
- Depth Pre-Pass 매 Early-Z를 maximize 하는 standard pattern (z-only first pass → color pass).
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
## 🔗 Graph
|
||||
- 부모: [[Depth Pre-Pass]] (canonical)
|
||||
- Adjacent: [[Z-Buffer]] · [[Hi-Z Culling]]
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[Overdraw]], [[InstancedMesh]], [[Alpha Blending]]
|
||||
- **Projects/Contexts:** Three.js [[WebGL]] 렌더링 최적화
|
||||
- **Contradictions/Notes:** 소스에 관련 정보가 부족합니다.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -2,91 +2,140 @@
|
||||
id: wiki-2026-0508-edge-bleeding
|
||||
title: Edge Bleeding
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-2BC744]
|
||||
aliases: [Texture Bleeding, Atlas Bleeding]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [graphics, texture, rendering]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Edge Bleeding"
|
||||
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: GLSL/HLSL
|
||||
framework: WebGL/Three.js/Unity/Unreal
|
||||
---
|
||||
|
||||
# [[Edge Bleeding]]
|
||||
# Edge Bleeding
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Edge Bleeding(경계선 블리딩)은 여러 이미지를 하나로 합친 텍스처 아틀라스([[Texture Atlas]])를 사용할 때 주로 발생하는 시각적 결함입니다 [1]. 특히 낮은 밉맵([[Mipmap]]) 레벨에서 텍스처 필터링이 일어날 때, 아틀라스 내에 인접해 있는 텍스처들의 색상이 서로 섞이거나 번지는 현상을 의미합니다 [1, 2]. 이를 방지하기 위해서는 텍스처 간에 여백을 두어 메모리를 희생하거나, 최신 텍스처 배열([[Data Array Textures]]) 기술을 활용해야 합니다 [2, 3].
|
||||
## 매 한 줄
|
||||
> **"매 texture sampling 의 인접 texel이 unintended 하게 leak — atlas seam의 colored line으로 manifest."**. 매 mipmap downsample / bilinear interpolation 매 texel boundary를 cross 하면서 발생. 매 sprite atlas, texture array, lightmap에서 매 visible artifact.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **발생 원인:** 동일한 재질을 공유하여 드로우 콜([[Draw Call]])을 최적화하기 위해 여러 텍스처를 하나의 큰 이미지로 병합하는 텍스처 아틀라스 방식을 사용할 때 발생합니다 [1, 2]. GPU가 거리에 따라 해상도를 낮춘 밉맵을 생성하고 필터링하는 과정에서 인접한 텍스처 영역의 픽셀이 침범하여 색상이 섞이게 됩니다 [1, 2].
|
||||
- **기존의 해결 방식과 한계:** 이 현상을 방지하기 위해 텍스처 아틀라스 내부의 개별 텍스처들 사이에 물리적인 여백(Padding)을 추가하는 우회 기법이 사용됩니다 [2]. 하지만 이 방식은 텍스처 공간을 낭비하게 만들어 메모리 비효율성을 초래합니다 [2].
|
||||
- **현대적인 해결책 (Data Array Textures):** [[WebGL]] 2.0에서 지원하는 데이터 배열 텍스처(Data Array Textures)를 사용하면 Edge Bleeding을 완벽히 제거할 수 있습니다 [3, 4]. 이 방식은 텍스처를 평면에 병합하는 대신 레이어(Layer) 구조의 스택으로 쌓아 인덱스로 접근하므로, 밉맵 생성 시 인접 텍스처 간의 교차 오염(Cross-contamination)이 발생하지 않습니다 [1, 3].
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 원인
|
||||
- **Bilinear filter**: 매 sample point 매 texel center 사이 → 인접 texel weighted.
|
||||
- **Mipmap downsample**: 매 box filter 매 atlas neighbor를 average.
|
||||
- **UV precision**: float precision 매 정확한 boundary 매 hit 못 함.
|
||||
- **Anisotropic filtering**: 매 large footprint → 매 더 많은 neighbor sampling.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[Texture Atlas]], [[Mipmap]], [[Data Array Textures]]
|
||||
- **Projects/Contexts:** [[InstancedMesh 최적화]], WebGL 2.0
|
||||
- **Contradictions/Notes:** 소스에 관련 정보가 부족합니다. (소스 내에서 명시적인 의견 대립은 발견되지 않으며, Edge Bleeding은 텍스처 아틀라스의 명확한 단점[1, 2]이자 WebGL 2.0의 텍스처 배열 도입으로 쉽게 극복 가능한 문제[3, 4]로 일관되게 설명됩니다.)
|
||||
### 매 manifestation
|
||||
- Sprite atlas: 매 sprite edge 매 인접 sprite color line.
|
||||
- Tilemap: 매 tile seam 매 dark/bright line.
|
||||
- Skybox cubemap: 매 face boundary 매 visible seam.
|
||||
- Lightmap: 매 chart boundary 매 dark crack.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
### 매 응용 (해결책)
|
||||
1. **Padding (gutter)**: 매 sprite 사이 1-2px transparent / replicated edge.
|
||||
2. **Half-texel UV inset**: UV 매 `(0.5/W, 0.5/H)` ~ `(1 - 0.5/W, 1 - 0.5/H)` 의 clamp.
|
||||
3. **CLAMP_TO_EDGE**: wrap mode 매 repeat → clamp.
|
||||
4. **Conservative UV**: 매 mesh UV 매 atlas region 의 inside 의 inset.
|
||||
5. **Mipmap-aware padding**: 매 mip level 별 padding (1px → 2px → 4px).
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
### Half-texel inset (GLSL)
|
||||
```glsl
|
||||
uniform vec2 atlasSize; // e.g. (2048, 2048)
|
||||
uniform vec4 spriteRect; // x, y, w, h in pixels
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(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
|
||||
vec2 sampleUV(vec2 localUV) {
|
||||
vec2 halfTexel = 0.5 / atlasSize;
|
||||
vec2 minUV = spriteRect.xy / atlasSize + halfTexel;
|
||||
vec2 maxUV = (spriteRect.xy + spriteRect.zw) / atlasSize - halfTexel;
|
||||
return mix(minUV, maxUV, localUV);
|
||||
}
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### Atlas packer with padding (TS)
|
||||
```typescript
|
||||
function packSprite(sprite: ImageData, padding = 2): PackedSprite {
|
||||
const w = sprite.width + padding * 2;
|
||||
const h = sprite.height + padding * 2;
|
||||
const padded = new ImageData(w, h);
|
||||
// edge replicate (not transparent) for bilinear safety
|
||||
for (let y = 0; y < h; y++) {
|
||||
for (let x = 0; x < w; x++) {
|
||||
const sx = clamp(x - padding, 0, sprite.width - 1);
|
||||
const sy = clamp(y - padding, 0, sprite.height - 1);
|
||||
copyPixel(sprite, sx, sy, padded, x, y);
|
||||
}
|
||||
}
|
||||
return { data: padded, padding };
|
||||
}
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Three.js NearestFilter (no bleed, no smooth)
|
||||
```javascript
|
||||
texture.minFilter = THREE.NearestFilter;
|
||||
texture.magFilter = THREE.NearestFilter;
|
||||
texture.generateMipmaps = false;
|
||||
texture.wrapS = texture.wrapT = THREE.ClampToEdgeWrapping;
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Mipmap-aware padding count
|
||||
```typescript
|
||||
function paddingForMipLevels(levels: number): number {
|
||||
return Math.pow(2, levels - 1); // 4 levels → 8px padding
|
||||
}
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### Conservative cubemap seam fix (HLSL)
|
||||
```hlsl
|
||||
float3 SampleCubeSeamless(TextureCube tex, SamplerState s, float3 dir, float roughness) {
|
||||
float mip = roughness * 8.0;
|
||||
float texSize = 512.0 / pow(2, mip);
|
||||
float scale = 1.0 - 1.0 / texSize;
|
||||
return tex.SampleLevel(s, dir * scale, mip).rgb;
|
||||
}
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| Pixel art sprite | NearestFilter + padding 1px |
|
||||
| 3D texture atlas (smooth) | Half-texel inset + padding (2 * mip levels) |
|
||||
| Tilemap | Padding + clamp + per-tile texture array (best) |
|
||||
| Cubemap | GL_TEXTURE_CUBE_MAP_SEAMLESS (GL 3.2+) |
|
||||
| Lightmap | Chart padding 4px + dilation |
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
**기본값**: 매 padding 2px + half-texel inset, 매 mipmap 매 사용 시 2 * (mip levels) px.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Texture Mapping]] · [[Texture Filtering]]
|
||||
- 변형: [[Atlas Bleeding]] · [[Cubemap Seam]]
|
||||
- 응용: [[Sprite Atlas]] · [[Lightmap]] · [[Texture Array]]
|
||||
- Adjacent: [[Mipmap]] · [[Bilinear Filtering]] · [[UV Mapping]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: sprite atlas / tilemap / lightmap 매 visible seam, 매 mipmap 매 사용한 atlas, 매 cubemap face 경계 artifact.
|
||||
**언제 X**: single texture (no atlas), 매 NEAREST filter 매 사용 + no mipmap, fully procedural texture.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Transparent padding alone**: 매 bilinear가 transparent와 mix → 매 dark fringe.
|
||||
- **Padding 너무 small**: mip level 3+ 매 도달 시 여전히 leak.
|
||||
- **Repeat wrap on atlas**: 매 opposite edge 매 sample → 완전한 wrong color.
|
||||
- **UV exactly at texel boundary**: 매 float precision 의해 random side 매 sample.
|
||||
- **Generate mipmap on packed atlas**: 매 mip downsample 매 인접 sprite를 average → mid-mip levels artifact.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Real-Time Rendering 4ed, Unity / Unreal docs, OpenGL spec).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — Edge bleeding 원인 / padding 전략 / mip-aware solution |
|
||||
|
||||
@@ -2,91 +2,169 @@
|
||||
id: wiki-2026-0508-effect-ts
|
||||
title: Effect TS
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-C7A07F]
|
||||
aliases: [Effect, Effect-TS, effect.ts]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [typescript, functional-programming, effect, error-handling]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Effect TS"
|
||||
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: Effect
|
||||
---
|
||||
|
||||
# [[Effect TS]]
|
||||
# Effect TS
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Effect TS는 타입이 풍부한(type-rich) TypeScript 애플리케이션을 구축하기 위해 널리 사용되는 인기 있는 프레임워크입니다 [1]. 이 프레임워크는 주로 구조적으로 동일해 보이는 타입들을 명확히 구분하기 위한 브랜디드 타입(Branded Types) 유틸리티를 제공합니다 [1, 2]. 또한, 예상되는 에러와 예상치 못한 에러를 구분하거나 `_tag` 속성을 통해 메타데이터를 관리하는 등 타입 시스템을 활용한 다양한 패턴의 기반을 제공합니다 [3, 4].
|
||||
## 매 한 줄
|
||||
> **"매 TypeScript 의 functional effect system — error · concurrency · resource 매 type-level encoding"**. 매 ZIO (Scala) inspired library 의 TS port. 2026 시점 v3.x stable, Discord · Vercel · Stripe internal services 가 production 채택.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **브랜디드 타입(Branded Types) 도구 제공**: Effect TS는 TypeScript 커뮤니티에서 널리 쓰이는 대표적인 브랜디드 타입 라이브러리 중 하나입니다 [2]. 타입 내에서 브랜드 역할을 하는 제네릭 타입인 `Brand.Brand`와 타입 브랜드 식별 함수를 반환하는 제네릭 함수 `Brand.nominal`을 제공하여 사용자가 브랜디드 타입을 쉽게 생성할 수 있도록 지원합니다 [1].
|
||||
* **정교한 타입 브랜드 단언 함수(`Brand.refined`)**: Effect TS는 제약 조건을 검증하기 위해 `Brand.refined`라는 함수를 별도로 제공합니다 [1, 5]. 이 함수는 값이 제약 조건을 충족하는지 확인하는 함수와, 제약 조건과 일치하지 않을 경우 에러를 던지는 함수라는 두 가지 매개변수를 활용하여 안전한 타입 단언(assertion)을 수행합니다 [5].
|
||||
* **에러 처리 및 메타데이터 컨벤션 모델링**: Effect TS는 시스템의 '예상되는 에러(Expected Errors)'와 '예상치 못한 에러(Defects)'를 명확히 구분하는 아키텍처적 접근법을 제시합니다 [3]. 이와 더불어 내부 로직이나 디버깅, 관측 도구에서 사용되는 데이터를 다른 응답 객체와 시각적으로 구분하기 위해 `_tag`와 같은 속성(메타데이터)을 사용하는 훌륭한 컨벤션을 제공합니다 [4, 6].
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 Effect<A, E, R>
|
||||
- `A`: success value type
|
||||
- `E`: error type (typed errors, no exceptions)
|
||||
- `R`: required services (DI context)
|
||||
- 매 lazy description — execution은 `Effect.runPromise` 시점.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** Branded Types, TypeScript
|
||||
- **Projects/Contexts:** Type-rich TypeScript Applications
|
||||
- **Contradictions/Notes:** 소스에 관련 정보가 부족합니다.
|
||||
### 매 핵심 primitives
|
||||
- `Effect.succeed` / `Effect.fail` / `Effect.sync` / `Effect.tryPromise`
|
||||
- `Effect.gen` (generator-based do-notation)
|
||||
- `Effect.all` (parallel), `Effect.forEach` (concurrency control)
|
||||
- `Layer` (DI composition), `Context.Tag` (service identity)
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
### 매 응용
|
||||
1. API gateway error contracts (`HttpClient` typed errors).
|
||||
2. Database transactional pipelines (`Effect.scoped` + `Layer`).
|
||||
3. Streaming ETL (`Stream` module).
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
### Effect.gen do-notation
|
||||
```ts
|
||||
import { Effect } from "effect"
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(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
|
||||
const getUser = (id: string) =>
|
||||
Effect.gen(function* () {
|
||||
const db = yield* DatabaseService
|
||||
const user = yield* db.findUser(id)
|
||||
if (!user) return yield* Effect.fail(new UserNotFound({ id }))
|
||||
return user
|
||||
})
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### Typed errors (Data.TaggedError)
|
||||
```ts
|
||||
import { Data } from "effect"
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
class UserNotFound extends Data.TaggedError("UserNotFound")<{
|
||||
id: string
|
||||
}> {}
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
class DbConnectionError extends Data.TaggedError("DbConnectionError")<{
|
||||
cause: unknown
|
||||
}> {}
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### Layer composition
|
||||
```ts
|
||||
import { Effect, Layer, Context } from "effect"
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
class DatabaseService extends Context.Tag("DatabaseService")<
|
||||
DatabaseService,
|
||||
{ findUser: (id: string) => Effect.Effect<User | null, DbConnectionError> }
|
||||
>() {}
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
const DatabaseLive = Layer.succeed(DatabaseService, {
|
||||
findUser: (id) =>
|
||||
Effect.tryPromise({
|
||||
try: () => pgClient.query("SELECT * FROM users WHERE id=$1", [id]),
|
||||
catch: (cause) => new DbConnectionError({ cause }),
|
||||
}),
|
||||
})
|
||||
```
|
||||
|
||||
### Concurrent execution
|
||||
```ts
|
||||
const fetchAll = Effect.forEach(
|
||||
["a", "b", "c"],
|
||||
(id) => getUser(id),
|
||||
{ concurrency: 5 }
|
||||
)
|
||||
```
|
||||
|
||||
### Retry + timeout
|
||||
```ts
|
||||
import { Schedule, Duration } from "effect"
|
||||
|
||||
const robust = getUser("123").pipe(
|
||||
Effect.retry(Schedule.exponential(Duration.millis(100)).pipe(
|
||||
Schedule.compose(Schedule.recurs(3))
|
||||
)),
|
||||
Effect.timeout(Duration.seconds(5))
|
||||
)
|
||||
```
|
||||
|
||||
### Resource scoping
|
||||
```ts
|
||||
const program = Effect.scoped(
|
||||
Effect.gen(function* () {
|
||||
const file = yield* Effect.acquireRelease(
|
||||
openFile("data.txt"),
|
||||
(f) => closeFile(f)
|
||||
)
|
||||
return yield* readContent(file)
|
||||
})
|
||||
)
|
||||
```
|
||||
|
||||
### Schema validation
|
||||
```ts
|
||||
import { Schema } from "effect"
|
||||
|
||||
const User = Schema.Struct({
|
||||
id: Schema.String,
|
||||
age: Schema.Number.pipe(Schema.int(), Schema.nonNegative()),
|
||||
})
|
||||
|
||||
const parse = Schema.decodeUnknown(User)
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| 단순 CRUD app | plain async/await + zod |
|
||||
| 복잡한 error taxonomy | Effect (typed errors) |
|
||||
| Concurrency-heavy pipeline | Effect (Schedule + Stream) |
|
||||
| Team unfamiliar with FP | neverthrow / fp-ts 시작 |
|
||||
|
||||
**기본값**: greenfield TS backend with complex error contracts → Effect 채택. 매 learning curve 높음 — team buy-in 매 우선.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Functional Programming]] · [[TypeScript 타입 시스템 및 인터페이스 설계]]
|
||||
- 변형: [[Result Type]] · [[neverthrow]]
|
||||
- 응용: [[견고한 도메인 모델 및 API 계약 설계]] · [[API 응답 및 에러 핸들링 아키텍처]]
|
||||
- Adjacent: [[Zod 런타임 유효성 검사 통합]] · [[ts-brand]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: TS backend with strict error typing, dependency injection at type level, retry/circuit-breaker policies.
|
||||
**언제 X**: 매 simple script · prototype · React component logic — overhead 매 큼.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Effect.runSync everywhere**: 매 sync execution 강제 — async benefit 상실.
|
||||
- **Fail with strings**: typed `TaggedError` 의 사용해야 매 discriminated handling 가능.
|
||||
- **Layer.merge spaghetti**: 매 dependency graph 의 명시적 organize.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (effect.website official docs · Effect 3.x release notes 2025).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — Effect 3.x patterns, Layer/Schema/typed errors |
|
||||
|
||||
@@ -2,91 +2,160 @@
|
||||
id: wiki-2026-0508-electron
|
||||
title: Electron
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-687305]
|
||||
aliases: [Electron Framework, Atom Shell]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [desktop, javascript, chromium, nodejs]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Electron"
|
||||
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/JavaScript
|
||||
framework: Electron 33+
|
||||
---
|
||||
|
||||
# [[Electron]]
|
||||
# Electron
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Electron은 대규모 CAD 애플리케이션 등에서 사용되는 런타임 환경으로, 전체 시스템 메모리에 접근할 수 있지만 격리된 프로세스 간에 메모리를 관리해야 하는 특징이 있습니다 [1, 2]. [[Chromium]] GPU 프로세스와 렌더러 프로세스가 분리되어 있어 GPU 메모리 누수나 OOM(Out of [[memory]]) 오류가 발생하기 쉬운 구조적 위험성을 내포하고 있습니다 [3, 4].
|
||||
## 매 한 줄
|
||||
> **"매 Chromium + Node.js를 묶어 web tech 으로 desktop app 을 build"**. GitHub 이 Atom editor 용으로 만든 framework 가 VS Code, Slack, Discord, Figma desktop, 1Password 의 backbone 이 되었음. 2026 현재 Electron 33+ 가 process model 강화 (utility process), V8 sandbox, ASAR integrity 검사 의 기본화.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **메모리 관리의 양날의 검**: 대규모 CAD 애플리케이션을 Electron에서 구동할 때, 전체 시스템 메모리에 접근할 수 있다는 장점이 있지만 프로세스가 격리되어 있어 메모리 관리에 세심한 주의가 필요합니다 [2]. 예를 들어 메인 스레드와 Web Worker 간에 'Structured Cloning' 방식으로 메시지를 전달할 경우, 데이터가 전체 복사되어 메모리 사용량이 두 배로 증가할 수 있으며 이로 인해 Electron의 OOM(Out of Memory) 킬러가 작동할 수 있습니다 [3].
|
||||
- **GPU 메모리 누수 취약성**: Electron 앱은 Chromium GPU 프로세스가 렌더러 프로세스와 완전히 분리되어 있기 때문에 GPU 메모리 누수로 악명이 높습니다 [4]. 3D 씬에서 객체를 삭제하더라도 단순히 씬 그래프에서 제거하는 것만으로는 연관된 GPU 버퍼가 자동으로 해제되지 않습니다 [4].
|
||||
- **최적화 및 안정성 확보 전략**: Electron 런타임 환경 내에서 메모리 안정성을 유지하기 위해서는 `SharedArrayBuffer`를 활용하여 데이터 복제 오버헤드 없이 다중 스레딩을 처리해야 합니다 [1, 3]. 더불어 메모리 누수를 막기 위해, 삭제 시 씬을 순회하며 모든 기하학적 구조와 재질에 대해 명시적으로 `.dispose()`를 호출하는 엄격한 리소스 폐기(Disposal) 패턴을 강제해야 합니다 [4].
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 process model
|
||||
- **Main process**: Node.js runtime, app lifecycle, native API (file, dialog, tray) 의 owner. 매 1 개 instance.
|
||||
- **Renderer process**: Chromium tab 마다 1 개. BrowserWindow content. Sandbox 기본 ON (Electron 20+).
|
||||
- **Preload script**: Renderer 의 isolated world 에서 실행, `contextBridge` 로 main 과 안전 bridge.
|
||||
- **Utility process**: 매 v22+ 추가. Heavy CPU/IO offload (image decode, ffmpeg).
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** SharedArrayBuffer, OOM (Out of Memory), Chromium GPU process
|
||||
- **Projects/Contexts:** Large-scale CAD applications, [[WebGL]]/Three.js Rendering [[Optimization]]
|
||||
- **Contradictions/Notes:** 소스에 Electron 프레임워크 자체의 전반적인 동작 원리나 일반적인 데스크톱 앱 개발과 관련된 정보가 부족합니다. 제공된 문서는 대규모 3D/CAD 렌더링 최적화 환경에서의 메모리 관리 및 누수 문제에 국한하여 Electron을 설명하고 있습니다.
|
||||
### 매 IPC 패턴
|
||||
- `ipcRenderer.invoke` ↔ `ipcMain.handle` (Promise-based, 권장).
|
||||
- `ipcRenderer.send` ↔ `ipcMain.on` (fire-and-forget).
|
||||
- `webContents.send` ↔ `ipcRenderer.on` (main → renderer push).
|
||||
- 매 `contextIsolation: true` + `nodeIntegration: false` 의 mandatory.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
### 매 응용
|
||||
1. **Editor**: VS Code, Atom, Obsidian.
|
||||
2. **Communication**: Slack, Discord, Microsoft Teams.
|
||||
3. **Design**: Figma desktop, Notion.
|
||||
4. **Crypto/Wallet**: 1Password, Exodus.
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
### Secure preload bridge
|
||||
```typescript
|
||||
// preload.ts
|
||||
import { contextBridge, ipcRenderer } from 'electron'
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(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
|
||||
contextBridge.exposeInMainWorld('api', {
|
||||
readFile: (path: string) => ipcRenderer.invoke('fs:read', path),
|
||||
onUpdate: (cb: (v: string) => void) => {
|
||||
const listener = (_: unknown, v: string) => cb(v)
|
||||
ipcRenderer.on('app:update', listener)
|
||||
return () => ipcRenderer.removeListener('app:update', listener)
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### Main IPC handler with validation
|
||||
```typescript
|
||||
// main.ts
|
||||
import { ipcMain, app } from 'electron'
|
||||
import { promises as fs } from 'node:fs'
|
||||
import path from 'node:path'
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
ipcMain.handle('fs:read', async (_event, requested: string) => {
|
||||
const userData = app.getPath('userData')
|
||||
const resolved = path.resolve(userData, requested)
|
||||
if (!resolved.startsWith(userData)) throw new Error('path traversal')
|
||||
return await fs.readFile(resolved, 'utf-8')
|
||||
})
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### BrowserWindow secure defaults
|
||||
```typescript
|
||||
import { BrowserWindow } from 'electron'
|
||||
import path from 'node:path'
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
const win = new BrowserWindow({
|
||||
width: 1200,
|
||||
height: 800,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js'),
|
||||
contextIsolation: true,
|
||||
nodeIntegration: false,
|
||||
sandbox: true,
|
||||
webSecurity: true,
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
### Auto-updater (electron-updater)
|
||||
```typescript
|
||||
import { autoUpdater } from 'electron-updater'
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
autoUpdater.checkForUpdatesAndNotify()
|
||||
autoUpdater.on('update-downloaded', () => autoUpdater.quitAndInstall())
|
||||
```
|
||||
|
||||
### Utility process offload
|
||||
```typescript
|
||||
import { utilityProcess, MessageChannelMain } from 'electron'
|
||||
|
||||
const { port1, port2 } = new MessageChannelMain()
|
||||
const child = utilityProcess.fork(path.join(__dirname, 'worker.js'))
|
||||
child.postMessage({ task: 'transcode' }, [port2])
|
||||
port1.on('message', (msg) => console.log('result', msg))
|
||||
```
|
||||
|
||||
### Code signing build (electron-builder)
|
||||
```json
|
||||
{
|
||||
"build": {
|
||||
"appId": "com.example.app",
|
||||
"mac": { "hardenedRuntime": true, "gatekeeperAssess": false, "notarize": true },
|
||||
"win": { "signingHashAlgorithms": ["sha256"] },
|
||||
"asar": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| Cross-platform desktop, web team | Electron |
|
||||
| Bundle size critical (<50MB) | Tauri (Rust) 고려 |
|
||||
| Native feel mandatory | Native (Swift/Kotlin) |
|
||||
| Existing web app → wrap | Electron |
|
||||
| Mobile target 도 필요 | React Native / Flutter |
|
||||
|
||||
**기본값**: 매 Electron 33+ + contextIsolation + electron-builder + auto-updater.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Chromium]] · [[Nodejs]]
|
||||
- 변형: [[Tauri]] · [[NW.js]]
|
||||
- 응용: [[VS Code]] · [[Slack Desktop]]
|
||||
- Adjacent: [[Chrome DevTools(크롬 개발자 도구)]] · [[V8 엔진 힙 아키텍처]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: web stack 재사용, 빠른 cross-platform delivery, rich web-based UI 필요.
|
||||
**언제 X**: 매 100MB+ binary 가 unacceptable, 매 deep OS integration (kernel ext, system tray 만 의 limit), battery-critical mobile.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **nodeIntegration: true with remote content**: 매 RCE risk. 매 contextIsolation 강제.
|
||||
- **`require('electron').remote`**: deprecated, removed v14+. `@electron/remote` 도 안티 — IPC handle 로 교체.
|
||||
- **불특정 origin loadURL**: 매 untrusted web 을 BrowserWindow 에 load 하면 sandbox escape 위험.
|
||||
- **ASAR 만 의 protection**: ASAR 는 압축 일 뿐. Source 보호 의 X — 매 native module / 서버 side 로 logic 이동.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (electronjs.org docs, Electron 33 release notes 2026).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — Electron 33 process model + secure IPC patterns |
|
||||
|
||||
@@ -2,91 +2,203 @@
|
||||
id: wiki-2026-0508-escape-hatch-탈출구
|
||||
title: Escape Hatch (탈출구)
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-71F155]
|
||||
aliases: [React escape hatch, useRef escape hatch, useEffect escape hatch]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [react, hooks, useref, useeffect, framework-design]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Escape Hatch (탈출구)"
|
||||
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
|
||||
---
|
||||
|
||||
# [[Escape Hatch (탈출구)]]
|
||||
# Escape Hatch (탈출구)
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Escape Hatch(탈출구)는 SDK나 시스템 설계 시, 고수준의 추상화된 인터페이스(Facade)가 가지는 제약을 넘어 사용자가 세밀한 제어를 원할 때 활용할 수 있도록 제공하는 저수준(Low-level) API를 의미합니다 [1, 2]. 전체 사용 사례의 약 80%는 직관적인 고수준 인터페이스로 처리하고, 나머지 20%의 특수한 경우를 처리하기 위해 마련된 구조적 수단입니다 [1]. 이를 통해 편의성에만 안주하지 않고 세밀한 조작까지 가능한 설계적 균형을 유지할 수 있습니다 [2, 3].
|
||||
## 매 한 줄
|
||||
> **"매 framework 가 model 외의 reality 의 reach 매 escape hatch"**. React 의 escape hatch — useRef, useEffect, flushSync, ref callback 의 declarative model 외의 imperative DOM/non-React system 의 bridge. 매 2026 React 19 (Activity API, useOptimistic) 의 도입 매 escape hatch 의 사용 빈도 의 감소 but 매 여전히 essential.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **도입 목적 및 필요성:** SDK에 Facade 패턴을 적용해 복잡한 내부 로직을 숨기고 고수준의 인터페이스를 제공하면 사용자의 인지 부하를 줄일 수 있습니다 [4]. 그러나 추상화 수준이 높아질수록 특정 연결만 유지하거나 세부적인 제어가 필요한 특수 상황에서는 높은 추상화가 오히려 제약으로 다가올 수 있습니다 [1, 3]. 이러한 편의성의 단점을 보완하기 위해 언제든 저수준 인터페이스로 내려가 조작할 수 있도록 의도적으로 마련하는 것이 탈출구(Escape Hatch)입니다 [2].
|
||||
- **고수준과 저수준 인터페이스의 공존:** 좋은 SDK일수록 고수준과 저수준 인터페이스가 공존하도록 설계됩니다 [1]. 흔한 유즈케이스를 한 번에 끝내는 워크플로우(예: `start` 메서드)를 제공하는 동시에, 앱 브릿지(서버) 호출에 가까운 원자적인 저수준 호출(예: `open`, `send`, `listen`, `close` 등)을 탈출구로써 함께 제공해야 합니다 [1, 2].
|
||||
- **확장성 및 호환성 확보:** 저수준의 탈출구를 명확하게 제공하면, 편의성을 위해 고수준 메서드를 지속적으로 개선하더라도 저수준 메서드를 안정적으로 유지할 수 있어 하위 호환성 유지에 큰 도움이 됩니다 [2]. 이는 단기적인 개발자 경험(DX)을 개선할 뿐만 아니라, SDK의 장기적인 확장성과 호환성을 지켜주는 핵심적인 역할을 수행합니다 [1].
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 왜 필요
|
||||
- React model: declarative — UI = f(state).
|
||||
- 매 reality 매 imperative — DOM focus, video play, third-party (D3, Chart.js, Three.js), browser API (IntersectionObserver).
|
||||
- 매 escape hatch 의 controlled bridge 의 제공.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** Facade 패턴, Low-level 인터페이스, [[추상화(Abstraction)]]
|
||||
- **Projects/Contexts:** Toss Front SDK, AWS CDK
|
||||
- **Contradictions/Notes:** 소스에 따르면 추상화 수준이 높아질수록 세밀한 제어가 어려워진다는 필연적인 트레이드오프가 존재하지만, 20%의 특수 케이스를 위한 탈출구(Escape Hatch)를 제공함으로써 편의성과 유연성 사이의 이상적인 균형을 잡을 수 있다고 강조합니다 [1-3].
|
||||
### 매 React 의 4 hatch
|
||||
- **useRef**: 매 mutable container 매 re-render trigger 없음.
|
||||
- **useEffect**: 매 commit 후 의 side-effect — 매 subscription, manual DOM, external system.
|
||||
- **flushSync**: 매 sync update 의 force — 매 layout measurement before paint.
|
||||
- **ref callback**: 매 mount/unmount lifecycle 의 ref level access.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
### 매 응용
|
||||
1. Third-party library integration (D3, Three.js).
|
||||
2. Imperative DOM (focus, scroll, select).
|
||||
3. Subscription (WebSocket, EventSource).
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
### useRef Mutable Value
|
||||
```tsx
|
||||
function Stopwatch() {
|
||||
const intervalRef = useRef<number | null>(null)
|
||||
const [time, setTime] = useState(0)
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(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
|
||||
const start = () => {
|
||||
if (intervalRef.current) return
|
||||
intervalRef.current = window.setInterval(() => setTime((t) => t + 1), 1000)
|
||||
}
|
||||
const stop = () => {
|
||||
if (intervalRef.current) clearInterval(intervalRef.current)
|
||||
intervalRef.current = null
|
||||
}
|
||||
return <button onClick={start}>{time}</button>
|
||||
}
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### useRef DOM Reference
|
||||
```tsx
|
||||
function AutoFocus() {
|
||||
const inputRef = useRef<HTMLInputElement>(null)
|
||||
useEffect(() => {
|
||||
inputRef.current?.focus()
|
||||
}, [])
|
||||
return <input ref={inputRef} />
|
||||
}
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### useEffect External System
|
||||
```tsx
|
||||
function ChatRoom({ roomId }: { roomId: string }) {
|
||||
useEffect(() => {
|
||||
const conn = createConnection(roomId)
|
||||
conn.connect()
|
||||
return () => conn.disconnect() // 매 cleanup essential
|
||||
}, [roomId])
|
||||
return <h1>Welcome to {roomId}</h1>
|
||||
}
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Third-party Integration (Three.js)
|
||||
```tsx
|
||||
function ThreeScene() {
|
||||
const containerRef = useRef<HTMLDivElement>(null)
|
||||
useEffect(() => {
|
||||
const scene = new THREE.Scene()
|
||||
const camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000)
|
||||
const renderer = new THREE.WebGLRenderer()
|
||||
renderer.setSize(800, 600)
|
||||
containerRef.current?.appendChild(renderer.domElement)
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
let raf: number
|
||||
const animate = () => {
|
||||
raf = requestAnimationFrame(animate)
|
||||
renderer.render(scene, camera)
|
||||
}
|
||||
animate()
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
return () => {
|
||||
cancelAnimationFrame(raf)
|
||||
renderer.dispose()
|
||||
containerRef.current?.removeChild(renderer.domElement)
|
||||
}
|
||||
}, [])
|
||||
return <div ref={containerRef} />
|
||||
}
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### flushSync (force sync)
|
||||
```tsx
|
||||
import { flushSync } from "react-dom"
|
||||
|
||||
function ScrollToBottom() {
|
||||
const [items, setItems] = useState<string[]>([])
|
||||
const listRef = useRef<HTMLUListElement>(null)
|
||||
|
||||
const addItem = (text: string) => {
|
||||
flushSync(() => {
|
||||
setItems((prev) => [...prev, text])
|
||||
})
|
||||
// 매 flushSync 후 매 DOM 매 updated 의 guaranteed
|
||||
listRef.current?.scrollTo(0, listRef.current.scrollHeight)
|
||||
}
|
||||
return (/* ... */)
|
||||
}
|
||||
```
|
||||
|
||||
### Ref Callback (mount/unmount)
|
||||
```tsx
|
||||
function ObservedItem({ onVisible }: { onVisible: () => void }) {
|
||||
const refCallback = useCallback((node: HTMLDivElement | null) => {
|
||||
if (!node) return
|
||||
const obs = new IntersectionObserver(([entry]) => {
|
||||
if (entry.isIntersecting) onVisible()
|
||||
})
|
||||
obs.observe(node)
|
||||
return () => obs.disconnect() // React 19+ cleanup
|
||||
}, [onVisible])
|
||||
return <div ref={refCallback}>Observed</div>
|
||||
}
|
||||
```
|
||||
|
||||
### useImperativeHandle (parent 의 controlled API)
|
||||
```tsx
|
||||
type ModalHandle = { open: () => void; close: () => void }
|
||||
|
||||
const Modal = forwardRef<ModalHandle>((_, ref) => {
|
||||
const [open, setOpen] = useState(false)
|
||||
useImperativeHandle(ref, () => ({
|
||||
open: () => setOpen(true),
|
||||
close: () => setOpen(false),
|
||||
}), [])
|
||||
return open ? <div>Modal</div> : null
|
||||
})
|
||||
|
||||
function App() {
|
||||
const modalRef = useRef<ModalHandle>(null)
|
||||
return <button onClick={() => modalRef.current?.open()}>Open</button>
|
||||
}
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Hatch |
|
||||
|---|---|
|
||||
| Mutable value 매 no re-render | useRef |
|
||||
| DOM focus/scroll | useRef + useEffect |
|
||||
| External lib (D3/Three.js) | useEffect |
|
||||
| Sync DOM measurement | flushSync |
|
||||
| Mount/unmount lifecycle | ref callback |
|
||||
| Parent imperative API | useImperativeHandle |
|
||||
|
||||
**기본값**: 매 declarative 매 first — 매 hatch 매 last resort.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[React]] · [[React Hooks]]
|
||||
- 변형: [[Vue Composition API]] · [[Solid Signals]]
|
||||
- 응용: [[Three.js Integration]] · [[D3 Integration]] · [[IntersectionObserver]]
|
||||
- Adjacent: [[useEffect]] · [[useRef]] · [[useImperativeHandle]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 third-party imperative library 의 React 의 integration, DOM 의 manual control.
|
||||
**언제 X**: 매 pure UI state — 매 useState/useReducer 의 사용.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **useRef 매 derived state**: 매 useState 또는 useMemo 매 사용.
|
||||
- **useEffect 매 data fetch (cascading)**: 매 React Query / RSC 매 사용.
|
||||
- **Stale ref read in render**: 매 ref.current 의 render 의 read 매 X.
|
||||
- **Cleanup 의 omit**: 매 memory leak — 매 return 매 always.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (React 공식 docs "Escape Hatches" chapter, React 19 — 2026).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — React 19 escape hatch 4종 + 패턴 작성 |
|
||||
|
||||
@@ -2,91 +2,120 @@
|
||||
id: wiki-2026-0508-flame-chart
|
||||
title: Flame Chart
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-41DF27]
|
||||
aliases: [Flame Graph, 플레임 차트]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [profiling, performance, devtools, visualization]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Flame Chart"
|
||||
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: JavaScript
|
||||
framework: Chrome DevTools
|
||||
---
|
||||
|
||||
# [[Flame Chart]]
|
||||
# Flame Chart
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> 플레임 차트(Flame Chart)는 [[Chrome DevTools]]의 Performance 패널에서 메인 스레드의 활동을 시간에 따라 시각적으로 보여주는 도구입니다 [1, 2]. X축은 기록된 시간을 나타내며 막대가 넓을수록 이벤트 실행에 긴 시간이 소요되었음을 의미하고, Y축은 콜 스택([[Call Stack]])을 나타냅니다 [1, 2]. 이를 통해 개발자는 성능 병목 현상을 파악하고 자바스크립트 함수 호출의 인과 관계 및 장기 실행 작업([[Long Tasks]])을 분석할 수 있습니다 [1-3].
|
||||
## 매 한 줄
|
||||
> **"매 시간축 stack frame 의 visual profile — width=duration, depth=call stack"**. Brendan Gregg (2013) 의 flame graph 매 origin. 2026 시점 Chrome DevTools Performance panel · Node `--prof` · Linux `perf` · Speedscope 매 standard tooling.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **차트의 구조:** 플레임 차트에서 상단에 위치한 이벤트는 하단에 있는 이벤트를 발생시킨 원인(호출자)을 의미합니다 [1, 2]. 브라우저가 작업을 수행하도록 원인을 제공하는 '루트 활동(Root activities)'은 플레임 차트의 가장 맨 위에 표시됩니다 [4].
|
||||
- **시각적 구분:** 차트의 가독성을 높이기 위해 스크립트마다 무작위로 색상이 지정됩니다 [2]. 일반적으로 어두운 노란색은 스크립팅 활동을, 보라색은 렌더링 활동을 나타냅니다 [2]. 특히 작업 시간이 긴 작업(Long tasks)은 빨간색 삼각형으로 강조 표시되며, 50밀리초를 넘긴 구간은 차트에서 빨간색으로 음영 처리되어 성능 저하의 원인을 직관적으로 식별할 수 있습니다 [1, 3].
|
||||
- **차트 제어 및 디버깅:** 사용자는 플레임 차트를 깔끔하게 정리하기 위해 특정 함수나 그 하위 항목을 숨길 수 있으며, 관련 없는 스크립트를 무시 목록(Ignore list)에 추가하여 차트에서 제외할 수 있습니다 [5-7]. 또한 자바스크립트 샘플링([[JavaScript]] samples)을 비활성화하면 상세한 자바스크립트 콜 스택 정보가 생략되고, 대신 `Event (click)`나 `Function Call`과 같은 상위 수준의 이벤트만 플레임 차트에 짧게 표시됩니다 [3, 8].
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 Flame Chart vs Flame Graph
|
||||
- **Flame Chart**: x축 = 매 wall-clock time (left→right chronological). DevTools default.
|
||||
- **Flame Graph**: x축 = 매 aggregated time (alphabetical), 매 hot path 발견.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[Chrome DevTools]], [[Call Stack]], [[Main Thread]], [[Long Tasks]]
|
||||
- **Projects/Contexts:** [[Performance Panel]], [[Analyze runtime performance]]
|
||||
- **Contradictions/Notes:** 소스 내에서 플레임 차트의 기능이나 정의와 관련하여 상충되는 정보는 없습니다.
|
||||
### 매 reading rules
|
||||
- 매 wide bar = 매 long-running function.
|
||||
- 매 tall stack = 매 deep call chain (recursion · over-abstraction signal).
|
||||
- 매 plateau = 매 single function dominate.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
### 매 응용
|
||||
1. JS main-thread bottleneck 식별.
|
||||
2. React render 의 expensive component 추적.
|
||||
3. Backend RPC handler latency 분해.
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
### Chrome DevTools 캡처
|
||||
```js
|
||||
// 1. DevTools → Performance → Record
|
||||
// 2. Reproduce slow interaction
|
||||
// 3. Stop → bottom-up / call tree / flame chart 탭
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(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
|
||||
// Programmatic mark
|
||||
performance.mark("render-start")
|
||||
expensiveRender()
|
||||
performance.mark("render-end")
|
||||
performance.measure("render", "render-start", "render-end")
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### Node.js CPU profile
|
||||
```bash
|
||||
node --cpu-prof --cpu-prof-dir=./profiles app.js
|
||||
# .cpuprofile 의 Chrome DevTools "Performance" 탭에 drag-drop
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### 0x flame graph 생성
|
||||
```bash
|
||||
npx 0x -o server.js
|
||||
# HTML 매 자동 open — interactive flame graph
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### React Profiler API
|
||||
```tsx
|
||||
import { Profiler } from "react"
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
function onRender(id, phase, actualDuration) {
|
||||
if (actualDuration > 16) console.warn(`slow ${id}: ${actualDuration}ms`)
|
||||
}
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
<Profiler id="UserList" onRender={onRender}>
|
||||
<UserList />
|
||||
</Profiler>
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### Speedscope (universal viewer)
|
||||
```bash
|
||||
# Node, Chrome, py-spy, perf 매 모두 import
|
||||
npx speedscope profile.cpuprofile
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| Browser frontend lag | Chrome DevTools Performance |
|
||||
| Node server CPU spike | `--cpu-prof` + DevTools |
|
||||
| Production hot-path discovery | Flame **graph** (aggregated) |
|
||||
| Specific user interaction | Flame **chart** (chronological) |
|
||||
|
||||
**기본값**: Chrome DevTools Performance panel — 매 60% case cover.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Performance Profiling]] · [[Chrome DevTools(크롬 개발자 도구)]]
|
||||
- 변형: [[할당 타임라인(Allocation Timeline)]]
|
||||
- 응용: [[Nodejs 성능 디버깅]] · [[SPA 라우트 전환 성능 최적화]]
|
||||
- Adjacent: [[Cumulative Layout Shift (CLS)]] · [[Google Lighthouse]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 latency / jank / unknown bottleneck 발견 → flame chart 의 first tool.
|
||||
**언제 X**: 매 memory leak (heap snapshot 사용) · 매 network waterfall (Network panel).
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Optimize the wide-but-shallow bar**: 매 actually unimportant 일 수 있음 — call tree로 cross-check.
|
||||
- **Sampling rate 신뢰**: 매 short bursts (<1ms) 의 missed — `performance.mark` precise.
|
||||
- **Production 에서 always-on profiling**: 매 overhead — sampling profiler (e.g. `pprof`) 만 OK.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Brendan Gregg flame graph paper · Chrome DevTools docs 2026).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — DevTools/0x/Speedscope tooling 매 설명 |
|
||||
|
||||
@@ -2,92 +2,153 @@
|
||||
id: wiki-2026-0508-fuzzing
|
||||
title: Fuzzing
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-CE0886]
|
||||
aliases: [Fuzz Testing, Coverage-Guided Fuzzing]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [security, testing, dast]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Fuzzing"
|
||||
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: C/Rust/Go
|
||||
framework: AFL++/libFuzzer/cargo-fuzz
|
||||
---
|
||||
|
||||
# [[Fuzzing]]
|
||||
# Fuzzing
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> 퍼징(Fuzzing)은 애플리케이션에 스트레스를 가해 예상치 못한 동작, 프로그램 충돌(크래시) 또는 리소스 누수를 유발함으로써 소프트웨어의 취약점을 찾아내는 동적 애플리케이션 보안 테스트(DAST) 기법입니다 [1]. 소스에 관련 정보가 부족합니다.
|
||||
## 매 한 줄
|
||||
> **"매 random/mutated input 으로 crash, hang, UB 의 hunt"**. 매 1988 Miller (Wisconsin) 의 random input shell experiment 가 origin. 2026 현재 매 coverage-guided (AFL++, libFuzzer, Honggfuzz), structure-aware (libprotobuf-mutator), grammar-based (Nautilus), LLM-augmented (OSS-Fuzz Gen) 가 mainstream. Google OSS-Fuzz 가 100K+ bug 발견, Chrome/Linux kernel/OpenSSL 의 routine workflow.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **DAST의 일환:** 퍼징은 실행 중인 애플리케이션을 테스트하는 동적 애플리케이션 보안 테스트(DAST) 방법 중 하나로 분류됩니다 [1].
|
||||
- **스트레스 테스트:** 애플리케이션에 의도적으로 스트레스를 주어 예상치 못한 동작이나 시스템 크래시, 그리고 리소스 누수(resource leaks) 등을 유발하도록 작동합니다 [1].
|
||||
- **취약점 이해 도모:** 이러한 과정을 통해 개발자는 애플리케이션의 런타임 동작 방식과 내재된 취약점들을 보다 포괄적이고 종합적으로 이해할 수 있게 됩니다 [1].
|
||||
- 소스에 관련 정보가 부족합니다.
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 fuzzing categories
|
||||
- **Black-box (dumb)**: random input, no instrumentation. 매 zzuf, radamsa.
|
||||
- **Coverage-guided (grey-box)**: input 의 mutation + branch coverage feedback. 매 AFL++, libFuzzer, Honggfuzz.
|
||||
- **White-box (concolic)**: symbolic execution + solver. 매 KLEE, SAGE.
|
||||
- **Structure-aware**: protobuf, JSON 의 grammar 의 valid input. 매 libprotobuf-mutator, FuzzGrammar.
|
||||
- **Differential**: 매 동일 input 을 두 implementation 에 → divergence 의 bug.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** DAST, Vulnerabilities
|
||||
- **Projects/Contexts:** 애플리케이션의 동작 및 취약점을 포괄적으로 이해하기 위한 소프트웨어 보안 테스트 컨텍스트에서 활용됩니다 [1].
|
||||
- **Contradictions/Notes:** 소스에 관련 정보가 부족합니다.
|
||||
### 매 sanitizers
|
||||
- ASan (heap/stack OOB, UAF), UBSan (UB), MSan (uninit read), TSan (data race), LSan (leak).
|
||||
- 매 fuzzing 의 corpus 는 sanitizer 와 함께 build 의 mandatory.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
### 매 응용
|
||||
1. Memory-safety bug discovery (C/C++ codebases).
|
||||
2. Parser hardening (image, video, network protocols).
|
||||
3. Browser engine (V8 fuzzilli, JSC fuzzer).
|
||||
4. Crypto library (OpenSSL, BoringSSL via OSS-Fuzz).
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
### libFuzzer (C++)
|
||||
```cpp
|
||||
// fuzz_target.cc — clang -fsanitize=fuzzer,address fuzz_target.cc parser.cc
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "parser.h"
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(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
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
if (size < 4) return 0;
|
||||
Parser p;
|
||||
p.Parse(reinterpret_cast<const char*>(data), size); // ASan catches OOB/UAF
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### cargo-fuzz (Rust)
|
||||
```rust
|
||||
// fuzz/fuzz_targets/parse.rs
|
||||
#![no_main]
|
||||
use libfuzzer_sys::fuzz_target;
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
if let Ok(s) = std::str::from_utf8(data) {
|
||||
let _ = mycrate::parse(s); // panics 는 fuzz crash 로 catch
|
||||
}
|
||||
});
|
||||
```
|
||||
```bash
|
||||
cargo fuzz run parse -- -max_total_time=600
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Go native fuzzing (1.18+)
|
||||
```go
|
||||
func FuzzParseURL(f *testing.F) {
|
||||
f.Add("http://example.com")
|
||||
f.Fuzz(func(t *testing.T, s string) {
|
||||
u, err := url.Parse(s)
|
||||
if err == nil && u.String() != s && url.QueryEscape(u.String()) == "" {
|
||||
t.Errorf("roundtrip mismatch: %q", s)
|
||||
}
|
||||
})
|
||||
}
|
||||
```
|
||||
```bash
|
||||
go test -fuzz=FuzzParseURL -fuzztime=10m
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### AFL++ (compile-time instrumentation)
|
||||
```bash
|
||||
CC=afl-clang-fast CXX=afl-clang-fast++ ./configure
|
||||
make -j8
|
||||
mkdir in; echo "seed" > in/0
|
||||
afl-fuzz -i in -o out -- ./target @@
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
### Structure-aware (libprotobuf-mutator)
|
||||
```cpp
|
||||
DEFINE_PROTO_FUZZER(const my::Message& msg) {
|
||||
HandleMessage(msg); // valid proto guaranteed → deeper coverage
|
||||
}
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### OSS-Fuzz integration
|
||||
```dockerfile
|
||||
FROM gcr.io/oss-fuzz-base/base-builder
|
||||
RUN apt-get install -y libssl-dev
|
||||
COPY . $SRC/myproject
|
||||
COPY build.sh $SRC/
|
||||
WORKDIR $SRC/myproject
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| C/C++ memory bug hunt | libFuzzer + ASan/UBSan |
|
||||
| Rust panic / logic bug | cargo-fuzz |
|
||||
| Network protocol parser | AFL++ + structure-aware mutator |
|
||||
| Two implementations comparison | Differential fuzzing |
|
||||
| Continuous (open-source) | OSS-Fuzz |
|
||||
| Grammar-rich (JS, SQL) | Grammar-based (Nautilus, fuzzilli) |
|
||||
|
||||
**기본값**: 매 coverage-guided (libFuzzer/AFL++) + ASan + corpus minimization + CI 에 5min smoke.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[DAST (동적 애플리케이션 보안 테스트)]]
|
||||
- 변형: [[SCA (소프트웨어 구성 분석)]]
|
||||
- 응용: [[OSS-Fuzz]] · [[V8 엔진 힙 아키텍처]]
|
||||
- Adjacent: [[Symbolic Execution]] · [[Property-Based Testing]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 untrusted input 의 parser, codec, deserializer 가 있는 경우. 매 security-critical library 의 release 전 mandatory.
|
||||
**언제 X**: pure functional code 의 deterministic 한 input space (property-based testing 이 더 적절). 매 GUI / network state-heavy code.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Sanitizer 없이 fuzz**: 매 silent corruption 을 miss. 매 ASan 의 mandatory.
|
||||
- **Seed corpus 없음**: 매 coverage 의 plateau 가 빠름. 매 valid sample 10-100 개 의 seed.
|
||||
- **CI 에 30s 만 fuzz**: 매 너무 짧음. 매 minimum 10min, ideal continuous (OSS-Fuzz pattern).
|
||||
- **Crash 만 의 focus**: 매 hang, OOM, slow input 도 bug. 매 timeout / rss_limit 설정.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Miller 1990 "Empirical Study of Reliability of UNIX Utilities"; AFL++ docs; OSS-Fuzz reports).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — coverage-guided + sanitizers + OSS-Fuzz |
|
||||
|
||||
@@ -2,91 +2,173 @@
|
||||
id: wiki-2026-0508-gc-root
|
||||
title: GC Root
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-31335C]
|
||||
aliases: [Garbage Collection Root, GC 루트, Root Set]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [gc, jvm, memory, runtime]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - GC Root"
|
||||
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: Java/Kotlin
|
||||
framework: JVM/HotSpot/ZGC
|
||||
---
|
||||
|
||||
# [[GC Root]]
|
||||
# GC Root
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> GC Root(가비지 컬렉션 루트)는 가비지 컬렉터가 메모리 내에서 사용 중인 살아있는(live) 객체를 식별하기 위해 참조 추적을 시작하는 기준점 역할을 하는 객체입니다 [1-3]. 힙(heap) 외부에서 접근할 수 있는 객체로서 기본적으로 살아있는 것으로 정의되며, 힙 내부의 다른 객체들이 메모리 회수 대상에서 제외되려면 반드시 이 루트 객체로부터 시작되는 포인터 체인을 통해 도달 가능(reachable)하게 연결되어 있어야 합니다 [1, 2, 4].
|
||||
## 매 한 줄
|
||||
> **"매 도달 가능성(reachability) 의 출발점"**. GC Root 는 garbage collector 가 live object 를 판별하기 위해 traversal 을 시작하는 reference set. 매 root 에서 도달 불가능한 object 는 collectible 로 marking 된다. JVM, .NET CLR, V8, Go runtime 모두 같은 개념을 공유한다.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **GC 루트의 정의와 주요 종류:** GC 루트는 V8 자바스크립트 엔진이나 웹 브라우저, 자바 가상 머신(VM) 외부에서 직접 가리키는 객체들을 의미합니다 [1]. 주요 종류로는 호출 스택(stack)에 존재하는 로컬 변수, 항상 접근이 가능한 전역 객체(Global objects), 클래스 정적 필드(class static field), JNI 참조, 그리고 브라우저의 DOM 요소 등이 있습니다 [1, 2]. 웹 브라우저 환경의 메모리 누수와 관련하여 창(window), 활성 클로저(active closures), 이벤트 리스너, 타이머 등도 루트 역할을 하여 연관된 객체들이 메모리에서 해제되는 것을 방지합니다 [5].
|
||||
- **마킹 및 추적 과정(Marking and Tracing):** [[Mark-Sweep]] 알고리즘 등에서 살아있는 객체를 찾는 과정은 루트 세트(root set)에서 출발합니다 [3]. 가비지 컬렉터의 초기 단계에서 루트 스캔을 실행하여 모든 루트 객체를 식별하고, 이를 처리를 위한 작업 스택(work stack)에 푸시합니다 [2]. 그런 다음 GC는 루트 객체에서 시작해 다른 객체를 가리키는 모든 포인터를 재귀적으로 추적하여 도달 가능한 객체들을 마킹(Mark)합니다 [2, 3]. 루트로부터 도달할 수 없는 나머지 모든 것들은 가비지로 간주됩니다 [4, 6].
|
||||
- **마이너 GC를 위한 특수 루트(V8 [[Scavenge]]r):** V8 엔진의 젊은 세대(young generation)를 수집하는 마이너 GC(Scavenger)의 경우, GC가 실행될 때마다 전체 구세대(old generation) 힙을 모두 스캔하는 비효율을 피하기 위해 쓰기 장벽([[Write Barrier]]s)을 활용합니다 [7]. 이를 통해 구세대에서 젊은 세대로 향하는 참조(old-to-new [[Reference]]s) 목록을 유지하며, 이를 스택 및 전역 변수 등과 결합하여 젊은 세대 가비지 컬렉션을 위한 추가적인 루트 세트로 사용합니다 [7].
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 GC Root 종류 (HotSpot 기준)
|
||||
- **Stack reference**: 매 thread 의 local variable / parameter / operand stack.
|
||||
- **Static field**: 매 loaded class 의 static reference.
|
||||
- **JNI local/global**: 매 native code 가 hold 한 reference.
|
||||
- **Active thread**: 매 살아있는 `Thread` object 자체.
|
||||
- **Class metadata**: 매 ClassLoader, Class object (Metaspace).
|
||||
- **Synchronization monitor**: 매 `synchronized` 로 lock 된 object.
|
||||
- **Weak/Soft/Phantom 제외**: 매 reachability 약한 reference 는 root 가 아님.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[Garbage Collection]], Mark-Sweep Algorithm, [[memory]] Leak, Reachability
|
||||
- **Projects/Contexts:** [[V8 Engine]], IBM SDK Java Technology
|
||||
- **Contradictions/Notes:** 소스에 따르면 V8 엔진([[JavaScript]])과 IBM Java 구현 모두 GC 루트를 통한 참조 추적이라는 핵심 원리를 공유하고 있습니다. 다만 실행 환경의 차이에 따라 V8은 DOM 요소나 클로저 등을 주로 다루고 [1, 5], Java는 JNI 참조나 클래스 정적 필드 등을 다룬다는 세부적인 특성의 차이를 보입니다 [2].
|
||||
### 매 Reachability tier
|
||||
1. **Strongly reachable**: root 에서 strong ref 만으로 도달 → never collected.
|
||||
2. **Softly reachable**: SoftReference 로만 도달 → 매 memory pressure 시 collect.
|
||||
3. **Weakly reachable**: WeakReference 만 → 매 next GC cycle 에 collect.
|
||||
4. **Phantom reachable**: PhantomReference → enqueue 후 cleaning.
|
||||
5. **Unreachable**: → collectible.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
### 매 응용
|
||||
1. **Memory leak 진단** (heap dump → root path 추적).
|
||||
2. **Escape analysis** (root 도달 안 되는 local → stack alloc).
|
||||
3. **Concurrent GC 의 root scanning** (ZGC, Shenandoah, G1 의 phase 1).
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
### 1. Heap dump 에서 root path 찾기 (Eclipse MAT / jhat)
|
||||
```bash
|
||||
# JVM heap dump 생성
|
||||
jcmd <pid> GC.heap_dump /tmp/heap.hprof
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(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
|
||||
# Eclipse MAT CLI 로 leak suspects 분석
|
||||
./MemoryAnalyzer -consoleLog -application org.eclipse.mat.api.parse \
|
||||
/tmp/heap.hprof org.eclipse.mat.api:suspects
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### 2. JFR 로 GC root 통계 수집 (JDK 21+)
|
||||
```bash
|
||||
java -XX:StartFlightRecording=duration=60s,filename=app.jfr,settings=profile \
|
||||
-XX:+UseZGC -Xmx4g -jar app.jar
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
jfr print --events GarbageCollection,GCReferenceStatistics app.jfr
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### 3. WeakReference 로 root 진입 회피
|
||||
```java
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
// Cache 가 GC root 가 되어 leak 발생하는 anti-pattern 회피
|
||||
public class Cache<K, V> {
|
||||
private final WeakHashMap<K, V> map = new WeakHashMap<>();
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
public void put(K key, V value) { map.put(key, value); }
|
||||
public V get(K key) { return map.get(key); }
|
||||
// key 가 외부에서 strong ref 사라지면 entry 자동 제거
|
||||
}
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### 4. ThreadLocal leak 회피 (매 typical root leak)
|
||||
```java
|
||||
public class RequestContext {
|
||||
private static final ThreadLocal<UserSession> CTX = new ThreadLocal<>();
|
||||
|
||||
public static void set(UserSession s) { CTX.set(s); }
|
||||
public static UserSession get() { return CTX.get(); }
|
||||
|
||||
// 매 critical: thread pool 환경에서 반드시 remove() 호출
|
||||
public static void clear() { CTX.remove(); }
|
||||
}
|
||||
|
||||
// Servlet filter 에서:
|
||||
try {
|
||||
RequestContext.set(session);
|
||||
chain.doFilter(req, res);
|
||||
} finally {
|
||||
RequestContext.clear(); // 매 root reference 끊기
|
||||
}
|
||||
```
|
||||
|
||||
### 5. JNI global ref 정리 (native code 가 GC root)
|
||||
```c
|
||||
// JNI: global ref 는 명시적으로 free 해야 함
|
||||
jobject globalRef = (*env)->NewGlobalRef(env, localObj);
|
||||
// ... 사용 ...
|
||||
(*env)->DeleteGlobalRef(env, globalRef); // 매 빠뜨리면 영구 leak
|
||||
```
|
||||
|
||||
### 6. Static field 로 의도된 long-lived root
|
||||
```kotlin
|
||||
object AppMetrics { // 매 Kotlin object → static singleton → GC root
|
||||
private val counter = AtomicLong(0)
|
||||
fun increment() = counter.incrementAndGet()
|
||||
fun snapshot() = counter.get()
|
||||
}
|
||||
```
|
||||
|
||||
### 7. ZGC / Shenandoah concurrent root scanning 활성화
|
||||
```bash
|
||||
# JDK 21+: ZGC generational
|
||||
java -XX:+UseZGC -XX:+ZGenerational \
|
||||
-XX:SoftMaxHeapSize=8g -Xmx16g -jar app.jar
|
||||
|
||||
# Shenandoah
|
||||
java -XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational -jar app.jar
|
||||
```
|
||||
|
||||
### 8. Async profiler 로 allocation root 찾기
|
||||
```bash
|
||||
./profiler.sh -e alloc -d 60 -f alloc.html <pid>
|
||||
# 매 flamegraph 에서 root → leaking site path 시각화
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| Long-lived cache | `WeakHashMap` / Caffeine `weakKeys()` |
|
||||
| Per-request state in pool | `ThreadLocal` + `try/finally remove()` |
|
||||
| Native handle wrapping | `Cleaner` (java.lang.ref.Cleaner, JDK 9+) |
|
||||
| Listener registration | `WeakReference` 로 listener wrap |
|
||||
| 매 short-lived burst alloc | 매 그냥 strong ref + young gen 의존 |
|
||||
|
||||
**기본값**: 매 strong ref + escape analysis 신뢰. WeakReference 는 매 진짜 leak 패턴 (cache, listener, ThreadLocal in pool) 에만.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Garbage Collection]] · [[JVM Memory Model]]
|
||||
- 변형: [[ZGC]] · [[G1 GC]] · [[Shenandoah]]
|
||||
- 응용: [[Memory Leak Detection]] · [[Heap Dump Analysis]]
|
||||
- Adjacent: [[Reference Types]] · [[Escape Analysis]] · [[ThreadLocal]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: heap dump 의 leak suspect 해석, root path 의 의미 설명, ThreadLocal/static leak pattern detection.
|
||||
**언제 X**: 매 production 의 실제 GC tuning (real profiling 데이터 없이 추측 X).
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Static collection 무한 grow**: `static List` 에 매 add 만 하고 remove 안 함 → 영구 root.
|
||||
- **ThreadLocal in pool no remove**: 매 thread 재사용 시 이전 request data 가 root 로 남음.
|
||||
- **JNI GlobalRef leak**: native 에서 `DeleteGlobalRef` 누락.
|
||||
- **Anonymous inner class capture**: `new Runnable() {}` 가 outer `this` 를 capture → outer 가 root 에 매달림.
|
||||
- **Listener 등록 후 unregister 안 함**: 매 EventBus, Observer 패턴의 classic leak.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (OpenJDK HotSpot source, JEP 376/439, Eclipse MAT docs).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — GC root taxonomy + leak 진단 패턴 |
|
||||
|
||||
@@ -2,110 +2,30 @@
|
||||
id: wiki-2026-0508-garbage-collection-가비지-컬렉션
|
||||
title: Garbage Collection(가비지 컬렉션)
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-CA2F39]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: wiki-2026-0508-garbage-collection
|
||||
duplicate_of: "[[Garbage Collection (가비지 컬렉션)]]"
|
||||
aliases: [GC]
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - [[Garbage Collection]](가비지 컬렉션)"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, gc, memory]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[Garbage Collection(가비지 컬렉션)]]
|
||||
# Garbage Collection(가비지 컬렉션)
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> 가비지 컬렉션(Garbage Collection)은 애플리케이션의 메모리 고갈을 방지하기 위해 더 이상 필요하지 않거나 도달할 수 없는 객체가 차지한 메모리를 자동으로 식별하여 회수하는 프로세스입니다 [1-3]. 이 기술은 프로그래머가 직접 메모리를 관리하는 부담을 덜어주고 메모리 누수와 같은 오류를 줄여주지만, 메모리 정리 작업 중 애플리케이션 실행이 멈추는 '[[Stop-the-world]]' 지연을 발생시킬 수 있습니다 [2, 4, 5]. 현대의 가비지 컬렉터들은 이러한 지연 시간을 최소화하기 위해 세대별 힙 구조(Generational Layout)와 병렬 및 동시 처리 알고리즘을 도입하여 성능을 최적화하고 있습니다 [6-8].
|
||||
> **이 문서는 [[Garbage Collection (가비지 컬렉션)]] 의 중복본입니다.** (parenthesis spacing 만 의 차이) Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **생존 객체 식별 원리 (Discovering Reachability)**
|
||||
가비지 컬렉터가 해결해야 할 핵심 문제는 죽은 메모리 영역을 식별하는 것입니다 [1]. 객체의 미래 접근 여부를 완벽히 예측하는 것은 정지 문제(Halting Problem)와 같아 불가능하므로, GC는 스택의 로컬 변수나 글로벌 객체와 같은 '루트(Root) 객체'부터 시작하여 포인터 체인을 통해 도달할 수 있는 객체만을 '생존(Live)' 상태로 근사하여 판단하고, 도달 불가능한 모든 객체를 '가비지(Garbage)'로 간주합니다 [1, 9, 10].
|
||||
## 핵심 요약
|
||||
- Title 의 spacing variant — 매 canonical 의 [[Garbage Collection (가비지 컬렉션)]].
|
||||
|
||||
- **세대별 가설과 힙 메모리 구조 (Generational Collection & Heap Organization)**
|
||||
대부분의 객체는 생성 후 얼마 지나지 않아 죽는다는 '세대별 가설([[Generational Hypothesis]])'을 기반으로, V8과 같은 엔진은 힙 메모리를 세대별로 나누어 관리합니다 [6, 11, 12].
|
||||
* **New Space (Young Generation):** 대부분의 새 객체가 할당되는 작고 빠른 공간입니다 [6, 13]. 주기적으로 마이너 가비지 컬렉션이 빠르게 수행됩니다 [6].
|
||||
* **[[Old Space]] (Old Generation):** New Space에서 수행된 가비지 컬렉션을 두 번 살아남은 객체들이 승격(Promotion)되어 이동하는 공간입니다 [6, 14, 15].
|
||||
## 🔗 Graph
|
||||
- 부모: [[Garbage Collection (가비지 컬렉션)]] (canonical)
|
||||
|
||||
- **마이너 가비지 컬렉션 ([[Scavenge]]r)**
|
||||
Young Generation을 관리하는 고속 알고리즘입니다 [16, 17]. New Space를 'To-Space'와 'From-Space'라는 동일한 크기의 두 반공간(Semi-space)으로 분할하는 Cheney의 알고리즘(Scavenge)을 사용합니다 [16, 18]. 할당 공간이 가득 차면, 활성 객체를 추적하여 빈 공간(To-Space)이나 Old Space로 대피(Evacuate)시키면서 메모리를 압축합니다 [18, 19]. 이후 남은 From-Space의 쓰레기 데이터를 한 번에 비우고 두 공간의 역할을 바꿉니다 [18, 19].
|
||||
|
||||
- **메이저 가비지 컬렉션 ([[Mark-Sweep]]-Compact)**
|
||||
수백 메가바이트의 데이터를 포함할 수 있는 Old Space를 관리하기 위해 메이저 GC는 주로 세 가지 단계를 거칩니다 [20, 21].
|
||||
* **Marking (표시):** 깊이 우선 탐색(DFS)을 통해 힙 내의 활성 객체를 발견합니다 [22]. 객체를 흰색(미발견), 회색(발견되었으나 이웃 객체 미처리), 검은색(발견 및 이웃 처리 완료)의 3색 마킹 상태로 분류하여 추적합니다 [23, 24].
|
||||
* **Sweeping (쓸기):** 마킹되지 않은 죽은 객체의 연속된 메모리 범위를 스캔하여 Free list(여유 공간)로 변환하여 후속 할당에 대비합니다 [24-26].
|
||||
* **Compacting (압축):** 메모리 단편화(Fragmentation)를 줄이기 위해 생존 객체들을 빈 공간으로 마이그레이션합니다 [24, 27, 28]. 이는 비용이 많이 드는 작업이지만 실제 메모리 사용량을 대폭 줄여줍니다 [27, 29].
|
||||
|
||||
- **현대 GC의 성능 최적화 ([[Orinoco]] 등)**
|
||||
수백 밀리초에 달하던 과거의 'Stop-the-world' 일시 정지 현상을 줄이기 위해 현대적인 GC는 다양한 기법을 동원합니다 [30, 31].
|
||||
* **Parallel (병렬 처리):** 메인 스레드와 여러 보조 스레드가 GC 작업을 동시에 분담하여 총 정지 시간을 줄입니다 [32, 33].
|
||||
* **Incremental (점진적 처리):** 자바스크립트 실행 중간중간에 작은 단위로 GC 작업을 번갈아 수행(Interleaving)하여 응답성을 유지합니다 [30, 32, 34].
|
||||
* **Concurrent (동시 처리):** 메인 스레드가 자바스크립트를 계속 실행하는 동안 보조 스레드들이 백그라운드에서 전적으로 Marking 및 Sweeping 작업을 수행합니다 [7, 32, 35].
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[Mark-Sweep]], Scavenger, [[Stop-the-world]], [[Generational Hypothesis]], [[memory]] Leak
|
||||
- **Projects/Contexts:** [[V8 [[JavaScript]] Engine]], IBM E[[CLIP]]se OpenJ9, Orinoco Garbage Collector
|
||||
- **Contradictions/Notes:** 가비지 컬렉션은 메모리 누수를 대폭 줄여주지만, 프로그래머가 메모리 관리에 대한 전적인 통제권을 잃는다는 단점이 존재합니다(모바일 앱 등에서는 큰 문제점) [4, 5]. 또한 대안으로 거론되는 레퍼런스 카운팅([[Reference]] Counting) 방식 역시 대규모 객체 그래프의 마지막 참조가 제거될 때 가비지 컬렉션과 유사한 예측 불가능한 정지 현상을 유발할 수 있어 완벽한 대체재는 아닙니다 [5].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -1,25 +1,34 @@
|
||||
---
|
||||
id: wiki-20260508-generational-hypothesis-redir
|
||||
title: Generational Hypothesis
|
||||
category: Programming & Language
|
||||
status: merged
|
||||
redirect_to: Generational_Hypothesis
|
||||
canonical_id: Generational_Hypothesis
|
||||
aliases: []
|
||||
duplicate_of: none
|
||||
category: 10_Wiki/Topics
|
||||
status: duplicate
|
||||
canonical_id: wiki-2026-0508-garbage-collection
|
||||
duplicate_of: "[[Garbage Collection (가비지 컬렉션)]]"
|
||||
aliases: [Weak Generational Hypothesis]
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [redirect]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
confidence_score: 0.9
|
||||
verification_status: redirected
|
||||
tags: [duplicate, gc, theory]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-merge 2026-05-08)
|
||||
---
|
||||
|
||||
# Generational Hypothesis
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 이 문서는 P-Reinforce Phase 2 자동 MERGE에 의해 **[[Generational_Hypothesis]]**로 통합되었습니다.
|
||||
> **이 문서는 [[Garbage Collection (가비지 컬렉션)]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
---
|
||||
*Redirected to: [[Generational_Hypothesis]]*
|
||||
## 핵심 요약
|
||||
- 매 "most objects die young" — Lieberman & Hewitt 1984.
|
||||
- Young/old space 분리의 이론적 근거.
|
||||
- V8 Orinoco, JVM G1/ZGC 의 design foundation.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Garbage Collection (가비지 컬렉션)]] (canonical)
|
||||
- Adjacent: [[Orinoco 가비지 컬렉터]] · [[Old Space]] · [[Mark-Sweep-Compact 알고리즘]]
|
||||
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -2,91 +2,160 @@
|
||||
id: wiki-2026-0508-google-lighthouse
|
||||
title: Google Lighthouse
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-88077C]
|
||||
aliases: [Lighthouse, Web Vitals Audit]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [performance, web-vitals, audit, ci]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Google [[Lighthouse]]"
|
||||
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: JavaScript
|
||||
framework: Lighthouse 12+ / lighthouse-ci
|
||||
---
|
||||
|
||||
# [[Google Lighthouse]]
|
||||
# Google Lighthouse
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Google Lighthouse는 웹사이트의 페이지 속도를 측정하고 성능 개선을 위한 권장 사항을 제공하는 구글의 무료 오픈 소스 도구입니다 [1], [2]. 주로 개발 단계에서 브라우저의 성능을 시뮬레이션하여 Synthetic Lab Data(합성 랩 데이터)를 수집하며, [[Chrome DevTools]], 명령줄, 그리고 [[PageSpeed Insights]]를 통해 사용할 수 있습니다 [2], [3].
|
||||
## 매 한 줄
|
||||
> **"매 web page 의 performance, accessibility, best-practices, SEO, PWA 를 자동 audit"**. Chrome DevTools 내장, CLI, Node API, lighthouse-ci 의 form. 2026 현재 v12+ 가 INP (Interaction to Next Paint) 의 primary metric, LCP/CLS/INP 의 Core Web Vitals 와 align. 매 PR 마다 budget 검증 의 standard practice.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **주요 목적 및 기능:** Lighthouse는 웹 페이지의 로드 성능을 분석하고 최적화할 수 있는 진단 정보를 제공합니다 [1], [2]. 로컬 컴퓨터의 하드웨어와 네트워크 환경을 기반으로 성능을 시뮬레이션하는 'Synthetic Lab Data(합성 랩 데이터)' 수집 도구로 분류되며, 특히 개발 단계의 테스트나 직접 접근할 수 없는 웹사이트의 감사(audit) 목적에 가장 유용합니다 [2], [3]. Lighthouse가 측정하는 대표적인 성능 지표 중 하나로는 페이지가 완전히 상호 작용할 수 있게 되는 시간을 측정하는 'Time to Interactive(TTI)'가 있습니다 [4].
|
||||
* **도구 통합 및 엔진 재사용:** Lighthouse는 Google의 PageSpeed Insights 진단을 구동하는 핵심 엔진입니다 [1], [2]. 또한 Google은 [[Chrome]] DevTools의 성능 탭과 Lighthouse 보고서 양쪽 모두에서 사용할 수 있는 새로운 '인사이트 감사(Insights audits)' 기능을 도입하여, 성능 권장 사항을 식별하기 위해 별도의 엔진을 유지하는 대신 동일한 코드를 재사용하도록 개선했습니다 [1].
|
||||
* **스로틀링(Throttling) 시뮬레이션의 한계 및 개선:** Lighthouse는 점수를 결정하기 위해 스로틀링 시뮬레이션을 사용하는데, 이로 인해 때때로 부정확한 데이터가 생성되기도 합니다 [5]. 예를 들어, 페이지 콘텐츠가 미리 로드된(preloaded) 리소스에 의존하지 않음에도 불구하고 해당 리소스가 렌더링을 차단한다고 잘못 가정하는 경우가 있습니다 [5]. 이러한 부정확성을 해결하고 Lighthouse 지표를 더욱 신뢰할 수 있도록 실제 브라우저 동작과 더 잘 일치하게 스로틀링 시뮬레이션을 업데이트하는 작업이 진행 중입니다 [5], [6].
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 5 categories
|
||||
- **Performance**: LCP, INP, CLS, TBT, FCP, Speed Index → 0-100 score.
|
||||
- **Accessibility**: axe-core 기반 a11y 검사.
|
||||
- **Best Practices**: HTTPS, secure headers, deprecated API.
|
||||
- **SEO**: meta tags, mobile viewport, structured data.
|
||||
- **PWA** (deprecated 2024 후 separate plugin).
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[Chrome DevTools]], [[PageSpeed Insights]], [[Time to Interactive (TTI)]], Synthetic Lab Data
|
||||
- **Projects/Contexts:** [[Web Performance Optimization]]
|
||||
- **Contradictions/Notes:** 소스에 따르면 Lighthouse 점수의 단순 평균값은 일부 특이값(outlier)에 의해 왜곡될 수 있으므로 해석 시 주의가 필요합니다 [7]. 또한, Lighthouse의 스로틀링 시뮬레이션은 때때로 실제 브라우저 동작과 다르게 자원 로딩 영향을 평가하는 한계가 지적되어 최적화 작업이 요구되고 있습니다 [5].
|
||||
### 매 Performance 의 weight (v12)
|
||||
- LCP 25%, TBT 30%, CLS 25%, FCP 10%, SI 10%.
|
||||
- INP 의 field metric 만 — lab 에서 measure X (Total Blocking Time 으로 proxy).
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
### 매 응용
|
||||
1. Local audit (DevTools).
|
||||
2. CI gate (lighthouse-ci, budgets.json).
|
||||
3. Field monitoring 보조 (CrUX + RUM 와 결합).
|
||||
4. PageSpeed Insights backend.
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 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
|
||||
### CLI run
|
||||
```bash
|
||||
npm i -g lighthouse
|
||||
lighthouse https://example.com --output=html --output=json \
|
||||
--output-path=./report --chrome-flags="--headless"
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### Node programmatic
|
||||
```javascript
|
||||
import lighthouse from 'lighthouse'
|
||||
import * as chromeLauncher from 'chrome-launcher'
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
const chrome = await chromeLauncher.launch({ chromeFlags: ['--headless'] })
|
||||
const result = await lighthouse('https://example.com', {
|
||||
port: chrome.port,
|
||||
output: 'json',
|
||||
onlyCategories: ['performance'],
|
||||
})
|
||||
console.log(result.lhr.categories.performance.score)
|
||||
await chrome.kill()
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Lighthouse CI in GitHub Actions
|
||||
```yaml
|
||||
# .github/workflows/lhci.yml
|
||||
name: lhci
|
||||
on: [pull_request]
|
||||
jobs:
|
||||
lhci:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with: { node-version: 20 }
|
||||
- run: npm ci && npm run build
|
||||
- run: npm i -g @lhci/cli@0.14.x
|
||||
- run: lhci autorun
|
||||
env:
|
||||
LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### lighthouserc.js with budgets
|
||||
```javascript
|
||||
module.exports = {
|
||||
ci: {
|
||||
collect: {
|
||||
url: ['http://localhost:3000/', 'http://localhost:3000/about'],
|
||||
numberOfRuns: 3,
|
||||
startServerCommand: 'npm start',
|
||||
},
|
||||
assert: {
|
||||
assertions: {
|
||||
'categories:performance': ['error', { minScore: 0.9 }],
|
||||
'largest-contentful-paint': ['error', { maxNumericValue: 2500 }],
|
||||
'cumulative-layout-shift': ['error', { maxNumericValue: 0.1 }],
|
||||
'total-blocking-time': ['warn', { maxNumericValue: 200 }],
|
||||
},
|
||||
},
|
||||
upload: { target: 'temporary-public-storage' },
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
### User flow (multi-step)
|
||||
```javascript
|
||||
import { startFlow } from 'lighthouse'
|
||||
import puppeteer from 'puppeteer'
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
const browser = await puppeteer.launch()
|
||||
const page = await browser.newPage()
|
||||
const flow = await startFlow(page, { name: 'Checkout flow' })
|
||||
await flow.navigate('https://shop.example.com')
|
||||
await flow.startTimespan({ name: 'Add to cart' })
|
||||
await page.click('#add')
|
||||
await flow.endTimespan()
|
||||
await flow.snapshot({ name: 'Cart loaded' })
|
||||
const report = await flow.generateReport()
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| Local optimization | DevTools Lighthouse panel |
|
||||
| PR budget gate | lighthouse-ci + assertions |
|
||||
| Multi-page audit | lhci with multiple URLs |
|
||||
| SPA route transitions | User flows API |
|
||||
| Real-user metrics | CrUX / web-vitals JS (Lighthouse 의 X) |
|
||||
|
||||
**기본값**: 매 lhci + budgets.json + GitHub Action + 3 runs median.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Performance Profiling]]
|
||||
- 변형: [[WebPageTest]] · [[CrUX]]
|
||||
- 응용: [[CI_CD Pipeline]] · [[Continuous Integration (CI)]]
|
||||
- Adjacent: [[Cumulative Layout Shift (CLS)]] · [[SPA 라우트 전환 성능 최적화]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: pre-deploy quality gate, regression catch, web vitals tracking.
|
||||
**언제 X**: 매 real-user perf 측정 (lab condition 일 뿐 — RUM 사용). Native app, server-only API.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **단일 run score 의 의존**: variance 가 큼 — 매 median of 3-5 runs.
|
||||
- **Lab score = field score 의 가정**: throttling profile 이 user 와 다름. 매 CrUX 와 cross-check.
|
||||
- **High score 만 의 chase**: 100 score ≠ good UX. 매 INP/LCP 의 actual budget 의 focus.
|
||||
- **CI 에 emulated mobile 만 의 test**: desktop user 도 audit.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (web.dev/lighthouse, lighthouse-ci docs, Lighthouse 12 release notes 2025).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — Lighthouse 12 + CI integration patterns |
|
||||
|
||||
@@ -2,91 +2,169 @@
|
||||
id: wiki-2026-0508-index-masking
|
||||
title: Index Masking
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-42C840]
|
||||
aliases: [Bitmask Index, Power-of-Two Masking]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [optimization, low-level, ring-buffer, hash]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Index Masking"
|
||||
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: C/C++/Rust/JavaScript
|
||||
framework: General
|
||||
---
|
||||
|
||||
# [[Index Masking]]
|
||||
# Index Masking
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Index Masking은 [[Spectre]] 및 Meltdown과 같은 캐시 사이드 채널 공격을 방어하기 위해 브라우저 엔진에 도입된 보안 완화(security mitigation) 기법 중 하나이다 [1, 2]. 이 기법은 길이(length)를 다음 2의 거듭제곱으로 올림한 후 1을 빼는 방식으로 마스크(mask)를 계산하여 적용하는 분기 없는(branchless) 보안 검사 방식이다 [3, 4]. 비록 경계를 벗어난(out-of-bounds) 읽기를 완전히 막지는 못하지만, 공격자가 임의의 메모리에 접근하는 것을 방지하는 역할을 한다 [4].
|
||||
## 매 한 줄
|
||||
> **"매 capacity 가 power-of-two 일 때 `% N` 의 `& (N-1)` replacement"**. 매 modulo 의 expensive (CPU cycle 10-30) 의 single-cycle `AND` 로 대체. Ring buffer, hash table bucket, fixed-size LRU, lock-free queue 의 hot path 의 universal trick. CPU branch predictor 와 cache line 의 friendly.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **동작 원리 및 한계:** Index Masking은 데이터의 길이를 다음 2의 거듭제곱으로 올림하고 1을 빼는 방식으로 마스크를 계산하여 사용한다 [4]. 이 방법은 OOB(Out-of-Bounds) 접근에 대한 완벽한 해결책은 아니며 여전히 범위를 벗어난 읽기를 허용할 수 있지만, 임의의 메모리 영역(arbitrary [[memory]])에 대한 접근은 확실하게 차단한다 [4].
|
||||
- **보안을 위한 아키텍처 도입:** Spectre 및 Meltdown 공격을 방어하기 위해 [[WebKit]]을 비롯한 웹 브라우저 엔진들은 기존의 분기(branch) 기반 보안 검사의 한계를 보완하고자 Index Masking과 [[Pointer Poisoning]] 같은 분기 없는(branchless) 보안 검사 방식을 도입하였다 [1, 3, 4].
|
||||
- **성능에 미치는 영향:** 이 보안 완화 기법은 자바스크립트 엔진 및 JIT(Just-In-Time) 컴파일러가 수행하는 그래픽 실행의 크리티컬 패스에 추가 명령어를 도입하므로, 기본 마이크로 지연 시간(base micro-latency)을 약간 증가시킨다 [5]. 그러나 WebKit의 테스트에 따르면 Speedometer 및 ARES-6 벤치마크에서는 측정 가능한 성능 영향이 없었으며, JetStream 벤치마크에서는 성능에 미치는 영향이 2.5% 미만인 것으로 확인되었다 [4].
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 정확성 조건
|
||||
- N 이 power-of-two: `2^k`.
|
||||
- `index % N == index & (N - 1)` (unsigned 또는 non-negative).
|
||||
- `N - 1` 이 모든 lower bit 의 1 의 mask.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[Spectre and Meltdown]], [[Pointer Poisoning]], [[Branchless Security Checks]]
|
||||
- **Projects/Contexts:** [[WebKit]], Micro-latency Measurement in Web Graphics Pipelines
|
||||
- **Contradictions/Notes:** 소스 [5]에서는 Index Masking 기술이 그래픽 실행의 크리티컬 패스에 명령어를 추가하여 마이크로 지연 시간을 증가시킨다고 설명하지만, 소스 [4]의 벤치마크 결과에 따르면 실제 환경의 주요 성능 테스트(Speedometer 등)에서는 그 영향이 측정되지 않거나 2.5% 미만으로 매우 미미하다고 보고합니다.
|
||||
### 매 대표 사용 처
|
||||
- Ring buffer / circular queue.
|
||||
- Open-addressing hash table bucket index.
|
||||
- Game loop frame index modulo history size.
|
||||
- Hardware register address calc.
|
||||
- Lock-free SPSC/MPMC queue (Disruptor pattern).
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
### 매 응용
|
||||
1. LMAX Disruptor (Java) — sequence & ringMask.
|
||||
2. Linux kernel ringbuffer.
|
||||
3. Redis hash table — sizemask.
|
||||
4. V8 hidden class transitions table.
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
### Basic ring buffer (C)
|
||||
```c
|
||||
#define RB_CAP 1024 // must be power of two
|
||||
typedef struct {
|
||||
int data[RB_CAP];
|
||||
uint32_t head, tail; // free-running counters
|
||||
} RingBuf;
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(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
|
||||
static inline void rb_push(RingBuf *r, int v) {
|
||||
r->data[r->head & (RB_CAP - 1)] = v;
|
||||
r->head++;
|
||||
}
|
||||
static inline int rb_pop(RingBuf *r) {
|
||||
int v = r->data[r->tail & (RB_CAP - 1)];
|
||||
r->tail++;
|
||||
return v;
|
||||
}
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### TypeScript fixed-size circular log
|
||||
```typescript
|
||||
class CircularLog<T> {
|
||||
private buf: (T | undefined)[]
|
||||
private mask: number
|
||||
private head = 0
|
||||
constructor(capacityPow2: number) {
|
||||
if ((capacityPow2 & (capacityPow2 - 1)) !== 0)
|
||||
throw new Error('capacity must be power of two')
|
||||
this.buf = new Array(capacityPow2)
|
||||
this.mask = capacityPow2 - 1
|
||||
}
|
||||
push(v: T) {
|
||||
this.buf[this.head & this.mask] = v
|
||||
this.head++
|
||||
}
|
||||
recent(n: number): T[] {
|
||||
const out: T[] = []
|
||||
for (let i = 0; i < n; i++) {
|
||||
const v = this.buf[(this.head - 1 - i) & this.mask]
|
||||
if (v !== undefined) out.push(v)
|
||||
}
|
||||
return out
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Round-up to next power of two
|
||||
```c
|
||||
uint32_t next_pow2(uint32_t v) {
|
||||
v--;
|
||||
v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16;
|
||||
return v + 1;
|
||||
}
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Hash table bucket
|
||||
```rust
|
||||
struct Map<K, V> {
|
||||
buckets: Vec<Option<(K, V)>>,
|
||||
mask: usize,
|
||||
}
|
||||
impl<K: Hash + Eq, V> Map<K, V> {
|
||||
fn bucket(&self, k: &K) -> usize {
|
||||
let mut h = DefaultHasher::new();
|
||||
k.hash(&mut h);
|
||||
(h.finish() as usize) & self.mask // mask = capacity - 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### SPSC lock-free (Disruptor-style)
|
||||
```c
|
||||
// producer
|
||||
void produce(RingBuf *r, int v) {
|
||||
uint32_t h = atomic_load(&r->head);
|
||||
while (h - atomic_load(&r->tail) >= RB_CAP) cpu_relax(); // full
|
||||
r->data[h & (RB_CAP - 1)] = v;
|
||||
atomic_store(&r->head, h + 1);
|
||||
}
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
### Branch-free wrap (negative-safe)
|
||||
```c
|
||||
// for signed wrap, use bit-and after cast
|
||||
int idx = ((int)(counter) & ((int)CAP - 1)); // counter must be non-negative
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| Hot path, capacity 가 control 가능 | Power-of-2 + masking |
|
||||
| Capacity 가 user-input arbitrary | `%` (or round up to pow2) |
|
||||
| Capacity 가 dynamic resize | resize 시 `mask` recompute |
|
||||
| Signed counter | unsigned cast 또는 modulo |
|
||||
| Hardware-aligned (cache line) | pow2 + alignment 조합 |
|
||||
|
||||
**기본값**: 매 ring/hash table 는 power-of-two + bitmask. 매 capacity 의 dynamic 이면 round-up.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Bitwise Operations]]
|
||||
- 변형: [[Modulo Reduction]] · [[Fastrange]]
|
||||
- 응용: [[Ring Buffer]] · [[Object Pooling (오브젝트 풀링)]] · [[Hash Table]]
|
||||
- Adjacent: [[SharedArrayBuffer로 스레드 간 메모리 공유 효율 높이기]] · [[Pointer Compression]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 high-throughput data structure, lock-free queue, HFT, game engine frame loop.
|
||||
**언제 X**: capacity 의 control 안 되거나 readability priority 인 일반 application code.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Non-pow2 size 에 mask 적용**: 매 silent index out-of-range, data corruption.
|
||||
- **Signed negative index 의 masking**: `-1 & (N-1)` 의 N-1 이 됨 → 매 unsigned cast 또는 `((i % N) + N) % N` pattern.
|
||||
- **Capacity 1 의 mask 0**: 매 always index 0, degenerate.
|
||||
- **Premature application**: 매 측정 없이 micro-optimization. 매 hot path 만 의 적용.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Hacker's Delight Ch.3, LMAX Disruptor paper, Linux kfifo source, Redis dict.c).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — power-of-2 masking patterns + ring/hash applications |
|
||||
|
||||
@@ -2,96 +2,257 @@
|
||||
id: wiki-2026-0508-instancedmesh-동적-버퍼-확장
|
||||
title: InstancedMesh 동적 버퍼 확장
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-D6CCE0]
|
||||
aliases: [Dynamic InstancedMesh, Resize InstancedMesh, InstancedMesh Growth]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [threejs, webgl, webgpu, performance, buffer]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - [[InstancedMesh]] 동적 버퍼 확장"
|
||||
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: Three.js r172
|
||||
---
|
||||
|
||||
# [[InstancedMesh 동적 버퍼 확장]]
|
||||
# InstancedMesh 동적 버퍼 확장
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> InstancedMesh 동적 버퍼 확장은 렌더링 중 인스턴스 수가 초기 할당된 용량(Capacity)을 초과할 때, 시스템이 새로운 더 큰 버퍼를 할당하고 기존 데이터를 복사하는 과정을 의미한다 [1]. 이 과정에서 수십 메가바이트 크기의 배열이 빈번하게 생성되고 파괴되어 가비지 컬렉션(GC)을 유발하며, 이는 프레임 지연(스터터링)이나 메모리 할당 오류로 이어진다 [1, 2]. 결과적으로 이러한 성능 병목을 피하기 위해 개발자들은 런타임 확장을 피하고, 최대 예상 인스턴스 수에 맞춘 버퍼 사전 할당이나 객체 풀링 전략을 권장하고 있다 [1, 3].
|
||||
## 매 한 줄
|
||||
> **"매 InstancedMesh 의 capacity 부족 시 GPU buffer 를 reallocate"**. Three.js InstancedMesh 의 `count` 는 fixed allocation. 매 instance 추가가 capacity 초과하면 새 buffer 를 만들고 기존 data 를 copy. 매 amortized O(1) 을 위한 geometric growth 가 정석.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **동적 버퍼 확장의 발생 원리**
|
||||
InstancedMesh는 객체 수가 동적으로 변하는 환경(예: 적들이 수시로 생성되거나 파괴되는 상황)에서 초기 용량을 넘어서면 새로운 버퍼를 동적으로 확장해야 한다 [1]. 이때 기존 데이터를 새롭고 더 큰 버퍼로 복사하는 작업이 필연적으로 수반된다 [1].
|
||||
## 매 핵심
|
||||
|
||||
- **성능 저하 및 메모리 문제**
|
||||
동적 버퍼 확장은 메모리 할당 빈도가 매우 잦아 CPU 부하를 극도로 높이며, 데이터 전송 효율을 떨어뜨린다 [1]. 구형 `[[TypedArray]]` 데이터가 메모리에서 빈번하게 해제되는 과정에서 자바스크립트 가비지 컬렉터(GC)가 작동하여 프레임이 일시적으로 멈추는 현상(Stuttering)이 발생한다 [1]. A-Frame 기반 구현 등 일부 환경에서는 용량 증가 시 이전 InstancedMesh를 깔끔하게 해제(dispose)하지 못해 작은 메모리 누수([[memory]] Leak)가 발생할 우려도 존재한다 [4]. [[Needle Engine]] 환경에서도 버퍼가 동적으로 확장될 때 "[[[Instancing]]] Growing Buffer"라는 로그와 함께 렌더링이 일시적으로 수 초간 멈추는 성능 병목이 관찰되었다 [2].
|
||||
### 매 기본 한계
|
||||
- 매 `new InstancedMesh(geo, mat, count)` 는 매 `count` 만큼 GPU buffer alloc.
|
||||
- 매 `mesh.count` 변경은 draw 만 줄이지 buffer 는 그대로.
|
||||
- 매 capacity 초과 → 매 새 mesh / 새 InstancedBufferAttribute 가 필요.
|
||||
|
||||
- **최적화 및 대안 전략**
|
||||
이러한 성능 하락을 방지하려면 런타임에 동적으로 버퍼를 확장하는 대신, 앱 시작 시점이나 로드 시 최대 예상 인스턴스 수에 맞춰 충분한 크기의 버퍼를 미리 할당(Preallocate)하는 방식이 권장된다 [3, 5]. 또한, 대규모 프로젝트에서는 예측 불가능한 버퍼 확장을 막기 위해 사전에 엄격한 메모리 예산을 수립해야 한다 [1]. 메모리 할당 및 해제의 오버헤드를 최소화하기 위해 한 번 생성된 인스턴스 데이터를 재사용하는 객체 풀링(Object [[Pooling]])이나 링 버퍼(Ring Buffer) 구조를 채택하는 것이 효율적이다 [1].
|
||||
### 매 Strategy
|
||||
- **Geometric growth**: 매 capacity 부족 시 ×1.5 또는 ×2 로 resize.
|
||||
- **Pool & free list**: 매 deletion 후 빈 slot 재사용 (compact 회피).
|
||||
- **Chunked**: 매 fixed-size chunk N 개로 운영 (한 chunk 가득 차면 새 chunk).
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 응용
|
||||
1. **Realtime particle spawn / despawn**.
|
||||
2. **User-placed object editor** (매 추가 무한).
|
||||
3. **Streaming voxel chunk** (매 LOD 별 instance 수 가변).
|
||||
4. **NPC spawn system**.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[InstancedMesh]], [[가비지 컬렉션 ([[Garbage Collection]])]], 객체 풀링 ([[Object Pooling]]), 버퍼 사전 할당 (Buffer Preallocation)
|
||||
- **Projects/Contexts:** [[Needle Engine]], A-Frame (instanced-mesh 컴포넌트), 실시간 웹 그래픽스 최적화
|
||||
- **Contradictions/Notes:** 예측 불가능한 다량의 객체를 렌더링하려면 동적 확장이 필수적인 기능처럼 보이나, 실제 렌더링 환경에서는 이 과정이 프레임 드랍과 메모리 누수 위험 등 높은 리스크를 수반하므로 오히려 고정 용량 할당이나 풀링을 통해 원천적으로 확장을 회피하는 것이 강력히 권장된다 [1, 3, 4].
|
||||
## 💻 패턴
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
### 1. Geometric resize utility
|
||||
```typescript
|
||||
class DynamicInstancedMesh {
|
||||
private mesh: THREE.InstancedMesh;
|
||||
private capacity: number;
|
||||
private size = 0;
|
||||
private freeList: number[] = [];
|
||||
|
||||
---
|
||||
constructor(
|
||||
private geo: THREE.BufferGeometry,
|
||||
private mat: THREE.Material,
|
||||
initialCapacity = 64,
|
||||
private maxCapacity = 1_000_000,
|
||||
) {
|
||||
this.capacity = initialCapacity;
|
||||
this.mesh = this.makeMesh(initialCapacity);
|
||||
}
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
private makeMesh(cap: number): THREE.InstancedMesh {
|
||||
const m = new THREE.InstancedMesh(this.geo, this.mat, cap);
|
||||
m.instanceMatrix.setUsage(THREE.DynamicDrawUsage);
|
||||
m.count = this.size;
|
||||
return m;
|
||||
}
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(TODO)*
|
||||
add(matrix: THREE.Matrix4): number {
|
||||
let idx: number;
|
||||
if (this.freeList.length > 0) {
|
||||
idx = this.freeList.pop()!;
|
||||
} else {
|
||||
if (this.size >= this.capacity) this.grow();
|
||||
idx = this.size++;
|
||||
}
|
||||
this.mesh.setMatrixAt(idx, matrix);
|
||||
this.mesh.instanceMatrix.needsUpdate = true;
|
||||
this.mesh.count = this.size;
|
||||
return idx;
|
||||
}
|
||||
|
||||
**언제 쓰면 안 되는가:**
|
||||
- *(TODO)*
|
||||
remove(idx: number) {
|
||||
// 매 zero-scale matrix 로 hide → free list 등록
|
||||
const zero = new THREE.Matrix4().scale(new THREE.Vector3(0, 0, 0));
|
||||
this.mesh.setMatrixAt(idx, zero);
|
||||
this.mesh.instanceMatrix.needsUpdate = true;
|
||||
this.freeList.push(idx);
|
||||
}
|
||||
|
||||
## 🧪 검증 상태 (Validation)
|
||||
private grow() {
|
||||
const newCap = Math.min(this.capacity * 2, this.maxCapacity);
|
||||
if (newCap <= this.capacity) throw new Error('Max capacity hit');
|
||||
const newMesh = this.makeMesh(newCap);
|
||||
|
||||
- **정보 상태:** needs_review
|
||||
- **출처 신뢰도:** A
|
||||
- **검토 이유:** *(P-Reinforce Phase 1 자동 정규화. 본문 검증 필요.)*
|
||||
// 매 기존 matrix 복사
|
||||
const m = new THREE.Matrix4();
|
||||
for (let i = 0; i < this.size; i++) {
|
||||
this.mesh.getMatrixAt(i, m);
|
||||
newMesh.setMatrixAt(i, m);
|
||||
}
|
||||
// 매 color 도 있으면 copy
|
||||
if (this.mesh.instanceColor) {
|
||||
const oldColor = this.mesh.instanceColor.array as Float32Array;
|
||||
const newColor = new Float32Array(newCap * 3);
|
||||
newColor.set(oldColor);
|
||||
newMesh.instanceColor = new THREE.InstancedBufferAttribute(newColor, 3);
|
||||
}
|
||||
|
||||
## 🧬 중복 검사 (Duplicate Check)
|
||||
// 매 swap
|
||||
const parent = this.mesh.parent;
|
||||
if (parent) {
|
||||
parent.remove(this.mesh);
|
||||
parent.add(newMesh);
|
||||
}
|
||||
this.mesh.dispose(); // 매 매 critical: GPU buffer free
|
||||
this.mesh = newMesh;
|
||||
this.capacity = newCap;
|
||||
console.log(`[DynamicInstancedMesh] grew → ${newCap}`);
|
||||
}
|
||||
|
||||
- **기존 유사 문서:** *(TODO: 인덱서 클러스터 리포트 참조)*
|
||||
- **처리 방식:** UPDATE (자동 정규화)
|
||||
- **처리 이유:** Phase 1 정규화 — 옛 템플릿/누락 필드 보강.
|
||||
|
||||
## 🕓 변경 이력 (Changelog)
|
||||
|
||||
| 날짜 | 변경 내용 | 처리 방식 | 신뢰도 |
|
||||
|------|-----------|-----------|--------|
|
||||
| 2026-05-08 | P-Reinforce Phase 1 정규화 (frontmatter + 헤더 표준화) | UPDATE | A |
|
||||
|
||||
## 💻 코드 패턴 (Code Patterns)
|
||||
|
||||
**패턴 1:** *(TODO: 이 프로젝트 컨벤션 반영한 구조 스켈레톤)*
|
||||
|
||||
```text
|
||||
# TODO
|
||||
get object(): THREE.InstancedMesh { return this.mesh; }
|
||||
get instanceCount(): number { return this.size - this.freeList.length; }
|
||||
}
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### 2. Chunked strategy (매 large N 친화적)
|
||||
```typescript
|
||||
class ChunkedInstancedMesh {
|
||||
private chunks: THREE.InstancedMesh[] = [];
|
||||
private group = new THREE.Group();
|
||||
private CHUNK_SIZE = 4096;
|
||||
private currentChunkSize = 0;
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
constructor(private geo: THREE.BufferGeometry, private mat: THREE.Material) {
|
||||
this.addChunk();
|
||||
}
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
private addChunk() {
|
||||
const m = new THREE.InstancedMesh(this.geo, this.mat, this.CHUNK_SIZE);
|
||||
m.instanceMatrix.setUsage(THREE.DynamicDrawUsage);
|
||||
m.count = 0;
|
||||
this.chunks.push(m);
|
||||
this.group.add(m);
|
||||
this.currentChunkSize = 0;
|
||||
}
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
add(matrix: THREE.Matrix4): { chunk: number; idx: number } {
|
||||
if (this.currentChunkSize >= this.CHUNK_SIZE) this.addChunk();
|
||||
const chunkIdx = this.chunks.length - 1;
|
||||
const chunk = this.chunks[chunkIdx];
|
||||
const idx = this.currentChunkSize++;
|
||||
chunk.setMatrixAt(idx, matrix);
|
||||
chunk.count = idx + 1;
|
||||
chunk.instanceMatrix.needsUpdate = true;
|
||||
return { chunk: chunkIdx, idx };
|
||||
}
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
get object(): THREE.Group { return this.group; }
|
||||
}
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### 3. Partial buffer update (updateRange)
|
||||
```typescript
|
||||
// 매 매 frame 일부만 변경 시 매 전체 upload 회피
|
||||
function updateInstanceRange(
|
||||
mesh: THREE.InstancedMesh, startIdx: number, count: number
|
||||
) {
|
||||
mesh.instanceMatrix.updateRange.offset = startIdx * 16; // mat4 = 16 floats
|
||||
mesh.instanceMatrix.updateRange.count = count * 16;
|
||||
mesh.instanceMatrix.needsUpdate = true;
|
||||
}
|
||||
```
|
||||
|
||||
### 4. WebGPU StorageBuffer 동적 grow
|
||||
```typescript
|
||||
import { storage, instanceIndex } from 'three/tsl';
|
||||
|
||||
class GPUDynamicInstances {
|
||||
private buffer: THREE.StorageBufferAttribute;
|
||||
private capacity: number;
|
||||
|
||||
constructor(initial = 1024) {
|
||||
this.capacity = initial;
|
||||
this.buffer = new THREE.StorageBufferAttribute(initial, 16);
|
||||
}
|
||||
|
||||
grow(needed: number) {
|
||||
const newCap = Math.max(this.capacity * 2, needed);
|
||||
const newBuf = new THREE.StorageBufferAttribute(newCap, 16);
|
||||
// 매 GPU-side copy: compute pass 로 old → new
|
||||
// 매 또는 CPU readback 후 재upload (매 비싸지만 단순)
|
||||
newBuf.array.set(this.buffer.array);
|
||||
this.buffer = newBuf;
|
||||
this.capacity = newCap;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Defragment (free list 가 너무 커지면)
|
||||
```typescript
|
||||
defragment(dim: DynamicInstancedMesh) {
|
||||
// 매 freeList sort 후 살아있는 instance 를 앞으로 compact
|
||||
// 매 user-facing index 가 바뀌므로 index map 도 업데이트해야 함
|
||||
// ... (구현은 use case 별 — id↔index 매핑 유지가 매 critical)
|
||||
}
|
||||
```
|
||||
|
||||
### 6. dispose 와 GPU memory 관리
|
||||
```typescript
|
||||
function disposeInstanced(mesh: THREE.InstancedMesh) {
|
||||
mesh.geometry.dispose();
|
||||
if (Array.isArray(mesh.material)) mesh.material.forEach(m => m.dispose());
|
||||
else mesh.material.dispose();
|
||||
mesh.dispose(); // 매 InstancedMesh 자체 buffer
|
||||
}
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| 매 instance 수가 천천히 변동 | Geometric grow ×2 |
|
||||
| 매 instance 수 매 frame 격변 | Pre-alloc max + count 조절 |
|
||||
| 매 매우 큰 N + streaming | Chunked (CHUNK_SIZE 4-16k) |
|
||||
| 매 frequent delete | Free list + zero-scale hide |
|
||||
| 매 free list ≥ 30% | Defragment 한 번 |
|
||||
| 매 GPU-driven spawn | WebGPU StorageBuffer + compute |
|
||||
|
||||
**기본값**: 매 generic dynamic case → DynamicInstancedMesh (×2 grow + free list + zero-scale remove).
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[InstancedMesh 최적화]] · [[Three.js]]
|
||||
- 변형: [[BatchedMesh]] · [[GPU Particle Systems]]
|
||||
- 응용: [[Realtime Editors]] · [[Voxel Streaming]]
|
||||
- Adjacent: [[Free List]] · [[Geometric Resize]] · [[Buffer Pool]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: dynamic spawn/despawn 시스템 설계, free list vs chunked 의 trade-off 설명.
|
||||
**언제 X**: 매 specific WebGL driver memory bug.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **매 add 마다 new InstancedMesh**: 매 GPU alloc storm — 반드시 amortize.
|
||||
- **dispose() 빠뜨림**: 매 grow 후 옛 mesh GPU buffer 의 leak.
|
||||
- **Linear grow (+1, +1)**: O(N²) total copy. 매 geometric (×1.5 or ×2) 만 사용.
|
||||
- **remove 후 splice**: 매 모든 후속 idx shift → 비싸다. 매 zero-scale + free list.
|
||||
- **매 free list 만 쓰고 defrag 없음**: 매 hide 된 instance 도 vertex shader 실행 (zero-scale 은 깎임).
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Three.js r172 source `src/objects/InstancedMesh.js`).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — dynamic grow + free list + chunked |
|
||||
|
||||
@@ -2,105 +2,171 @@
|
||||
id: wiki-2026-0508-instancedmesh-사용-시-드로우-콜-최적화의-한계
|
||||
title: InstancedMesh 사용 시 드로우 콜 최적화의 한계점 사례 연구
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-88CEC2]
|
||||
aliases: [InstancedMesh Limits, Instancing Limits]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [graphics, three-js, performance, instancing]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - [[InstancedMesh]] 사용 시 드로우 콜 최적화의 한계점 사례 연구"
|
||||
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: JavaScript/GLSL
|
||||
framework: Three.js r170+/WebGL2/WebGPU
|
||||
---
|
||||
|
||||
# [[InstancedMesh 사용 시 드로우 콜 최적화의 한계점 사례 연구]]
|
||||
# InstancedMesh 사용 시 드로우 콜 최적화의 한계점 사례 연구
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> InstancedMesh는 단일 드로우 콜([[Draw Call]])로 동일한 기하학적 구조와 재질을 가진 수많은 객체를 렌더링하여 CPU 오버헤드를 획기적으로 줄이는 최적화 기술입니다 [1, 2]. 그러나 실무 환경에서는 지오메트리 단일성 제약, 시야 절두체 컬링([[Frustum Culling]])의 비효율성, 오버드로우([[Overdraw]]), 동적 데이터 갱신 시의 메모리 대역폭 포화 등 여러 구조적 한계를 드러냅니다 [3-7]. 본 사례 연구는 이러한 한계들로 인해 드로우 콜 횟수의 감소가 반드시 전반적인 렌더링 프레임 레이트(FPS) 상승으로 이어지지는 않음을 실증적으로 분석합니다 [3].
|
||||
## 매 한 줄
|
||||
> **"매 InstancedMesh 매 1 draw call로 N copies — but 매 frustum culling, material variation, animation, picking 의 cost가 instance 수에 따라 explode."**. 매 naive 사용 시 draw call 매 줄어들어도 GPU vertex/fragment 매 burden, CPU matrix update 매 bottleneck. 매 production 매 LOD + spatial partition + GPU culling 매 결합.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **드로우 콜 최적화 원리와 맹점**
|
||||
InstancedMesh는 GPU 메모리에 단일 정점 버퍼를 업로드하고 개별 인스턴스의 변환 행렬만을 속성으로 관리하여 한 번의 명령으로 수천 개의 객체를 병렬 복제합니다 [1, 2]. 하지만 **모든 인스턴스가 반드시 동일한 기하학적 데이터([[BufferGeometry]])와 재질(Material)을 공유해야 하므로 자산의 다양성을 확보하기 어렵습니다** [4]. 개별 인스턴스에 다른 텍스처를 적용하기 위해 텍스처 아틀라스([[Texture Atlas]])를 사용하면 경계선 블리딩([[Edge Bleeding]])이 발생할 수 있으며, 텍스처 배열(Texture Array)은 해상도 제약을 수반해 셰이더 복잡도를 높입니다 [8].
|
||||
## 매 핵심
|
||||
|
||||
* **시야 절두체 컬링(Frustum Culling)의 비효율성**
|
||||
InstancedMesh의 컬링은 전체 인스턴스를 포함하는 거대한 바운딩 볼륨을 기준으로 단 한 번만 수행되는 '전부 아니면 전무' 방식으로 작동합니다 [5]. 이로 인해 **단 하나의 객체만 시야에 있어도 화면 밖의 수많은 객체에 대한 정점 변환 연산이 강제되어 GPU를 크게 낭비합니다** [5]. 이를 피하고자 자바스크립트 수준에서 CPU 기반의 수동 개별 컬링을 구현하면 대규모 배열 조작으로 인해 메인 스레드에 극심한 병목이 유발됩니다 [9].
|
||||
### 매 한계 list
|
||||
- **No per-instance frustum culling**: 매 single bounding sphere → 매 모든 instance가 frustum 안에 있다고 GPU가 가정.
|
||||
- **No per-instance material**: 매 same material → color/texture variation 매 instanceColor / instance attribute 의 manual.
|
||||
- **Animation cost**: 매 instance마다 matrix update → CPU bound at 10k+.
|
||||
- **Picking 어려움**: raycaster 매 instance index 매 별도 처리.
|
||||
- **Memory**: 16 floats × N instances = 매 1M instances → 64MB matrix buffer.
|
||||
- **Shadow map**: 매 light 마다 또 한 번 instanced draw — culling 없으면 shadow waste.
|
||||
|
||||
* **오버드로우(Overdraw)와 렌더링 정렬의 부재**
|
||||
InstancedMesh는 버퍼에 저장된 순서대로만 렌더링되며, 불투명 객체의 조기 깊이 판정([[Early-Z]])을 위한 '앞에서 뒤로' 자동 정렬 기능이 없습니다 [6]. **드로우 콜이 1회로 최적화되었음에도 불구하고, 무작위 정렬로 인한 막대한 오버드로우 비용 때문에 GPU 프래그먼트 병목이 발생하여 오히려 일반 메쉬 방식보다 FPS가 떨어질 수 있습니다** [6]. 투명/반투명 객체는 '뒤에서 앞으로' 렌더링되어야 시각적 오류가 없으나 동적인 순서 변경이 지원되지 않으며, 강제로 재정렬([[Radix Sort]] 등)을 수행하면 CPU에 치명적인 부하를 줍니다 [10].
|
||||
### 매 case: 100k cubes
|
||||
- Naive InstancedMesh: 매 1 draw call, GPU 60fps but matrix update 60ms/frame on CPU.
|
||||
- Static (`setMatrixAt` once): 매 GPU bound, fillrate 매 issue → LOD 필요.
|
||||
- Dynamic: 매 매 frame matrix update → useDynamicDrawUsage + partial updates.
|
||||
|
||||
* **메모리 대역폭 임계점과 데이터 전송 병목**
|
||||
각 인스턴스의 위치 및 회전 정보는 64바이트의 부동 소수점 행렬로 구성됩니다 [7]. **대규모 씬(예: 200만 개 인스턴스)에서 매 프레임 객체들이 동적으로 움직여 버퍼를 갱신해야 할 경우, 수 GB/s 단위의 막대한 데이터가 CPU에서 GPU로 이동해야 하므로 PCIe 대역폭을 포화시킵니다** [7]. 또한 할당된 버퍼 용량을 초과해 새 버퍼를 동적 할당할 때는 가비지 컬렉션(GC)이 작동해 순간적인 프레임 스터터링(Stuttering)을 유발합니다 [11].
|
||||
### 매 응용 (해결 전략)
|
||||
1. **GPU instancing + GPU culling**: compute shader 매 frustum check, 매 indirect draw.
|
||||
2. **Spatial partitioning**: octree / BVH로 매 chunk 단위 InstancedMesh.
|
||||
3. **LOD groups**: distance 별 다른 InstancedMesh (high/med/low/billboard).
|
||||
4. **BatchedMesh (Three.js r170+)**: 매 different geometries를 single draw call.
|
||||
5. **Hierarchical LOD + impostor**: 매 far away는 single quad billboard.
|
||||
|
||||
* **상호작용(Picking) 및 애니메이션 연동의 한계**
|
||||
대규모 인스턴스에 대해 사용자가 객체를 선택하는 **CPU 기반 피킹([[Raycasting]])을 시도하면 수만 번의 행렬 역산이 발생하여 즉각적인 반응성이 저해됩니다** [12]. GPU 픽셀 기반 피킹은 파이프라인 동기화 지연(Sync stall)과 오클루전(Occlusion) 한계가 있습니다 [13]. 또한 본(Bone) 행렬 기반의 **스킨드 메쉬(Skinned Mesh) 애니메이션을 기본 지원하지 않아**, 인스턴스마다 고유한 본 행렬을 전달하려 하면 버퍼 크기 제한을 초과하게 됩니다 [14].
|
||||
## 💻 패턴
|
||||
|
||||
* **대안 기술 및 최적화 전략**
|
||||
InstancedMesh의 한계를 보완하기 위해 서로 다른 기하학적 구조를 수용하고 개별 컬링/가시성 제어가 가능한 **`BatchedMesh`**가 활용되고 있으나, 이 역시 지나치게 많은 삼각형을 처리할 때는 버퍼 패킹 오버헤드가 발생합니다 [15]. 궁극적으로는 **[[WebGPU]]의 컴퓨트 셰이더([[Compute Shader]])를 도입하여 가시성 판별과 오클루전 처리를 GPU 내부에서 해결하는 GPU 주도 렌더링([[Indirect Draw]]) 방식**이 강력한 대안으로 부상하고 있습니다 [16, 17].
|
||||
### Frustum culling 수동 (Three.js)
|
||||
```javascript
|
||||
const frustum = new THREE.Frustum();
|
||||
const m = new THREE.Matrix4();
|
||||
m.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
|
||||
frustum.setFromProjectionMatrix(m);
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[Frustum Culling]], [[Overdraw]], BatchedMesh, [[WebGPU Compute Shader]], [[Texture Atlas]], [[Garbage Collection]] (GC)
|
||||
- **Projects/Contexts:** [[대규모 웹 그래픽스 프로젝트]], [[CAD 렌더링 최적화]], [[BIM 모델 렌더링]]
|
||||
- **Contradictions/Notes:** 소스에 따르면 InstancedMesh 기술은 드로우 콜을 획기적으로 줄여 CPU 부담을 최소화하지만, 자체적인 정렬 부재와 컬링의 한계로 인해 조명 연산이 복잡한 환경에서는 오버드로우를 유발하여 결과적으로 GPU 픽셀 처리 성능을 상회하게 만들어 전체 FPS를 하락시킬 수 있다는 모순된 현상이 발생함을 강력히 지적합니다 [6]. 또한 대안으로 제시되는 BatchedMesh 역시 드로우 콜을 줄일 수는 있으나, 극한의 대규모 삼각형 렌더링 시에는 버퍼 패킹 비용이 오히려 일반 메쉬 렌더링보다 낮은 성능을 보이는 병목 사례가 보고됩니다 [15].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
const dummy = new THREE.Object3D();
|
||||
const sphere = new THREE.Sphere(new THREE.Vector3(), boundingRadius);
|
||||
let visibleCount = 0;
|
||||
for (let i = 0; i < totalInstances; i++) {
|
||||
sphere.center.copy(positions[i]);
|
||||
if (frustum.intersectsSphere(sphere)) {
|
||||
dummy.position.copy(positions[i]);
|
||||
dummy.updateMatrix();
|
||||
instancedMesh.setMatrixAt(visibleCount++, dummy.matrix);
|
||||
}
|
||||
}
|
||||
instancedMesh.count = visibleCount;
|
||||
instancedMesh.instanceMatrix.needsUpdate = true;
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### Per-instance color
|
||||
```javascript
|
||||
const mesh = new THREE.InstancedMesh(geo, mat, N);
|
||||
const color = new THREE.Color();
|
||||
for (let i = 0; i < N; i++) {
|
||||
color.setHSL(i / N, 0.7, 0.5);
|
||||
mesh.setColorAt(i, color);
|
||||
}
|
||||
mesh.instanceColor.needsUpdate = true;
|
||||
// shader auto: gl_InstanceID → vInstanceColor
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Dynamic draw usage (partial updates)
|
||||
```javascript
|
||||
mesh.instanceMatrix.setUsage(THREE.DynamicDrawUsage);
|
||||
// only update changed instances
|
||||
mesh.setMatrixAt(idx, newMatrix);
|
||||
mesh.instanceMatrix.updateRange = { offset: idx * 16, count: 16 };
|
||||
mesh.instanceMatrix.needsUpdate = true;
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Chunked InstancedMesh (spatial bucket)
|
||||
```javascript
|
||||
class ChunkedInstances {
|
||||
constructor(geo, mat, chunkSize = 64) {
|
||||
this.chunks = new Map(); // "x,y,z" → InstancedMesh
|
||||
this.chunkSize = chunkSize;
|
||||
}
|
||||
add(pos) {
|
||||
const key = this.chunkKey(pos);
|
||||
if (!this.chunks.has(key)) {
|
||||
this.chunks.set(key, new THREE.InstancedMesh(geo, mat, 1024));
|
||||
}
|
||||
// ...
|
||||
}
|
||||
cullChunks(frustum) {
|
||||
for (const [key, mesh] of this.chunks) {
|
||||
mesh.visible = frustum.intersectsBox(this.chunkBox(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### BatchedMesh (Three.js r170+)
|
||||
```javascript
|
||||
const batched = new THREE.BatchedMesh(maxGeoms, maxVerts, maxIdx);
|
||||
const geoIdA = batched.addGeometry(geoA);
|
||||
const geoIdB = batched.addGeometry(geoB);
|
||||
const instA = batched.addInstance(geoIdA);
|
||||
batched.setMatrixAt(instA, matrixA);
|
||||
// 매 different geometries 매 single draw call
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
### GPU compute culling (WebGPU)
|
||||
```javascript
|
||||
// compute shader: input matrices + frustum planes → atomic counter + visible matrix buffer
|
||||
const cullPipeline = device.createComputePipeline({...});
|
||||
pass.setPipeline(cullPipeline);
|
||||
pass.dispatchWorkgroups(Math.ceil(N / 64));
|
||||
// then drawIndexedIndirect from visible buffer
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| < 1k static instances | Plain InstancedMesh |
|
||||
| 1k–100k mostly static | InstancedMesh + manual frustum culling |
|
||||
| 100k+ static | Chunked InstancedMesh (spatial) + LOD |
|
||||
| Dynamic per-frame (particles) | Points / GPU particle system |
|
||||
| Different geometries | BatchedMesh (r170+) |
|
||||
| Massive (1M+) | WebGPU compute culling + indirect draw |
|
||||
| Picking 필요 | InstancedMesh + raycaster.firstHitOnly = true |
|
||||
|
||||
**기본값**: < 10k는 plain InstancedMesh, 그 이상 매 chunked + LOD.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[GPU Instancing]] · [[Three.js]]
|
||||
- 변형: [[BatchedMesh]] · [[GPU Particle]]
|
||||
- 응용: [[Foliage Rendering]] · [[Crowd Rendering]]
|
||||
- Adjacent: [[Frustum Culling]] · [[LOD]] · [[Indirect Draw]] · [[WebGPU]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 같은 geometry+material의 N copies, 매 N > 50, 매 draw call 매 hot path bottleneck.
|
||||
**언제 X**: 매 highly varying geometry (use BatchedMesh), 매 < 50 copies (overhead > benefit), 매 fully dynamic mesh (skinning per instance은 expensive).
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **No bounding 갱신**: 매 instance 매 spread out 매 single boundingSphere가 too large → frustum culling 작동 안 함.
|
||||
- **매 frame full matrix rebuild**: 매 instance 매 100% update assumption 매 wrong → updateRange 활용.
|
||||
- **Different materials → multiple InstancedMesh**: 매 점 defeats the purpose. Use texture atlas + instance attribute.
|
||||
- **Skip LOD**: 매 far instance 매 close instance와 same vertex count → fillrate explosion.
|
||||
- **InstancedMesh on top of skinned mesh**: 매 shader 매 manual instancing 필요 — Three.js native skinning 매 instance와 conflict.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Three.js docs r170+, mrdoob InstancedMesh PR, WebGPU spec).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — InstancedMesh 한계 / 해결 패턴 / BatchedMesh + WebGPU compute culling |
|
||||
|
||||
@@ -2,105 +2,225 @@
|
||||
id: wiki-2026-0508-instancedmesh-최적화
|
||||
title: InstancedMesh 최적화
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-7D070F]
|
||||
aliases: [InstancedMesh, GPU Instancing, Three.js Instancing]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [threejs, webgl, webgpu, rendering, performance]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - [[InstancedMesh]] 최적화"
|
||||
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: Three.js r172 / WebGPU
|
||||
---
|
||||
|
||||
# [[InstancedMesh 최적화]]
|
||||
# InstancedMesh 최적화
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> [[InstancedMesh 최적화]]는 동일한 기하학적 구조(Geometry)와 재질(Material)을 가진 수많은 객체를 단 한 번의 드로우 콜([[Draw Call]])로 GPU에 전달하여 렌더링 성능을 극대화하는 기법입니다 [1], [2]. 수천, 수만 개의 반복적인 객체(나무, 풀, 파티클 등)를 렌더링할 때 CPU의 명령 발행 오버헤드를 대폭 줄이고 메모리 사용량을 최소화할 수 있습니다 [3], [4], [5]. 그러나 전체 인스턴스에 대한 전역적 시야 절두체 컬링, 개별 객체의 깊이 정렬 부재로 인한 오버드로우 등 구조적 한계가 존재하므로, 프로젝트의 특성과 병목 구간에 맞춘 전략적인 도입이 필요합니다 [6], [7].
|
||||
## 매 한 줄
|
||||
> **"매 동일 geometry 의 N 개를 1 draw call 로"**. InstancedMesh 는 매 같은 mesh 를 instance attribute (matrix, color) 만 바꿔 GPU 에 한 번에 제출. 매 forest, particle, crowd 같은 thousands-of-objects scene 에서 50-1000x throughput.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **드로우 콜 및 메모리 최적화 원리**
|
||||
* InstancedMesh는 GPU 메모리에 단 하나의 정점 버퍼만 업로드하고, 각 인스턴스에 고유하게 적용될 변환 행렬(위치, 회전, 축척) 및 색상 정보를 별도의 인스턴스 속성(Instance Attribute)으로 관리합니다 [2].
|
||||
* 이 기술을 사용하면 일반 메쉬로 수천 번 호출해야 할 드로우 콜을 1회로 줄일 수 있어, CPU 병목 현상을 해소하고 시스템 메모리 및 VRAM을 획기적으로 절약할 수 있습니다 [8], [1], [9].
|
||||
* 개별 인스턴스의 변환 행렬이나 색상을 변경(`setMatrixAt`, `setColorAt`)한 후에는 반드시 `needsUpdate` 속성을 `true`로 설정해야 렌더링 파이프라인에 반영됩니다 [10], [11]. 동적으로 인스턴스가 이동한 경우, 정확한 레이캐스팅(Picking) 및 컬링을 위해 `computeBoundingSphere()`와 `computeBoundingBox()`를 호출하여 바운딩 볼륨을 갱신해야 합니다 [12], [13], [14].
|
||||
## 매 핵심
|
||||
|
||||
* **구조적 한계 및 성능 병목 요인**
|
||||
* **컬링(Culling)의 비효율성:** InstancedMesh는 엔진 수준에서 단일 객체로 취급되므로, 개별 인스턴스 단위가 아닌 전체를 아우르는 거대한 바운딩 볼륨을 기준으로 단 한 번의 시야 절두체 컬링([[Frustum Culling]])을 수행합니다 [15]. 이로 인해 시야 밖의 수많은 객체에 대해서도 불필요한 GPU 정점 연산이 강제될 수 있습니다 [15], [16].
|
||||
* **정렬 부재와 오버드로우([[Overdraw]]):** 카메라 거리에 따른 자동 정렬 기능을 제공하지 않기 때문에, 뒤에 가려진 픽셀 연산을 조기에 종료([[Early-Z]])하지 못해 오버드로우가 발생합니다 [17], [18]. 특히 투명/반투명 객체 렌더링 시에는 깊이 정렬이 뒤섞여 시각적 오류를 초래합니다 [19].
|
||||
* **메모리 대역폭 한계:** 애니메이션 등으로 매 프레임 수백만 개의 인스턴스 변환 행렬(인스턴스당 64바이트)을 갱신해야 할 경우, 데이터 전송량이 시스템 버스 대역폭을 포화시켜 프레임 지연(Stuttering)을 유발할 수 있습니다 [20], [21].
|
||||
* **다양성 표현의 제약:** 단일 지오메트리와 단일 재질만 참조할 수 있어 다양한 에셋을 표현하기 어렵습니다 [22]. 개별 인스턴스에 서로 다른 텍스처를 적용하려면 [[Texture Atlas]]나 데이터 배열 텍스처([[Data Array Textures]])를 활용하고 UV 오프셋을 조정하는 추가적인 셰이더 조작이 강제됩니다 [23], [24], [25].
|
||||
### 매 작동 원리
|
||||
- 매 vertex shader 는 `gl_InstanceID` (WebGL2) / `instance_index` (WebGPU) 로 per-instance 데이터 lookup.
|
||||
- 매 instanceMatrix (mat4) 는 default attribute. 매 추가로 instanceColor, custom attribute 가능.
|
||||
- 매 draw call: `gl.drawElementsInstanced(mode, count, type, offset, instanceCount)`.
|
||||
|
||||
* **한계 극복을 위한 개선 및 대안 전략**
|
||||
* **공간 분할 기반 그룹화:** 모든 객체를 하나의 거대한 InstancedMesh로 묶기보다는, 공간적으로 인접한 객체끼리 소규모(100~500개)로 분할하여 관리하면 절두체 컬링의 정밀도를 높여 GPU 연산 낭비를 줄일 수 있습니다 [7].
|
||||
* **[[InstancedMesh2]] 및 BatchedMesh 활용:** 단일 지오메트리 제약이 문제가 된다면, 서로 다른 지오메트리를 하나의 드로우 콜로 묶어주는 BatchedMesh 사용이 권장됩니다 [26], [27]. 또한, 커뮤니티 생태계의 `InstancedMesh2` 라이브러리를 활용하면 개별 인스턴스의 프러스텀 컬링, 정렬, [[Level of Detail (LOD)]], BVH 기반의 빠른 레이캐스팅, 스킨드 애니메이션 최적화 등의 기능을 확장 적용할 수 있습니다 [28], [29], [30].
|
||||
* **[[WebGPU]] 컴퓨트 셰이더 도입:** WebGPU 환경에서는 GPU가 직접 가시성 판단과 컬링을 처리하여 CPU와 GPU 간의 통신 비용을 "0"에 수렴하게 하는 간접 그리기([[Indirect Draw]]) 방식이 차세대 대안으로 떠오르고 있습니다 [31].
|
||||
### 매 비용 분석
|
||||
- **CPU 절감**: 매 N draw call → 1. 매 binding state 변경 N → 1.
|
||||
- **GPU 비용**: 매 동일 (vertex 처리 N×). 매 절감은 driver overhead 에서.
|
||||
- **Break-even**: 매 보통 ~50-100 instance 부터 이득. 매 이하면 batched geometry 가 더 빠를 수도.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 응용
|
||||
1. **Forest / vegetation** (10k trees).
|
||||
2. **Particle system** (smoke, sparks).
|
||||
3. **Crowd / NPC swarm**.
|
||||
4. **Voxel chunk rendering**.
|
||||
5. **UI marker overlay** (map pins).
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[Draw Call]], [[Frustum Culling]], BatchedMesh, [[Texture Atlas]], [[Level of Detail (LOD)]], [[Overdraw]]
|
||||
- **Projects/Contexts:** Three.js, [[WebGL]]/WebGPU Rendering, Babylon.js, [[Unity]] GPU [[Instancing]]
|
||||
- **Contradictions/Notes:**
|
||||
* "InstancedMesh를 사용하면 항상 성능이 향상된다고 가정하기 쉽지만, 소스는 매우 단순한 기하학(예: 단일 삼각형)의 경우 인스턴싱 변환 행렬 데이터를 처리하는 오버헤드가 더 커서 단순히 지오메트리를 병합(Merging)하는 방식이 오히려 프레임 레이트 측면에서 유리할 수 있다고 주장합니다 [32], [33]."
|
||||
* "드로우 콜 수가 극적으로 감소함에도 불구하고, 5,000개 수준의 객체 환경에서는 인스턴스 정렬 부재로 인한 오버드로우 비용이 CPU 이득을 상회하여 일반 메쉬 렌더링보다 낮은 FPS를 기록할 수 있다고 경고합니다 [18]."
|
||||
## 💻 패턴
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
### 1. 기본 InstancedMesh 셋업 (Three.js r172)
|
||||
```typescript
|
||||
import * as THREE from 'three';
|
||||
|
||||
---
|
||||
const geo = new THREE.BoxGeometry(1, 1, 1);
|
||||
const mat = new THREE.MeshStandardMaterial({ color: 0x88aaff });
|
||||
const COUNT = 10_000;
|
||||
const mesh = new THREE.InstancedMesh(geo, mat, COUNT);
|
||||
mesh.instanceMatrix.setUsage(THREE.DynamicDrawUsage); // 매 자주 업데이트면
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
const m = new THREE.Matrix4();
|
||||
const q = new THREE.Quaternion();
|
||||
const s = new THREE.Vector3(1, 1, 1);
|
||||
const p = new THREE.Vector3();
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(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
|
||||
for (let i = 0; i < COUNT; i++) {
|
||||
p.set((Math.random() - 0.5) * 200, 0, (Math.random() - 0.5) * 200);
|
||||
q.setFromAxisAngle(new THREE.Vector3(0, 1, 0), Math.random() * Math.PI * 2);
|
||||
m.compose(p, q, s);
|
||||
mesh.setMatrixAt(i, m);
|
||||
}
|
||||
mesh.instanceMatrix.needsUpdate = true;
|
||||
scene.add(mesh);
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### 2. Per-instance color (vertex color attribute)
|
||||
```typescript
|
||||
const colors = new Float32Array(COUNT * 3);
|
||||
for (let i = 0; i < COUNT; i++) {
|
||||
colors[i*3] = Math.random();
|
||||
colors[i*3+1] = Math.random();
|
||||
colors[i*3+2] = Math.random();
|
||||
}
|
||||
mesh.instanceColor = new THREE.InstancedBufferAttribute(colors, 3);
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### 3. Frustum culling per-instance (BVH-based)
|
||||
```typescript
|
||||
import { computeBoundsTree, MeshBVH } from 'three-mesh-bvh';
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
// 매 default InstancedMesh 는 whole-mesh frustum culling 만 함.
|
||||
// 매 instance-level 은 manual: BVH 로 visible instance 만 update.
|
||||
const bvh = new MeshBVH(geo);
|
||||
const visibleMatrices: THREE.Matrix4[] = [];
|
||||
const frustum = new THREE.Frustum().setFromProjectionMatrix(
|
||||
new THREE.Matrix4().multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse)
|
||||
);
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
let visibleCount = 0;
|
||||
for (let i = 0; i < COUNT; i++) {
|
||||
mesh.getMatrixAt(i, m);
|
||||
p.setFromMatrixPosition(m);
|
||||
if (frustum.containsPoint(p)) {
|
||||
mesh.setMatrixAt(visibleCount++, m);
|
||||
}
|
||||
}
|
||||
mesh.count = visibleCount; // 매 핵심: count 만 줄여 draw 절감
|
||||
mesh.instanceMatrix.needsUpdate = true;
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
### 4. WebGPU instancing (Three.js r172 WebGPURenderer)
|
||||
```typescript
|
||||
import { WebGPURenderer, MeshBasicNodeMaterial } from 'three/webgpu';
|
||||
import { instanceIndex, vec3, color } from 'three/tsl';
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
const mat = new MeshBasicNodeMaterial();
|
||||
// 매 TSL 로 per-instance color 계산
|
||||
mat.colorNode = color(vec3(
|
||||
instanceIndex.toFloat().div(COUNT).fract(),
|
||||
0.5,
|
||||
0.8
|
||||
));
|
||||
const mesh = new THREE.InstancedMesh(geo, mat, COUNT);
|
||||
```
|
||||
|
||||
### 5. LOD + InstancedMesh 결합
|
||||
```typescript
|
||||
class InstancedLOD {
|
||||
constructor(private high: THREE.InstancedMesh,
|
||||
private mid: THREE.InstancedMesh,
|
||||
private low: THREE.InstancedMesh) {}
|
||||
|
||||
update(camera: THREE.Camera, positions: THREE.Vector3[]) {
|
||||
let h = 0, m = 0, l = 0;
|
||||
const matrix = new THREE.Matrix4();
|
||||
for (const p of positions) {
|
||||
const d = p.distanceTo(camera.position);
|
||||
const target = d < 30 ? this.high : d < 100 ? this.mid : this.low;
|
||||
const idx = d < 30 ? h++ : d < 100 ? m++ : l++;
|
||||
matrix.setPosition(p);
|
||||
target.setMatrixAt(idx, matrix);
|
||||
}
|
||||
this.high.count = h; this.mid.count = m; this.low.count = l;
|
||||
[this.high, this.mid, this.low].forEach(x => x.instanceMatrix.needsUpdate = true);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6. GPU compute 로 instance 위치 (WebGPU)
|
||||
```typescript
|
||||
import { Fn, instanceIndex, storage, vec3, time } from 'three/tsl';
|
||||
import { compute } from 'three/tsl';
|
||||
|
||||
const positionBuffer = storage(new THREE.StorageBufferAttribute(COUNT, 3), 'vec3');
|
||||
|
||||
const updateFn = Fn(() => {
|
||||
const i = instanceIndex.toFloat();
|
||||
const t = time;
|
||||
positionBuffer.element(instanceIndex).assign(
|
||||
vec3(i.mul(0.1).sin().mul(50), t.add(i).sin().mul(5), i.mul(0.1).cos().mul(50))
|
||||
);
|
||||
});
|
||||
|
||||
const computePass = updateFn().compute(COUNT);
|
||||
renderer.computeAsync(computePass); // 매 frame 마다
|
||||
```
|
||||
|
||||
### 7. Memory layout 최적화 (matrix → quat+pos+scale)
|
||||
```typescript
|
||||
// 매 mat4 (16 floats × 4B = 64B) 대신 quat (4) + pos (3) + scale (1) = 32B
|
||||
const compactBuffer = new Float32Array(COUNT * 8);
|
||||
mesh.geometry.setAttribute('iQuat',
|
||||
new THREE.InstancedBufferAttribute(compactBuffer, 4, false, 1).setUsage(THREE.DynamicDrawUsage));
|
||||
// shader 에서 quat → matrix reconstruct
|
||||
```
|
||||
|
||||
### 8. Sort by depth (transparency)
|
||||
```typescript
|
||||
const indices = Array.from({length: COUNT}, (_, i) => i);
|
||||
indices.sort((a, b) => {
|
||||
mesh.getMatrixAt(a, m); const da = p.setFromMatrixPosition(m).distanceTo(camera.position);
|
||||
mesh.getMatrixAt(b, m); const db = p.setFromMatrixPosition(m).distanceTo(camera.position);
|
||||
return db - da; // 매 back-to-front
|
||||
});
|
||||
const sorted = new Float32Array(COUNT * 16);
|
||||
for (let i = 0; i < COUNT; i++) {
|
||||
mesh.getMatrixAt(indices[i], m);
|
||||
m.toArray(sorted, i * 16);
|
||||
}
|
||||
mesh.instanceMatrix.array.set(sorted);
|
||||
mesh.instanceMatrix.needsUpdate = true;
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| Static, identical mesh × thousands | `InstancedMesh` |
|
||||
| Static, varied meshes | `BatchedMesh` (Three.js r158+) |
|
||||
| 매 < 50 instance | 매 그냥 separate Mesh, 차이 없음 |
|
||||
| 매 frequent matrix update | `setUsage(DynamicDrawUsage)` + partial `updateRange` |
|
||||
| Per-instance custom data | `InstancedBufferAttribute` |
|
||||
| GPU-driven motion | TSL compute + storage buffer |
|
||||
|
||||
**기본값**: 매 ≥100 identical instance → InstancedMesh + DynamicDrawUsage + frustum culling.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Three.js]] · [[GPU Instancing]] · [[WebGL/WebGPU]]
|
||||
- 변형: [[BatchedMesh]] · [[InstancedBufferGeometry]]
|
||||
- 응용: [[Particle Systems]] · [[Vegetation Rendering]] · [[Voxel Engines]]
|
||||
- Adjacent: [[InstancedMesh 동적 버퍼 확장]] · [[Frustum Culling]] · [[LOD]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: instance 수에 따른 기법 선택, draw call 분석 해석, TSL compute shader 작성.
|
||||
**언제 X**: 매 specific GPU/driver bug 진단 (실측 profile 없이).
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **매 frame 마다 setMatrixAt 전체 N**: 매 변하지 않는 instance 까지 update → CPU bound. 매 dirty flag 사용.
|
||||
- **DynamicDrawUsage 빠뜨림**: 매 default StaticDrawUsage 면 매 update 시 driver hint mismatch.
|
||||
- **count 줄이지 않고 culling**: 매 invisible 도 vertex shader 실행됨.
|
||||
- **너무 작은 N (< 50)**: 매 instancing overhead 가 이득보다 큼.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Three.js r172 docs, WebGPU spec, Khronos WebGL2 spec).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — InstancedMesh 패턴 + WebGPU TSL compute |
|
||||
|
||||
@@ -2,91 +2,150 @@
|
||||
id: wiki-2026-0508-interop-2025
|
||||
title: Interop 2025
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-48DB08]
|
||||
aliases: [Web Interop 2025]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [web-platform, browser, standards]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Interop 2025"
|
||||
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: HTML/CSS/JavaScript
|
||||
framework: Web Platform
|
||||
---
|
||||
|
||||
# [[Interop 2025]]
|
||||
# Interop 2025
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Interop 2025는 주로 [[Chrome]]에 국한되어 있던 핵심 웹 지표([[Core Web Vitals]])를 다른 주요 웹 브라우저로 확대 지원하여 호환성을 높이기 위해 시작된 프로젝트입니다[1]. 이 프로젝트를 통해 Firefox와 Safari 같은 브라우저들이 특정 웹 성능 지표에 대한 지원 및 구현 작업을 본격적으로 시작하게 되었습니다[1]. 이를 통해 다양한 브라우저 환경에서 웹 성능을 일관되게 측정할 수 있는 기반이 마련되기 시작했습니다.
|
||||
## 매 한 줄
|
||||
> **"매 browser vendor 들이 매년 합의하여 fix 하는 web platform inconsistency list"**. Apple, Google, Microsoft, Mozilla, Bocoup, Igalia 가 공동으로 select 한 focus area 를 1년간 implement, web-platform-tests pass rate 의 dashboard 로 progress 의 track. 2025 cycle 의 anchor positioning, scrollbar styling, navigation API, View Transitions cross-document, storage access API 가 highlight.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **핵심 웹 지표(Core Web Vitals)의 크로스 브라우저 확장**: 기존의 핵심 웹 지표들은 대부분 Chrome 전용 측정 항목(Chrome-only metrics)으로 사용되고 있었으나, Interop 2025 프로젝트를 기점으로 이러한 한계가 변화하기 시작했습니다[1].
|
||||
- **주요 브라우저의 참여 및 지표 구현**: Interop 2025 프로젝트의 일환으로 Firefox와 Safari는 핵심 웹 지표 중 '최대 콘텐츠 풀 페인트(Largest Contentful Paint, LCP)'와 '다음 페인트에 대한 상호작용(Interaction to Next Paint, INP)'을 지원하기 위한 작업을 시작했습니다[1].
|
||||
- **누적 레이아웃 이동(CLS) 지원 보류**: 또 다른 주요 지표인 '누적 레이아웃 이동(Cumulative Layout [[Shift]], CLS)'에 대한 지원은 Interop 2025 계획에 현재 포함되어 있지 않습니다[1]. 다만, 이를 후속 프로젝트인 [[Interop 2026]]에 포함하려는 제안이 존재합니다[1].
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 origin & process
|
||||
- 2021 Compat 2021 시작, 2022 부터 "Interop" 명칭.
|
||||
- 매년 vendor 공동 선정 + community proposal.
|
||||
- WPT (web-platform-tests) score 로 measure — wpt.fyi dashboard.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[Core Web Vitals]], Largest Contentful Paint, Interaction to Next Paint, Cumulative Layout Shift
|
||||
- **Projects/Contexts:** [[Interop 2026]]
|
||||
- **Contradictions/Notes:** 소스에 관련 정보가 부족합니다. (특별한 모순이나 상충하는 의견은 발견되지 않음)
|
||||
### 매 Interop 2025 의 focus areas
|
||||
- **Anchor positioning** (CSS): tooltip/popover 의 declarative anchor.
|
||||
- **View Transitions cross-document**: MPA 도 SPA 같은 transition.
|
||||
- **Scrollbar gutter / colors**: scrollbar styling cross-browser.
|
||||
- **Navigation API**: history API replacement.
|
||||
- **Storage Access API**: cross-site cookie consent flow.
|
||||
- **Container queries** (residual gaps).
|
||||
- **Custom highlights API**: native highlight rendering.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
### 매 응용
|
||||
1. Web feature 의 production-safe baseline 결정 (Baseline initiative 와 align).
|
||||
2. Polyfill / progressive enhancement strategy 의 기준.
|
||||
3. Browser team 의 quarterly priority.
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
### Anchor positioning (CSS)
|
||||
```css
|
||||
/* Trigger */
|
||||
.btn { anchor-name: --my-anchor; }
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(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
|
||||
/* Popover positioned relative to anchor */
|
||||
.tooltip {
|
||||
position: absolute;
|
||||
position-anchor: --my-anchor;
|
||||
top: anchor(bottom);
|
||||
left: anchor(center);
|
||||
translate: -50% 8px;
|
||||
}
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### View Transitions cross-document
|
||||
```html
|
||||
<!-- both pages opt in -->
|
||||
<meta name="view-transition" content="same-origin">
|
||||
<style>
|
||||
@view-transition { navigation: auto; }
|
||||
.hero { view-transition-name: hero; }
|
||||
</style>
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Navigation API
|
||||
```javascript
|
||||
navigation.addEventListener('navigate', (e) => {
|
||||
if (!e.canIntercept || e.hashChange) return
|
||||
e.intercept({
|
||||
handler: async () => {
|
||||
const data = await fetch(e.destination.url).then(r => r.json())
|
||||
render(data)
|
||||
},
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Storage Access API
|
||||
```javascript
|
||||
// inside iframe — request 1P-like cookie access
|
||||
if (await document.hasStorageAccess() === false) {
|
||||
try {
|
||||
await document.requestStorageAccess()
|
||||
} catch (e) { /* user denied */ }
|
||||
}
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### Scrollbar styling (modern)
|
||||
```css
|
||||
.list {
|
||||
scrollbar-gutter: stable both-edges;
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--thumb) transparent;
|
||||
}
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
### Feature detect via Baseline / `@supports`
|
||||
```css
|
||||
@supports (anchor-name: --x) {
|
||||
.tooltip { position-anchor: --my-anchor; }
|
||||
}
|
||||
@supports not (anchor-name: --x) {
|
||||
.tooltip { /* fallback positioning JS */ }
|
||||
}
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| New feature production use | Interop 2025 list + Baseline check |
|
||||
| 필요한 feature 가 still red | polyfill or feature flag |
|
||||
| Cross-browser bug found | wpt.fyi 에 issue file |
|
||||
| Greenfield SPA | Navigation API 채택 검토 |
|
||||
| Tooltip / popover | Anchor positioning + popover API |
|
||||
|
||||
**기본값**: 매 Baseline Newly Available + Interop 2025 통과 feature 만 의 default 사용.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Web Platform Standards]]
|
||||
- 변형: [[Interop 2024]] · [[Interop 2026]]
|
||||
- 응용: [[CSS Anchor Positioning]] · [[View Transitions API]] · [[Navigation API]]
|
||||
- Adjacent: [[Chromium]] · [[web-platform-tests]] · [[Baseline]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 web platform feature 의 cross-browser readiness 의 query, polyfill strategy, modern CSS/JS adoption 결정.
|
||||
**언제 X**: server-side, native, non-browser runtime.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Single-vendor preview 의 production**: Chrome canary 만 의 working ≠ ship-ready.
|
||||
- **WPT pass = bug-free 의 가정**: real-world edge case 는 WPT 가 다 cover X.
|
||||
- **Polyfill 의 무지성 적용**: native 가 ship 된 후에도 polyfill 유지 = bundle bloat.
|
||||
- **Interop list 의 구속**: list 외 의 feature 도 needed 면 채택 가능 — list 는 priority 일 뿐.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (web.dev/interop-2025, wpt.fyi/interop-2025, vendor blog posts 2025).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — Interop 2025 focus areas + adoption patterns |
|
||||
|
||||
@@ -2,91 +2,151 @@
|
||||
id: wiki-2026-0508-inventory-management-example
|
||||
title: Inventory Management Example
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-9C355C]
|
||||
aliases: [Inventory Domain Model, 재고 관리 예제]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
source_trust_level: B
|
||||
confidence_score: 0.85
|
||||
verification_status: applied
|
||||
tags: [example, domain-modeling, typescript, ddd]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Inventory [[Management]] Example"
|
||||
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: Zod
|
||||
---
|
||||
|
||||
# [[Inventory Management Example]]
|
||||
# Inventory Management Example
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> 이 주제는 프론트엔드 모델과 백엔드 응답 간의 데이터 변환 시 발생할 수 있는 타입 불일치 문제를 보여주는 실제 사례입니다. 인벤토리 관리 시스템에서 백엔드의 데이터 형식과 프론트엔드의 정의된 타입 구조가 다를 때 발생할 수 있는 매핑 오류의 위험성을 다룹니다. TypeScript의 `satisfies` 키워드를 사용하여 엄격한 속성 검사를 강제함으로써 오타나 원치 않는 초과 필드의 포함을 방지하는 방법을 설명합니다.
|
||||
## 매 한 줄
|
||||
> **"매 SKU · stock · reservation 의 type-safe domain model 의 walking example"**. 매 branded types · discriminated unions · runtime validation 매 결합 — 2026 modern TS pattern 의 canonical illustration.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **데이터 구조의 차이**: 인벤토리 관리 시스템에서 프론트엔드는 `id`, `name`, `quantity` 속성을 가진 `InventoryItem` 타입을 정의하여 사용합니다 [1, 2]. 그러나 외부 백엔드에서 전달되는 데이터는 `qty`나 `lastUpdated`와 같이 프론트엔드 타입과 다른 형식으로 도착할 수 있습니다 [2].
|
||||
- **매핑 오류와 조용한 실패**: 백엔드 데이터를 프론트엔드 타입으로 매핑할 때, 속성 이름을 잘못 입력하거나(`quantity` 대신 `qty` 사용 등) 불필요한 필드를 포함하는 등의 오류가 쉽게 발생할 수 있습니다 [2]. 엄격한 검사가 없다면 TypeScript는 이러한 오타를 잡아내지 못할 수 있으며, 조용히 오류를 통과시킬 위험이 있습니다 [2].
|
||||
- **`satisfies` 키워드를 통한 엄격성 강제**: 데이터 매핑 함수 내에서 `satisfies` 키워드를 사용하면 엄격한 타입 계약을 강제할 수 있습니다 [3]. 이를 통해 대상 타입에 정의된 유효한 속성만 포함되도록 보장하며, 그렇지 않을 경우 발생할 수 있는 초과 속성 문제나 오타를 컴파일 단계에서 포착하여 방지할 수 있습니다 [3, 4].
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 도메인 entities
|
||||
- `SKU` (branded string)
|
||||
- `Stock` (positive int)
|
||||
- `Reservation` (id, sku, qty, expiresAt)
|
||||
- `InventoryEvent` (Tagged: Received | Reserved | Shipped | Cancelled)
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[satisfies Keyword]], [[Excess Property Checking]], [[Type Casting]]
|
||||
- **Projects/Contexts:** [[Frontend]]-[[Backend]] Data Transformation
|
||||
- **Contradictions/Notes:** 소스는 데이터 변환 시 `as` 키워드를 사용한 타입 캐스팅에 의존하는 것을 경고합니다. 타입 캐스팅은 초과 속성 검사를 우회하여 조용한 오류(silent errors)와 의도치 않은 동작을 유발할 수 있으므로, 엄격한 계약을 강제하기 위해서는 `satisfies`를 사용하는 것이 더 안전합니다 [3, 4].
|
||||
### 매 invariants
|
||||
- 매 stock ≥ 0 항상.
|
||||
- 매 reservation 의 release 후 stock 회복.
|
||||
- 매 ship 의 reservation 의 존재 시.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
### 매 응용
|
||||
1. E-commerce checkout flow (재고 차감 · 복구).
|
||||
2. Warehouse management (multi-location).
|
||||
3. Event-sourced inventory ledger.
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
### Branded SKU
|
||||
```ts
|
||||
type SKU = string & { readonly __brand: "SKU" }
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(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
|
||||
const SkuSchema = z.string().regex(/^[A-Z]{3}-\d{6}$/).brand("SKU")
|
||||
const sku = SkuSchema.parse("ABC-123456") // SKU
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### Stock value object
|
||||
```ts
|
||||
class Stock {
|
||||
private constructor(public readonly value: number) {}
|
||||
static of(n: number): Stock {
|
||||
if (!Number.isInteger(n) || n < 0) throw new Error("invalid stock")
|
||||
return new Stock(n)
|
||||
}
|
||||
reserve(qty: number): Stock { return Stock.of(this.value - qty) }
|
||||
release(qty: number): Stock { return Stock.of(this.value + qty) }
|
||||
}
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Discriminated event union
|
||||
```ts
|
||||
type InventoryEvent =
|
||||
| { type: "Received"; sku: SKU; qty: number; at: Date }
|
||||
| { type: "Reserved"; sku: SKU; qty: number; reservationId: string }
|
||||
| { type: "Shipped"; reservationId: string }
|
||||
| { type: "Cancelled"; reservationId: string }
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
function reduce(state: Map<SKU, Stock>, e: InventoryEvent): Map<SKU, Stock> {
|
||||
switch (e.type) {
|
||||
case "Received":
|
||||
return new Map(state).set(e.sku, (state.get(e.sku) ?? Stock.of(0)).release(e.qty))
|
||||
case "Reserved":
|
||||
return new Map(state).set(e.sku, state.get(e.sku)!.reserve(e.qty))
|
||||
case "Shipped":
|
||||
case "Cancelled":
|
||||
return state
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### Reservation lifecycle (Result type)
|
||||
```ts
|
||||
type Result<T, E> = { ok: true; value: T } | { ok: false; error: E }
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
function reserve(stock: Stock, qty: number): Result<Stock, "INSUFFICIENT"> {
|
||||
if (stock.value < qty) return { ok: false, error: "INSUFFICIENT" }
|
||||
return { ok: true, value: stock.reserve(qty) }
|
||||
}
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### Zod runtime parse (API boundary)
|
||||
```ts
|
||||
const ReserveCmd = z.object({
|
||||
sku: SkuSchema,
|
||||
qty: z.number().int().positive(),
|
||||
customerId: z.string().uuid(),
|
||||
})
|
||||
|
||||
app.post("/reserve", (req, res) => {
|
||||
const cmd = ReserveCmd.safeParse(req.body)
|
||||
if (!cmd.success) return res.status(400).json(cmd.error.flatten())
|
||||
// ... cmd.data is fully typed
|
||||
})
|
||||
```
|
||||
|
||||
### Exhaustive switch guard
|
||||
```ts
|
||||
function never(x: never): never { throw new Error(`unhandled: ${x}`) }
|
||||
// switch default → never(e) 매 새 event 추가 시 compile error
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| Single-location inventory | In-memory `Map<SKU, Stock>` |
|
||||
| Multi-location | Add `LocationId` brand · partition state |
|
||||
| Audit-required | Event sourcing (full event log) |
|
||||
| High-concurrency | Optimistic concurrency token + retry |
|
||||
|
||||
**기본값**: event-sourced reduce 매 audit + replay benefit. 매 단순 case도 future-proof.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Domain-Driven Design]] · [[견고한 도메인 모델 및 API 계약 설계]]
|
||||
- 변형: [[Result Type]] · [[Discriminated Unions]]
|
||||
- 응용: [[Zod 파싱과 브랜디드 타입을 결합한 런타임 데이터 검증]]
|
||||
- Adjacent: [[브랜디드 타입 (Branded Types)]] · [[ts-brand]] · [[완전성 검사(Exhaustiveness Checking)]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 type-safe domain modeling 의 teaching example 으로 reuse.
|
||||
**언제 X**: 매 production app 의 직접 copy — 매 oversimplified.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Plain `number` for stock**: 매 invariant 의 enforce 의 X — class · brand 의 사용.
|
||||
- **Stringly-typed events**: 매 discriminated union 의 사용.
|
||||
- **Skipping runtime parse at boundary**: 매 type erasure 후 — Zod / Effect Schema 의 필수.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (DDD blue book · Effect/Zod docs · TypeScript handbook 2026).
|
||||
- 신뢰도 B (illustrative example, not canonical implementation).
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — full domain example with brands · DU · event sourcing |
|
||||
|
||||
@@ -1,95 +1,34 @@
|
||||
---
|
||||
id: wiki-2026-0508-mark-sweep-compact-알고리즘
|
||||
title: Mark Sweep Compact 알고리즘
|
||||
title: Mark-Sweep-Compact 알고리즘
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-AF3315]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: garbage-collection
|
||||
duplicate_of: "[[Garbage Collection]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - [[Mark-Sweep]]-Compact 알고리즘"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, gc, v8, memory]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[Mark-Sweep-Compact 알고리즘]]
|
||||
# Mark-Sweep-Compact 알고리즘
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Mark-Sweep-Compact 알고리즘은 애플리케이션의 힙 메모리에서 더 이상 사용되지 않는 객체를 식별하여 메모리를 회수하고, 발생한 메모리 단편화를 해결하는 주요 가비지 컬렉션(GC) 기법입니다 [1]. 도달 가능한 객체를 식별하여 표시하는 마크(Mark) 단계, 참조되지 않는 죽은 객체의 메모리를 회수하는 스윕(Sweep) 단계, 그리고 살아남은 객체들을 모아 힙 메모리 단편화를 줄이는 컴팩트(Compact) 단계로 이루어집니다 [1]. 이 알고리즘은 주로 V8 엔진의 Old Generation이나 JVM의 전역 힙(Java heap)을 정리하는 데 활용되며, 메모리 효율성을 극대화하지만 객체 이동에 따른 비용이 크다는 특징이 있습니다 [2], [3], [4].
|
||||
> **이 문서는 [[Garbage Collection]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **마크(Mark) 단계**: 루트(Root) 객체에서 시작하여 포인터를 통해 도달할 수 있는 모든 살아있는(live) 객체를 식별하고 마크합니다 [5], [1].
|
||||
- V8 엔진에서는 객체의 마크 상태를 3가지 상태(흰색: 아직 발견되지 않음, 회색: 발견되었으나 이웃 미처리, 검은색: 모든 이웃 객체 처리 완료)로 구분하며, 힙을 객체와 포인터로 연결된 방향 그래프로 간주하여 깊이 우선 탐색(DFS) 방식으로 순회합니다 [6], [5].
|
||||
- JVM 환경에서는 마크 맵(mark map)이라는 비트 배열을 사용하여 각 객체가 도달 가능한 상태인지 그 위치를 기록합니다 [7].
|
||||
- **스윕(Sweep) 단계**: 마크 단계 완료 후 마크되지 않은(흰색) 죽은 객체들의 범위를 찾아 빈 공간으로 변환하여 회수합니다 [8], [9]. 이렇게 확보된 영역들은 각 크기에 따라 분리된 여유 목록(free lists)에 추가되어 이후 새로운 객체 할당이나 객체 이주를 위한 공간으로 재사용됩니다 [8].
|
||||
- **컴팩트(Compact) 단계**: 살아있는 객체들을 다른 페이지의 빈 공간으로 이동시켜 단편화된 메모리 페이지(작은 빈 공간이 많은 상태)의 실제 사용량을 줄이고 최적화합니다 [10], [11]. 이 단계에서는 기존 객체를 복사하고 원본의 첫 단어 자리에 포워딩 주소(forwarding address)를 남기며, 이주가 끝나면 관련된 모든 포인터를 새로운 복사본의 위치로 업데이트합니다 [10].
|
||||
- **성능과 실행 특징**: 스윕 알고리즘은 각 페이지의 마크 비트맵을 순회하며 마크되지 않은 객체의 범위를 찾기만 하므로 매우 간단합니다 [8]. 반면 컴팩트 작업은 살아있는 대량의 객체를 이동시키고 이 객체들을 가리키는 모든 참조([[Reference]]) 값을 변경해야 하므로 연산 비용이 매우 큽니다 [3], [4]. 따라서 컴팩트 작업은 매번 수행되지 않고 힙이 심하게 단편화되었거나 메모리 할당 실패가 발생하는 등 선택적이고 필수적인 상황에서만 실행되도록 제어됩니다 [3], [4].
|
||||
## 핵심 요약 (specialization aspects)
|
||||
- 매 Mark-Sweep-Compact 는 V8 Old Space 의 major GC 알고리즘.
|
||||
- 매 3-phase: Mark (live obj 표시) → Sweep (dead 제거) → Compact (fragmentation 해소).
|
||||
- 매 stop-the-world 의 X — Orinoco 의 incremental + concurrent 의 mix.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
## 🔗 Graph
|
||||
- 부모: [[Garbage Collection]] (canonical)
|
||||
- Adjacent: [[Orinoco 가비지 컬렉터]] · [[Old Space]] · [[Incremental Marking]] · [[Write Barrier]]
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[Garbage Collection]], [[V8 Engine]], [[Old Space]], Java Heap [[memory]]
|
||||
- **Projects/Contexts:** V8 엔진의 Old Generation 메모리 관리, IBM JVM의 가비지 컬렉션 메커니즘
|
||||
- **Contradictions/Notes:** 컴팩트(Compact) 작업은 단편화를 해결하여 캐시 지역성(cache locality)을 높이지만, 포인터 재조정과 객체 이동 비용으로 인해 애플리케이션의 '[[Stop-the-world]](STW)' 일시 중지 시간을 증가시킬 수 있습니다 [3]. 이를 보완하기 위해 V8 엔진은 객체 그래프가 변경될 가능성을 쓰기 장벽([[Write Barrier]])으로 제어하며 점진적 마킹([[Incremental Marking]]) 및 지연 스윕(Lazy sweeping) 기술을 도입하여 메인 스레드 멈춤 시간을 줄이고 있습니다 [12], [13], [14].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -1,25 +1,34 @@
|
||||
---
|
||||
id: wiki-20260508-netflix--redir
|
||||
title: Netflix 마이크로서비스 전환
|
||||
category: Programming & Language
|
||||
status: merged
|
||||
redirect_to: Netflix_마이크로서비스_전환
|
||||
canonical_id: Netflix_마이크로서비스_전환
|
||||
category: 10_Wiki/Topics
|
||||
status: duplicate
|
||||
canonical_id: netflix-cosmos-platform
|
||||
duplicate_of: "[[Netflix 마이크로서비스 및 코스모스 플랫폼 전환]]"
|
||||
aliases: []
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [redirect]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
confidence_score: 0.9
|
||||
verification_status: redirected
|
||||
tags: [duplicate, netflix, microservices, architecture]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-merge 2026-05-08)
|
||||
---
|
||||
|
||||
# Netflix 마이크로서비스 전환
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 이 문서는 P-Reinforce Phase 2 자동 MERGE에 의해 **[[Netflix_마이크로서비스_전환]]**로 통합되었습니다.
|
||||
> **이 문서는 [[넷플릭스(Netflix)의 마이크로서비스 및 코스모스 플랫폼 전환]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
---
|
||||
*Redirected to: [[Netflix_마이크로서비스_전환]]*
|
||||
## 핵심 요약
|
||||
- 매 Netflix 의 monolith → microservices 전환 (2008-2016).
|
||||
- 매 Cosmos 플랫폼: 매 next-gen media processing — workflow + service 의 통합.
|
||||
- 매 OSS 산출물: Eureka, Hystrix, Zuul, Chaos Monkey.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[넷플릭스(Netflix)의 마이크로서비스 및 코스모스 플랫폼 전환]] (canonical)
|
||||
- Adjacent: [[Cosmos 플랫폼 (Netflix)]] · [[넷플릭스 코스모스 플랫폼 (Netflix Cosmos)]]
|
||||
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -2,108 +2,33 @@
|
||||
id: wiki-2026-0508-nodejs-메모리-최적화
|
||||
title: Nodejs 메모리 최적화
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-4670EE]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: nodejs-performance
|
||||
duplicate_of: "[[Nodejs 성능 최적화 및 디버깅]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - [[Nodejs]] 메모리 최적화"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, nodejs, memory, performance]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[Nodejs 메모리 최적화]]
|
||||
# Nodejs 메모리 최적화
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Node.js는 V8 엔진을 기반으로 실행되는 단일 프로세스이므로, 시간이 지남에 따라 메모리 누수가 지속적으로 누적될 수 있어 효율적인 메모리 관리가 필수적입니다 [1]. 정상적인 상태의 힙 메모리 사용량은 가비지 컬렉션(GC) 이후 원래 수준으로 돌아가는 톱니바퀴(sawtooth) 패턴을 보이지만, 메모리 누수가 발생하면 반환되지 않고 지속적으로 상승하는 래칫(ratchet) 패턴을 그립니다 [2]. 메모리 최적화는 각종 힙 프로파일링 도구와 명령줄 플래그를 활용하여 애플리케이션의 누수 패턴을 찾아 해결하고, GC 설정 및 힙 공간 크기를 튜닝하여 시스템의 안정성과 성능을 극대화하는 과정입니다 [2-4].
|
||||
> **이 문서는 [[Nodejs 성능 최적화 및 디버깅]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
**V8 메모리 구조 및 가비지 컬렉션(GC)**
|
||||
* Node.js의 V8 엔진은 메모리를 힙(Heap)과 스택(Stack)으로 나누어 관리합니다 [5]. 스택은 지역 변수 및 함수 호출 프레임을 후입선출(LIFO) 원칙에 따라 관리하며, 힙은 동적으로 생성된 자바스크립트 객체와 데이터가 저장되는 곳으로 가비지 컬렉터의 주요 관리 대상이 됩니다 [6, 7].
|
||||
* 세대별 가설([[Generational Hypothesis]])에 기반하여 힙은 '새로운 공간(New Space)'과 '오래된 공간([[Old Space]])'으로 나뉩니다 [5]. New Space에서는 단기 객체가 할당되며, 가볍고 빠른 마이너 GC([[Scavenge]]r)가 자주 실행되어 사용되지 않는 메모리를 회수합니다 [5, 8].
|
||||
* New Space에서 여러 번의 GC 주기를 생존한 객체들은 장기 보존 데이터로 간주되어 Old Space로 승격(Promotion)되며, 이 영역은 무겁지만 덜 빈번하게 실행되는 메이저 GC([[Mark-Sweep]]-Compact 알고리즘)를 통해 관리됩니다 [5, 9, 10].
|
||||
## 핵심 요약
|
||||
- 매 V8 heap tuning: `--max-old-space-size`, `--max-semi-space-size`.
|
||||
- 매 leak detection: heap snapshot diff, allocation timeline.
|
||||
- 매 production: `clinic.js`, `0x` flamegraph, `node --inspect`.
|
||||
|
||||
**메모리 누수 감지 및 모니터링**
|
||||
* `process.[[memory]]Usage()`를 사용하면 RSS(Resident Set Size), `heapTotal`, `heapUsed` 등의 수치를 통해 실행 중인 프로세스의 메모리 상태를 파악할 수 있습니다 [11].
|
||||
* 상용 환경에서는 `prom-client`를 통해 메모리 메트릭을 추출하고 Grafana와 같은 도구로 경고 규칙(Alert rule)을 설정하여, 메모리 부족(OOM) 크래시가 발생하기 전 누수를 조기 감지하는 것이 좋습니다 [12].
|
||||
* 누수가 의심될 때는 `--inspect` 플래그를 통해 [[Chrome DevTools]]에 연결하여 객체 할당 타임라인을 기록하거나, `heapdump` 라이브러리 및 `--heap-prof` 플래그를 활용해 힙 스냅샷을 캡처하여 추적할 수 있습니다 [2, 12, 13]. 트래픽 발생 전후의 두 가지 힙 스냅샷을 비교하면 반환되지 않고 남아 있는 메모리 할당 객체들을 정확히 찾아낼 수 있습니다 [13].
|
||||
## 🔗 Graph
|
||||
- 부모: [[Nodejs 성능 최적화 및 디버깅]] (canonical)
|
||||
- Adjacent: [[Nodejs 메모리 튜닝]] · [[브라우저 및 Nodejs 메모리 튜닝]] · [[Garbage Collection]]
|
||||
|
||||
**자주 발생하는 메모리 누수 원인과 해결 패턴**
|
||||
* **이벤트 리스너 누적:** `on('event', fn)` 호출 후 리스너를 명시적으로 제거하지 않아 발생하며, 단일 이벤트 발생기에 리스너가 10개를 초과하면 `MaxListenersExceededWarning`이 발생하여 누수를 강력히 암시합니다 [14, 15].
|
||||
* **클로저(Closure) 변수 유지:** 요청 및 응답 객체 전체와 같은 커다란 변수가 클로저에 캡처된 상태로 콜백이나 비동기 체인 내에 남겨지면 가비지 컬렉터가 이를 수집하지 못합니다 [15].
|
||||
* **무제한 캐시 및 잊혀진 타이머:** 인메모리 캐시를 사용할 때 한도를 설정하지 않거나, `setInterval`로 생성된 타이머를 `clearInterval`로 정리하지 않으면 연관된 클로저 전체가 메모리에 영구적으로 보존됩니다 [15, 16].
|
||||
* **종료되지 않은 스트림과 소켓:** 스트림이나 네트워크 핸들의 응답 본문을 다 소비하지 않은 경우, 내부 버퍼가 유지되므로 반드시 `cancel()`이나 `destroy()`를 호출해 정리해야 합니다 [16].
|
||||
|
||||
**메모리 튜닝용 명령줄 플래그(CLI Flags)**
|
||||
* `--max-old-space-size`: Old Space의 한계를 메가바이트(MB) 단위로 설정하며, 대량의 데이터 배치 처리나 많은 사용자 세션 등 메모리 소모가 큰 애플리케이션의 성능 저하 및 OOM 방지에 사용됩니다 [4].
|
||||
* `--max-semi-space-size`: New Space의 크기를 조절하며, 단기 객체(예: API 요청마다 생성되는 임시 객체)가 대량으로 생성되는 환경에서 늘려주면 잦은 마이너 GC 실행을 줄여 전반적인 성능을 높일 수 있습니다 [17].
|
||||
* `--gc-interval` 및 `--expose-gc`: 가비지 컬렉션의 빈도를 강제로 조정하거나, 프로그램 내부에서 `global.gc()`를 호출해 수동으로 가비지 컬렉션을 실행할 수 있도록 하는 옵션입니다 [18-20].
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[V8 [[JavaScript]] Engine]], [[Garbage Collection]] (GC), [[Heap Snapshot]]
|
||||
- **Projects/Contexts:** [[Chrome DevTools Memory Profiling]], Node.js Production Environments
|
||||
- **Contradictions/Notes:** `--expose-gc` 플래그를 통한 수동 가비지 컬렉션 호출(`global.gc()`)은 대량의 데이터 처리 후 즉시 메모리를 회수해야 하는 특수 상황에서 유용할 수 있지만, 일반적인 V8의 자동 GC 메커니즘을 대체하는 것은 아니며 남용 시 과도한 GC 사이클 실행으로 인해 애플리케이션 성능을 크게 저하시킬 위험이 있습니다 [20].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -2,111 +2,33 @@
|
||||
id: wiki-2026-0508-nodejs-메모리-튜닝
|
||||
title: Nodejs 메모리 튜닝
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-EA5D5E]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: nodejs-performance
|
||||
duplicate_of: "[[Nodejs 성능 최적화 및 디버깅]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - [[Nodejs]] 메모리 튜닝"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, nodejs, memory, tuning]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[Nodejs 메모리 튜닝]]
|
||||
# Nodejs 메모리 튜닝
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Node.js 메모리 튜닝은 V8 자바스크립트 엔진의 메모리 구조와 가비지 컬렉션(GC) 메커니즘을 이해하고, 이를 최적화하여 애플리케이션의 성능 저하 및 메모리 누수를 방지하는 과정을 의미합니다 [1, 2]. 개발자는 `--max-old-space-size`와 같은 커맨드라인 플래그를 활용해 힙(Heap) 공간을 조절하거나, `process.[[memory]]Usage()`, 힙 스냅샷 등의 도구를 사용하여 비효율적인 메모리 할당 및 해제되지 않은 참조를 추적할 수 있습니다 [3-5]. 결과적으로 주기적인 메모리 모니터링과 올바른 튜닝은 Out-Of-Memory(OOM) 충돌을 예방하고 애플리케이션의 응답 속도를 일정하게 유지하는 데 핵심적인 역할을 합니다 [6, 7].
|
||||
> **이 문서는 [[Nodejs 성능 최적화 및 디버깅]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **V8 엔진의 메모리 구조와 세대별 가비지 컬렉션**
|
||||
* V8은 메모리를 스택(Stack)과 힙(Heap)으로 분리하여 관리합니다 [8-10]. 스택은 원시 값과 함수 호출 프레임을 저장하며, 힙은 동적 데이터(객체)를 보관합니다 [10-12].
|
||||
* 힙 영역은 객체의 수명에 따라 '[[New Space(Young Generation)]]'와 '[[Old Space(Old Generation)]]'로 나뉩니다 [9, 13].
|
||||
* **Minor GC ([[Scavenge]]r):** 짧은 수명의 객체가 할당되는 New Space를 관리하며, 도달할 수 없는 객체를 자주, 그리고 매우 빠르게 정리합니다 [9, 13, 14].
|
||||
* **[[Major GC]] ([[Mark-Sweep]]-Compact):** Minor GC를 여러 번 생존한 객체들은 [[Old Space]]로 이동(Promotion)하며, 메모리가 부족해질 때 Mark-Sweep 및 Mark-Compact 알고리즘을 통해 사용되지 않는 메모리를 확보하고 단편화를 제거합니다 [13, 15-18].
|
||||
## 핵심 요약
|
||||
- 매 heap size flag: `--max-old-space-size=4096` 의 default 1.5GB 의 확장.
|
||||
- 매 GC tuning: `--expose-gc`, `--trace-gc`, `--trace-gc-verbose`.
|
||||
- 매 container 환경: 매 cgroup memory limit 의 인지 — `--max-old-space-size` 의 manual 설정 필요.
|
||||
|
||||
* **메모리 튜닝을 위한 커맨드라인 플래그**
|
||||
* `--max-old-space-size`: 수명이 긴 객체들이 저장되는 Old Space의 최대 한도를 설정합니다. 캐시나 대규모 세션 데이터를 유지하는 애플리케이션에서 OOM 에러를 방지하기 위해 이 값을 증가시킬 수 있습니다 [5, 19].
|
||||
* `--max-semi-space-size`: New Space의 크기를 조절합니다. 고트래픽 API 서버처럼 수명이 짧은 임시 객체가 대량으로 생성되는 환경에서 이 값을 늘리면 Minor GC 발생 빈도를 줄여 성능을 향상할 수 있습니다 [19, 20].
|
||||
* `--gc-interval`: GC 주기를 강제로 조정할 수 있으나, 과도하게 낮추면 GC가 빈번하게 발생하여 성능 저하를 유발할 수 있습니다 [20, 21].
|
||||
* `--expose-gc`: 코드 내에서 `global.gc()`를 통해 수동으로 GC를 트리거할 수 있게 해 주지만, 잦은 호출은 성능에 악영향을 미치므로 주의해서 사용해야 합니다 [21, 22].
|
||||
## 🔗 Graph
|
||||
- 부모: [[Nodejs 성능 최적화 및 디버깅]] (canonical)
|
||||
- Adjacent: [[Nodejs 메모리 최적화]] · [[브라우저 및 Nodejs 메모리 튜닝]] · [[V8 엔진 힙 아키텍처]]
|
||||
|
||||
* **메모리 누수 감지 및 모니터링 도구**
|
||||
* **`process.memoryUsage()`:** rss(Resident Set Size), heapTotal, heapUsed 등의 수치를 제공하여 현재 Node.js 프로세스의 메모리 상태를 지속적으로 모니터링할 수 있습니다 [4, 23].
|
||||
* **`--trace-gc` 로그 추적:** 애플리케이션 시작 시 해당 플래그를 제공하면, Scavenge나 Mark-sweep 같은 GC 이벤트가 발생할 때마다 메모리 변화량, 소요 시간, 발생 원인(예: allocation failure) 등의 상세 로그를 콘솔에 출력합니다 [24-27].
|
||||
* **힙 스냅샷([[Heap Snapshot]]s):** [[Chrome DevTools]]나 `heapdump` 라이브러리를 사용하여 메모리 상태를 캡처할 수 있습니다. 로드 테스트 전후의 스냅샷을 비교(Comparison view)하여 GC 이후에도 회수되지 않고 남아 있는 객체(메모리 누수 후보)를 식별할 수 있습니다 [3, 28-30].
|
||||
* **Performance Hooks:** Node.js의 `perf_hooks` 모듈에서 `PerformanceObserver`를 사용하면 프로그래밍 방식으로 GC 통계를 추적하여 성능 오버헤드를 정밀하게 모니터링할 수 있습니다 [31].
|
||||
|
||||
* **주요 메모리 누수 패턴 (Memory Leak Patterns)**
|
||||
* Node.js에서의 누수는 메모리가 유실된 것이 아니라 GC 루트로부터의 참조가 끈질기게 남아있어 V8이 이를 회수하지 못하는 상태를 뜻합니다 [32].
|
||||
* 주요 누수 패턴으로는 해제되지 않은 이벤트 리스너(`EventEmitter`), 변수 참조를 잃지 않는 클로저(Closures), 크기 제한이 없는 인메모리 캐시, 정리되지 않은 타이머(`setInterval`), 제대로 닫히지 않은 스트림과 소켓 등이 있습니다 [33-35].
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** V8 자바스크립트 엔진, 가비지 컬렉션(GC), 힙 스냅샷(Heap Snapshot), 메모리 누수(Memory Leak)
|
||||
- **Projects/Contexts:** [[Orinoco]] GC 프로젝트, [[Chrome]] DevTools 메모리 분석
|
||||
- **Contradictions/Notes:**
|
||||
- V8 엔진의 포인터 압축([[Pointer Compression]]) 기능 활성화 시, 64비트 시스템에 128GB의 RAM이 있더라도 단일 V8 프로세스(Isolate)의 관리 힙 크기는 4GB의 연속된 메모리 케이지(Cage)로 엄격하게 제한됩니다 [36-38]. 이 제한에 도달하면 메모리를 확보하기 위해 Major GC의 빈도가 극적으로 증가하며, 결과적으로 OOM 충돌을 유발할 수 있습니다 [38].
|
||||
- 메모리 최적화를 위해 애플리케이션 코드 내에서 `global.gc()`를 수동으로 지속 호출하는 것은 V8의 자동화된 GC 알고리즘을 방해하고 성능을 떨어뜨릴 수 있으므로 권장되지 않습니다 [22, 39].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -2,107 +2,33 @@
|
||||
id: wiki-2026-0508-nodejs-성능-디버깅
|
||||
title: Nodejs 성능 디버깅
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-7A23E5]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: nodejs-performance
|
||||
duplicate_of: "[[Nodejs 성능 최적화 및 디버깅]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - [[Nodejs]] 성능 디버깅"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, nodejs, debugging, performance]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[Nodejs 성능 디버깅]]
|
||||
# Nodejs 성능 디버깅
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Node.js 성능 디버깅은 주로 V8 엔진의 힙(Heap) 메모리 사용량을 추적하고 가비지 컬렉션(GC) 동작을 분석하여 애플리케이션의 성능 저하 및 메모리 누수([[memory]] Leak)를 해결하는 과정이다 [1, 2]. 힙 스냅샷([[Heap Snapshot]]), 할당 타임라인, GC 트레이싱 등의 진단 도구를 활용하여 메모리 내에서 불필요하게 유지되는 참조 객체를 식별한다 [3-5]. 이와 더불어, 실시간 모니터링 API 및 V8 명령줄 플래그 튜닝을 통해 메모리 한계를 조정하여 서버 안정성과 처리량을 최적화할 수 있다 [6-8].
|
||||
> **이 문서는 [[Nodejs 성능 최적화 및 디버깅]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **메모리 누수의 정의와 주요 패턴**
|
||||
Node.js에서 메모리 누수는 가비지 컬렉터(GC)에 의해 수거되어야 할 객체가 클로저(Closure), 전역 변수 등에 의해 여전히 참조를 유지하고 있을 때 발생한다 [3, 9]. 이로 인해 시간이 지남에 따라 메모리가 지속적으로 증가하며, 결과적으로 프로세스가 Out-Of-Memory(OOM) 오류로 인해 중단될 수 있다 [10, 11]. Node.js 환경에서 가장 흔하게 발생하는 누수 패턴은 다음과 같다:
|
||||
* **이벤트 리스너 누적**: `on('event', fn)`을 지속적으로 추가하고 제거하지 않으면 해당 콜백 함수와 관련된 메모리가 누수된다 [12].
|
||||
* **클로저(Closure) 변수 보존**: 비동기 체인이나 스코프를 공유하는 클로저 내부에 큰 객체를 캡처해 두면 해당 클로저의 수명 주기 동안 메모리가 유지된다 [13, 14].
|
||||
* **무제한 캐시(Unbounded Cache)**: 인메모리 캐시의 크기나 만료를 제한하지 않으면 데이터가 끝없이 축적된다 [14].
|
||||
* **정리되지 않은 타이머**: `clearInterval`이 호출되지 않은 `setInterval`은 콜백 클로저에 있는 모든 항목의 GC를 방지한다 [15, 16].
|
||||
* **닫히지 않은 스트림 및 소켓**: 올바르게 종료되지 않은 스트림은 내부 버퍼와 네트워크 핸들을 점유한다 [16].
|
||||
## 핵심 요약
|
||||
- 매 `node --inspect` + Chrome DevTools 의 connection.
|
||||
- 매 CPU profiling: `--prof` flag + `--prof-process` 분석.
|
||||
- 매 production-safe: `clinic.js doctor/flame/bubbleprof` 의 활용.
|
||||
|
||||
* **메모리 디버깅 및 프로파일링 도구**
|
||||
* **힙 스냅샷(Heap Snapshots)**: 특정 시점의 전체 메모리 상태를 캡처하는 기능으로, [[Chrome DevTools]]에서 스냅샷들을 비교('Comparison' 뷰)하여 메모리 누수를 검사할 수 있다 [4, 17-19]. `--inspect` 플래그로 연결하거나 `heapdump` 패키지를 사용해 캡처한 뒤 '할당된 후 해제되지 않은 객체(Objects allocated between snapshots)'를 찾아낸다 [4, 5, 18].
|
||||
* **할당 타임라인([[Allocation Timeline]])**: 특정 시간 동안의 메모리 할당을 시각적으로 추적한다 [17, 20]. 가비지 컬렉션 후에도 살아있는 객체는 파란색 막대로 표시되며, 이를 통해 메모리 누수 후보를 특정할 수 있다 [5, 17, 20].
|
||||
* **GC 트레이싱(--trace-gc)**: `--trace-gc` 플래그를 사용해 실행하면 가비지 컬렉션의 세부 발생 시간, 소요 시간, GC 전후의 힙 용량 변화를 콘솔에서 확인할 수 있다 [5, 21, 22]. 만약 [[Mark-Sweep]](오래된 세대 GC) 작업이 지나치게 빈번하거나 GC 이후에도 힙이 원래 수준으로 줄어들지 않으면 메모리 누수의 강력한 신호이다 [23].
|
||||
* **메모리 모니터링 API**: 코드 내에서 `process.memoryUsage()`를 호출하여 프로세스에 할당된 전체 메모리(`rss`)와 힙의 총량(`heapTotal`), 현재 사용 중인 힙(`heapUsed`) 등을 실시간으로 파악할 수 있다 [6, 7].
|
||||
## 🔗 Graph
|
||||
- 부모: [[Nodejs 성능 최적화 및 디버깅]] (canonical)
|
||||
- Adjacent: [[Nodejs 프로세스 모니터링 및 메모리 분석]] · [[Chrome DevTools(크롬 개발자 도구)]] · [[Flame Chart]]
|
||||
|
||||
* **메모리 튜닝 및 최적화**
|
||||
Node.js는 V8 엔진의 메모리 제한 및 GC 빈도를 직접 제어할 수 있는 명령줄 플래그를 제공한다 [7].
|
||||
* `--max-old-space-size`: 수명이 긴 객체들이 저장되는 [[Old Space]]의 크기 한도를 설정하여, 지속적인 데이터를 다룰 때 OOM을 지연시키거나 예방할 수 있다 [8, 24].
|
||||
* `--max-semi-space-size`: 빈번하게 생성 및 소멸되는 객체가 저장되는 New Space의 크기를 조절한다. 처리량이 많은 상황에서 이 크기를 늘리면 잦은 [[Scavenge]](마이너 GC) 사이클을 줄여 성능을 향상할 수 있다 [24, 25].
|
||||
* `--expose-gc`: 이를 설정하면 애플리케이션 코드 내에서 `global.gc()`를 수동으로 호출하여 대량의 데이터 처리 후 명시적으로 메모리를 회수할 수 있다 [26, 27].
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[V8 [[JavaScript]] Engine]], [[Garbage Collection]], [[Heap Snapshot]], Memory Leak
|
||||
- **Projects/Contexts:** [[Chrome DevTools Memory Panel]], Node.js Production Environment
|
||||
- **Contradictions/Notes:** 애플리케이션 개발자가 `System.gc()` 또는 `global.gc()`를 사용하여 수동으로 가비지 컬렉션을 트리거할 수는 있으나, GC 동작을 임의로 예측 및 강제 실행하는 행위는 오히려 애플리케이션의 성능을 저하시킬 수 있으므로 주의해서 사용해야 한다 [27, 28].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -2,101 +2,179 @@
|
||||
id: wiki-2026-0508-nodejs-성능-최적화-및-디버깅
|
||||
title: Nodejs 성능 최적화 및 디버깅
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-C8E2E0]
|
||||
aliases: [Nodejs 메모리 최적화, Nodejs 메모리 튜닝, Nodejs 성능 디버깅, Nodejs 프로세스 모니터링]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [nodejs, performance, debugging, memory, v8]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - [[Nodejs]] 성능 최적화 및 디버깅"
|
||||
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: javascript
|
||||
framework: nodejs
|
||||
---
|
||||
|
||||
# [[Nodejs 성능 최적화 및 디버깅]]
|
||||
# Nodejs 성능 최적화 및 디버깅
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> '할당 타임라인([[Allocation Timeline]])' 도구는 힙 프로파일러의 세부적인 스냅샷 정보와 타임라인 패널의 점진적인 추적 기능을 결합하여 브라우저와 Node.js 환경에서 메모리 할당을 모니터링하는 기능이다 [1, 2]. 이 도구는 기록 세션 동안 최대 50ms마다 주기적으로 힙 스냅샷을 캡처하여 객체의 생명주기를 시각화한다 [3, 4]. 이를 통해 가비지 컬렉션(GC) 이후에도 메모리에 남아있는 객체와 그 참조 경로를 파악함으로써 애플리케이션의 메모리 누수를 감지하고 디버깅하는 데 필수적으로 활용된다 [5-8].
|
||||
## 매 한 줄
|
||||
> **"매 production Node 의 성능 의 V8 heap + event loop + async I/O 의 3-축 의 governing"**. 매 2026 의 Node 22 LTS 의 default — 매 V8 12.x 의 Maglev/Turbofan tier 의 활용 + native diagnostic_channel + clinic.js 4.x 의 standard toolchain.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **할당 타임라인의 동작 및 추적 원리:**
|
||||
할당 타임라인 도구는 타임라인 기록을 시작하고 작업을 수행한 뒤 기록을 중지하는 과정 동안 주기적으로 힙 스냅샷을 캡처하며, 기록 종료 시 최종 스냅샷을 한 번 더 찍는다 [1-4]. V8 엔진의 가비지 컬렉션 과정에서 객체의 물리적 메모리 주소는 변경될 수 있으므로, 해당 도구는 여러 스냅샷에 걸쳐 일관되게 유지되는 객체 ID(`@` 뒤에 붙는 숫자)를 부여하여 힙 상태의 변화를 정밀하게 추적하고 비교할 수 있게 한다 [3, 4].
|
||||
## 매 핵심
|
||||
|
||||
- **메모리 할당 시점별 로그 시각화:**
|
||||
타임라인 도구의 상단 막대는 특정 시점에 힙에서 발견된 새로운 객체의 크기와 발생 시점을 나타낸다 [5, 8]. 이 막대의 색상은 객체의 생존 여부를 시각적으로 보여준다.
|
||||
- **파란색 막대 (Blue bars):** 타임라인 기록이 끝날 때까지 가비지 컬렉션에 수거되지 않고 살아남은 객체를 의미하며, 이 객체들은 메모리 누수([[memory]] Leak)의 주요 후보군이 된다 [5, 8-10].
|
||||
- **회색 막대 (Gray bars):** 특정 시점에 할당되었으나 이후 가비지 컬렉터에 의해 정상적으로 수거(해제)된 객체를 의미한다 [5, 8-10].
|
||||
### 매 3-축 model
|
||||
- **Heap**: 매 V8 의 Old/New Space 의 GC pressure.
|
||||
- **Event Loop**: 매 microtask + macrotask + nextTick 의 priority.
|
||||
- **Async I/O**: 매 libuv thread pool (`UV_THREADPOOL_SIZE` default 4).
|
||||
|
||||
- **보존 트리(Retaining Tree)를 통한 힙 동작 상세 분석:**
|
||||
할당 타임라인에서 파란색 막대 범위를 좁혀 힙 내의 특정 객체를 클릭하면, 하단 패널(Retainers pane)에 보존 트리가 표시된다 [6, 11, 12]. 이 트리는 가비지 컬렉션의 루트(예: 전역 객체나 활성 스택)로부터 해당 객체를 살아있게 유지시키는 참조 체인을 역추적하여 보여준다 [6, 11]. 개발자는 이 보존 경로를 조사하여 객체가 수거되지 않은 원인을 이해하고, 불필요한 참조 코드를 수정하여 메모리를 해제할 수 있다 [6, 12].
|
||||
### 매 진단 toolkit (2026)
|
||||
- `node --inspect` + Chrome DevTools.
|
||||
- `clinic.js doctor / flame / bubbleprof / heapprofiler`.
|
||||
- `0x` (flamegraph generator).
|
||||
- `node --prof` + `--prof-process`.
|
||||
- `diagnostic_channel` (Node 16+) — 매 production-safe instrumentation.
|
||||
|
||||
- **Node.js 운영 환경에서의 적용 및 로그(Log) 수집:**
|
||||
Node.js 환경에서도 `--inspect` 플래그를 사용하여 크롬 개발자 도구에 연결한 뒤 'Memory > Allocation instrumentation on timeline'을 활용할 수 있다 [7]. 부하 테스트(예: 100~1,000건의 요청)를 진행하면서 타임라인을 기록하고 수거되지 않는 파란색 막대를 확인하여 메모리 누수 위치를 신속하게 특정할 수 있다 [7, 13]. 또한 터미널 레벨에서 `--trace-gc` 플래그를 지정하면 V8 엔진은 메모리 할당 실패(allocation failure) 시 발생하는 GC 이벤트마다 타임스탬프(ms), GC 유형(예: [[Scavenge]], [[Mark-Sweep]]), GC 전후의 힙 사용량(MB) 및 소요 시간 등을 상세한 텍스트 로그 형태로 출력하여 메모리 포화 상태를 디버깅할 수 있게 해준다 [14-16].
|
||||
### 매 응용
|
||||
1. Memory leak 의 추적 — heap snapshot diff.
|
||||
2. CPU bottleneck 의 식별 — flame graph.
|
||||
3. Event loop lag 의 monitoring — `perf_hooks.monitorEventLoopDelay`.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
## 💻 패턴
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[할당 타임라인(Allocation Timeline)]], 힙 스냅샷([[Heap Snapshot]]), [[V8 힙(Heap)]], 가비지 컬렉션([[Garbage Collection]])
|
||||
- **Projects/Contexts:** [[Chrome DevTools(크롬 개발자 도구)]], Node.js 메모리 누수 분석
|
||||
- **Contradictions/Notes:** 그래프에서 메모리 사용량이 증가한다고 해서 그것이 모두 메모리 누수를 의미하는 것은 아니다. 캐시(Caches), 실행 취소 기록(Undo histories) 등은 의도적으로 데이터를 메모리에 유지하므로, 정상적인 데이터 보존과 우발적인 메모리 누수를 명확히 구분하여 분석해야 한다 [17].
|
||||
### Heap snapshot 비교
|
||||
```javascript
|
||||
const v8 = require('v8');
|
||||
const fs = require('fs');
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
function snapshot(label) {
|
||||
const file = `/tmp/heap-${label}-${Date.now()}.heapsnapshot`;
|
||||
const stream = v8.getHeapSnapshot();
|
||||
stream.pipe(fs.createWriteStream(file));
|
||||
return file;
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
// usage
|
||||
const before = snapshot('before');
|
||||
runWorkload();
|
||||
global.gc?.(); // --expose-gc
|
||||
const after = snapshot('after');
|
||||
// → load both into Chrome DevTools, compare retainers
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### Event loop delay monitoring
|
||||
```javascript
|
||||
import { monitorEventLoopDelay } from 'node:perf_hooks';
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
const h = monitorEventLoopDelay({ resolution: 20 });
|
||||
h.enable();
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
setInterval(() => {
|
||||
const p99 = h.percentile(99) / 1e6; // ms
|
||||
if (p99 > 100) console.warn(`event loop p99 lag: ${p99.toFixed(1)}ms`);
|
||||
h.reset();
|
||||
}, 5000);
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### CPU profile (production-safe)
|
||||
```javascript
|
||||
import { Session } from 'node:inspector/promises';
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
const session = new Session();
|
||||
session.connect();
|
||||
await session.post('Profiler.enable');
|
||||
await session.post('Profiler.start');
|
||||
// ... run workload
|
||||
const { profile } = await session.post('Profiler.stop');
|
||||
fs.writeFileSync('cpu.cpuprofile', JSON.stringify(profile));
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### Heap limit 설정
|
||||
```bash
|
||||
# 8GB heap
|
||||
node --max-old-space-size=8192 server.js
|
||||
|
||||
# container-aware
|
||||
node --max-old-space-size=$(echo "$(cat /sys/fs/cgroup/memory.max) * 0.75 / 1024 / 1024" | bc) server.js
|
||||
```
|
||||
|
||||
### diagnostic_channel instrumentation
|
||||
```javascript
|
||||
import diagnostics_channel from 'node:diagnostics_channel';
|
||||
|
||||
const ch = diagnostics_channel.channel('app:slow-query');
|
||||
ch.subscribe((msg) => {
|
||||
metrics.histogram('db.query.slow', msg.duration);
|
||||
});
|
||||
|
||||
// publisher
|
||||
ch.publish({ query, duration });
|
||||
```
|
||||
|
||||
### Async resource tracking
|
||||
```javascript
|
||||
import { AsyncLocalStorage } from 'node:async_hooks';
|
||||
|
||||
const als = new AsyncLocalStorage();
|
||||
|
||||
app.use((req, res, next) => {
|
||||
als.run({ requestId: req.id }, next);
|
||||
});
|
||||
|
||||
logger.info = (msg) => {
|
||||
const ctx = als.getStore();
|
||||
console.log(JSON.stringify({ msg, requestId: ctx?.requestId }));
|
||||
};
|
||||
```
|
||||
|
||||
### Worker thread offload
|
||||
```javascript
|
||||
import { Worker } from 'node:worker_threads';
|
||||
|
||||
function cpuHeavyTask(data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const w = new Worker('./worker.js', { workerData: data });
|
||||
w.on('message', resolve);
|
||||
w.on('error', reject);
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| Memory leak 의심 | heap snapshot diff (3개 시점) |
|
||||
| CPU spike | clinic flame / 0x flamegraph |
|
||||
| Latency p99 ↑ | event loop delay monitor |
|
||||
| OOM kill (container) | `--max-old-space-size` 의 container limit 의 75% |
|
||||
| Async chain debugging | AsyncLocalStorage + diagnostic_channel |
|
||||
|
||||
**기본값**: clinic doctor 로 시작 → 매 specific tool (flame/bubbleprof) 의 narrowing.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[V8 엔진 힙 아키텍처]] · [[Garbage Collection]]
|
||||
- 변형: [[Nodejs 메모리 최적화]] · [[Nodejs 메모리 튜닝]] · [[Nodejs 성능 디버깅]]
|
||||
- 응용: [[Nodejs 프로세스 모니터링 및 메모리 분석]] · [[브라우저 및 Nodejs 메모리 튜닝]]
|
||||
- Adjacent: [[Chrome DevTools(크롬 개발자 도구)]] · [[Flame Chart]] · [[할당 타임라인(Allocation Timeline)]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: production Node 의 성능 회귀 의 진단, heap leak 의 root cause analysis.
|
||||
**언제 X**: synthetic benchmark — 매 real workload profile 만 의 trustworthy.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Premature optimization**: 매 profile 의 X — guess 의 X.
|
||||
- **`global.gc()` 의 production 호출**: 매 stop-the-world — latency spike.
|
||||
- **`UV_THREADPOOL_SIZE` 의 무분별 증가**: 매 context switch 의 overhead.
|
||||
- **heap snapshot 의 production load 의 down**: 매 GB-scale 의 dump — disk + pause.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Node.js 22 docs, V8 blog, Matteo Collina's perf talks).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — Node 22 / clinic 4.x / diagnostic_channel 반영 |
|
||||
|
||||
@@ -2,111 +2,33 @@
|
||||
id: wiki-2026-0508-nodejs-프로세스-모니터링-및-메모리-분석
|
||||
title: Nodejs 프로세스 모니터링 및 메모리 분석
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-56A451]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: nodejs-performance
|
||||
duplicate_of: "[[Nodejs 성능 최적화 및 디버깅]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - [[Nodejs]] 프로세스 모니터링 및 메모리 분석"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, nodejs, monitoring, memory]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[Nodejs 프로세스 모니터링 및 메모리 분석]]
|
||||
# Nodejs 프로세스 모니터링 및 메모리 분석
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Node.js는 V8 엔진 위에서 실행되며, 메모리는 주로 힙(Heap)과 스택(Stack)으로 나뉘어 관리됩니다 [1, 2]. 단일 프로세스로 오랫동안 실행되는 환경 특성상, 코드 상의 실수로 해제되지 않은 메모리 참조가 누적되면 가비지 컬렉터(GC)가 이를 회수하지 못해 Out-Of-[[memory]](OOM) 크래시로 이어질 수 있습니다 [2, 3]. 따라서 지속적인 메모리 사용량 모니터링과 함께, 힙 스냅샷([[Heap Snapshot]])과 할당 타임라인([[Allocation Timeline]]) 등의 도구를 활용하여 누수(Leak)의 근본 원인이 되는 객체 참조를 찾아내는 분석 과정이 필수적입니다 [4-6].
|
||||
> **이 문서는 [[Nodejs 성능 최적화 및 디버깅]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **메모리 구조 및 작동 원리**
|
||||
- V8 엔진의 메모리는 크게 힙(Heap)과 스택(Stack)으로 구분됩니다 [1, 2]. 스택은 원시 값(Primitive values)과 힙 객체에 대한 포인터, 그리고 함수 실행 프레임과 같은 정적 데이터를 저장하며 운영 체제에 의해 빠르게 자동으로 관리됩니다 [7-11].
|
||||
- 힙은 객체와 동적 데이터가 저장되는 가장 큰 메모리 영역이며 가비지 컬렉션의 주 대상이 됩니다 [12]. 힙은 생성 주기에 따라 짧은 수명의 객체가 머무는 New Space(젊은 세대)와 오래 살아남은 객체가 승격되는 [[Old Space]](오래된 세대) 등으로 나뉘며, 각각 [[Scavenge]](마이너 GC)와 [[Mark-Sweep]]-Compact(메이저 GC) 알고리즘으로 관리됩니다 [12-14].
|
||||
## 핵심 요약
|
||||
- 매 `process.memoryUsage()` 의 5개 metric: rss, heapTotal, heapUsed, external, arrayBuffers.
|
||||
- 매 PM2 / systemd 의 process supervision + restart-on-OOM.
|
||||
- 매 Prometheus + `prom-client` 의 metric export — Grafana dashboard.
|
||||
|
||||
- **프로세스 메모리 모니터링 방법**
|
||||
- **코드 기반 모니터링**: `process.memoryUsage()`를 호출하면 프로세스의 메모리 사용량을 RSS(Resident Set Size), heapTotal(할당된 힙 총량), heapUsed(사용 중인 힙), external(C++ 바인딩 등 외부 메모리) 등으로 상세히 확인할 수 있습니다 [15].
|
||||
- **프로덕션 환경 모니터링**: `prom-client`를 이용해 메모리 메트릭을 Prometheus에 내보내고, Grafana 알림을 설정하여 프로세스가 OOM으로 종료되기 전에 선제적으로 누수를 포착할 수 있습니다 [16].
|
||||
- **GC 활동 추적**: `--trace-gc` 플래그를 사용하거나 `perf_hooks`의 PerformanceObserver를 사용하여 가비지 컬렉션 로그를 확인할 수 있습니다 [17, 18]. 정상적인 프로세스는 트래픽이 몰릴 때 힙이 증가했다가 GC 이후 다시 기준선으로 돌아오는 '톱니바퀴(sawtooth)' 패턴을 보이지만, 메모리 누수가 발생하면 기준선이 계속 상승하는 '래칫(ratchet)' 패턴이 관찰됩니다 [4, 19].
|
||||
## 🔗 Graph
|
||||
- 부모: [[Nodejs 성능 최적화 및 디버깅]] (canonical)
|
||||
- Adjacent: [[Nodejs 성능 디버깅]] · [[Nodejs 메모리 최적화]] · [[V8 엔진 힙 아키텍처]]
|
||||
|
||||
- **메모리 분석 및 누수 탐지 도구**
|
||||
- **할당 타임라인 (Allocation Timeline)**: [[Chrome DevTools]]에서 일정 시간 동안의 할당을 기록할 수 있습니다 [20, 21]. 분석 화면에서 해제되지 않고 메모리에 여전히 남아있는 객체는 파란색 막대로 표시되며, 이 파란색 막대를 조사하여 누수 후보를 찾아낼 수 있습니다 [22-24].
|
||||
- **힙 스냅샷 (Heap Snapshot)**: 프로세스의 메모리 상태를 포착하며, 두 개 이상의 스냅샷을 찍고 "비교(Comparison)" 뷰를 이용해 두 시점 사이에 생성되었으나 삭제되지 않은 객체들을 필터링할 수 있습니다 [25, 26]. 이 뷰를 통해 해당 객체 자체가 차지하는 얕은 크기(Shallow size)와, 객체 삭제 시 회수 가능한 보존 크기(Retained size)를 파악하고, Retainers 트리를 추적해 메모리를 붙잡고 있는 루트 원인을 찾아냅니다 [27, 28].
|
||||
- 프로덕션 서버와 같이 UI가 없는 환경에서는 `heapdump` 패키지를 통해 스냅샷을 생성하거나, V8 네이티브 프로파일링 기능인 `--heap-prof` 플래그를 사용하여 npm 패키지 의존성 없이 할당 내역을 파일로 저장하여 분석할 수 있습니다 [16, 29].
|
||||
|
||||
- **주요 메모리 누수 패턴 (Memory Leak Patterns)**
|
||||
- **이벤트 리스너 누적**: 요청 핸들러 내에서 `on('event', fn)`과 같은 리스너를 지속적으로 추가하고 제거하지 않는 경우 발생합니다. (Node.js에서 단일 에미터에 10개 이상의 리스너가 등록될 때 발생하는 `MaxListenersExceededWarning`은 프로덕션 누수를 확정하는 주요 신호입니다) [29].
|
||||
- **클로저 변수 유지 (Closure Variable Retention)**: 여러 클로저가 스코프를 공유할 때, 의도치 않게 대용량 데이터(예: 전체 요청/응답 객체)가 캡처된 채 요청 수명주기를 초과해 유지되면서 발생합니다 [30, 31].
|
||||
- 그 외 무제한 캐시(Unbounded Cache) 증가, `clearInterval`이 누락된 타이머 인터벌, 복잡한 순환 참조(Circular [[Reference]]s), `destroy()`나 `cancel()` 호출 없이 방치된 스트림(Stream)과 소켓 등이 대표적인 원인입니다 [31, 32].
|
||||
|
||||
- **명령줄 플래그를 활용한 메모리 튜닝 (Memory Tuning)**
|
||||
- `--max-old-space-size`: 장기 생존 객체가 저장되는 Old Space의 최대 크기를 메가바이트 단위로 설정하여 무거운 작업이나 세션 데이터 저장을 최적화합니다 [33].
|
||||
- `--max-semi-space-size`: New Space의 크기를 조절하여 단기 객체의 잦은 생성으로 인한 마이너 GC 발생 빈도를 늦출 수 있습니다 [34].
|
||||
- `--expose-gc`: 애플리케이션 코드 내에서 `global.gc()`를 호출해 개발자가 수동으로 가비지 컬렉션을 트리거할 수 있게 합니다 [35, 36].
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** V8 [[Garbage Collection]], [[Heap Snapshot]], Memory Leak Patterns
|
||||
- **Projects/Contexts:** Node.js Production Environment, [[Chrome DevTools Memory Panel]]
|
||||
- **Contradictions/Notes:** `--expose-gc` 플래그를 사용하여 수동으로 GC를 실행(`global.gc()`)할 수 있지만, 이것이 V8의 일반적인 자동 GC 알고리즘을 비활성화하는 것은 아닙니다. 수동 호출은 보조적인 역할일 뿐이며, 과도하게 사용할 경우 오히려 애플리케이션 성능에 심각한 악영향을 미칠 수 있습니다 [36].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -2,105 +2,229 @@
|
||||
id: wiki-2026-0508-object-pooling-오브젝트-풀링
|
||||
title: Object Pooling (오브젝트 풀링)
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-1F94B3]
|
||||
aliases: [오브젝트 풀링, Object Pool Pattern]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [pattern, performance, memory, gc, gamedev]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Object [[Pooling]] (오브젝트 풀링)"
|
||||
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: agnostic
|
||||
---
|
||||
|
||||
# [[Object Pooling (오브젝트 풀링)]]
|
||||
# Object Pooling (오브젝트 풀링)
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> 오브젝트 풀링은 객체의 빈번한 생성과 파괴로 인해 발생하는 메모리 할당 비용과 가비지 컬렉션(GC) 스파이크를 방지하기 위해, 미리 고정된 개수의 객체 풀(Pool)을 할당해 두고 필요할 때 꺼내어 재사용한 뒤 다시 반환하는 소프트웨어 성능 최적화 디자인 패턴입니다.
|
||||
## 매 한 줄
|
||||
> **"매 expensive object 의 reuse 로 GC pressure + allocation cost 의 회피"**. 매 game loop / hot path / high-frequency event handler 의 standard 의 패턴 — 매 2026 의 game engine (Three.js, Bevy, Unity DOTS), DB connection pool, HTTP keep-alive, worker pool 의 universal 의 pattern.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
**1. 도입 목적과 메모리 파편화 방지** 실시간 상호작용이 중요한 게임(예: 슈팅 게임의 탄환, 파티클 시스템)에서 매 프레임마다 수백 개의 객체를 생성하고 삭제하면 시스템 자원을 소모하여 화면이 끊기는 지연(Lag) 현상이 발생합니다. 이는 가비지 컬렉터가 메모리를 정리하는 데 시간이 걸리기 때문입니다. 또한, 잦은 할당과 해제는 힙 메모리의 가용 공간을 작은 조각으로 나누어버리는 '메모리 파편화([[memory]] Fragmentation)'를 유발하여 결국 메모리 할당 실패와 크래시를 초래할 수 있습니다. 오브젝트 풀은 로딩 시점 등 초기에 큰 메모리를 한 번에 할당하고 이를 유지함으로써 이러한 문제를 원천 차단합니다.
|
||||
## 매 핵심
|
||||
|
||||
**2. 작동 원리** 오브젝트 풀은 카드의 내용을 지우고 다시 덱에 넣는 것과 같습니다.
|
||||
### 매 3-component
|
||||
- **Pool**: 매 object 의 collection (free list).
|
||||
- **Acquire**: 매 free object 의 dequeue (또는 신규 생성).
|
||||
- **Release**: 매 object 의 reset + enqueue.
|
||||
|
||||
- **사전 할당 (Pre-warming):** 초기 크기만큼 객체를 생성하여 비활성 상태로 보관합니다.
|
||||
- **활성화 및 재사용:** 객체가 필요할 때 풀에서 가용한 객체를 가져와 상태를 초기화한 뒤 활성화(In-use)합니다.
|
||||
- **반환:** 사용이 끝난 객체는 메모리에서 삭제하는 대신 비활성 상태로 변경하여 풀에 반환합니다.
|
||||
### 매 언제 적용
|
||||
- 매 allocation rate > 10K/sec.
|
||||
- 매 object lifetime 의 짧음 (< 1 frame).
|
||||
- 매 GC pause 의 user-visible (game, real-time).
|
||||
- 매 expensive constructor (DB connect, file open, GPU buffer alloc).
|
||||
|
||||
**3. 한계점 및 부작용 관리**
|
||||
### 매 응용
|
||||
1. Game particle system — bullet, explosion, enemy.
|
||||
2. DB connection pool — `pg-pool`, HikariCP.
|
||||
3. HTTP agent — `http.Agent({ keepAlive: true })`.
|
||||
4. Web Worker pool — `piscina`.
|
||||
|
||||
- **메모리 낭비와 크기 고정:** 풀의 크기가 너무 크면 사용되지 않는 객체들이 메모리를 계속 점유하여 자원을 낭비하게 되며, 반대로 너무 작으면 필요한 순간에 객체를 가져오지 못할 수 있습니다.
|
||||
- **객체 크기 고정:** 서로 다른 타입이나 크기의 객체를 하나의 풀에서 관리할 경우, 가장 큰 객체의 크기에 맞춰 슬롯 메모리를 할당해야 하므로 메모리 낭비가 발생합니다.
|
||||
- **불완전한 초기화 위험:** 재사용되는 객체는 이전 생애(Past life)의 데이터 흔적이 남아있을 수 있습니다. 객체를 풀에서 꺼낼 때 새로운 상태로 완벽하게 덮어쓰기(초기화)하지 않으면 심각한 버그가 발생할 수 있습니다.
|
||||
- **참조 유지 버그:** 풀에 반환된 객체를 다른 클래스에서 여전히 참조하고 조작할 경우, 엉뚱한 곳에서 객체가 변경되는 추적하기 힘든 버그(Use-after-free)가 발생할 수 있습니다.
|
||||
## 💻 패턴
|
||||
|
||||
**4. 고속화를 위한 Free List (프리 리스트) 기법** 가장 단순한 오브젝트 풀은 가용한 객체를 찾기 위해 풀 전체를 순회하므로 $O(n)$의 시간이 걸립니다. 이를 최적화하기 위해 비활성 상태인 객체들의 사용하지 않는 메모리 공간(예: C++의 `union`)을 활용하여 다음 빈 객체를 가리키는 포인터를 저장하는 **프리 리스트(Free List)**를 구축하면, 추가적인 메모리 낭비 없이 $O(1)$의 속도로 즉시 객체를 할당할 수 있습니다.
|
||||
### Generic pool (TypeScript)
|
||||
```typescript
|
||||
class ObjectPool<T> {
|
||||
private free: T[] = [];
|
||||
constructor(
|
||||
private factory: () => T,
|
||||
private reset: (obj: T) => void,
|
||||
initialSize = 0
|
||||
) {
|
||||
for (let i = 0; i < initialSize; i++) this.free.push(factory());
|
||||
}
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
acquire(): T {
|
||||
return this.free.pop() ?? this.factory();
|
||||
}
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[Garbage Collection]] (GC) 최적화, Generational GC (세대별 가비지 컬렉션), Memory Fragmentation (메모리 파편화), [[InstancedMesh (드로우 콜 최적화)]]
|
||||
- **Projects/Contexts:** [[대규모 파티클 시스템 최적화]], 슈팅 게임의 대규모 탄환(Bullet) 제어 시스템, React Three Fiber 엔진 아키텍처
|
||||
- **Contradictions/Notes:** 오브젝트 풀링이 모든 상황에서 정답은 아닙니다. V8과 같은 최신 자바스크립트 엔진의 세대별 가비지 컬렉터(Generational GC)는 단기 생존 객체(Short-lived objects)를 수거하는 비용이 사실상 0에 가깝습니다. 이 환경에서 객체 풀링을 잘못 적용하면, 객체들이 강제로 오래 살아남게 되어 구세대(Old Generation) 메모리를 압박하고 오히려 GC 성능을 악화시키며 메모리 사용량만 늘릴 위험이 있습니다. 반드시 프로파일러를 통한 성능 병목 확인 후 선별적으로 도입해야 합니다.
|
||||
|
||||
---
|
||||
|
||||
_Last updated: 2026-04-15_
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
release(obj: T): void {
|
||||
this.reset(obj);
|
||||
this.free.push(obj);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### Three.js Vector3 pool (game loop)
|
||||
```typescript
|
||||
import { Vector3 } from 'three';
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
const vec3Pool = new ObjectPool<Vector3>(
|
||||
() => new Vector3(),
|
||||
(v) => v.set(0, 0, 0),
|
||||
256
|
||||
);
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
function updateBullet(b: Bullet, dt: number) {
|
||||
const tmp = vec3Pool.acquire();
|
||||
tmp.copy(b.velocity).multiplyScalar(dt);
|
||||
b.position.add(tmp);
|
||||
vec3Pool.release(tmp);
|
||||
}
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### Particle system pool
|
||||
```typescript
|
||||
class Particle {
|
||||
position = new Vector3();
|
||||
velocity = new Vector3();
|
||||
life = 0;
|
||||
active = false;
|
||||
}
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
class ParticleSystem {
|
||||
private pool: Particle[];
|
||||
private active: Particle[] = [];
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
constructor(maxParticles: number) {
|
||||
this.pool = Array.from({ length: maxParticles }, () => new Particle());
|
||||
}
|
||||
|
||||
spawn(pos: Vector3, vel: Vector3, life: number) {
|
||||
const p = this.pool.pop();
|
||||
if (!p) return; // pool exhausted
|
||||
p.position.copy(pos);
|
||||
p.velocity.copy(vel);
|
||||
p.life = life;
|
||||
p.active = true;
|
||||
this.active.push(p);
|
||||
}
|
||||
|
||||
update(dt: number) {
|
||||
for (let i = this.active.length - 1; i >= 0; i--) {
|
||||
const p = this.active[i];
|
||||
p.life -= dt;
|
||||
if (p.life <= 0) {
|
||||
p.active = false;
|
||||
this.active.splice(i, 1);
|
||||
this.pool.push(p); // return to pool
|
||||
} else {
|
||||
p.position.addScaledVector(p.velocity, dt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### DB connection pool (pg)
|
||||
```typescript
|
||||
import { Pool } from 'pg';
|
||||
|
||||
const pool = new Pool({
|
||||
max: 20,
|
||||
idleTimeoutMillis: 30_000,
|
||||
connectionTimeoutMillis: 2000,
|
||||
});
|
||||
|
||||
async function query(sql: string, params: unknown[]) {
|
||||
const client = await pool.connect();
|
||||
try {
|
||||
return await client.query(sql, params);
|
||||
} finally {
|
||||
client.release(); // ← back to pool
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Worker thread pool (piscina)
|
||||
```typescript
|
||||
import Piscina from 'piscina';
|
||||
|
||||
const piscina = new Piscina({
|
||||
filename: new URL('./worker.js', import.meta.url).href,
|
||||
minThreads: 2,
|
||||
maxThreads: 8,
|
||||
});
|
||||
|
||||
const result = await piscina.run({ payload: data });
|
||||
```
|
||||
|
||||
### Bounded pool with backpressure
|
||||
```typescript
|
||||
class BoundedPool<T> {
|
||||
private free: T[] = [];
|
||||
private waiters: ((obj: T) => void)[] = [];
|
||||
private created = 0;
|
||||
|
||||
constructor(
|
||||
private factory: () => T,
|
||||
private reset: (obj: T) => void,
|
||||
private max: number
|
||||
) {}
|
||||
|
||||
async acquire(): Promise<T> {
|
||||
if (this.free.length) return this.free.pop()!;
|
||||
if (this.created < this.max) {
|
||||
this.created++;
|
||||
return this.factory();
|
||||
}
|
||||
return new Promise((resolve) => this.waiters.push(resolve));
|
||||
}
|
||||
|
||||
release(obj: T): void {
|
||||
this.reset(obj);
|
||||
const w = this.waiters.shift();
|
||||
if (w) w(obj);
|
||||
else this.free.push(obj);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| Hot path allocation (game loop) | object pool (generic) |
|
||||
| DB / network connection | bounded pool with backpressure |
|
||||
| Heavy CPU task | worker thread pool (piscina) |
|
||||
| Short-lived simple obj (< 1KB) | 매 V8 의 young-gen GC 의 충분 — pool 의 X |
|
||||
| Object 의 reset cost > construct cost | pool 의 X |
|
||||
|
||||
**기본값**: 매 profile 후 의 적용 — premature pooling 의 X.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Garbage Collection]] · [[V8 엔진 힙 아키텍처]]
|
||||
- 변형: [[bitECS와 SharedArrayBuffer를 결합한 멀티스레드 고성능 아키텍처]]
|
||||
- 응용: [[InstancedMesh 최적화]] · [[가변적 LOD(Level of Detail) 시스템]]
|
||||
- Adjacent: [[Old Space]] · [[세대 가설(Generational Hypothesis)]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: game loop / real-time pipeline 의 GC pause 회피, expensive resource (DB conn, GPU buffer) 의 reuse.
|
||||
**언제 X**: simple short-lived object — 매 modern GC 의 충분.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Reset 의 누락**: 매 stale state 의 leak — 매 security risk (sensitive data).
|
||||
- **Unbounded pool**: 매 memory leak — 매 max size 의 강제.
|
||||
- **Pool 의 lock contention**: 매 multi-thread 의 sync overhead — thread-local pool 의 고려.
|
||||
- **Object 의 over-aliasing**: 매 release 후 의 reference 유지 — use-after-free 의 bug.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Game Programming Patterns / R. Nystrom, V8 blog, piscina docs).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — TS generic pool, Three.js, piscina 패턴 추가 |
|
||||
|
||||
@@ -2,99 +2,33 @@
|
||||
id: wiki-2026-0508-old-space-구-세대-공간
|
||||
title: Old Space (구 세대 공간)
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-9214B8]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: old-space
|
||||
duplicate_of: "[[Old Space]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - [[Old Space]] (구 세대 공간)"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, v8, gc, memory]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[Old Space (구 세대 공간)]]
|
||||
# Old Space (구 세대 공간)
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Old Space(구 세대 공간)는 V8 자바스크립트 엔진의 힙(Heap) 메모리 영역 중, New Space(신규 공간)에서 발생하는 가비지 컬렉션(GC)을 두 번 이상 생존한 객체들이 승격(Promotion)되어 이동하는 공간입니다 [1-3]. 주로 사용자 세션이나 캐시 데이터 등 수명이 길고 지속적인 상태를 유지하는 객체들을 장기간 저장하는 데 사용됩니다 [4, 5]. 이 공간의 메모리 회수는 빈도가 낮지만 리소스 소모가 큰 [[Major GC]]([[Mark-Sweep]] 및 Mark-Compact 알고리즘)에 의해 관리됩니다 [1, 3, 5].
|
||||
> **이 문서는 [[Old Space]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **공간의 세분화 및 역할:**
|
||||
Old Space는 효율적인 가비지 컬렉션을 위해 두 개의 하위 영역으로 나뉩니다. 첫째는 다른 객체를 가리키는 포인터를 포함하는 객체들이 저장되는 **Old-pointer-space**입니다 [3, 6, 7]. 둘째는 문자열, 박싱된 숫자 등 포인터가 없는 원시 데이터만 포함하는 객체들이 저장되는 **Old-data-space**입니다 [3, 6, 7]. GC가 Old-data-space를 처리할 때는 내부 포인터 추적 단계를 건너뛸 수 있어 마킹(Marking) 단계에 소요되는 시간을 단축할 수 있습니다 [4].
|
||||
## 핵심 요약
|
||||
- 매 V8 heap 의 long-lived object region — 매 New Space 의 promotion 의 destination.
|
||||
- 매 Mark-Sweep-Compact 의 major GC 의 대상.
|
||||
- 매 default 1.5GB — `--max-old-space-size` 의 확장 가능.
|
||||
|
||||
- **가비지 컬렉션 (Major GC):**
|
||||
크기가 작고 수집이 빠른 New Space(Minor GC)와 달리, Old Space는 수백 메가바이트의 데이터를 포함할 수 있으므로 **마크-스윕(Mark-Sweep)** 및 **마크-컴팩트(Mark-Compact)** 알고리즘을 통해 관리됩니다 [8]. Major GC는 객체의 참조를 따라가며 살아있는 객체(Black)와 죽은 객체(White)를 식별(Mark)하고, 죽은 객체가 차지한 메모리를 회수(Sweep)합니다 [9, 10].
|
||||
## 🔗 Graph
|
||||
- 부모: [[Old Space]] (canonical)
|
||||
- Adjacent: [[V8 엔진 힙 아키텍처]] · [[세대 가설(Generational Hypothesis)]] · [[Mark-Sweep-Compact 알고리즘]] · [[오래된 공간(Old Space)]]
|
||||
|
||||
- **메모리 단편화 및 압축(Compaction):**
|
||||
Old Space에서는 죽은 메모리가 페이지에 남기는 "구멍(holes)"으로 인해 메모리 단편화(Fragmentation) 문제가 크게 발생합니다 [11]. 큰 공간에서 객체를 이동시키는 것은 계산 비용이 매우 높고 모든 참조 포인터를 업데이트해야 하므로, V8은 매 주기마다 객체를 압축하지 않고 필요할 때만 단편화된 페이지에서 라이브 객체를 다른 페이지의 빈 공간으로 마이그레이션(Compaction)하는 방식을 사용합니다 [12, 13].
|
||||
|
||||
- **메모리 튜닝 및 누수 탐지:**
|
||||
Node.js 애플리케이션에서 대규모 데이터를 처리할 때 `--max-old-space-size` 커맨드라인 플래그를 사용하면 Old Space의 최대 크기(예: 4096MB)를 명시적으로 늘릴 수 있어 잦은 가비지 컬렉션으로 인한 성능 저하를 방지할 수 있습니다 [14, 15]. 또한 `--trace-gc-verbose` 로깅 분석 시, Major GC가 발생한 이후에도 "Old space, used" 크기가 지속적으로 증가한다면 강력한 메모리 누수([[memory]] Leak)의 징후로 판단할 수 있습니다 [16].
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** New Space (신규 공간), Major GC (주요 가비지 컬렉션), Mark-Sweep-Compact, Memory Leak (메모리 누수)
|
||||
- **Projects/Contexts:** [[V8 [[JavaScript]] Engine]], Node.js Memory [[Management]]
|
||||
- **Contradictions/Notes:** 소스에 따르면 Old Space 내의 객체를 옮기는 압축(Compaction) 작업은 비용이 매우 많이 들기 때문에, Minor GC처럼 모든 라이브 객체를 복사하는 방식([[Scavenge]]r)을 쓰지 않고 단편화가 심한 특정 페이지에 대해서만 제한적으로 압축을 수행합니다 [12, 13].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -1,25 +1,34 @@
|
||||
---
|
||||
id: wiki-20260508-old-space-old-generation--redir
|
||||
title: Old Space(Old Generation)
|
||||
category: Programming & Language
|
||||
status: merged
|
||||
redirect_to: Old_Space(Old_Generation)
|
||||
canonical_id: Old_Space(Old_Generation)
|
||||
category: 10_Wiki/Topics
|
||||
status: duplicate
|
||||
canonical_id: old-space
|
||||
duplicate_of: "[[Old Space]]"
|
||||
aliases: []
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [redirect]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
confidence_score: 0.9
|
||||
verification_status: redirected
|
||||
tags: [duplicate, v8, gc, memory]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-merge 2026-05-08)
|
||||
---
|
||||
|
||||
# Old Space(Old Generation)
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 이 문서는 P-Reinforce Phase 2 자동 MERGE에 의해 **[[Old_Space(Old_Generation)]]**로 통합되었습니다.
|
||||
> **이 문서는 [[Old Space]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
---
|
||||
*Redirected to: [[Old_Space(Old_Generation)]]*
|
||||
## 핵심 요약
|
||||
- 매 V8 의 generational heap 의 old generation region.
|
||||
- 매 2회 이상 minor GC 의 survivor → promotion.
|
||||
- 매 major GC (Mark-Sweep-Compact) 의 대상 — 매 incremental + concurrent 의 mix.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Old Space]] (canonical)
|
||||
- Adjacent: [[Old Space (구 세대 공간)]] · [[오래된 공간(Old Space)]] · [[이전 세대(Old Generation_Space)]] · [[세대 가설(Generational Hypothesis)]]
|
||||
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -2,95 +2,31 @@
|
||||
id: wiki-2026-0508-old-space
|
||||
title: Old Space
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-C312D4]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: old-space
|
||||
duplicate_of: "[[Old_Space]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Old Space"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, v8, gc]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[Old Space]]
|
||||
# Old Space
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Old Space(또는 Old generation)는 V8 엔진의 메모리 힙 구조에서 단기 생존 영역인 New Space에서 여러 차례의 가비지 컬렉션(GC)을 견뎌낸 장기 생존 객체들이 저장되는 공간입니다 [1-3]. 주로 사용자 세션, 캐시 데이터, 영구 상태와 같은 장기 보존 데이터가 이곳에 보관됩니다 [4]. 이 공간은 수백 메가바이트 이상의 데이터를 담을 수 있도록 훨씬 크게 설계되었으며, [[Mark-Sweep]] 및 Mark-Compact 알고리즘을 사용하는 [[Major GC]]에 의해 덜 빈번하지만 더 많은 리소스를 소모하여 관리됩니다 [4-7].
|
||||
> **이 문서는 [[Old_Space]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **객체 승격(Promotion) 메커니즘:** 객체는 처음에 New Space에 할당된 후, 두 번의 마이너 가비지 컬렉션(Minor GC 또는 [[Scavenge]])에서 살아남으면 Old Space로 승격(promotion)됩니다 [1, 3, 8]. Old Space는 단기 객체를 빈번하게 수집하는 New Space와 달리 장기적인 저장 목적으로 설계되었습니다 [6].
|
||||
* **공간의 세분화:** Old Space는 가비지 컬렉션 처리를 최적화하기 위해 두 가지 하위 공간으로 분리되어 관리됩니다 [2, 3, 6].
|
||||
* **Old-pointer-space:** 다른 객체들을 가리키는 내부 포인터를 가질 수 있는 대부분의 장기 생존 객체들이 보관됩니다 [2, 3, 9].
|
||||
* **Old-data-space:** 다른 객체에 대한 포인터 없이 순수하게 로우 데이터(문자열, unboxed double 배열 등)만 포함하는 객체들이 저장됩니다 [2, 3, 9]. 이 데이터 공간은 GC의 마킹 단계에서 포인터 추적(tracing)을 건너뛸 수 있어 가비지 컬렉션 소요 시간을 줄여줍니다 [6].
|
||||
* **Major GC (가비지 컬렉션):** Old Space의 메모리 관리는 Mark-Sweep 및 Mark-Compact 알고리즘을 수행하는 Major GC(전체 가비지 컬렉션) 사이클을 통해 이루어집니다 [1, 3, 5]. 일정량의 메모리가 Old Space로 승격되면 Major GC가 트리거되어 사용되지 않는 메모리(Garbage)를 해제하고 라이브 객체들을 압축하여 파편화를 줄입니다 [1, 7, 10].
|
||||
* **[[Write Barrier]]s 및 저장 버퍼(Store Buffer):** Old Space의 객체가 New Space의 객체를 참조하는 경우, V8 엔진은 이 참조를 추적하기 위해 'Write Barrier' 코드와 'Store Buffer'를 활용합니다 [11-13]. 이는 스캐빈저(Scavenger)가 New Space를 수집할 때 Old Space 전체를 스캔하지 않고도 해당 참조를 파악할 수 있게 해줍니다 [11, 13].
|
||||
* **메모리 튜닝 및 누수 감지:** `--trace-gc-verbose` 플래그를 사용하여 로그를 확인할 때, Major GC 이벤트 이후에도 Old space의 사용량이 지속적으로 증가한다면 메모리 누수([[memory]] Leak)가 발생하고 있다는 강력한 지표가 됩니다 [14]. 개발자는 애플리케이션의 메모리 사용량에 맞게 `--initial_old_space_size` 및 `--max-old-space-size` 커맨드라인 플래그를 사용하여 Old Space의 크기를 직접 제어할 수 있습니다 [3, 15].
|
||||
## 핵심 요약
|
||||
- V8 heap 의 long-lived object 영역 (Mark-Sweep / Mark-Compact).
|
||||
- Young generation 에서 2회 GC 생존 시 promotion.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
## 🔗 Graph
|
||||
- 부모: [[Old_Space]] (canonical)
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** New Space, [[Major GC]], Mark-Sweep-Compact, [[Write Barrier]], [[Garbage Collection]]
|
||||
- **Projects/Contexts:** [[V8 Engine]], Node.js Memory [[Management]]
|
||||
- **Contradictions/Notes:** 소스에 따르면 V8은 필요할 경우 운영체제에 더 많은 공간을 요청하여 Old Space 크기를 확장할 수 있으나, V8 Memory Cage(보안 샌드박스 및 포인터 압축) 기능이 활성화된 64비트 시스템에서는 물리적 RAM 용량에 관계없이 V8 힙 전체 크기가 최대 4GB의 연속적인 영역으로 엄격히 제한됩니다 [16-18]. 따라서 Old Space 역시 이 4GB 제한의 영향을 받습니다.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -2,101 +2,31 @@
|
||||
id: wiki-2026-0508-orinoco-가비지-컬렉터
|
||||
title: Orinoco 가비지 컬렉터
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-3353DC]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: orinoco
|
||||
duplicate_of: "[[Orinoco]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - [[Orinoco]] 가비지 컬렉터"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, v8, gc]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[Orinoco 가비지 컬렉터]]
|
||||
# Orinoco 가비지 컬렉터
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Orinoco는 V8 [[JavaScript]] 엔진의 가비지 컬렉션(GC) 성능을 최적화하기 위해 도입된 프로젝트의 코드명입니다 [1, 2]. 기존의 순차적이고 프로그램 실행을 멈추게 하는 '[[Stop-the-world]]' 방식의 수집기를 점진적(Incremental) 폴백(Fallback)을 갖춘 병렬(Parallel) 및 동시성(Concurrent) 수집기로 탈바꿈시켰습니다 [1, 3]. 이를 통해 메인 스레드의 GC 작업 부담을 최소화하여 애플리케이션의 지연 시간(Latency)을 줄이고 스크롤 및 애니메이션 렌더링을 훨씬 부드럽게 만들었습니다 [4, 5].
|
||||
> **이 문서는 [[Orinoco]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
**핵심 가비지 컬렉션 기술**
|
||||
Orinoco는 메인 스레드를 해방시키기 위해 다음 세 가지 주요 최적화 기법을 혼합하여 사용합니다 [2].
|
||||
* **병렬(Parallel) 처리**: 메인 스레드와 헬퍼 스레드가 동시에 대략 같은 양의 GC 작업을 수행합니다 [2]. 애플리케이션 실행을 멈추는 'stop-the-world' 접근법이긴 하지만, 총 중단 시간을 참여하는 스레드 수만큼 나누어 대기 시간을 단축시킵니다 [2].
|
||||
* **점진적(Incremental) 처리**: 전체 GC를 한 번에 하는 대신, 메인 스레드가 간헐적으로 소량의 GC 작업만 수행합니다 [6]. JavaScript 실행과 GC 작업이 번갈아 발생하도록 분산시켜 애플리케이션이 사용자 입력과 애니메이션 처리에 지속적으로 응답할 수 있게 합니다 [6, 7].
|
||||
* **동시성(Concurrent) 처리**: 메인 스레드가 JavaScript를 계속 실행하는 동안, 헬퍼 스레드들이 백그라운드에서 GC 작업을 전적으로 수행합니다 [8]. 이는 메인 스레드를 자유롭게 하지만, 객체의 변경 사항을 관리하기 위해 스레드 간 동기화와 읽기/쓰기 충돌을 제어해야 하는 가장 고난도의 기술입니다 [8].
|
||||
## 핵심 요약
|
||||
- V8 의 modern parallel/concurrent/incremental GC.
|
||||
- Mark-Sweep-Compact 단계 분산 → main thread pause 최소화.
|
||||
|
||||
**주요 GC 단계별 Orinoco의 적용**
|
||||
* **Minor GC ([[Scavenge]]r)**: V8의 Young 세대 가비지 컬렉터는 병렬 스캐빈징(Parallel scavenging)을 사용하여 여러 헬퍼 스레드에 작업을 분산시킵니다 [9, 10]. 각 헬퍼 스레드는 포인터를 따라가며 살아있는 객체를 새로운 메모리 공간(To-Space)으로 대피시키고 포인터를 병렬로 업데이트합니다 [9].
|
||||
* **[[Major GC]] (Mark-Compact)**: Old 세대의 수집은 주로 동시 마킹(Concurrent marking)으로 시작됩니다 [11]. 백그라운드의 헬퍼 스레드들이 살아있는 객체를 찾아 마킹하는 동안 메인 스레드는 JavaScript를 실행하며, 새로 생성된 참조는 '쓰기 장벽([[Write Barrier]]s)'을 통해 추적됩니다 [11, 12]. 이후 메인 스레드는 잠시 멈춰 빠른 마킹 완료 처리를 한 뒤, 헬퍼 스레드들과 함께 병렬 압축(Parallel compaction)을 수행하고 백그라운드에서는 동시 스윕(Concurrent sweeping)을 진행합니다 [13, 14].
|
||||
## 🔗 Graph
|
||||
- 부모: [[Orinoco]] (canonical)
|
||||
|
||||
**기타 최적화 기법**
|
||||
* **Idle-time GC (유휴 시간 GC)**: [[Chrome]]과 같은 환경에서 애니메이션 프레임(예: 초당 60프레임, 약 16.6ms)을 렌더링한 후 여유 시간이 남을 경우, GC가 해당 유휴 시간을 활용하여 선제적으로 가비지 컬렉션 작업을 수행합니다 [5, 15].
|
||||
* 기타 V8의 블랙 할당(Black allocation) 기능과 포인터 추적(Tracking Pointers) 기법을 개선하여 On-heap 및 Off-heap 메모리의 피크 사용량을 큰 폭으로 줄였습니다 [3, 16, 17].
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** 가비지 컬렉션([[Garbage Collection]]), V8 JavaScript 엔진, Minor GC (Scavenger), Major GC (Mark-Compact), 세대별 가비지 컬렉션(Generational Garbage Collection)
|
||||
- **Projects/Contexts:** V8 메모리 관리 및 최적화, Node.js 및 Chrome 브라우저 렌더링 성능 최적화
|
||||
- **Contradictions/Notes:** 과거 V8 버전은 Cheney의 동기식 세미스페이스 복사 알고리즘을 사용했으나, V8 v6.2부터 Orinoco 프로젝트의 일환으로 동적 작업 훔치기(Work stealing) 기법을 사용하는 Halstead 방식의 병렬 스캐빈저로 대체되었습니다 [10, 18].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -2,93 +2,134 @@
|
||||
id: wiki-2026-0508-orinoco-프로젝트
|
||||
title: Orinoco 프로젝트
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-6EB2FE]
|
||||
aliases: [Orinoco, V8 Orinoco]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [v8, gc, performance]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - [[Orinoco]] 프로젝트"
|
||||
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: C++
|
||||
framework: V8 12+
|
||||
---
|
||||
|
||||
# [[Orinoco 프로젝트]]
|
||||
# Orinoco 프로젝트
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Orinoco 프로젝트는 V8 [[JavaScript]] 엔진의 가비지 컬렉터(GC)를 최신 기술로 개선하기 위해 진행된 프로젝트의 코드명입니다 [1-3]. 이 프로젝트는 기존의 순차적이고 모든 실행을 멈추는 '[[Stop-the-world]]' 방식의 가비지 컬렉터를 병렬(parallel), 동시(concurrent), 점진적(incremental) 기술을 활용하는 형태로 진화시켰습니다 [1, 2, 4]. 주된 목적은 메인 스레드의 부하를 덜어주어 가비지 컬렉션으로 인한 프로그램 중지 시간(pause time)을 최소화하고 사용자 경험을 향상시키는 것입니다 [2, 5].
|
||||
## 매 한 줄
|
||||
> **"매 V8 의 GC 의 mostly-parallel, mostly-concurrent 의 evolution"**. 2016 발표된 Orinoco initiative 가 V8 의 stop-the-world phase 를 minimize — incremental marking, parallel scavenge, concurrent sweeping, compaction 의 background offload. 2026 현재 V8 12+ 의 default. Main thread pause time 이 100ms+ → sub-10ms 로 reduce.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **GC 모델의 현대화:** Orinoco는 기존의 'stop-the-world' 중지 방식을 벗어나, 동시적이고 병렬적이며 점진적인 GC 모델로의 전환을 의미합니다 [1, 4]. 이를 위해 스마트 페이징과 동시성 친화적 알고리즘을 도입하여 '구 세대(Old Generation)'와 '신 세대(Young Generation)' 가비지 컬렉터를 병렬화했습니다 [5].
|
||||
- **병렬(Parallel) 기법 도입:** 메인 스레드와 다수의 헬퍼 스레드가 동시에 거의 동일한 양의 작업을 수행하도록 처리합니다 [2]. 이 역시 실행을 일시 중지하는 방식이지만, 동기화에 필요한 약간의 오버헤드를 제외하면 전체 중지 시간을 참여하는 스레드의 수만큼 나누어 크게 줄일 수 있습니다 [2].
|
||||
- **점진적(Incremental) 마킹:** 마킹 작업을 아주 작은 덩어리로 나누어 JavaScript 실행 중간중간에 교차로 배치(interleave)하는 방식입니다 [6, 7]. 이 방식은 총 GC 시간을 줄이지는 못하지만 긴 중지 시간을 잘게 분산시킴으로써, 애플리케이션이 끊김 없이 사용자 입력이나 애니메이션에 반응할 수 있도록 돕습니다 [6, 7].
|
||||
- **동시(Concurrent) 처리:** 메인 스레드가 멈추지 않고 JavaScript를 실행하는 동안, 백그라운드의 헬퍼 스레드들이 GC 작업을 전담하여 처리합니다 [8]. 객체의 상태가 언제든 변할 수 있어 읽기/쓰기 경합(read/write races)을 처리해야 하는 가장 복잡한 기술이지만, 메인 스레드를 온전히 자유롭게 해방시킬 수 있습니다 [8].
|
||||
- **프로젝트의 성과 및 확장:** Orinoco 프로젝트를 통해 많은 GC 작업이 백그라운드로 이동하면서 지연 시간과 페이지 로딩 성능이 비약적으로 향상되었으며, 스크롤이나 애니메이션이 훨씬 부드러워졌습니다 [9]. 더 나아가, 여기서 개발된 새로운 기술의 일부는 [[Chrome]]의 렌더러([[Blink]])에 내장된 가비지 컬렉터인 '[[Oilpan]]'으로 이식하여 협력을 개선하는 작업도 진행 중입니다 [10].
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 design pillars
|
||||
- **Parallelism**: 동시 main thread 를 멈추고 worker thread 다수 사용 (parallel scavenge, parallel compaction).
|
||||
- **Concurrency**: main thread 는 mutator 의 user code 실행, GC thread 가 background marking/sweeping.
|
||||
- **Incremental**: long pause 를 작은 step 으로 split, frame 사이 의 짤끔.
|
||||
- **Idle-time GC**: main thread idle window (rAF gap) 의 활용.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[V8 Engine]], [[Garbage Collection]] (GC), [[Stop-the-world]], [[Incremental Marking]]
|
||||
- **Projects/Contexts:** [[Oilpan]], [[Blink]]
|
||||
- **Contradictions/Notes:** 소스에 관련 정보가 부족합니다. (소스 내에서 Orinoco 프로젝트에 대한 상충되는 주장은 발견되지 않습니다.)
|
||||
### 매 collector phases
|
||||
- **Young (Scavenger)**: parallel copying, 보통 <1ms.
|
||||
- **Old marking**: incremental + concurrent (mutator 동시 실행).
|
||||
- **Old sweeping**: concurrent free-list rebuild.
|
||||
- **Old compaction**: parallel evacuation, 매 page-level.
|
||||
- **Write barrier**: 매 mutator 가 mark 와 race 의 prevent.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
### 매 응용
|
||||
1. Chrome / Edge / Brave (V8 host).
|
||||
2. Node.js / Deno / Bun (runtime GC 의 같은 Orinoco 기반, Bun 은 JSC 라 다름).
|
||||
3. Electron, VS Code (V8 backend).
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 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
|
||||
### Orinoco trace 보기
|
||||
```bash
|
||||
node --trace-gc --trace-gc-verbose app.js
|
||||
# [Mark-Compact (incremental) ...]
|
||||
# [Scavenge (parallel) ...]
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### Heap stats with v8 module
|
||||
```javascript
|
||||
const v8 = require('v8')
|
||||
const stats = v8.getHeapStatistics()
|
||||
console.log({
|
||||
used: stats.used_heap_size,
|
||||
total: stats.total_heap_size,
|
||||
limit: stats.heap_size_limit,
|
||||
})
|
||||
const spaces = v8.getHeapSpaceStatistics()
|
||||
spaces.forEach(s => console.log(s.space_name, s.space_used_size))
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Triggering Orinoco-friendly allocation
|
||||
```javascript
|
||||
// O — short-lived 의 young space 에 머무름
|
||||
function processBatch(items) {
|
||||
return items.map(i => ({ id: i.id, val: i.val * 2 })) // returns die fast
|
||||
}
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
// X — large pre-allocated buffer 의 old promotion 강제
|
||||
const giant = new Array(1e7).fill(0) // bypasses young entirely
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### --max-old-space-size tuning
|
||||
```bash
|
||||
node --max-old-space-size=4096 app.js # 4GB old space ceiling
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
### Idle-time GC hint
|
||||
```javascript
|
||||
// Chrome internal — webpages cannot directly trigger,
|
||||
// but rAF-aligned work 의 GC 가 idle gap 을 활용
|
||||
requestIdleCallback((deadline) => {
|
||||
while (deadline.timeRemaining() > 0 && tasks.length) doWork(tasks.pop())
|
||||
})
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### Heap snapshot diff
|
||||
```javascript
|
||||
const v8 = require('v8'); const fs = require('fs')
|
||||
v8.writeHeapSnapshot('before.heapsnapshot')
|
||||
runWorkload()
|
||||
v8.writeHeapSnapshot('after.heapsnapshot')
|
||||
// Chrome DevTools → Memory → Comparison
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| Browser frame budget (16.6ms) | Orinoco 의 default 충분 |
|
||||
| Large heap (4GB+) | --max-old-space-size + monitoring |
|
||||
| Latency-critical (game, RT) | Object pool + young-friendly allocation |
|
||||
| Server long-running | --gc-interval + heap dump 주기 |
|
||||
|
||||
**기본값**: 매 V8 default Orinoco + workload 의 short-lived bias.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[V8 엔진 힙 아키텍처]]
|
||||
- 변형: [[Orinoco 가비지 컬렉터]]
|
||||
- 응용: [[Incremental Marking]] · [[Mark-Sweep-Compact 알고리즘]]
|
||||
- Adjacent: [[Generational Hypothesis]] · [[Old Space]] · [[Write Barrier]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: V8 GC 의 internals 설명, Node.js / Chrome heap tuning, `--trace-gc` 분석.
|
||||
**언제 X**: 다른 engine (JSC, SpiderMonkey, Hermes) 의 GC.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **`global.gc()` 강제**: 매 production 의 X. Orinoco 가 의 better job 의 함.
|
||||
- **--expose-gc 의 production**: 매 attack surface 와 perf degradation.
|
||||
- **Heavy sync work**: incremental marking 의 main thread 가 idle 해야 진행 → tight loop 의 GC 의 starve.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (V8 blog "Orinoco" 2016, "Concurrent marking" 2017, V8 12.x release notes).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — Orinoco design pillars + tracing patterns |
|
||||
|
||||
@@ -1,25 +1,147 @@
|
||||
---
|
||||
id: wiki-20260508-pointer-compression-redir
|
||||
title: Pointer Compression
|
||||
category: Programming & Language
|
||||
status: merged
|
||||
redirect_to: Pointer_Compression
|
||||
canonical_id: Pointer_Compression
|
||||
aliases: []
|
||||
category: 10_Wiki/Topics
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [pointer-compression, V8 pointer compression, 32-bit pointer]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [redirect]
|
||||
verification_status: applied
|
||||
tags: [v8, memory, gc, optimization, runtime]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-merge 2026-05-08)
|
||||
tech_stack:
|
||||
language: JavaScript/C++
|
||||
framework: V8
|
||||
---
|
||||
|
||||
# Pointer Compression
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 이 문서는 P-Reinforce Phase 2 자동 MERGE에 의해 **[[Pointer_Compression]]**로 통합되었습니다.
|
||||
## 매 한 줄
|
||||
> **"매 64-bit pointer를 32-bit offset으로 packing해서 heap memory를 거의 반으로 줄임"**. V8 v8.0 (2020) 부터 default — heap base register + 32-bit compressed pointer 의 조합. 매 modern 2026 V8 (Node 22, Chrome 120+)에서 매 표준 동작.
|
||||
|
||||
---
|
||||
*Redirected to: [[Pointer_Compression]]*
|
||||
## 매 핵심
|
||||
|
||||
### 매 동작 원리
|
||||
- 매 4GB heap 안의 모든 object 의 32-bit offset 으로 표현 — base pointer 1개만 64-bit, 나머지는 32-bit.
|
||||
- 매 Tagged pointer scheme: 매 LSB 1 bit 의 SMI (Small Integer) vs HeapObject 구분 의 사용.
|
||||
- 매 decompression: `real_addr = base + (compressed << 1)` — 매 single ALU op.
|
||||
- 매 compression: 매 store 시 `(real_addr - base) >> 1` 의 자동 계산.
|
||||
|
||||
### 매 trade-off
|
||||
- 매 heap size limit: 매 single isolate 의 4GB cap — 매 worker / cluster 의 우회.
|
||||
- 매 CPU overhead: 매 매 dereference 의 add 1 instruction — 매 ~3% slower.
|
||||
- 매 memory savings: 매 typical Node heap 의 30-43% 감소 — 매 pointer-heavy workload 의 클수록 효과 큼.
|
||||
|
||||
### 매 응용
|
||||
1. Chrome tab 의 RAM 의 ~10% 감소 — 매 tab 수십 개 의 환경.
|
||||
2. Node.js process 의 startup memory 의 약 200MB→130MB.
|
||||
3. Edge / serverless 의 cold start 의 RSS reduction.
|
||||
|
||||
## 💻 패턴
|
||||
|
||||
### 매 Compressed pointer 구조 의 이해
|
||||
```cpp
|
||||
// V8 internal — Tagged<Object> representation
|
||||
class Tagged {
|
||||
uint32_t ptr_; // 32-bit compressed pointer (was 64-bit)
|
||||
|
||||
// Decompress on access
|
||||
Address decompress(Address base) const {
|
||||
return base + (ptr_ & ~kSmiTagMask);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### 매 Heap base register 의 활용
|
||||
```cpp
|
||||
// Generated machine code (x86_64)
|
||||
// Before: mov rax, [rbx+0x8] ; 8 bytes load
|
||||
// After: mov eax, [rbx+0x8] ; 4 bytes load
|
||||
// add rax, r13 ; r13 holds heap base
|
||||
```
|
||||
|
||||
### 매 Node 의 heap 의 4GB cap 우회
|
||||
```javascript
|
||||
// 매 single isolate 의 4GB 제한 — worker thread 의 분리
|
||||
import { Worker } from 'node:worker_threads';
|
||||
|
||||
// 매 각 worker 의 own isolate (own 4GB heap)
|
||||
const workers = Array.from({ length: 4 }, () =>
|
||||
new Worker('./heavy-task.js')
|
||||
);
|
||||
// 총 16GB heap usage 가능 (4GB × 4 isolates)
|
||||
```
|
||||
|
||||
### 매 SMI (Small Integer) 활용
|
||||
```javascript
|
||||
// 매 V8 의 SMI optimization — 31-bit int 의 boxing 없이 tagged pointer 안에 직접
|
||||
const x = 42; // 매 SMI — 매 heap 할당 X
|
||||
const y = 2**32; // 매 HeapNumber — 매 heap allocation
|
||||
// 매 SMI 의 GC pressure 의 감소 효과
|
||||
```
|
||||
|
||||
### 매 Pointer compression 의 disable (rare)
|
||||
```bash
|
||||
# 매 Node build flag — 매 4GB heap 초과 필요 시
|
||||
node --no-pointer-compression server.js
|
||||
# 매 large in-memory cache (>4GB) 의 use case
|
||||
```
|
||||
|
||||
### 매 Heap 측정
|
||||
```javascript
|
||||
import v8 from 'node:v8';
|
||||
|
||||
const stats = v8.getHeapStatistics();
|
||||
console.log({
|
||||
total: stats.total_heap_size / 1e6, // MB
|
||||
limit: stats.heap_size_limit / 1e6, // 매 ~4GB 의 cap
|
||||
external: stats.external_memory / 1e6,
|
||||
});
|
||||
// 매 pointer compression 의 enabled 의 limit 의 4GB 근처
|
||||
```
|
||||
|
||||
### 매 SharedArrayBuffer 의 outside-heap 활용
|
||||
```javascript
|
||||
// 매 4GB cap 의 우회 — 매 binary data 의 SAB 의 사용
|
||||
const sab = new SharedArrayBuffer(8 * 1024 * 1024 * 1024); // 8GB
|
||||
// 매 SAB 의 V8 heap 의 외부 allocation — 매 limit 의 영향 X
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| 일반 Node 앱 | default ON (compression enabled) |
|
||||
| Heap > 4GB 필요 | --no-pointer-compression OR worker split |
|
||||
| 대용량 binary | SharedArrayBuffer / Buffer (off-heap) |
|
||||
| Memory-constrained | default 의 유지 — 매 30%+ saving |
|
||||
|
||||
**기본값**: pointer compression의 ON 의 유지. 매 4GB cap 의 hit 시 worker thread 의 split.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[V8 Engine]] · [[Garbage Collection]]
|
||||
- 변형: [[Tagged Pointer]] · [[SMI Small Integer]]
|
||||
- 응용: [[Nodejs 메모리 최적화]] · [[V8 엔진 힙 아키텍처 및 로그 분석]]
|
||||
- Adjacent: [[Old Space]] · [[Mark-Sweep-Compact 알고리즘]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: V8 heap memory 의 분석, Node.js 의 RSS 의 unexpected size 의 explain, 4GB OOM 의 debug.
|
||||
**언제 X**: 매 user 의 application code 의 직접 영향 X — 매 V8 internal optimization 임 의 인지.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Disable 의 무분별**: `--no-pointer-compression` 의 default 의 사용 — 매 30% memory waste.
|
||||
- **Single-isolate 의 4GB+**: 매 limit 의 무시 후 OOM — worker split 의 필요.
|
||||
- **SMI 의 violation**: 매 hot path 의 large int 의 사용 — 매 HeapNumber boxing 의 GC pressure.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (V8 blog "Pointer Compression in V8" 2020, Chromium docs).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — V8 pointer compression FULL 작성 |
|
||||
|
||||
@@ -1,25 +1,159 @@
|
||||
---
|
||||
id: wiki-20260508-reachability-analysis-redir
|
||||
title: Reachability Analysis
|
||||
category: Programming & Language
|
||||
status: merged
|
||||
redirect_to: Reachability_Analysis
|
||||
canonical_id: Reachability_Analysis
|
||||
aliases: []
|
||||
category: 10_Wiki/Topics
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [reachability, GC reachability, mark-and-sweep reachability]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [redirect]
|
||||
verification_status: applied
|
||||
tags: [gc, memory, algorithm, runtime]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-merge 2026-05-08)
|
||||
tech_stack:
|
||||
language: JavaScript/C++
|
||||
framework: V8
|
||||
---
|
||||
|
||||
# Reachability Analysis
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 이 문서는 P-Reinforce Phase 2 자동 MERGE에 의해 **[[Reachability_Analysis]]**로 통합되었습니다.
|
||||
## 매 한 줄
|
||||
> **"매 GC root 부터 reference graph 의 traverse — reachable object 의 keep, unreachable 의 collect"**. 매 modern GC 의 fundamental algorithm — V8, JVM, .NET, Go 의 동일 원리. 2026 의 incremental + concurrent variant 의 mainstream.
|
||||
|
||||
---
|
||||
*Redirected to: [[Reachability_Analysis]]*
|
||||
## 매 핵심
|
||||
|
||||
### 매 GC Root 종류
|
||||
- **Stack root**: 매 active call stack 의 local variable / parameter.
|
||||
- **Global root**: 매 globalThis / window — 매 module-level binding.
|
||||
- **Register root**: 매 CPU register 의 held reference.
|
||||
- **Compilation root**: 매 V8 의 compiled code 의 reference table.
|
||||
- **Handle root**: 매 native binding 의 Handle / Persistent reference.
|
||||
|
||||
### 매 Traversal algorithm
|
||||
- **Tri-color marking**: White (unvisited) → Gray (queued) → Black (done).
|
||||
- **Worklist-based**: 매 root 의 enqueue → pop → mark → push referents.
|
||||
- **Incremental**: 매 small chunks 의 분할 — 매 main thread pause 의 단축.
|
||||
- **Concurrent**: 매 background thread 의 동시 mark — write barrier 의 sync.
|
||||
|
||||
### 매 응용
|
||||
1. V8 의 Mark-Sweep-Compact GC 의 base.
|
||||
2. Memory leak 의 발견 — DevTools heap snapshot 의 retainer path.
|
||||
3. Cycle detection — refcount 의 약점 의 보완.
|
||||
|
||||
## 💻 패턴
|
||||
|
||||
### 매 Reachability 의 tri-color 의 idea
|
||||
```javascript
|
||||
// 매 conceptual mark phase
|
||||
function mark(roots) {
|
||||
const gray = new Set(roots); // 매 worklist
|
||||
const black = new Set(); // 매 marked
|
||||
|
||||
while (gray.size > 0) {
|
||||
const obj = gray.values().next().value;
|
||||
gray.delete(obj);
|
||||
black.add(obj);
|
||||
|
||||
for (const ref of getReferences(obj)) {
|
||||
if (!black.has(ref)) gray.add(ref);
|
||||
}
|
||||
}
|
||||
// 매 black = reachable, 매 white (heap - black) = collect
|
||||
}
|
||||
```
|
||||
|
||||
### 매 DevTools Heap snapshot 의 root 의 확인
|
||||
```javascript
|
||||
// Chrome DevTools → Memory → Heap snapshot
|
||||
// 매 retainer path 의 (GC root) 까지 추적
|
||||
// 매 closure / detached DOM / event listener 의 leak 의 발견
|
||||
|
||||
// 매 typical leak pattern
|
||||
let leakedRef;
|
||||
window.addEventListener('click', () => {
|
||||
leakedRef = bigData; // 매 GC root (global) 까지 retained
|
||||
});
|
||||
```
|
||||
|
||||
### 매 WeakRef 의 reachability 의 우회
|
||||
```javascript
|
||||
// 매 weak reference — 매 reachability 의 contribute X
|
||||
const cache = new Map();
|
||||
function set(key, val) {
|
||||
cache.set(key, new WeakRef(val)); // 매 GC 의 collect 가능
|
||||
}
|
||||
function get(key) {
|
||||
return cache.get(key)?.deref(); // 매 collected 시 undefined
|
||||
}
|
||||
```
|
||||
|
||||
### 매 FinalizationRegistry 의 cleanup hook
|
||||
```javascript
|
||||
const registry = new FinalizationRegistry((heldValue) => {
|
||||
console.log('Object collected:', heldValue);
|
||||
externalResources.delete(heldValue);
|
||||
});
|
||||
|
||||
function trackResource(obj, id) {
|
||||
registry.register(obj, id);
|
||||
}
|
||||
// 매 obj 의 unreachable 시 cleanup 의 trigger
|
||||
```
|
||||
|
||||
### 매 v8 의 heap snapshot 의 programmatic
|
||||
```javascript
|
||||
import v8 from 'node:v8';
|
||||
import fs from 'node:fs';
|
||||
|
||||
const snapshot = v8.getHeapSnapshot();
|
||||
snapshot.pipe(fs.createWriteStream('heap.heapsnapshot'));
|
||||
// 매 Chrome DevTools 의 import → reachability graph 의 분석
|
||||
```
|
||||
|
||||
### 매 Cycle 의 detection
|
||||
```javascript
|
||||
// 매 Refcount 의 약점 — 매 cycle 의 leak
|
||||
let a = {}, b = {};
|
||||
a.ref = b;
|
||||
b.ref = a;
|
||||
// 매 V8 의 reachability-based GC 의 cycle 의 collect (root 의 unreachable 시)
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| 일반 object | implicit reachability — 매 default |
|
||||
| Cache | WeakRef + FinalizationRegistry |
|
||||
| External resource | FinalizationRegistry 의 cleanup |
|
||||
| Cycle 의심 | heap snapshot 의 retainer path |
|
||||
| Memory leak debug | DevTools Memory tab |
|
||||
|
||||
**기본값**: 매 explicit ref 의 nullify 보다 매 scope 의 의도된 사용 의 reachability 의 자연스러운 종료.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Garbage Collection]] · [[Mark-Sweep-Compact 알고리즘]]
|
||||
- 변형: [[Incremental Marking]] · [[Tri-color Marking]]
|
||||
- 응용: [[GC Root]] · [[Memory Leak Debugging]]
|
||||
- Adjacent: [[Generational Hypothesis]] · [[Write Barrier]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: GC 동작 의 explain, memory leak 의 diagnose, WeakRef vs Map 의 권장.
|
||||
**언제 X**: 매 application 의 GC 의 strict timing 의 의존 의 답변 — 매 non-deterministic 임 의 인지.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Global cache**: 매 unbounded Map 의 GC root 까지 retained — 매 WeakMap 의 사용.
|
||||
- **Closure leak**: 매 outer function 의 large var 의 inner closure 의 capture.
|
||||
- **Detached DOM**: 매 removed node 의 JS reference 의 retained — 매 listener cleanup.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (V8 docs, Garbage Collection Handbook by Jones).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — Reachability analysis FULL 작성 |
|
||||
|
||||
@@ -2,101 +2,31 @@
|
||||
id: wiki-2026-0508-readonly-유틸리티-타입
|
||||
title: Readonly 유틸리티 타입
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-33C0BF]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: readonly-type
|
||||
duplicate_of: "[[Readonly Type]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - [[readonly]] 유틸리티 타입"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, typescript]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[Readonly 유틸리티 타입]]
|
||||
# Readonly 유틸리티 타입
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Readonly 유틸리티 타입(`Readonly<T>`)은 TypeScript에서 특정 객체 타입의 모든 속성에 `readonly` 수식어를 추가하여 초기화 이후 값을 재할당할 수 없도록 변환하는 기능입니다[1, 2]. 이는 런타임 성능 저하 없이 컴파일 타임에만 엄격하게 불변성을 강제하여, 의도치 않은 데이터 변형으로 인한 버그를 사전에 차단합니다[3, 4]. 단, 최상위 속성에만 적용되는 얕은(shallow) 불변성만을 제공하므로, 중첩된 객체를 완전히 동결하려면 재귀적인 형태의 딥 리드온리(Deep Readonly) 패턴이 별도로 필요합니다[5, 6].
|
||||
> **이 문서는 [[Readonly Type]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **기본 작동 원리와 문법:**
|
||||
`Readonly<T>`는 주어진 타입 `T`의 모든 프로퍼티를 읽기 전용으로 매핑합니다[1, 2]. 설정이나 API 응답, 상태 관리 리듀서 등 앱 내내 값이 유지되어야 하는 객체를 보호할 때 주로 사용됩니다[7, 8]. TypeScript 코드가 컴파일된 후에는 관련 어노테이션이 모두 사라지므로 실행 시점(Runtime)에는 어떠한 오버헤드도 발생시키지 않습니다[3, 9].
|
||||
## 핵심 요약
|
||||
- TS `Readonly<T>` — shallow immutability, mapped type 으로 모든 prop readonly.
|
||||
- Deep readonly 는 별도 recursive type 필요.
|
||||
|
||||
- **유사 개념과의 차이점:**
|
||||
- **`const`와의 차이:** `const`는 변수 자체의 재할당을 막지만 참조된 객체의 내부 속성 변경은 막지 못합니다. 반면 `readonly`는 변수 바인딩이 아닌 객체 속성이나 배열 요소 자체의 변경을 제한합니다[10, 11].
|
||||
- **`Object.freeze()`와의 차이:** `Object.freeze()`는 런타임에 객체를 동결하며 실행 성능에 비용을 청구하지만, `readonly`는 컴파일 타임에 타입 시스템을 통해서만 수정을 금지합니다[4, 12].
|
||||
## 🔗 Graph
|
||||
- 부모: [[Readonly Type]] (canonical)
|
||||
|
||||
- **배열에서의 활용:**
|
||||
객체뿐만 아니라 배열에도 `ReadonlyArray<T>` 또는 `readonly T[]` 형태로 사용할 수 있습니다[13, 14]. 이렇게 선언된 배열은 요소의 재할당이 불가능할 뿐만 아니라, `push()`, `pop()` 등 원본을 수정하는 메서드가 타입 정의에서 완전히 제거됩니다[15, 16].
|
||||
|
||||
- **한계점 및 우회 취약점 (Gotcha):**
|
||||
- **얕은 불변성(Shallow Immutability):** `Readonly<T>`는 1단계 깊이의 속성에만 작용합니다. 객체 내부의 중첩된 객체 속성은 여전히 수정이 가능하며, 이를 해결하기 위해서는 매핑된 타입과 조건부 타입을 결합한 커스텀 `[[DeepReadonly]]<T>` 유틸리티를 구현해야 합니다[5, 6, 17].
|
||||
- **에일리어싱(Aliasing) 문제:** `readonly` 타입의 데이터를, 수정 가능한 타입(mutable)을 매개변수로 받는 함수에 전달할 경우 타입 호환성 규칙에 의해 통과될 수 있습니다. 이로 인해 함수 내부에서 원본 데이터가 변경되는 우회 돌연변이가 발생할 수 있습니다[18, 19].
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[불변성(Immutability)]], 매핑된 타입(Mapped Types), [[DeepReadonly]]
|
||||
- **Projects/Contexts:** 변경 불가한 외부 API 응답 데이터 모델링, 상태 관리 시스템(Redux 리듀서 등)의 데이터 무결성 보장, 그리고 애플리케이션의 전역 환경 설정(Configuration) 객체 보호 맥락에서 광범위하게 쓰입니다[8, 17].
|
||||
- **Contradictions/Notes:** TypeScript의 에일리어싱 한계로 인해 `readonly` 데이터가 `mutable` 타입을 요구하는 함수로 전달되어 내부에서 값이 변경될 위험이 존재하므로, 완전한 불변성을 지키려면 함수 시그니처 전반에 걸쳐 읽기 전용 파라미터를 강제하거나 데이터의 복사본을 넘기는 설계가 필요합니다[18, 19]. 또한, 모든 `readonly` 속성을 다시 수정 가능하게 되돌려야 할 때는 `Mutable`이라는 커스텀 헬퍼 타입을 만들어 매핑 수식어를 제거(`-readonly`)하는 방식으로 해결할 수 있습니다[6].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -2,91 +2,170 @@
|
||||
id: wiki-2026-0508-result-type
|
||||
title: Result Type
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-ED64AE]
|
||||
aliases: [Result, Either, Outcome]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [error-handling, types, functional]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Result Type"
|
||||
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/Rust
|
||||
framework: neverthrow/Effect TS/std::result
|
||||
---
|
||||
|
||||
# [[Result Type]]
|
||||
# Result Type
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Result Type(결과 타입)은 함수나 메서드의 반환 값으로 성공 데이터 또는 예상되는 실패(에러)를 명시적으로 함께 표현하는 타입 구조입니다 [1-3]. 예외(Exception)를 무분별하게 던지는 대신 결괏값을 직접 반환하여 프로그램의 실행 흐름이 임의로 끊기는 것을 방지하고 성능 오버헤드를 줄입니다 [4-6]. 개발자가 함수 시그니처만으로 발생 가능한 에러를 명확히 알 수 있게 하며, 컴파일 단계에서 모든 경우의 수에 대한 에러 처리를 강제하여 런타임 안정성을 높이는 데 활용됩니다 [7-9].
|
||||
## 매 한 줄
|
||||
> **"매 error 를 value 로 만들어 type system 이 강제 handle 하게 함"**. Rust 의 `Result<T, E>`, Haskell `Either e a`, OCaml `result`, Swift `Result` 가 origin. TypeScript ecosystem 에서 매 neverthrow, Effect TS, ts-results 가 mainstream. 매 throw/catch 의 invisible control flow 와 unsafe error 의 alternative.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **예외 처리(Exception)의 안전한 대안:** Result Type은 예상 가능한 에러(예: 데이터베이스 조회 실패, 입력값 유효성 검사 실패 등)를 처리하는 데 효과적입니다 [10-12]. 전통적인 예외 처리는 호출 스택([[Call Stack]])을 거슬러 올라가야 하므로 비용이 크고 디버깅 추적이 어렵지만, Result Type은 단순한 객체 반환이므로 더 빠르고 효율적입니다 [5, 6, 13]. 따라서 예기치 못한 치명적 결함(Defect)에만 예외를 던지고, 예상 가능한 비즈니스 로직상의 에러에는 Result Type을 반환하는 방식이 권장됩니다 [14, 15].
|
||||
- **타입 안전성(Type Safety)과 예측 가능성 향상:** Result Type은 반환 타입 안에 성공(`Ok`)과 실패(`Err`)의 형태를 모두 담기 때문에, 개발자가 코드를 분석할 때 시그니처만 보더라도 어떤 결과와 에러가 반환될지 예측할 수 있습니다 [1, 7]. 이는 '최소 놀람의 원칙(Principle of least astonishment)'을 충족시키며, 컴파일러가 모든 반환 경우를 확인(Exhaustiveness check)하도록 강제하여 런타임 오류 가능성을 원천적으로 차단합니다 [3, 9].
|
||||
- **언어별 구현 및 활용:** 이 패턴은 본래 F#, Elixir, Erlang, Rust와 같은 함수형 프로그래밍 언어에서 기원하였으며, 주로 구별된 유니온([[Discriminated Unions]])이나 Either 모나드의 형태를 띠고 있습니다 [5, 16, 17]. TypeScript 생태계에서는 `neverthrow`와 같은 외부 라이브러리를 활용하여 명시적인 `Err` 및 `Ok` 객체로 에러 제어 흐름을 구현할 수 있습니다 [1, 18].
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 motivation
|
||||
- Exception 은 type signature 에 안 보임 → 매 caller 가 forget 가능.
|
||||
- `Result<T, E>` 는 매 return type 에 explicit → handle X 면 type error.
|
||||
- 매 functional composition 에 friendly (map, andThen, mapErr).
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[Discriminated Unions]], Exception Handling
|
||||
- **Projects/Contexts:** neverthrow, OneOf, Railway Oriented Programming
|
||||
- **Contradictions/Notes:** C# 생태계에서는 Result Type 도입을 둘러싼 논쟁이 존재합니다. 도입을 지지하는 쪽은 타입 안전성과 명확한 에러 파악을 장점으로 꼽지만, 반대하는 개발자들은 C#이 기본적으로 예외(Exception) 기반의 언어이므로 두 가지 에러 처리 방식이 섞이면 혼란을 야기할 수 있으며, 결괏값을 포장(Wrapping)하고 푸는 과정에서 보일러플레이트 코드가 증가해 오히려 가독성을 해칠 수 있다고 지적합니다 [2, 6, 19, 20].
|
||||
### 매 ADT shape
|
||||
- `Ok(T)` | `Err(E)` — 매 두 variant 의 sum type.
|
||||
- `unwrap`, `unwrap_or`, `map`, `andThen` (flatMap), `match`.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
### 매 응용
|
||||
1. Validation pipeline (parse → transform → save).
|
||||
2. Network call wrapping (fetch, DB query).
|
||||
3. Domain error modeling (NotFound, Unauthorized, Conflict).
|
||||
4. Recoverable failure (vs panic / unrecoverable).
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
### TypeScript discriminated union
|
||||
```typescript
|
||||
type Result<T, E = Error> =
|
||||
| { ok: true; value: T }
|
||||
| { ok: false; error: E }
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(TODO)*
|
||||
const ok = <T,>(value: T): Result<T, never> => ({ ok: true, value })
|
||||
const err = <E,>(error: E): Result<never, E> => ({ ok: false, error })
|
||||
|
||||
**언제 쓰면 안 되는가:**
|
||||
- *(TODO)*
|
||||
function parseAge(s: string): Result<number, 'NaN' | 'Negative'> {
|
||||
const n = Number(s)
|
||||
if (Number.isNaN(n)) return err('NaN')
|
||||
if (n < 0) return err('Negative')
|
||||
return ok(n)
|
||||
}
|
||||
|
||||
## 🧪 검증 상태 (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
|
||||
const r = parseAge('42')
|
||||
if (r.ok) console.log(r.value)
|
||||
else console.error(r.error)
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### neverthrow library
|
||||
```typescript
|
||||
import { Result, ok, err, ResultAsync } from 'neverthrow'
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
const fetchUser = (id: string): ResultAsync<User, 'NotFound' | 'Network'> =>
|
||||
ResultAsync.fromPromise(
|
||||
fetch(`/api/users/${id}`).then(r => r.ok ? r.json() : Promise.reject('NotFound')),
|
||||
(e): 'NotFound' | 'Network' => e === 'NotFound' ? 'NotFound' : 'Network',
|
||||
)
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
await fetchUser('u1')
|
||||
.map(u => u.email)
|
||||
.mapErr(e => `failed: ${e}`)
|
||||
.match(
|
||||
email => console.log(email),
|
||||
err => console.error(err),
|
||||
)
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### Effect TS (richer)
|
||||
```typescript
|
||||
import { Effect, pipe } from 'effect'
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
const parseJSON = (s: string) =>
|
||||
Effect.try({
|
||||
try: () => JSON.parse(s),
|
||||
catch: () => new Error('InvalidJSON'),
|
||||
})
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
const program = pipe(
|
||||
parseJSON('{"x":1}'),
|
||||
Effect.map((o: { x: number }) => o.x * 2),
|
||||
Effect.catchAll(e => Effect.succeed(0)),
|
||||
)
|
||||
Effect.runPromise(program).then(console.log) // 2
|
||||
```
|
||||
|
||||
### Rust (canonical)
|
||||
```rust
|
||||
fn divide(a: i32, b: i32) -> Result<i32, &'static str> {
|
||||
if b == 0 { Err("division by zero") } else { Ok(a / b) }
|
||||
}
|
||||
|
||||
fn pipeline() -> Result<i32, &'static str> {
|
||||
let x = divide(10, 2)?; // ? propagates Err
|
||||
let y = divide(x, 0)?;
|
||||
Ok(y)
|
||||
}
|
||||
```
|
||||
|
||||
### Validation accumulation (multiple errors)
|
||||
```typescript
|
||||
type Validated<T, E> = { ok: true; value: T } | { ok: false; errors: E[] }
|
||||
|
||||
const combine = <T, E>(rs: Result<T, E>[]): Validated<T[], E> => {
|
||||
const errs: E[] = []
|
||||
const vals: T[] = []
|
||||
for (const r of rs) r.ok ? vals.push(r.value) : errs.push(r.error)
|
||||
return errs.length ? { ok: false, errors: errs } : { ok: true, value: vals }
|
||||
}
|
||||
```
|
||||
|
||||
### Match helper
|
||||
```typescript
|
||||
function match<T, E, R>(r: Result<T, E>, on: { ok: (v: T) => R; err: (e: E) => R }): R {
|
||||
return r.ok ? on.ok(r.value) : on.err(r.error)
|
||||
}
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| Recoverable error, type-safety 중요 | Result type |
|
||||
| Truly unrecoverable (bug, OOM) | throw / panic |
|
||||
| Multiple errors 누적 | Validated / Either with NonEmptyArray |
|
||||
| Async + retry + interrupt | Effect TS |
|
||||
| Simple library, no dep | hand-rolled discriminated union |
|
||||
| Existing throw-based API | wrap with try/catch → Result |
|
||||
|
||||
**기본값**: 매 domain layer 는 Result, infrastructure boundary 에서 unwrap → throw 변환.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Error Handling]] · [[Discriminated Unions]]
|
||||
- 변형: [[Effect TS]] · [[Either Monad]]
|
||||
- 응용: [[Zod 런타임 유효성 검사 통합]] · [[API 응답 및 에러 핸들링 아키텍처]]
|
||||
- Adjacent: [[Type Theory]] · [[Functional Programming]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 explicit error path, validation pipeline, FP-style composition, "this can fail" type-level documentation.
|
||||
**언제 X**: 매 trivial script, throw 가 더 idiomatic 한 case (e.g. assertion, programmer error).
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **`unwrap()` 의 production**: 매 `Result` 의 의도 의 부정. 매 explicit `match` / `mapErr`.
|
||||
- **`Result<T, Error>` 의 generic**: 매 specific tagged union (`'NotFound' | 'Conflict'`) 가 useful.
|
||||
- **Mixed throw + Result**: layer 의 inconsistent → caller 의 confusing. 매 boundary 의 명확.
|
||||
- **Async 에 raw Promise<Result>**: rejection 도 발생 → 매 ResultAsync / Effect 가 안전.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Rust std::result docs, neverthrow README, Effect TS docs 3.x, "Domain Modeling Made Functional" Wlaschin).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — Result patterns (TS, neverthrow, Effect, Rust) |
|
||||
|
||||
@@ -2,23 +2,33 @@
|
||||
id: wiki-2026-0508-sca-소프트웨어-구성-분석
|
||||
title: SCA (소프트웨어 구성 분석)
|
||||
category: 10_Wiki/Topics
|
||||
status: merged
|
||||
redirect_to: SCA
|
||||
canonical_id: SCA
|
||||
aliases: [sca_korean_redirect]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: software-composition-analysis
|
||||
duplicate_of: "[[Software Composition Analysis]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [uncategorized]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
confidence_score: 0.9
|
||||
verification_status: redirected
|
||||
tags: [duplicate, security, supply-chain, sast]
|
||||
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
|
||||
---
|
||||
|
||||
# Redirect
|
||||
# SCA (소프트웨어 구성 분석)
|
||||
|
||||
이 문서는 [[SCA]]으로 통합되었습니다.
|
||||
> **이 문서는 [[Software Composition Analysis]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 핵심 요약 (specialization aspects)
|
||||
- 매 dependency 의 known CVE 의 scan — npm audit, Snyk, Dependabot, Trivy.
|
||||
- 매 SBOM (Software Bill of Materials) 의 generate — CycloneDX / SPDX format.
|
||||
- 매 transitive dependency 의 vulnerability 의 catch.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Software Composition Analysis]] (canonical)
|
||||
- Adjacent: [[DAST (동적 애플리케이션 보안 테스트)]] · [[CI_CD 파이프라인]]
|
||||
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — SCA canonical 로 redirect |
|
||||
|
||||
@@ -2,99 +2,30 @@
|
||||
id: wiki-2026-0508-solid-원칙
|
||||
title: SOLID 원칙
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-FAB206]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: solid-principles
|
||||
duplicate_of: "[[SOLID Principles]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - SOLID 원칙"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, oop, design-principles]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[SOLID 원칙]]
|
||||
# SOLID 원칙
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> SOLID 원칙은 객체 지향 프로그래밍에서 소프트웨어 설계를 더 이해하기 쉽고, 유연하며, 유지보수하기 좋게 만들기 위해 고안된 5가지 핵심 설계 원칙의 집합이다 [1]. 로버트 C. 마틴(Ro[[BERT]] C. Martin)에 의해 대중화된 이 원칙들은 코드의 부패를 방지하고 견고한 기반을 구축하는 데 필수적인 지침으로 작용한다 [1]. 이 원칙들을 올바르게 적용하면 시스템 내 컴포넌트 간의 의존성이 줄어들어 한 부분의 변경이 다른 부분에 미치는 영향을 최소화할 수 있다 [1].
|
||||
> **이 문서는 [[SOLID Principles]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
**SOLID의 5가지 핵심 원칙**
|
||||
* **단일 책임 원칙 (SRP, Single Responsibility Principle):** 클래스는 단 하나의 변경 이유만 가져야 하며, 이는 오직 하나의 역할(책임)만을 수행해야 함을 의미한다 [2, 3]. 이를 통해 클래스를 더 쉽게 이해하고 평가할 수 있으며, 코드의 명확성과 유지보수성이 향상된다 [3]. SRP는 '관심사의 분리(SoC)' 개념에서 직접적으로 파생된 원칙 중 하나이다 [4].
|
||||
* **개방-폐쇄 원칙 (OCP, Open/Closed Principle):** 소프트웨어 엔티티는 확장에는 열려 있어야 하지만 수정에는 닫혀 있어야 한다 [2, 3, 5]. 이는 인터페이스나 추상 클래스와 같은 추상화 및 다형성 과정을 사용하여, 기존 코드를 변경하지 않고도 새로운 하위 클래스를 통해 새 기능을 추가할 수 있게 함으로써 달성된다 [2, 3].
|
||||
* **리스코프 치환 원칙 (LSP, Liskov Substitution Principle):** 하위 타입(서브클래스)은 프로그램의 정확성을 훼손하지 않으면서 기본 타입(부모 클래스)을 대체할 수 있어야 한다 [2, 3]. 이는 파생 클래스가 기본 클래스의 동작을 임의로 변경하지 않고 매끄럽게 호환되어 시스템의 신뢰성과 견고성을 향상시킬 수 있도록 보장한다 [2, 3].
|
||||
* **인터페이스 분리 원칙 (ISP, Interface Segregation Principle):** 클라이언트는 자신이 사용하지 않는 인터페이스에 의존하도록 강요받아서는 안 된다 [2, 3]. 이를 위해 하나의 크고 범용적인 인터페이스보다는 작고 구체적이며 전문화된 인터페이스를 여러 개 만드는 것이 권장되며, 이 역시 '관심사의 분리(SoC)' 원칙에서 파생되었다 [2-4].
|
||||
* **의존성 역전 원칙 (DIP, Dependency [[Inversion]] Principle):** 고수준 모듈은 저수준 모듈에 의존해서는 안 되며, 양쪽 모두 추상화(예: 인터페이스)에 의존해야 한다 [2, 3, 6]. 이러한 접근은 종종 의존성 주입(Dependency Injection, DI) 프레임워크를 통해 구현되며, 모듈성을 높이고 시스템이 변화에 쉽게 적응할 수 있도록 만든다 [2, 3, 7].
|
||||
## 핵심 요약
|
||||
- SRP, OCP, LSP, ISP, DIP — Robert C. Martin 의 OOP 설계 5원칙.
|
||||
|
||||
**구현 팁 및 기대 효과**
|
||||
* SOLID 원칙을 레거시 애플리케이션 전체에 한 번에 적용하기보다는, 가장 적용하기 쉽고 즉각적인 이점을 제공하는 '단일 책임 원칙(SRP)'부터 시작하여 점진적으로 적용하는 것이 유리하다 [7].
|
||||
* 구현 방법(How)보다 컴포넌트가 해야 할 일인 인터페이스(What)를 먼저 설계하는 관행을 들이면 자연스럽게 OCP와 DIP 원칙을 뒷받침할 수 있다 [7].
|
||||
* 이 원칙들은 객체 지향 시스템, 라이브러리, 그리고 지속적으로 성장하는 대규모 코드베이스에 이상적으로 적용되며, 결합도가 낮고 테스트 가능성이 높으며 유연한 코드를 산출하는 핵심 기반이 된다 [8].
|
||||
## 🔗 Graph
|
||||
- 부모: [[SOLID Principles]] (canonical)
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[객체 지향 프로그래밍(OOP)]], [[관심사의 분리(SoC)]], [[의존성 주입(DI)]]
|
||||
- **Projects/Contexts:** [[클린 아키텍처(Clean [[Architecture]])]], [[소프트웨어 아키텍처 베스트 프랙티스]]
|
||||
- **Contradictions/Notes:** 소스 전반에 걸쳐 SOLID 원칙은 코드의 복잡성을 줄이고 유지보수성을 높이는 필수적인 기법으로 일관되게 강조되고 있으며, 서로 대립하거나 모순되는 주장은 존재하지 않습니다 [1, 3, 8].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -1,25 +1,34 @@
|
||||
---
|
||||
id: wiki-20260508-spa--redir
|
||||
title: SPA 라우트 전환 성능 최적화
|
||||
category: Programming & Language
|
||||
status: merged
|
||||
redirect_to: SPA_라우트_전환_성능_최적화
|
||||
canonical_id: SPA_라우트_전환_성능_최적화
|
||||
category: 10_Wiki/Topics
|
||||
status: duplicate
|
||||
canonical_id: code-splitting-lazy-loading
|
||||
duplicate_of: "[[Code Splitting Lazy Loading (코드 분할 및 지연 로딩)]]"
|
||||
aliases: []
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [redirect]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
confidence_score: 0.9
|
||||
verification_status: redirected
|
||||
tags: [duplicate, spa, performance, frontend]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-merge 2026-05-08)
|
||||
---
|
||||
|
||||
# SPA 라우트 전환 성능 최적화
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 이 문서는 P-Reinforce Phase 2 자동 MERGE에 의해 **[[SPA_라우트_전환_성능_최적화]]**로 통합되었습니다.
|
||||
> **이 문서는 [[Code Splitting Lazy Loading (코드 분할 및 지연 로딩)]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
---
|
||||
*Redirected to: [[SPA_라우트_전환_성능_최적화]]*
|
||||
## 핵심 요약 (specialization aspects)
|
||||
- 매 SPA route 전환 의 LCP / INP 최적화 — 매 route-level code split 의 핵심.
|
||||
- 매 prefetch on hover / intersection — 매 perceived latency 의 단축.
|
||||
- 매 React Router / Next App Router 의 lazy + Suspense 의 활용.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Code Splitting Lazy Loading (코드 분할 및 지연 로딩)]] (canonical)
|
||||
- Adjacent: [[Cumulative Layout Shift (CLS)]] · [[Google Lighthouse]]
|
||||
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — Code Splitting canonical 로 redirect |
|
||||
|
||||
@@ -2,91 +2,125 @@
|
||||
id: wiki-2026-0508-scheduler-api
|
||||
title: Scheduler API
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-6B64AB]
|
||||
aliases: [scheduler.postTask, Prioritized Task Scheduling]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [web, performance, scheduling, browser-api]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Scheduler API"
|
||||
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: JavaScript
|
||||
framework: Web Platform
|
||||
---
|
||||
|
||||
# [[Scheduler API]]
|
||||
# Scheduler API
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Scheduler API는 개발자가 브라우저 내에서 다양한 처리 작업이 실행되는 시점을 더 쉽게 제어할 수 있도록 도와주는 기능입니다 [1]. 길게 실행되는 작업은 여러 개의 짧은 작업보다 상호작용 지연을 더 많이 유발하기 때문에, 이 API를 통해 작업을 분할하여 사용자 경험을 개선할 수 있습니다 [1]. 특히 작업 중간에 제어권을 브라우저에 양보함으로써 다른 중요한 상호작용이 지연 없이 우선적으로 처리될 수 있게 합니다 [1].
|
||||
## 매 한 줄
|
||||
> **"매 priority-aware task scheduling for the main thread"**. Scheduler API (`scheduler.postTask`, `scheduler.yield`) 는 long task breakup + priority hint (user-blocking / user-visible / background) 로 INP/responsiveness 최적화. 2026 Chromium + Firefox stable.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **도입 배경:** 브라우저에서의 CPU 처리는 사용자 경험에 큰 영향을 미치며, 중요도가 각기 다른 작업들이 실행될 때 긴 처리 작업은 여러 개의 짧은 작업들보다 사용자 상호작용 지연을 훨씬 더 많이 발생시킵니다 [1]. Scheduler API는 개발자가 이러한 다양한 작업이 실행되는 시기를 원활하게 제어할 수 있도록 돕습니다 [1].
|
||||
- **핵심 기능 (`scheduler.yield()`):** 개발자는 `scheduler.yield()` 메서드를 사용하여 작업(job) 중간에 브라우저의 스케줄러로 제어권을 쉽게 양보(yield)할 수 있습니다 [1]. 이를 통해 브라우저는 기존에 진행 중이던 작업을 마저 처리하기 전에, 사용자 상호작용 처리와 같은 다른 긴급한 작업을 먼저 다룰 수 있게 됩니다 [1].
|
||||
- **브라우저 지원 현황:** [[Chrome]]은 2024년에 이 새로운 API를 처음 도입했으며, 2025년 8월부터는 Firefox에서도 지원을 시작했습니다 [2]. 하지만 Safari는 아직 Scheduler API를 지원하지 않는 상태입니다 [2].
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 Priorities
|
||||
- `user-blocking`: 매 immediate UI response (input handler post-work).
|
||||
- `user-visible`: 매 default — visible 하지만 non-blocking.
|
||||
- `background`: 매 lazy work (analytics, prefetch).
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** scheduler.yield(), [[Interaction to Next Paint (INP)]]
|
||||
- **Projects/Contexts:** [[Web Performance Optimization]]
|
||||
- **Contradictions/Notes:** 소스 내에 상충하는 정보는 없습니다. 다만, Chrome(2024년)과 Firefox(2025년 8월)는 해당 API를 지원하지만 Safari는 아직 지원하지 않는다는 호환성 제약이 명시되어 있습니다 [2].
|
||||
### 매 vs setTimeout(0) / requestIdleCallback
|
||||
- 매 setTimeout(0): no priority, no abort.
|
||||
- 매 rIC: idle only, deadline-based.
|
||||
- 매 postTask: explicit priority + AbortSignal + delay.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
### 매 응용
|
||||
1. 매 long list rendering 분할.
|
||||
2. 매 input handler 후 heavy work 양보.
|
||||
3. 매 background data prefetch.
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 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
|
||||
### postTask 기본
|
||||
```js
|
||||
scheduler.postTask(() => doWork(), { priority: 'background' });
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### scheduler.yield (long task breakup)
|
||||
```js
|
||||
async function processItems(items) {
|
||||
for (const item of items) {
|
||||
process(item);
|
||||
if (navigator.scheduling?.isInputPending?.() || items.indexOf(item) % 50 === 0) {
|
||||
await scheduler.yield();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### TaskController로 abort
|
||||
```js
|
||||
const controller = new TaskController({ priority: 'user-visible' });
|
||||
scheduler.postTask(longJob, { signal: controller.signal });
|
||||
// 매 cancel
|
||||
controller.abort();
|
||||
// 매 priority 동적 변경
|
||||
controller.setPriority('background');
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Delay
|
||||
```js
|
||||
scheduler.postTask(refresh, { priority: 'background', delay: 5000 });
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### Polyfill fallback
|
||||
```js
|
||||
const yield_ = () =>
|
||||
globalThis.scheduler?.yield?.() ??
|
||||
new Promise(r => setTimeout(r, 0));
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
### React + Scheduler API
|
||||
```js
|
||||
// React 19+ 의 useTransition + scheduler integration
|
||||
startTransition(() => {
|
||||
scheduler.postTask(() => setState(heavy), { priority: 'background' });
|
||||
});
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| Heavy work after input | `scheduler.yield()` mid-loop |
|
||||
| Lazy prefetch | `postTask({priority:'background'})` |
|
||||
| Cancel-able task | `TaskController` |
|
||||
| Idle-only callback | `requestIdleCallback` |
|
||||
| 매 simple deferral | `queueMicrotask` |
|
||||
|
||||
**기본값**: 매 long loops 의 `scheduler.yield()` + 매 background work `postTask({priority:'background'})`.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Browser_Event_Loop]] · [[Core_Web_Vitals]]
|
||||
- 변형: [[requestIdleCallback]] · [[queueMicrotask]]
|
||||
- 응용: [[INP_Optimization]] · [[Long_Task_Breakup]]
|
||||
- Adjacent: [[AbortController]] · [[React_useTransition]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 INP regression 발견 + 매 long task (>50ms) breakup 필요 시. 매 prioritized background work.
|
||||
**언제 X**: 매 worker offload 가 더 적합한 CPU-heavy work, 또는 매 framework scheduler (React) 가 이미 처리.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **postTask 안 yield**: 매 single long callback 은 여전히 long task. 매 internally yield 필요.
|
||||
- **user-blocking 남용**: 매 priority inversion 의. 매 진짜 input-critical 만.
|
||||
- **Polyfill 없는 production deploy**: 매 Safari 일부 버전 미지원.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (W3C Prioritized Task Scheduling, web.dev/optimize-inp).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — postTask + yield patterns |
|
||||
|
||||
@@ -2,89 +2,180 @@
|
||||
id: wiki-2026-0508-server-architecture
|
||||
title: Server Architecture
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
aliases: [서버 아키텍처, Backend Architecture]
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-F7D840]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [architecture, backend, distributed-systems, scalability]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Server [[Architecture]]"
|
||||
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: polyglot
|
||||
framework: cloud-native
|
||||
---
|
||||
|
||||
# [[Server Architecture]]
|
||||
# Server Architecture
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> 소스에 관련 정보가 부족합니다.
|
||||
## 매 한 줄
|
||||
> **"매 architecture 는 trade-off 의 명시화"**. Monolith → Modular monolith → Service-oriented → Microservices → Cells/Serverless 의 spectrum 에서 팀 규모, 도메인 복잡도, scale 요구에 맞춰 선택. 2026 현재 majority 는 modular monolith + targeted services.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
소스에 관련 정보가 부족합니다.
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 layer
|
||||
- **Edge**: CDN (Cloudflare, Fastly), DDoS, TLS termination.
|
||||
- **Gateway**: API gateway, authn, rate limit (Kong, Envoy, AWS API GW).
|
||||
- **Application**: stateless service tier (horizontal scale).
|
||||
- **Data**: OLTP DB, cache, search, object store, queue.
|
||||
- **Async**: message broker (Kafka, NATS, SQS), workers.
|
||||
- **Observability**: traces (OTel), metrics (Prom), logs.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** 소스에 관련 정보가 부족합니다.
|
||||
- **Projects/Contexts:** 소스에 관련 정보가 부족합니다.
|
||||
- **Contradictions/Notes:** 소스에 관련 정보가 부족합니다.
|
||||
### 매 archetype
|
||||
- **Monolith**: 단일 deploy unit — 작은 팀, 빠른 iteration.
|
||||
- **Modular monolith**: bounded context 명확, 단일 배포 — 2026 default.
|
||||
- **Microservices**: 팀당 service, 독립 배포 — Conway's law 정렬 시.
|
||||
- **Cells**: bulkhead 별 독립 stack — high-availability.
|
||||
- **Serverless**: Lambda/CF Workers — bursty, low-traffic OK.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
### 매 응용
|
||||
1. SaaS multi-tenant.
|
||||
2. E-commerce platform.
|
||||
3. Real-time messaging.
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 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
|
||||
### 1. Stateless service + sticky data
|
||||
```yaml
|
||||
# k8s deployment
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
spec:
|
||||
replicas: 6
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: api
|
||||
image: app:v1.42
|
||||
readinessProbe:
|
||||
httpGet: { path: /ready, port: 8080 }
|
||||
resources:
|
||||
requests: { cpu: 250m, memory: 512Mi }
|
||||
limits: { cpu: 1, memory: 1Gi }
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### 2. CQRS read replica fan-out
|
||||
```typescript
|
||||
class OrderService {
|
||||
constructor(private writeDb: Pool, private readDb: Pool) {}
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
async create(o: Order) {
|
||||
return this.writeDb.tx(async (tx) => {
|
||||
await tx.insert("orders", o);
|
||||
await tx.publish("order.created", o);
|
||||
});
|
||||
}
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
async query(userId: string) {
|
||||
return this.readDb.query("SELECT * FROM orders_view WHERE user_id=$1", [userId]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### 3. Circuit breaker
|
||||
```typescript
|
||||
import CircuitBreaker from "opossum";
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
const breaker = new CircuitBreaker(callPaymentApi, {
|
||||
timeout: 3000,
|
||||
errorThresholdPercentage: 50,
|
||||
resetTimeout: 30_000,
|
||||
});
|
||||
breaker.fallback(() => ({ status: "queued" }));
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### 4. Outbox pattern
|
||||
```sql
|
||||
BEGIN;
|
||||
INSERT INTO orders (...) VALUES (...);
|
||||
INSERT INTO outbox (topic, payload) VALUES ('order.created', $1);
|
||||
COMMIT;
|
||||
-- separate poller publishes outbox → kafka, then deletes
|
||||
```
|
||||
|
||||
### 5. Backpressure with bounded queue
|
||||
```go
|
||||
sem := make(chan struct{}, 100) // max 100 in-flight
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
select {
|
||||
case sem <- struct{}{}:
|
||||
defer func() { <-sem }()
|
||||
handle(w, r)
|
||||
default:
|
||||
http.Error(w, "busy", 503)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### 6. Cell-based isolation
|
||||
```
|
||||
Customer A → Cell-1 (LB, app, DB shard)
|
||||
Customer B → Cell-2 (LB, app, DB shard)
|
||||
Customer C → Cell-1
|
||||
# Cell failure blast radius = 1 cell only
|
||||
```
|
||||
|
||||
### 7. SLO-based deploy gate
|
||||
```yaml
|
||||
# Argo Rollouts
|
||||
strategy:
|
||||
canary:
|
||||
steps:
|
||||
- setWeight: 10
|
||||
- analysis:
|
||||
templates: [{ templateName: error-rate-slo }]
|
||||
- setWeight: 50
|
||||
- pause: { duration: 10m }
|
||||
- setWeight: 100
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| 팀 < 20명, 단일 도메인 | Modular monolith |
|
||||
| 팀 > 50명, 다 도메인 | Microservices (bounded context별) |
|
||||
| Bursty traffic, 0 → 1000 RPS | Serverless |
|
||||
| Multi-tenant, blast radius 우려 | Cells |
|
||||
| Strong consistency 핵심 | Single-writer + read replicas |
|
||||
| Eventual OK, throughput 핵심 | Event-driven + CQRS |
|
||||
|
||||
**기본값**: modular monolith + Postgres + Redis + 1-2 async workers. 명확히 필요할 때 split.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Distributed Systems]] · [[Cloud Native]]
|
||||
- 변형: [[Microservices]] · [[Serverless]] · [[Event-Driven Architecture]]
|
||||
- 응용: [[SaaS Architecture]] · [[E-commerce Architecture]]
|
||||
- Adjacent: [[Kubernetes]] · [[Service Mesh]] · [[Observability]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 신규 시스템 설계, scale 병목 분석, monolith → service split 시점 판단.
|
||||
**언제 X**: 작은 internal tool (overengineering 위험), prototype (속도 우선).
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Distributed monolith**: 서비스 분리 + 동기 호출 chain — latency, 장애 전파.
|
||||
- **Premature microservices**: 팀 < 10명에 서비스 20개 — ops 폭발.
|
||||
- **Shared DB across services**: coupling, schema migration 지옥.
|
||||
- **No observability**: 분산 시 trace 없으면 디버깅 불가.
|
||||
- **Synchronous everything**: queue/event 활용 안 하면 cascading failure.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (AWS Well-Architected, Google SRE book, Sam Newman "Building Microservices").
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — server architecture archetypes & patterns (2026 cloud-native) |
|
||||
|
||||
@@ -2,97 +2,33 @@
|
||||
id: wiki-2026-0508-sharedarraybuffer-동시성-문제-해결법
|
||||
title: SharedArrayBuffer 동시성 문제 해결법
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-918534]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: sharedarraybuffer
|
||||
duplicate_of: "[[SharedArrayBuffer]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - SharedArrayBuffer 동시성 문제 해결법"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, concurrency, web-workers, atomics]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[SharedArrayBuffer 동시성 문제 해결법]]
|
||||
# SharedArrayBuffer 동시성 문제 해결법
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> `SharedArrayBuffer`는 여러 스레드가 동일한 메모리 영역을 동시에 공유하기 때문에 데이터 경쟁 상태(Data Race)가 발생할 수 있으며, 이를 해결하기 위해 **원자적 연산(Atomic [[Opera]]tions)** 지원을 활용하거나 **아키텍처 설계(ECS 등)**를 통해 스레드 간의 읽기/쓰기 역할을 명확히 분리해야 합니다.
|
||||
> **이 문서는 [[SharedArrayBuffer]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
**1. 원자적 연산 (Atomic Operations) 활용** `SharedArrayBuffer`는 메인 스레드와 워커 스레드 등 서로 다른 컨텍스트에서 데이터를 복사 없이 공유할 수 있도록 지원하며, 동시 접근으로 인한 충돌을 막기 위해 원자적 연산(Atomic operations)을 지원합니다. _(※ 외부 지식 참고: 자바스크립트에서는 이를 위해 내장된 `Atomics` 전역 객체를 사용합니다. `Atomics.load()`, `Atomics.store()`, `Atomics.add()`, `Atomics.compareExchange()` 등의 API를 사용하면 특정 메모리 주소에 대한 읽기와 쓰기가 중간에 끊기지 않는 '단일 연산'으로 보장되어 안전하게 데이터를 제어할 수 있습니다.)_
|
||||
## 핵심 요약 (specialization aspects)
|
||||
- 매 race condition 의 해결 — Atomics.compareExchange / Atomics.wait / notify.
|
||||
- 매 COOP/COEP header 의 cross-origin isolation 의 필수.
|
||||
- 매 worker 간 zero-copy data sharing — 매 WebGPU / WASM 의 backbone.
|
||||
|
||||
**2. 스레드 동기화 제어 (Lock / Wait 메커니즘)** _(※ 외부 지식 참고: 동시성 충돌을 더욱 엄격하게 제어해야 할 경우 `Atomics.wait()`와 `Atomics.notify()`를 활용해 특정 스레드를 대기 상태로 만들고 작업이 끝난 후 깨우는 방식(Lock, Mutex 패턴)을 구현하여 다중 스레드의 접근 순서를 동기화할 수 있습니다.)_
|
||||
## 🔗 Graph
|
||||
- 부모: [[SharedArrayBuffer]] (canonical)
|
||||
- Adjacent: [[Web Workers]] · [[Atomics API]]
|
||||
|
||||
**3. 아키텍처적 해결: ECS(Entity Component[[ system]])를 통한 읽기/쓰기 역할 분리** 가장 효율적인 방식은 엔진 구조 자체에서 데이터의 단방향 흐름을 강제하여 충돌을 회피하는 것입니다. 고성능 게임 엔진 아키텍처에서는 ECS의 컴포넌트 데이터를 `SharedArrayBuffer`에 할당한 후, 스레드의 역할을 엄격하게 분리합니다.
|
||||
|
||||
- **쓰기(Write) 전담 스레드:** 웹 워커(Web Worker)는 백그라운드에서 물리 연산이나 AI 로직 등을 수행하며 버퍼의 데이터를 업데이트(Write)합니다.
|
||||
- **읽기(Read) 전담 스레드:** 메인 스레드(React 및 렌더링 루프)는 렌더링 시점에 버퍼에서 데이터를 즉시 읽어와(Read) 복사 비용 없이 [[WebGL]]/Three.js 메시의 속성에 반영합니다. 이러한 데이터 지향 설계(Data-Oriented Design)를 채택하면 여러 스레드가 동일한 데이터에 동시에 쓰기 작업을 하는 상황을 구조적으로 방지할 수 있습니다.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** Web Worker, Atomics API, 경쟁 상태 (Race Condition), Data-Oriented Design (ECS)
|
||||
- **Projects/Contexts:** 멀티스레드 React WebGL 애플리케이션, 고성능 실시간 상호작용 시스템
|
||||
- **Contradictions/Notes:** `SharedArrayBuffer`는 지연 시간을 극도로 낮추고 복사 비용을 '0'으로 만들지만, 로우 레벨의 이진 데이터 버퍼를 직접 다뤄야 하고 `Atomics`로 동시성을 관리해야 하므로 구현 복잡도가 매우 높습니다 [264, 895, 이전 대화 내용 참조]. 따라서 충돌 제어와 개발 편의성이 더 중요한 일반적인 경우에는 Valtio 등 프록시(Proxy)를 사용해 `BroadcastChannel`이나 `postMessage`로 변경점(Delta)만 동기화하는 메시지 기반 패턴이 더 직관적일 수 있습니다.
|
||||
|
||||
---
|
||||
|
||||
_Last updated: 2026-04-14_
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — SharedArrayBuffer canonical 로 redirect |
|
||||
|
||||
+21
-89
@@ -1,100 +1,32 @@
|
||||
---
|
||||
id: wiki-2026-0508-sharedarraybuffer-보안-이슈와-cross-o
|
||||
title: SharedArrayBuffer 보안 이슈와 Cross Origin Isolation
|
||||
title: SharedArrayBuffer 보안 이슈와 Cross-Origin Isolation
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-C3F189]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: sharedarraybuffer-cross-origin-isolation
|
||||
duplicate_of: "[[SharedArrayBuffer_보안_이슈와_Cross-Origin_Isolation]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - SharedArrayBuffer 보안 이슈와 Cross-Origin Isolation"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, security, spectre, coop, coep]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[SharedArrayBuffer 보안 이슈와 Cross-Origin Isolation]]
|
||||
# SharedArrayBuffer 보안 이슈와 Cross-Origin Isolation
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> `SharedArrayBuffer`는 스펙터([[Spectre]])와 같은 CPU 취약점을 악용한 타이밍 공격([[Timing Attack]])의 위험이 있어 브라우저에서 사용이 제한되며, 이를 다시 활성화하려면 웹 서버에 **Cross-Origin Isolation(교차 출처 격리) 보안 헤더**를 명시적으로 설정하여 안전한 환경을 구축해야 합니다.
|
||||
> **이 문서는 [[SharedArrayBuffer_보안_이슈와_Cross-Origin_Isolation]] 의 중복본입니다.** (filename slug 변형 — canonical 과 동일 내용.)
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
**1. 보안 이슈의 배경: 스펙터(Spectre) 취약점** `SharedArrayBuffer`는 두 스레드가 메모리를 공유하면서 매우 정밀한 고해상도 타이머를 만들 수 있게 해줍니다. 해커들은 이를 악용하여 최신 CPU의 예측 실행([[Speculative Execution]]) 과정에서 발생하는 미세한 시간 차이를 측정하고, 결과적으로 같은 브라우저 프로세스 내에 로드된 다른 사이트의 비밀번호 등 **민감한 메모리 데이터를 탈취하는 스펙터(Spectre) 취약점**을 발견했습니다. 이 치명적인 보안 결함 때문에 브라우저 벤더들은 2018년경 이 기능을 일괄 비활성화했습니다.
|
||||
## 핵심 요약
|
||||
- Spectre side-channel 의 high-resolution timer 위험 → SAB 비활성화.
|
||||
- COOP+COEP 로 cross-origin isolation 활성화 시 SAB 재허용.
|
||||
|
||||
**2. Cross-Origin Isolation (교차 출처 격리) 도입** 이후 브라우저들은 멀티스레딩의 성능적 이점을 포기할 수 없었기에, 현재 실행 중인 웹 페이지가 신뢰할 수 없는 외부의 다른 사이트(Origin) 리소스와 철저히 분리된 안전한 환경에서만 `SharedArrayBuffer`를 다시 사용할 수 있도록 정책을 변경했습니다. 이 격리된 환경을 **'Cross-Origin Isolated'** 상태라고 부릅니다.
|
||||
## 🔗 Graph
|
||||
- 부모: [[SharedArrayBuffer_보안_이슈와_Cross-Origin_Isolation]] (canonical)
|
||||
|
||||
**3. COOP 및 COEP HTTP 헤더 설정법** 웹 애플리케이션에서 `SharedArrayBuffer`를 활성화하려면, 서버 측(Nginx, Apache, Node.js Express, Vercel, AWS CloudFront 등)에서 HTML 문서를 응답할 때 반드시 다음 **두 가지 HTTP 보안 헤더**를 내려보내야 합니다.
|
||||
|
||||
- **`Cross-Origin-Opener-Policy: same-origin` (COOP):** 현재 문서와 다른 출처를 가진 팝업창이나 외부 문서가 서로의 `window` 객체에 접근하지 못하도록 브라우징 실행 컨텍스트를 분리합니다.
|
||||
- **`Cross-Origin-Embedder-Policy: require-corp` (COEP):** 명시적으로 승인받지 않은 다른 출처의 리소스(외부 이미지, 스크립트, iframe 등)가 현재 페이지에 임베드되는 것을 원천적으로 차단합니다.
|
||||
|
||||
**4. 설정 시 발생할 수 있는 사이드 이펙트 및 주의사항** 위 헤더를 적용하여 고성능 환경을 얻는 대신, 보안 격리가 너무 엄격해져서 **기존에 잘 작동하던 외부 CDN 스크립트나 외부 이미지 등이 차단되는 문제**가 발생할 수 있습니다. 이를 해결하기 위해서는 외부 리소스를 제공하는 서버 측에서 `Cross-Origin-Resource-Policy: cross-origin` (CORP) 헤더나 적절한 CORS 설정(`Access-Control-Allow-Origin`)을 제공해야 하며, 클라이언트의 HTML 태그에도 `<img src="..." crossorigin="anonymous">`와 같이 명시적인 속성을 추가해 주어야 합니다.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** Spectre & Meltdown 취약점, CORS (Cross-Origin Resource Sharing), HTTP Security Headers (COOP, COEP, CORP), Web Worker 멀티스레딩 통신
|
||||
- **Projects/Contexts:** 보안 격리 환경에서의 고성능 웹 게임 개발, 멀티스레드 기반 렌더링 파이프라인(React Three Fiber)
|
||||
- **Contradictions/Notes:** 로컬 개발 환경(`localhost` 또는 `127.0.0.1`)에서는 개발 편의상 Cross-Origin Isolation 헤더 없이도 `SharedArrayBuffer`가 임시로 동작할 수 있으나, 실제 프로덕션(HTTPS 환경)에 배포할 때는 반드시 헤더 설정이 필요합니다.
|
||||
|
||||
---
|
||||
|
||||
_Last updated: 2026-04-14_
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
+22
-92
@@ -1,103 +1,33 @@
|
||||
---
|
||||
id: wiki-2026-0508-sharedarraybuffer-보안을-위한-cross-o
|
||||
title: SharedArrayBuffer 보안을 위한 Cross Origin Isolation 서버 헤더 설정
|
||||
title: SharedArrayBuffer 보안을 위한 Cross-Origin Isolation 서버 헤더 설정
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-32CC81]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: sharedarraybuffer-cross-origin-isolation
|
||||
duplicate_of: "[[SharedArrayBuffer_보안_이슈와_Cross-Origin_Isolation]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - SharedArrayBuffer 보안을 위한 Cross-Origin Isolation 서버 헤더 설정"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, security, coop, coep]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[SharedArrayBuffer 보안을 위한 Cross-Origin Isolation 서버 헤더 설정]]
|
||||
# SharedArrayBuffer 보안을 위한 Cross-Origin Isolation 서버 헤더 설정
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> `SharedArrayBuffer`의 스펙터([[Spectre]]) 취약점을 악용한 메모리 유출 공격을 방지하기 위해, 웹 서버에서 응답 시 **COOP 및 COEP HTTP 보안 헤더**를 설정하여 브라우저의 교차 출처 격리(Cross-Origin Isolation) 상태를 활성화하는 서버 설정 방법입니다.
|
||||
> **이 문서는 [[SharedArrayBuffer_보안_이슈와_Cross-Origin_Isolation]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
**1. Cross-Origin Isolation(교차 출처 격리)의 필요성** `SharedArrayBuffer`는 스레드 간 원자적 연산과 메모리 공유를 지원하지만, 이를 악용하면 타이밍 공격(Spectre)을 통해 브라우저 내 다른 사이트의 민감한 데이터를 탈취할 수 있습니다. 브라우저 벤더들은 이를 막기 위해 현재 페이지가 신뢰할 수 없는 외부 출처(Origin) 리소스와 철저히 분리된 안전한 **'Cross-Origin Isolated'** 환경에서만 객체 생성을 허용하도록 보안 정책을 강화했습니다.
|
||||
## 핵심 요약 (server header specialization)
|
||||
- `Cross-Origin-Opener-Policy: same-origin`.
|
||||
- `Cross-Origin-Embedder-Policy: require-corp` (or `credentialless`).
|
||||
- `crossOriginIsolated === true` 검증.
|
||||
|
||||
**2. 필수 HTTP 응답 헤더 설정 (COOP / COEP)** 이 격리 환경을 활성화하려면, HTML을 제공하는 웹 서버(Node.js Express, Nginx, Vercel 등)의 응답 헤더(Response Headers)에 다음 두 가지를 반드시 추가해야 합니다.
|
||||
## 🔗 Graph
|
||||
- 부모: [[SharedArrayBuffer_보안_이슈와_Cross-Origin_Isolation]] (canonical)
|
||||
|
||||
- **`Cross-Origin-Opener-Policy: same-origin` (COOP):** 현재 최상위 문서가 다른 교차 출처 문서(예: 타 사이트에서 열린 팝업창 등)와 브라우징 실행 컨텍스트를 공유하지 못하도록 차단하여 외부 간섭을 막습니다.
|
||||
- **`Cross-Origin-Embedder-Policy: require-corp` (COEP):** (경우에 따라 `credentialless` 사용 가능) 명시적인 보안 승인(CORS 또는 CORP 헤더)을 받지 않은 외부 리소스(외부 CDN 스크립트, 이미지, iframe 등)가 현재 페이지에 임베드(Embed)되는 것을 원천적으로 차단합니다.
|
||||
|
||||
**3. 브라우저 활성화 검증** 서버 헤더가 올바르게 설정되어 페이지가 로드되면, 클라이언트의 자바스크립트 환경에서 전역 속성인 **`crossOriginIsolated`가 `true`를 반환**합니다. 이 상태에서만 오류 없이 `new SharedArrayBuffer()`를 호출할 수 있습니다.
|
||||
|
||||
**4. 헤더 적용 시 발생하는 사이드 이펙트와 해결책** 이 보안 정책은 매우 엄격하여 **기존에 정상적으로 불러오던 외부 이미지나 서드파티 스크립트(Google Analytics 등)가 브라우저에 의해 렌더링 차단되는 심각한 부작용**이 발생할 수 있습니다. 이를 우회하고 해결하려면:
|
||||
|
||||
- HTML 내 모든 외부 리소스 태그(예: `<img>`, `<script>`)에 `crossorigin="anonymous"` 속성을 추가해야 합니다.
|
||||
- 해당 외부 리소스를 제공하는 서버 측에서 `Access-Control-Allow-Origin` (CORS) 또는 `Cross-Origin-Resource-Policy: cross-origin` (CORP) 응답 헤더를 함께 내려주어야 합니다.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** Spectre 부채널 공격 ([[Side-channel Attack]]), HTTP Security Headers (COOP/COEP/CORP), CORS (Cross-Origin Resource Sharing), Web Worker Multi-threading
|
||||
- **Projects/Contexts:** 보안이 강화된 고성능 [[WebGL]]/React 게임 엔진 배포 환경 구축
|
||||
- **Contradictions/Notes:** 로컬 개발 환경(`localhost` 또는 `127.0.0.1`)에서는 개발 편의를 위해 COOP/COEP 헤더 없이도 `SharedArrayBuffer`가 일시적으로 동작할 수 있습니다. 하지만 실제 도메인이 연결된 프로덕션(HTTPS) 환경으로 배포할 때는 서버 헤더 설정이 누락되면 즉시 앱이 중단되므로 인프라 수준에서의 꼼꼼한 설정이 필요합니다.
|
||||
|
||||
---
|
||||
|
||||
_Last updated: 2026-04-14_
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -2,94 +2,151 @@
|
||||
id: wiki-2026-0508-sharedarraybuffer로-스레드-간-메모리-공유-
|
||||
title: SharedArrayBuffer로 스레드 간 메모리 공유 효율 높이기
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-4A9AE0]
|
||||
aliases: [SAB, SharedArrayBuffer, Shared Memory JS]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [javascript, web-worker, concurrency, performance]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - SharedArrayBuffer로 스레드 간 메모리 공유 효율 높이기"
|
||||
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: JavaScript
|
||||
framework: Web Workers
|
||||
---
|
||||
|
||||
# [[SharedArrayBuffer로 스레드 간 메모리 공유 효율 높이기]]
|
||||
# SharedArrayBuffer로 스레드 간 메모리 공유 효율 높이기
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> **SharedArrayBuffer**는 웹 워커(Web Worker)와 메인 스레드 간의 전통적인 통신 방식인 `postMessage`의 데이터 직렬화(Serialization) 및 복사 오버헤드를 제거하고, **두 스레드가 동일한 메모리 영역을 복사 없이(Zero-copy) 직접 접근하고 공유**할 수 있게 해주는 저수준(Low-level)의 고성능 최적화 기법입니다.
|
||||
## 매 한 줄
|
||||
> **"매 zero-copy shared memory between JS threads"**. SharedArrayBuffer (SAB) 는 main thread + Web Worker 간 동일 raw bytes 를 공유. postMessage structured clone 의 copy 비용 제거 + Atomics 로 race-free coordination 가능.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
**1. 직렬화(Serialization) 병목 제거** 자바스크립트 환경에서 메인 스레드와 워커 스레드는 기본적으로 메모리를 공유하지 않기 때문에, 데이터를 주고받으려면 내부적으로 데이터를 복사하고 직렬화/역직렬화하는 과정을 거쳐야 합니다. 그러나 `SharedArrayBuffer`를 사용하면 이러한 복사 과정 없이 데이터가 포함된 원시 바이너리 버퍼 자체를 공유하므로, 메모리 전송에 소모되는 지연 시간(오버헤드)이 '0'에 가까워집니다.
|
||||
## 매 핵심
|
||||
|
||||
**2. ECS(Entity Component[[ system]]) 기반 아키텍처와의 시너지** 이 기술은 `bitECS`와 같은 고성능 게임 아키텍처 패턴(ECS)과 결합할 때 진가를 발휘합니다. 게임 내 수만 개의 엔티티(파티클, 총알, 적 등) 정보를 무거운 자바스크립트 객체 대신 연속된 메모리 블록인 `[[TypedArray]]` 구조로 구성한 뒤, 이를 `SharedArrayBuffer`에 적재합니다.
|
||||
### 매 동작 모델
|
||||
- 매 buffer instance 는 multiple threads 에서 동일 backing store 참조.
|
||||
- 매 TypedArray view (Int32Array, Float64Array) 로 typed access.
|
||||
- 매 Atomics.load/store/add 로 atomic ops.
|
||||
- 매 Atomics.wait/notify 로 futex-like blocking sync.
|
||||
|
||||
- **워커 스레드(물리 엔진/AI):** 물리 연산을 수행하여 버퍼 내의 좌표($x, y, z$) 데이터를 업데이트합니다.
|
||||
- **메인 스레드(React/Three.js):** 메시지 수신을 기다릴 필요 없이, 버퍼의 메모리 주소를 즉시 읽어와 `[[InstancedMesh]]` 등을 60FPS로 렌더링합니다.
|
||||
### 매 vs ArrayBuffer
|
||||
- 매 ArrayBuffer: postMessage 시 structured clone (copy) 또는 transfer (ownership move).
|
||||
- 매 SharedArrayBuffer: postMessage 시 reference 전달, 양쪽 동시 access.
|
||||
|
||||
**3. Atomics API를 통한 원자적(Atomic) 동기화 보장** 여러 스레드가 동시에 동일한 메모리 공간에 읽기/쓰기를 수행하면 데이터가 꼬이는 경쟁 상태(Race Condition)가 발생할 수 있습니다. `SharedArrayBuffer`는 `Atomics` 객체에서 제공하는 원자적 연산을 지원하여, 스레드 간에 안전하게 메모리를 조작하고 동기화할 수 있도록 보장합니다.
|
||||
### 매 응용
|
||||
1. WASM linear memory 공유 (multi-threaded WASM).
|
||||
2. 매 large image/audio buffer worker 처리 (zero-copy).
|
||||
3. Lock-free queue / ring buffer 구현.
|
||||
|
||||
**4. 한계점 및 개발 트레이드오프 (Trade-offs)**
|
||||
## 💻 패턴
|
||||
|
||||
- **매우 낮은 추상화 수준:** 일반적인 JSON 객체나 유연한 자바스크립트 데이터 구조를 사용할 수 없으며, 바이트 단위의 로우 레벨 바이너리 버퍼를 직접 계산하고 다뤄야 하므로 개발 난이도가 매우 높고 사용자 친화적이지 않습니다.
|
||||
- **보안 제약 (COOP/COEP):** 멜트다운(Meltdown) 및 스펙터([[Spectre]])와 같은 CPU 보안 취약점을 방지하기 위해, 웹 서버에서 보안 헤더(`Cross-Origin-Opener-Policy` 및 `Cross-Origin-Embedder-Policy`)를 엄격하게 설정해야만 브라우저에서 `SharedArrayBuffer` 기능을 활성화할 수 있습니다. (※ 이 내용은 제공된 소스 외부의 일반적인 웹 보안 지식입니다. 실제 도입 시 서버 설정 확인이 필요합니다.)
|
||||
### Worker 에 SAB 전달
|
||||
```js
|
||||
// main.js
|
||||
const sab = new SharedArrayBuffer(1024);
|
||||
const view = new Int32Array(sab);
|
||||
const worker = new Worker('worker.js');
|
||||
worker.postMessage({ sab });
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
// worker.js
|
||||
self.onmessage = ({ data }) => {
|
||||
const view = new Int32Array(data.sab);
|
||||
Atomics.store(view, 0, 42);
|
||||
Atomics.notify(view, 0, 1);
|
||||
};
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### Atomic counter
|
||||
```js
|
||||
const sab = new SharedArrayBuffer(4);
|
||||
const counter = new Int32Array(sab);
|
||||
Atomics.add(counter, 0, 1); // race-free increment
|
||||
const value = Atomics.load(counter, 0);
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Producer / Consumer wait+notify
|
||||
```js
|
||||
// consumer
|
||||
Atomics.wait(view, 0, 0); // sleep until view[0] != 0
|
||||
const data = Atomics.load(view, 0);
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
// producer
|
||||
Atomics.store(view, 0, 99);
|
||||
Atomics.notify(view, 0, 1); // wake 1 waiter
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### Lock (spinlock)
|
||||
```js
|
||||
function lock(view, idx) {
|
||||
while (Atomics.compareExchange(view, idx, 0, 1) !== 0) {
|
||||
Atomics.wait(view, idx, 1);
|
||||
}
|
||||
}
|
||||
function unlock(view, idx) {
|
||||
Atomics.store(view, idx, 0);
|
||||
Atomics.notify(view, idx, 1);
|
||||
}
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
### Ring buffer (lock-free SPSC)
|
||||
```js
|
||||
class RingBuffer {
|
||||
constructor(sab, capacity) {
|
||||
this.head = new Int32Array(sab, 0, 1);
|
||||
this.tail = new Int32Array(sab, 4, 1);
|
||||
this.data = new Int32Array(sab, 8, capacity);
|
||||
this.cap = capacity;
|
||||
}
|
||||
push(v) {
|
||||
const t = Atomics.load(this.tail, 0);
|
||||
const next = (t + 1) % this.cap;
|
||||
if (next === Atomics.load(this.head, 0)) return false; // full
|
||||
this.data[t] = v;
|
||||
Atomics.store(this.tail, 0, next);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### WASM threads memory
|
||||
```js
|
||||
const memory = new WebAssembly.Memory({ initial: 10, maximum: 100, shared: true });
|
||||
// memory.buffer is SharedArrayBuffer
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| Small data, infrequent | postMessage (clone) |
|
||||
| Large buffer, hot path | SAB + Atomics |
|
||||
| Transfer ownership once | postMessage with transfer list |
|
||||
| Multi-threaded WASM | shared:true Memory |
|
||||
|
||||
**기본값**: 매 small data postMessage, 매 hot-path large buffer SAB.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Web_Workers]] · [[JavaScript_Concurrency]]
|
||||
- 변형: [[SharedArrayBuffer_보안_이슈와_Cross-Origin_Isolation]]
|
||||
- 응용: [[WebAssembly_Threads]] · [[OffscreenCanvas]]
|
||||
- Adjacent: [[Atomics_API]] · [[Structured_Clone]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 large data parallel processing (image/video/ML inference) 의 + 매 worker 간 frequent sync 필요 시.
|
||||
**언제 X**: 매 simple task offload (postMessage 충분) 또는 매 COOP/COEP 헤더 설정 불가능한 환경.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Non-atomic access on shared view**: 매 race condition. 매 always Atomics.* 사용.
|
||||
- **Spin without wait**: 매 CPU burn. 매 Atomics.wait 으로 block.
|
||||
- **Missing COOP/COEP**: 매 modern browser 에서 SAB 비활성화. 매 cross-origin isolation 필수.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (MDN SharedArrayBuffer, ECMAScript Atomics spec).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — SAB + Atomics patterns |
|
||||
|
||||
@@ -2,102 +2,150 @@
|
||||
id: wiki-2026-0508-structural-typing
|
||||
title: Structural Typing
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-8C150A]
|
||||
aliases: [duck typing, shape typing, structural type system]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
confidence_score: 0.93
|
||||
verification_status: applied
|
||||
tags: [typescript, type-system, fundamentals]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Structural Typing"
|
||||
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: tsc
|
||||
---
|
||||
|
||||
# [[Structural Typing]]
|
||||
# Structural Typing
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> 구조적 타이핑(Structural Typing)은 명시적인 타입 선언이나 이름이 아닌, 객체가 가진 실제 형태와 구조(속성 및 메서드)를 기준으로 타입 호환성을 결정하는 시스템이다[1, 2]. "오리처럼 걷고 갉갉거리면 오리다"라는 '덕 타이핑(Duck Typing)' 원리와 동일한 맥락을 가지며, 대상 타입이 요구하는 최소한의 멤버(속성)를 모두 포함하고 있다면 호환되는 것으로 간주한다[2, 3]. 이는 타입의 이름이 일치해야만 호환성을 인정하는 명목적 타이핑(Nominal Typing)과 대비되는 TypeScript의 핵심 설계 철학이다[2].
|
||||
## 매 한 줄
|
||||
> **"매 type 의 compatibility 의 name 이 아닌 shape 으로 결정"**. TypeScript / Go 의 핵심 — 매 nominal typing (Java / C#) 의 반대. 매 2026 TS 5.7 의 동일 원칙 — 매 modern web 의 fundamental.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **동작 원리 및 특징**
|
||||
* 구조적 타이핑 하에서는 두 클래스나 객체의 이름 및 출처가 다르더라도 내부 속성의 구조가 동일하다면 서로 호환 가능한 것으로 취급된다[2, 4].
|
||||
* TypeScript에서는 변수 `y`의 타입에 정의된 모든 멤버를 객체 `x`가 최소한으로 포함하고 있다면, `x`는 `y`와 호환되어 할당이 가능하다[3]. 즉, 대상 타입의 요구사항 외에 추가적인 여분의 속성을 더 가지고 있더라도 호환이 허용된다[4].
|
||||
* 집합론의 관점에서 볼 때, 구조적 타이핑을 통해 클래스의 명시적인 상속 선언(`class X extends Y`) 없이도 특정 구조를 만족하는 객체는 더 넓은 타입의 부분집합으로 안전하게 취급될 수 있다[5, 6].
|
||||
## 매 핵심
|
||||
|
||||
* **명목적 타이핑(Nominal Typing)과의 차이 및 한계**
|
||||
* Java나 C#과 같은 언어는 신분증명처럼 타입의 명시적 선언이나 이름 일치를 요구하는 명목적 타이핑을 사용하지만, TypeScript의 모든 객체는 본질적으로 '비정확(inexact)'하며 구조적 타이핑의 지배를 받는다[2, 7].
|
||||
* 이러한 유연함은 매우 편리하지만, 의미적으로 엄격히 구분되어야 하는 동일한 구조의 데이터(예: User ID와 Order ID가 모두 단순 문자열인 경우)를 컴파일러가 구분하지 못하는 '기본 타입에의 집착(Primitive Obsession)' 문제를 야기한다[8].
|
||||
* 이를 방어하기 위해 개발자들은 런타임에는 존재하지 않지만 컴파일 시점에만 존재하는 고유한 가상의 식별자를 부여하는 브랜디드 타입(Branded Types / Opaque Types) 패턴을 활용하여 구조적 타이핑의 한계를 보완한다[8-10].
|
||||
### 매 Nominal vs Structural
|
||||
- **Nominal** (Java/C#): 매 declared name 의 일치 — 매 같은 shape 라도 다른 type 시 incompatible.
|
||||
- **Structural** (TS/Go): 매 properties / methods 의 shape 의 match 의 compatible — 매 declaration site 의 무관.
|
||||
|
||||
* **초과 속성 검사([[Excess Property Checking]])와의 상호작용**
|
||||
* 구조적 타이핑은 추가 속성의 존재를 근본적으로 허용하지만, 개발자의 오타나 예기치 않은 데이터 유입을 막기 위해 TypeScript는 예외적으로 객체 리터럴을 변수에 직접 할당하거나 함수의 인자로 직접 넘길 때 '초과 속성 검사(EPC)'를 발동시킨다[6, 11, 12].
|
||||
* 그러나 객체를 중간 변수에 먼저 할당한 뒤 전달하는 식의 간접 할당 상황이 되면 EPC가 작동하지 않고, 구조적 타이핑의 "최소 요건 충족" 원칙으로 되돌아가 초과 속성을 그대로 허용하게 된다[13, 14].
|
||||
* 이와 같은 우회 현상으로 인한 런타임 오류나 초과 속성 유입 문제를 방지하기 위해 `satisfies` 연산자를 활용하면, 구조의 구체성을 잃지 않으면서도 대상 타입과의 구조적 계약을 엄격히 준수하도록 강제할 수 있다[15, 16].
|
||||
### 매 동작 원리
|
||||
- 매 assignability check: 매 source type 의 모든 required member 의 target type 의 존재 의 확인.
|
||||
- 매 method signature: 매 parameter 의 contravariant, return 의 covariant.
|
||||
- 매 excess property checking: 매 object literal 의 special case — 매 추가 property 의 error.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 응용
|
||||
1. 매 function parameter 의 minimal interface 의 require — 매 flexibility.
|
||||
2. 매 mock / stub 의 작성 의 자연스러움 — 매 test 의 친화.
|
||||
3. 매 ad-hoc type 의 inline definition.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** Duck Typing, Nominal Typing, [[Excess Property Checking]], Branded Types, [[satisfies [[Opera]]tor]]
|
||||
- **Projects/Contexts:** TypeScript Type[[ system]]
|
||||
- **Contradictions/Notes:** 구조적 타이핑은 기본적으로 대상 객체가 추가적인 속성을 가지는 것을 허용하여 유연한 호환성을 부여하지만[4], 객체 리터럴을 직접 할당할 때는 이러한 유연성 대신 '초과 속성 검사(Excess Property Checking)'가 개입하여 선언되지 않은 속성의 존재를 엄격하게 에러로 처리한다는 상반된 동작 규칙이 공존한다[6, 11, 12].
|
||||
## 💻 패턴
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
### 매 Structural 의 기본
|
||||
```typescript
|
||||
interface Point { x: number; y: number; }
|
||||
class Vector { constructor(public x: number, public y: number) {} }
|
||||
|
||||
---
|
||||
function dist(p: Point): number {
|
||||
return Math.sqrt(p.x ** 2 + p.y ** 2);
|
||||
}
|
||||
|
||||
## 🤖 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
|
||||
dist(new Vector(3, 4)); // OK — 매 Vector 의 Point shape 의 satisfy
|
||||
dist({ x: 3, y: 4 }); // OK — 매 object literal 의 동일
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### 매 Branded type 의 nominal 의 흉내
|
||||
```typescript
|
||||
// 매 structural 의 약점 — 매 같은 shape 의 다른 의미 의 mix
|
||||
type UserId = string & { __brand: 'UserId' };
|
||||
type OrderId = string & { __brand: 'OrderId' };
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
function getUser(id: UserId) { /* ... */ }
|
||||
const oid = 'order-1' as OrderId;
|
||||
// getUser(oid); // 매 ERROR — 매 brand 의 mismatch
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### 매 Function 의 contravariance
|
||||
```typescript
|
||||
type Logger = (msg: string) => void;
|
||||
const wide: (msg: string | number) => void = (m) => console.log(m);
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
const log: Logger = wide; // OK — 매 parameter 의 contravariant
|
||||
// 매 wide 의 string 도 number 도 받으므로 string-only 의 substitute 가능
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
### 매 Excess property checking 의 우회
|
||||
```typescript
|
||||
interface Config { url: string; }
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
// declareConfig({ url: '/api', timeout: 5000 }); // ERROR — 매 excess
|
||||
const cfg = { url: '/api', timeout: 5000 };
|
||||
declareConfig(cfg); // OK — 매 variable 의 우회 (매 fresh literal 만 check)
|
||||
|
||||
function declareConfig(c: Config) { /* ... */ }
|
||||
```
|
||||
|
||||
### 매 Subtyping 의 자동
|
||||
```typescript
|
||||
interface Animal { name: string; }
|
||||
interface Dog { name: string; bark(): void; }
|
||||
|
||||
const dogs: Dog[] = [{ name: 'Rex', bark: () => {} }];
|
||||
const animals: Animal[] = dogs; // OK — 매 Dog 의 superset 의 자동 subtype
|
||||
```
|
||||
|
||||
### 매 Class 의 structural 의 trap
|
||||
```typescript
|
||||
class Cat { meow() {} }
|
||||
class Lion { meow() {} }
|
||||
|
||||
const c: Cat = new Lion(); // OK?? — 매 동일 shape 의 compatible
|
||||
// 매 nominal 기대 시 private field 의 brand 의 사용
|
||||
class CatN { #species = 'cat'; meow() {} }
|
||||
class LionN { #species = 'lion'; meow() {} }
|
||||
// 매 #private 의 nominal effect — 매 cross-class 의 incompatible
|
||||
```
|
||||
|
||||
### 매 Generic 의 structural 의 활용
|
||||
```typescript
|
||||
function pluck<T, K extends keyof T>(arr: T[], key: K): T[K][] {
|
||||
return arr.map(x => x[key]);
|
||||
}
|
||||
// 매 T 의 shape 의 자유 — 매 keyof T 의 structural inference
|
||||
const names = pluck([{ name: 'a' }, { name: 'b' }], 'name');
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| 일반 type | structural (default) — 매 TS 의 native |
|
||||
| Domain ID 의 mix 방지 | branded type |
|
||||
| Strict nominal 필요 | private field / unique symbol brand |
|
||||
| External library compat | structural — 매 자연스러운 fit |
|
||||
|
||||
**기본값**: structural typing 의 활용. 매 ID confusion 의 risk 시 branded type 의 추가.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[TypeScript]] · [[Type System]]
|
||||
- 변형: [[Nominal Typing]] · [[Duck Typing]]
|
||||
- 응용: [[Excess Property Checking]] · [[ts-brand]]
|
||||
- Adjacent: [[Discriminated Unions]] · [[Type Casting]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: TS type error 의 explain, branded type 의 권장, structural vs nominal 의 비교.
|
||||
**언제 X**: Java/C# 같은 nominal 언어 의 답변 의 mix — 매 언어 의 명시.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **ID confusion**: 매 UserId / OrderId 의 같은 string — 매 brand 의 추가.
|
||||
- **Class identity 의 의존**: 매 instanceof 없이 type 만 의 distinguish — 매 trap.
|
||||
- **Excess 의 silence**: 매 변수 거쳐 우회 후 typo 의 미발견.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (TypeScript Handbook, "Type Compatibility").
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — Structural typing FULL 작성 |
|
||||
|
||||
@@ -2,92 +2,159 @@
|
||||
id: wiki-2026-0508-teamcity
|
||||
title: TeamCity
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-63B068]
|
||||
aliases: [JetBrains TeamCity, TC]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [ci-cd, jetbrains, build, devops]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - TeamCity"
|
||||
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: Kotlin DSL
|
||||
framework: TeamCity 2025.x
|
||||
---
|
||||
|
||||
# [[TeamCity]]
|
||||
# TeamCity
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> TeamCity는 개봉 즉시 사용 가능한(out of the box) 강력한 지속적 통합(Continuous Integration) 도구입니다 [1, 2]. 이 도구는 팀을 위한 CI/CD 서버로 기능하며, 소프트웨어 빌드 프로세스 내에서 핵심적인 역할을 수행합니다 [3, 4]. 특히 정적 코드 분석 도구와 원활하게 통합되어 저품질의 코드가 프로덕션 환경에 배포되는 것을 사전에 차단할 수 있게 돕습니다 [4].
|
||||
## 매 한 줄
|
||||
> **"매 enterprise CI server with first-class build chains + Kotlin DSL config"**. JetBrains TeamCity 는 build configuration 의 strong dependency graph + snapshot/artifact dep + 매 versioned settings (Kotlin DSL) 를 제공하는 self-hosted CI. 2026 의 TeamCity 2025.x 는 cloud agents + GitHub Actions 호환성 + native AI test analytics.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **강력한 지속적 통합 서버:** TeamCity는 팀을 위한 도구(Team Tools) 라인업에 포함된 강력한 CI(Continuous Integration) 서버입니다 [1, 3].
|
||||
- **분석 도구와의 매끄러운 통합:** TeamCity는 코드 품질 분석 플랫폼인 Qodana와 같은 도구와 원활하게 통합되는 CI/CD 서버입니다 [4]. 이를 통해 개발 팀은 자동화된 코드 스캔 작업을 빌드 프로세스의 자연스러운 일부로 편입시킬 수 있습니다 [4].
|
||||
- **프로덕션 배포 전 품질 관리:** 파이프라인 내에서 TeamCity를 활용하면 저품질의 코드가 프로덕션 환경에 도달하기 전에 이를 사전에 차단하는 가드레일 역할을 수행할 수 있습니다 [4].
|
||||
- **한계:** 제공된 소스에서는 TeamCity가 강력한 CI 도구이며 Qodana와 통합된다는 점 외에, TeamCity 자체의 구체적인 아키텍처나 세부 기능에 대해서는 다루고 있지 않으므로 소스에 관련 정보가 부족합니다.
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 핵심 개념
|
||||
- **Project / Build Configuration / Build**: 3-tier hierarchy.
|
||||
- **Snapshot dependency**: 매 동일 VCS revision 보장된 build chain.
|
||||
- **Artifact dependency**: 매 upstream artifact pull.
|
||||
- **Build chain**: composite build (status rollup).
|
||||
- **Versioned settings**: 매 Kotlin DSL `.teamcity/settings.kts` git 관리.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** Continuous Integration, Qodana, CI/CD
|
||||
- **Projects/Contexts:** 정적 코드 분석 및 소프트웨어 빌드 자동화
|
||||
- **Contradictions/Notes:** 소스에는 TeamCity가 CI/CD 서버로서 Qodana와 통합되어 빌드 프로세스를 돕는다는 사실 외에 구체적인 기능이나 상세한 원리에 대한 설명은 없으므로, 전반적으로 소스에 관련 정보가 부족합니다.
|
||||
### 매 vs Jenkins / GitHub Actions
|
||||
- 매 Jenkins: plugin sprawl, 매 declarative 선택적.
|
||||
- 매 GitHub Actions: SaaS-first, 매 enterprise 의 self-host 약함.
|
||||
- 매 TeamCity: 매 enterprise self-host + Kotlin DSL + 매 strong test history.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
### 매 응용
|
||||
1. JVM monorepo (Gradle/Maven) build chain.
|
||||
2. .NET / Kotlin Multiplatform CI.
|
||||
3. Hybrid cloud agents (AWS/GCP/K8s) + on-prem.
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
### Kotlin DSL 의 build config
|
||||
```kotlin
|
||||
import jetbrains.buildServer.configs.kotlin.*
|
||||
import jetbrains.buildServer.configs.kotlin.buildSteps.gradle
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(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
|
||||
object Build : BuildType({
|
||||
name = "Build & Test"
|
||||
vcs { root(DslContext.settingsRoot) }
|
||||
steps {
|
||||
gradle {
|
||||
tasks = "clean build"
|
||||
useGradleWrapper = true
|
||||
}
|
||||
}
|
||||
triggers { vcs {} }
|
||||
features {
|
||||
perfmon {}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### Build chain (snapshot dep)
|
||||
```kotlin
|
||||
object Deploy : BuildType({
|
||||
name = "Deploy"
|
||||
dependencies {
|
||||
snapshot(Build) { onDependencyFailure = FailureAction.FAIL_TO_START }
|
||||
artifacts(Build) { artifactRules = "build/libs/*.jar => libs" }
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Parameter + secret
|
||||
```kotlin
|
||||
params {
|
||||
param("env.NODE_ENV", "production")
|
||||
password("env.NPM_TOKEN", "credentialsJSON:...")
|
||||
}
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Agent requirements
|
||||
```kotlin
|
||||
requirements {
|
||||
contains("teamcity.agent.jvm.os.name", "Linux")
|
||||
exists("env.DOCKER_HOST")
|
||||
}
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### Matrix-style (composite build)
|
||||
```kotlin
|
||||
object Matrix : BuildType({ name = "All Platforms"; type = Type.COMPOSITE
|
||||
dependencies {
|
||||
snapshot(BuildLinux) {}
|
||||
snapshot(BuildMac) {}
|
||||
snapshot(BuildWin) {}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
### REST API trigger
|
||||
```bash
|
||||
curl -u user:token -X POST \
|
||||
-H "Content-Type: application/xml" \
|
||||
-d '<build><buildType id="Build"/></build>' \
|
||||
https://tc.example.com/app/rest/buildQueue
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### Cloud agent profile (Kubernetes)
|
||||
```kotlin
|
||||
features {
|
||||
feature {
|
||||
type = "CloudImage"
|
||||
param("cloud-code", "kubernetes")
|
||||
param("image-name", "myorg/tc-agent:2025")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | CI choice |
|
||||
|---|---|
|
||||
| 매 JVM enterprise self-host | TeamCity |
|
||||
| 매 GitHub-centric OSS | GitHub Actions |
|
||||
| 매 plugin-heavy legacy | Jenkins |
|
||||
| 매 GitLab-native | GitLab CI |
|
||||
| 매 monorepo with cache focus | Buildkite / Bazel CI |
|
||||
|
||||
**기본값**: 매 enterprise JVM/.NET 의 TeamCity, 매 OSS GitHub repo 의 Actions.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[CI_CD]] · [[Build_Automation]]
|
||||
- 변형: [[Jenkins]] · [[GitHub_Actions]] · [[GitLab_CI]]
|
||||
- 응용: [[Gradle]] · [[Kotlin_DSL]]
|
||||
- Adjacent: [[Artifact_Repository]] · [[Test_Reporting]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 enterprise CI 설계, 매 build chain 의존성 모델링, 매 Kotlin DSL 마이그레이션.
|
||||
**언제 X**: 매 single-repo OSS — 매 GitHub Actions 가 zero-ops.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **UI-only config (no DSL)**: 매 settings drift, 매 review 불가능.
|
||||
- **Snapshot dep 없이 chain**: 매 inconsistent revision.
|
||||
- **Agent 의 secret 평문 저장**: 매 Token credentials 사용 필수.
|
||||
- **Build history retention 무한**: 매 server 디스크 폭발.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (JetBrains TeamCity 2025 docs, Kotlin DSL guide).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — TeamCity 2025 + Kotlin DSL |
|
||||
|
||||
@@ -2,93 +2,32 @@
|
||||
id: wiki-2026-0508-toss-front-sdk-기반-외부-연동사-플러그인-개발
|
||||
title: Toss Front SDK 기반 외부 연동사 플러그인 개발 생태계 구축
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-C43BEF]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: 토스-toss-front-sdk-퍼사드-패턴-적용
|
||||
duplicate_of: "[[토스(Toss) Front SDK 퍼사드 패턴 적용]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Toss Front SDK 기반 외부 연동사 플러그인 개발 생태계 구축"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, toss, sdk, plugin]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[Toss Front SDK 기반 외부 연동사 플러그인 개발 생태계 구축]]
|
||||
# Toss Front SDK 기반 외부 연동사 플러그인 개발 생태계 구축
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> 토스플레이스는 자체 개발한 결제 단말기인 'Toss Front(프론트)'에서 동작하는 플러그인 앱을 외부 연동사가 개발할 수 있도록 돕는 SDK를 개발하고 있습니다 [1]. 이는 내부 개발에만 의존하지 않고 서드파티(3rd-party)의 참여를 통해 단말기 생태계를 무한히 확장하기 위한 구조입니다 [1]. 외부 연동사의 휴먼 에러를 방지하고 안정적인 생태계를 구축하기 위해, 토스는 퍼사드(Facade) 패턴을 활용하여 사용자의 의도(Intent)에 맞춘 직관적이고 안전한 SDK 인터페이스를 설계하는 데 집중하고 있습니다 [2, 3].
|
||||
> **이 문서는 [[토스(Toss) Front SDK 퍼사드 패턴 적용]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **플러그인 생태계 확장의 기반**: Toss Front SDK를 이용하면 외부 연동사는 토스 서비스의 데이터를 연동하여 자신들이 원하는 플러그인 앱을 개발하고 프론트에서 동작시킬 수 있습니다 [1]. 이러한 3rd-party 연동 구조는 프론트 생태계를 무한히 확장 가능하게 만드는 핵심적인 역할을 합니다 [1].
|
||||
- **안정성과 직결되는 SDK 사용성**: 외부 연동 생태계를 성장시키려면 훌륭한 사용 경험을 제공하는 SDK 인터페이스가 필수적입니다 [2]. SDK 사용의 복잡성이나 모호한 가이드는 핸들러 부착 누락이나 메모리 누수([[memory]] Leak) 같은 연동사의 휴먼 에러를 유발하며, 이는 곧 플랫폼 전체의 장애와 안정성 문제로 직결됩니다 [2, 4].
|
||||
- **퍼사드(Facade) 패턴을 통한 사용자 의도 중심 설계**: 토스는 SDK 내부의 복잡한 로직(인증, 재시도, 상태 관리 등)을 단순히 숨기는 것을 넘어, 사용자의 '의도(Intent)'를 기준으로 인터페이스를 재구성하는 퍼사드 패턴을 채택했습니다 [3]. 이를 통해 사용자는 자연스러운 목적만 표현하면 되며, 인지 부하와 결합도를 크게 낮출 수 있습니다 [3, 5].
|
||||
- **파레토 법칙에 따른 인터페이스 공존 전략**: 좋은 SDK는 퍼사드를 통한 고수준(High-level) API뿐만 아니라 저수준(Low-level) API도 함께 제공합니다 [5]. 80%의 흔한 유즈케이스는 고수준 퍼사드 인터페이스로 간단히 해결하게 하고, 20%의 세밀한 제어가 필요한 경우에는 저수준 인터페이스를 탈출구(Escape Hatch)로 제공하여 개발자 경험과 SDK의 장기적인 호환성, 유연성을 동시에 확보합니다 [5-7].
|
||||
- **단일 책임 원칙(SRP)에 기반한 리소스 관리**: 구조적 안정성을 위해 "리소스를 만든 곳에서 닫는다"는 단일 책임 원칙을 적용했습니다 [8]. 명확한 클린업(Cleanup) 책임을 SDK 인터페이스 구조에 녹여냄으로써 이벤트나 리스너가 누수되는 것을 원천적으로 방지하고 효율적인 리소스 관리를 유도합니다 [7, 8].
|
||||
## 핵심 요약 (specialization aspects)
|
||||
- Plugin ecosystem 측면: 외부 연동사 onboarding 매 facade SDK 기반.
|
||||
- Versioning · adapter contract · sandboxing 매 추가 고려.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
## 🔗 Graph
|
||||
- 부모: [[토스(Toss) Front SDK 퍼사드 패턴 적용]] (canonical)
|
||||
- Adjacent: [[서드파티 라이브러리 및 API 연동]] · [[외부 라이브러리 API 설계]]
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** Toss Front SDK, Facade 패턴, Single Responsibility Principle (SRP), [[Escape Hatch (탈출구)]]
|
||||
- **Projects/Contexts:** 토스플레이스 결제 단말기 생태계 확장
|
||||
- **Contradictions/Notes:** 소스 내에 관련된 모순점이나 반대 의견은 존재하지 않습니다. 소스는 Toss Front SDK의 개발자 경험(DX)을 개선하고, 안정성을 확보하며, 휴먼 에러를 구조적으로 방지하기 위해 퍼사드 패턴과 책임 분리를 적용해야 한다는 일관된 주장을 펼치고 있습니다 [1, 3, 8].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -2,93 +2,31 @@
|
||||
id: wiki-2026-0508-turborepo-기반-모노레포-워크플로우
|
||||
title: Turborepo 기반 모노레포 워크플로우
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-5397E2]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: turborepo
|
||||
duplicate_of: "[[Turborepo]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - [[Turborepo]] 기반 모노레포 워크플로우"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, monorepo, turborepo, workflow]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[Turborepo 기반 모노레포 워크플로우]]
|
||||
# Turborepo 기반 모노레포 워크플로우
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Turborepo 기반 모노레포 워크플로우는 여러 패키지와 애플리케이션을 단일 저장소에서 효율적으로 관리하기 위해 린팅([[ESLint]]) 및 포매팅([[Prettier]]) 설정의 중복을 줄이고 실행 속도를 최적화하는 개발 프로세스입니다 [1], [2], [3]. 중앙 집중식 설정 패키지와 루트 오케스트레이션(Root Orchestration) 구성을 활용해 각 패키지의 자율성을 보장하면서도 변경된 파일에 대한 부분 검사와 Turborepo의 캐싱 이점을 극대화합니다 [4], [5], [6].
|
||||
> **이 문서는 [[Turborepo]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **기존 모노레포 환경의 한계:** 여러 [[Next.js]] 애플리케이션과 공유 라이브러리를 포함하는 대규모 모노레포에서는 패키지마다 `.eslintrc.json` 및 관련 설정 파일이 중복되는 유지보수 문제가 발생합니다 [7]. 특히 모노레포 루트(Root) 레벨에서 `[[lint-staged]]`를 실행할 때, 각 패키지에 맞는 린팅 규칙을 개별적으로 존중하도록 구성하는 것이 매우 까다롭습니다 [7].
|
||||
- **중앙 집중식 설정 패키지 도입:** 문제를 해결하기 위해 `@repo/eslint-config`와 같은 공통 내부 패키지를 생성하여 기본(Base), Next.js, 비-React 라이브러리용 프리셋(Preset) 구성을 만듭니다 [8]. 각 패키지는 이 프리셋을 임포트하여 단일 진실 공급원([[Single Source of Truth]])을 따르는 동시에, 필요시 패키지별 자율적인 오버라이드(override)를 적용할 수 있습니다 [4].
|
||||
- **루트 오케스트레이션 설정 (Root Orchestration Config):** 모노레포 루트에 위치한 `eslint.config.mjs` 파일에서 글로브(glob) 파일 패턴을 바탕으로 적절한 패키지 규칙에 매핑합니다 [5]. 이를 통해 전역 규칙을 적용하면서도 비-React 패키지와 Next.js 패키지의 경계를 명확하게 존중할 수 있습니다 [5].
|
||||
- **[[Husky]]와 Lint-staged의 효율적 연동:** 루트 오케스트레이션 구성이 마련되면 Husky의 pre-commit 훅을 통해 루트의 `lint-staged`가 실행됩니다 [6]. 이 과정에서 오직 변경된 파일만 식별되며, 루트 설정의 매핑에 따라 개별 패키지 룰에 맞게 빠르고 정확하게 린팅됩니다 [6], [9].
|
||||
- **Turborepo 캐싱 통합:** 공통 ESLint 설정 패키지를 `turbo.json`의 전역 의존성(global dependency)으로 추가함으로써 설정이 변경될 때 모든 패키지의 캐시가 적절히 무효화(invalidate) 되도록 구성합니다 [6]. 이는 결과적으로 린트 결과를 효과적으로 캐싱하여 작업 속도를 비약적으로 향상시킵니다 [6], [9].
|
||||
## 핵심 요약
|
||||
- workflow 측면 (dev/build/test pipeline + filter + cache)은 [[Turborepo]] 의 task graph section 참조.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
## 🔗 Graph
|
||||
- 부모: [[Turborepo]] (canonical)
|
||||
- Adjacent: [[Monorepo]] · [[CI CD Pipeline]]
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[ESLint]], [[Prettier]], [[Husky]], [[Lint-staged]]
|
||||
- **Projects/Contexts:** Next.js 애플리케이션, 공유 라이브러리(Library) 환경
|
||||
- **Contradictions/Notes:** 소스에 상충하는 내용이나 관련 정보가 부족합니다. 다만 기존의 중복되고 분산된 설정 방식과, 중앙 집중화 및 루트 오케스트레이션을 도입한 현대적 방식 간의 개발자 경험(DX) 차이가 극적으로 향상됨을 강조합니다 [1], [9].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -2,93 +2,31 @@
|
||||
id: wiki-2026-0508-turborepo-환경-구성
|
||||
title: Turborepo 환경 구성
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-C5884C]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: turborepo
|
||||
duplicate_of: "[[Turborepo]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - [[Turborepo]] 환경 구성"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, turborepo, monorepo]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[Turborepo 환경 구성]]
|
||||
# Turborepo 환경 구성
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Turborepo 모노레포 환경에서 [[ESLint]], [[Prettier]], [[lint-staged]]를 효율적으로 관리하기 위한 구성 방법입니다 [1]. 여러 패키지에 분산된 중복 설정과 규칙의 불일치 문제를 해결하기 위해 고안되었습니다 [1, 2]. 중앙 집중식 설정 패키지와 루트 오케스트레이션(Root Orchestration)을 결합하여, 각 패키지의 규칙을 존중하면서도 빠르고 확장 가능한 린팅 환경을 제공합니다 [3, 4].
|
||||
> **이 문서는 [[Turborepo]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **중앙 집중식 구성 패키지 구축:** 모노레포 내에 별도의 설정 패키지(예: `@repo/eslint-config`)를 생성하여 Base, [[Next.js]], Library용으로 조합 가능한 프리셋(preset) 설정을 제공합니다 [5, 6]. 이 패키지는 ESLint 9의 평면 구성(flat config) 형식을 사용하며, 전체 모노레포의 린팅 규칙을 제어하는 단일 진실 공급원([[Single Source of Truth]]) 역할을 합니다 [5, 7].
|
||||
- **패키지별 자율성 보장:** 개별 패키지에는 최소한의 `eslint.config.mjs` 파일만 남겨두고 중앙 패키지의 프리셋을 임포트하여 사용합니다 [7]. 이를 통해 전체 코어 규칙을 일관되게 관리하면서도, 필요한 경우 특정 패키지에서 개별적인 규칙 오버라이드(override)를 수행할 수 있는 자율성을 얻을 수 있습니다 [7, 8].
|
||||
- **루트 오케스트레이션 (Root Orchestration):** 모노레포 루트에 위치한 `eslint.config.mjs`에서 파일 패턴(glob 패턴)을 활용해 각 패키지를 적절한 설정에 매핑합니다 [9]. 이는 `lint-staged`와 [[Husky]] 같은 도구가 모노레포 루트에서 실행될 때 각 패키지의 경계와 고유 린팅 규칙을 정확하게 준수하도록 보장하는 핵심 설정입니다 [4, 9].
|
||||
- **Husky 및 lint-staged 통합:** 루트 `package.json` 파일과 Husky의 `pre-commit` 훅을 연동하여, 코드가 커밋될 때 루트 설정에 따라 변경된 파일만 효율적으로 린팅하도록 구성합니다 [10].
|
||||
- **Turborepo 캐시 무효화 적용:** `turbo.json` 설정 내 전역 의존성(`globalDependencies`)에 ESLint 설정 패키지를 등록합니다 [10]. 이를 통해 중앙의 린팅 설정이 변경될 때마다 Turborepo가 모든 관련 패키지의 캐시를 정확히 무효화(invalidate)하도록 처리합니다 [10].
|
||||
## 핵심 요약 (specialization aspects)
|
||||
- 매 setup 측면 — `turbo.json` pipeline 정의, `packages/*` workspace 구조, remote cache 활성화.
|
||||
- 매 install: `pnpm add -D turbo` + `npx create-turbo@latest`.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
## 🔗 Graph
|
||||
- 부모: [[Turborepo]] (canonical)
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[ESLint]], [[Prettier]], [[lint-staged]], [[Husky]], [[Monorepo]]
|
||||
- **Projects/Contexts:** Turborepo 기반 다중 패키지 프로젝트의 린팅 및 코드 포매팅 자동화 파이프라인 구축
|
||||
- **Contradictions/Notes:** 소스는 ESLint 9의 평면 구성 형식을 기준으로 최적의 환경 구성법을 제안하고 있습니다. 만약 ESLint 8 환경을 이용할 경우에는 `eslint.config.mjs` 대신 `.eslintrc.js`를 사용하고 ES 모듈 대신 CommonJS를 사용해야 하는 등 이전 형식에 맞춘 구조적 조정이 별도로 필요합니다 [11].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -2,99 +2,31 @@
|
||||
id: wiki-2026-0508-turborepo를-활용한-다중-애플리케이션-및-라이브러리
|
||||
title: Turborepo를 활용한 다중 애플리케이션 및 라이브러리 통합 관리
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-F2D6B7]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: turborepo
|
||||
duplicate_of: "[[Turborepo]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - [[Turborepo]]를 활용한 다중 애플리케이션 및 라이브러리 통합 관리"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, turborepo, monorepo]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[Turborepo를 활용한 다중 애플리케이션 및 라이브러리 통합 관리]]
|
||||
# Turborepo를 활용한 다중 애플리케이션 및 라이브러리 통합 관리
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Turborepo를 활용한 모노레포([[Monorepo]]) 환경에서 다중 애플리케이션([[Next.js]] 등) 및 공유 라이브러리의 린팅([[ESLint]])과 포매팅([[Prettier]])을 효율적으로 통합 관리하는 아키텍처에 대한 내용입니다. 중앙 집중식 설정 패키지와 루트 오케스트레이션(Root Orchestration) 기법을 도입함으로써, 패키지별 설정 중복을 방지하고 각 프로젝트의 자율성을 보장하면서도 일관되고 빠른 코드 품질 관리를 달성할 수 있습니다.
|
||||
> **이 문서는 [[Turborepo]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **기존 모노레포 관리의 문제점**
|
||||
여러 애플리케이션(Next.js 등)과 공유 라이브러리를 포함하는 대규모 모노레포 구조에서는 `.eslintrc.json` 및 `.eslintignore`와 같은 설정 파일이 각 패키지마다 중복 생성되는 문제가 흔히 발생합니다 [1, 2]. 이로 인해 구성의 일관성이 무너지고 전역적으로 규칙을 업데이트하기가 어려워지며, 특히 모노레포 루트(Root)에서 `[[lint-staged]]`를 실행할 때 각 패키지에 맞는 린팅 규칙을 선별적으로 적용하는 것에 한계가 생깁니다 [2, 3].
|
||||
## 핵심 요약 (specialization aspects)
|
||||
- 매 multi-app + shared lib 측면 — `apps/web`, `apps/admin`, `packages/ui`, `packages/config` 의 통합 관리.
|
||||
- 매 task graph: `dependsOn: ["^build"]` 의 topological order 보장.
|
||||
|
||||
* **중앙 집중식 구성과 루트 오케스트레이션 적용**
|
||||
이러한 문제를 해결하기 위해 3단계로 이루어진 구성 아키텍처를 도입할 수 있습니다.
|
||||
1. **중앙 집중식 ESLint 구성 패키지 생성**: 모노레포 내부에 공통으로 사용할 설정 패키지(예: `@repo/eslint-config`)를 만듭니다. 이 패키지는 Base, Next.js, 외부 라이브러리 전용 등 목적에 맞게 결합 가능한 프리셋(Preset)을 내보냅니다 [4, 5]. 이 공통 패키지에서 Prettier 통합 및 Turborepo 특화 규칙 등을 단일 진실 공급원([[Single Source of Truth]])으로 선언합니다 [3, 5, 6].
|
||||
2. **패키지 레벨 설정의 최소화**: 각 애플리케이션 및 라이브러리 패키지에는 최소한의 `eslint.config.mjs` 파일만 위치시킵니다. 이 파일은 중앙 구성 패키지의 프리셋을 가져와 적용하며, 필요한 경우 특정 패키지만의 예외 규칙을 오버라이드할 수 있어 자율성을 유지합니다 [6].
|
||||
3. **루트 오케스트레이션(Root Orchestration)**: 모노레포 최상위 디렉토리에 파일 패턴을 기반으로 각 패키지에 맞는 구성을 매핑하는 오케스트레이션 파일을 생성합니다. 이를 통해 루트에서 린트를 실행하더라도 파일 경로를 인식하여 올바른 패키지 규칙이 적용됩니다 [7, 8].
|
||||
## 🔗 Graph
|
||||
- 부모: [[Turborepo]] (canonical)
|
||||
|
||||
* **Turborepo 캐싱과 [[Husky]], lint-staged 통합 최적화**
|
||||
루트 오케스트레이션이 완성되면, `Husky`의 pre-commit 훅을 통해 `lint-staged`를 실행할 때 변경된 파일에 대해서만 빠르고 정확한 린팅을 수행할 수 있습니다 [8]. 추가적으로, `turbo.json` 설정 파일에 ESLint 구성 패키지를 글로벌 의존성(global dependency)으로 명시하면, 공통 설정이 변경될 때마다 Turborepo가 모든 패키지의 린트 캐시를 지능적으로 무효화합니다 [8]. 이를 통해 불필요한 중복 검사를 줄이고 린트 캐싱 성능을 극대화하여 전체적인 개발과 커밋 속도를 크게 단축할 수 있습니다 [9-11].
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** 모노레포(Monorepo), ESLint 및 Prettier 통합, lint-staged와 Husky
|
||||
- **Projects/Contexts:** Turborepo 기반의 확장 가능한 프론트엔드 환경 구축 및 중앙 집중형 코드 거버넌스
|
||||
- **Contradictions/Notes:** 모노레포 내 각 패키지마다 독립된 설정과 의존성을 중복해서 유지하는 전통적인 방식에 반대하며, 단일 진실 공급원(Single source of truth) 역할을 하는 전용 설정 패키지를 구축하여 루트에서 일괄 오케스트레이션하는 현대적이고 통합적인 관리 체계를 지향합니다 [2, 6, 10].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -1,25 +1,155 @@
|
||||
---
|
||||
id: wiki-20260508-type-casting-redir
|
||||
title: Type Casting
|
||||
category: Programming & Language
|
||||
status: merged
|
||||
redirect_to: Type_Casting
|
||||
canonical_id: Type_Casting
|
||||
aliases: []
|
||||
category: 10_Wiki/Topics
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [type assertion, type coercion, as cast]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [redirect]
|
||||
verification_status: applied
|
||||
tags: [typescript, type-system, fundamentals]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-merge 2026-05-08)
|
||||
tech_stack:
|
||||
language: TypeScript
|
||||
framework: tsc
|
||||
---
|
||||
|
||||
# Type Casting
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 이 문서는 P-Reinforce Phase 2 자동 MERGE에 의해 **[[Type_Casting]]**로 통합되었습니다.
|
||||
## 매 한 줄
|
||||
> **"매 compiler 에 'trust me' 의 signal — runtime 의 영향 X 의 compile-time 만 의 type 변경"**. TS 의 `as` operator / angle-bracket — 매 runtime conversion 의 X (cf. JS coercion). 매 2026 의 best practice 의 minimize + zod / type guard 의 prefer.
|
||||
|
||||
---
|
||||
*Redirected to: [[Type_Casting]]*
|
||||
## 매 핵심
|
||||
|
||||
### 매 종류
|
||||
- **Type assertion** (TS): `value as Type` — 매 compile-time only.
|
||||
- **Type coercion** (JS): `Number(x)`, `+x`, `String(x)` — 매 runtime 변환.
|
||||
- **Type guard**: `typeof / instanceof / in / custom predicate` — 매 narrowing.
|
||||
- **Type predicate**: `function isFoo(x): x is Foo` — 매 user-defined narrowing.
|
||||
|
||||
### 매 동작 원리
|
||||
- `as` 의 compile time 만 의 type swap — 매 generated JS 의 동일.
|
||||
- 매 unsafe — 매 actual shape 의 mismatch 시 runtime error 의 latent.
|
||||
- 매 double assertion `as unknown as T` — 매 incompatible type 의 강제.
|
||||
- 매 runtime validation (zod / valibot) 의 결합 의 권장.
|
||||
|
||||
### 매 응용
|
||||
1. External API response 의 typing — 매 zod 의 parse 후 타입 의 narrow.
|
||||
2. JSON.parse 의 unknown 의 narrowing.
|
||||
3. DOM query 의 Element → HTMLInputElement.
|
||||
|
||||
## 💻 패턴
|
||||
|
||||
### 매 Type assertion (basic)
|
||||
```typescript
|
||||
const el = document.querySelector('input') as HTMLInputElement;
|
||||
el.value = 'hello'; // 매 HTMLElement 가 아닌 HTMLInputElement 의 value 접근
|
||||
```
|
||||
|
||||
### 매 Double assertion (last resort)
|
||||
```typescript
|
||||
const raw = JSON.parse(text); // 매 any
|
||||
const data = raw as unknown as MyType; // 매 강제 cast
|
||||
// 매 BAD — 매 zod 의 prefer
|
||||
```
|
||||
|
||||
### 매 Type guard (preferred)
|
||||
```typescript
|
||||
function isUser(x: unknown): x is User {
|
||||
return typeof x === 'object' && x !== null
|
||||
&& 'id' in x && typeof (x as any).id === 'string';
|
||||
}
|
||||
|
||||
const data: unknown = JSON.parse(text);
|
||||
if (isUser(data)) {
|
||||
data.id; // 매 narrowed
|
||||
}
|
||||
```
|
||||
|
||||
### 매 Zod 의 runtime validation 의 결합
|
||||
```typescript
|
||||
import { z } from 'zod';
|
||||
|
||||
const UserSchema = z.object({
|
||||
id: z.string(),
|
||||
email: z.string().email(),
|
||||
});
|
||||
type User = z.infer<typeof UserSchema>;
|
||||
|
||||
const parsed = UserSchema.parse(JSON.parse(text));
|
||||
// 매 parsed 의 User type — 매 cast X, 매 actual validation
|
||||
```
|
||||
|
||||
### 매 const assertion
|
||||
```typescript
|
||||
const config = { url: '/api', method: 'GET' } as const;
|
||||
// 매 type: { readonly url: '/api'; readonly method: 'GET' }
|
||||
// 매 literal type 의 보존
|
||||
```
|
||||
|
||||
### 매 Non-null assertion
|
||||
```typescript
|
||||
const input = document.getElementById('email')!; // 매 null 의 부정
|
||||
// 매 dangerous — 매 optional chaining + guard 의 prefer
|
||||
const safe = document.getElementById('email');
|
||||
if (!safe) throw new Error('missing');
|
||||
```
|
||||
|
||||
### 매 Satisfies operator (TS 4.9+)
|
||||
```typescript
|
||||
type Color = 'red' | 'green' | 'blue';
|
||||
const palette = {
|
||||
primary: 'red',
|
||||
secondary: 'green',
|
||||
} satisfies Record<string, Color>;
|
||||
// 매 cast 와 달리 actual literal type 의 보존 + check 의 둘 다
|
||||
palette.primary; // type: 'red' (not Color)
|
||||
```
|
||||
|
||||
### 매 JS coercion (different topic)
|
||||
```javascript
|
||||
const n = Number('42'); // 매 string → number 의 runtime 변환
|
||||
const s = String(123); // 매 number → string
|
||||
const b = Boolean(0); // 매 falsy → false
|
||||
// 매 TS 의 cast 와 무관 — 매 actual conversion
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| External JSON | zod / valibot parse |
|
||||
| DOM query | type assertion `as HTMLInputElement` |
|
||||
| Custom narrowing | type predicate `x is T` |
|
||||
| Literal preserve | satisfies / as const |
|
||||
| any → known | type guard 의 prefer over cast |
|
||||
|
||||
**기본값**: 매 cast 의 minimize. 매 type guard / runtime validation 의 default.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[TypeScript]] · [[Type System]]
|
||||
- 변형: [[Type Guard]] · [[Type Predicate]]
|
||||
- 응용: [[Zod 파싱과 브랜디드 타입을 결합한 런타임 데이터 검증]] · [[DOM 요소 조작 및 타입 좁히기]]
|
||||
- Adjacent: [[Discriminated Unions]] · [[Structural Typing]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: TS unsafe cast 의 detect, zod migration 의 권장, satisfies 의 도입.
|
||||
**언제 X**: 매 cast 의 단순 추가 의 답변 — 매 root cause (validation 부재) 의 fix.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **`as any`**: 매 type system 의 escape — 매 unknown + guard 의 사용.
|
||||
- **Double cast**: `as unknown as T` 의 frequent 사용 — 매 design smell.
|
||||
- **Non-null `!`의 남용**: 매 actual null 시 silent crash.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (TypeScript Handbook "Type Assertions").
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — Type casting FULL 작성 |
|
||||
|
||||
@@ -2,89 +2,162 @@
|
||||
id: wiki-2026-0508-type-theory
|
||||
title: Type Theory
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AI-054]
|
||||
aliases: [Type System Theory, Lambda Calculus Types, Curry-Howard]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.96
|
||||
tags: [type theory, formal verification, type system, compiler]
|
||||
confidence_score: 0.9
|
||||
verification_status: applied
|
||||
tags: [type-theory, lambda-calculus, formal-methods, curry-howard, dependent-types]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-06-XX
|
||||
github_commit: "[P-Reinforce] Processed Type Theory."
|
||||
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: Haskell / Idris / Lean / Coq
|
||||
framework: theoretical
|
||||
---
|
||||
|
||||
# [[Type Theory]] (타입 이론)
|
||||
# Type Theory
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> 프로그래밍 언어의 타입 시스템을 수학적 공리(Axiom)와 논리학에 기반하여 분석하고, 프로그램의 안전성과 정확성을 컴파일 타임에 증명하는 학문이다.
|
||||
## 매 한 줄
|
||||
> **"매 타입은 명제, 매 프로그램은 증명 — Curry-Howard correspondence"**. Type theory 는 1902 Russell paradox 회피용 simple type theory 부터, 1934 Church 의 simply typed lambda calculus, 1972 Martin-Löf dependent type theory, 2026 Lean 4 / Idris 2 / Rocq (formerly Coq) 의 매 mathematical proof + program verification 의 통일 framework. 매 modern type system (Haskell, Rust, TypeScript) 의 매 핵심 개념 (parametric polymorphism, GADTs, refinement types) 의 출처.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **정의:** 타입을 단순히 데이터의 분류를 넘어, 시스템이 가질 수 있는 '속성'과 '규칙'으로 바라보는 접근법이다. 프로그램의 정적 분석을 수학적 증명 과정으로 확장한다.
|
||||
- **주요 개념:**
|
||||
1. **타입 추론 (Type Inference):** 코드를 작성할 때 타입을 명시하지 않아도 컴파일러가 타입 규칙에 따라 자동으로 타입을 유추하는 능력.
|
||||
2. **계산 가능성(Computability) 및 안전성:** 타입 이론의 궁극적 목표는 프로그램이 어떤 조건에서도 예측 불가능한 오류 없이 동작함을 수학적으로 증명하는 것이다 (Formal Verification).
|
||||
3. **Advanced Features:** 고급 언어 기능인 추상 데이터 타입, 범주론적 접근 등은 컴파일러 설계 자체를 학문적으로 다룬다.
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 완벽한 타입 안전성(Type Safety)을 달성하는 것은 매우 어려우며, 실제 개발에서는 '실용적인 타협점' (예: Runtime Validation, Zod 사용)이 필요하다.
|
||||
- **정책 변화:** 타입 시스템은 언어 차원의 기능뿐만 아니라, 도메인 모델링(DDD)의 규칙을 코드로 강제하는 도구로 활용되어 그 가치가 극대화되고 있다.
|
||||
### 매 type theory 의 계층
|
||||
- **Simply Typed Lambda Calculus (STLC)**: `τ ::= ι | τ → τ` — function types only.
|
||||
- **System F (parametric polymorphism)**: `∀α. τ` — generics 의 이론적 기반.
|
||||
- **System Fω (type operators)**: `* → *` kinds — Haskell 의 type-level computation.
|
||||
- **Calculus of Constructions (CoC)**: dependent types — Coq, Lean.
|
||||
- **Homotopy Type Theory (HoTT)**: types as spaces, equality as paths.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- Parent: Type Safety
|
||||
- Related: Formal Methods in Software Engineering , Algebraic-Data-Types , TypeScript Type System
|
||||
### 매 Curry-Howard correspondence
|
||||
- 매 propositions ⟺ types.
|
||||
- 매 proofs ⟺ programs.
|
||||
- 매 implication `A → B` ⟺ function `A → B`.
|
||||
- 매 conjunction `A ∧ B` ⟺ pair `(A, B)`.
|
||||
- 매 disjunction `A ∨ B` ⟺ sum `Either A B`.
|
||||
- 매 universal `∀x. P(x)` ⟺ dependent function `(x: A) → P(x)`.
|
||||
|
||||
---
|
||||
### 매 응용
|
||||
1. Theorem proving — Lean 4 (mathlib), Coq/Rocq (CompCert verified C compiler).
|
||||
2. Verified software — seL4 microkernel (Isabelle/HOL).
|
||||
3. Practical type systems — Haskell GADT, Rust lifetime, TypeScript conditional types.
|
||||
|
||||
## 🤖 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
|
||||
### Haskell: parametric polymorphism (System F)
|
||||
```haskell
|
||||
-- 매 ∀α. [α] → Int
|
||||
length :: forall a. [a] -> Int
|
||||
length [] = 0
|
||||
length (_:xs) = 1 + length xs
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### Haskell: GADT (refined return types)
|
||||
```haskell
|
||||
{-# LANGUAGE GADTs #-}
|
||||
data Expr a where
|
||||
IntLit :: Int -> Expr Int
|
||||
BoolLit :: Bool -> Expr Bool
|
||||
If :: Expr Bool -> Expr a -> Expr a -> Expr a
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
eval :: Expr a -> a
|
||||
eval (IntLit n) = n
|
||||
eval (BoolLit b) = b
|
||||
eval (If c t e) = if eval c then eval t else eval e
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Idris: dependent type (vector with length)
|
||||
```idris
|
||||
data Vect : Nat -> Type -> Type where
|
||||
Nil : Vect Z a
|
||||
(::) : a -> Vect n a -> Vect (S n) a
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
-- 매 length encoded in type — no runtime check needed
|
||||
append : Vect n a -> Vect m a -> Vect (n + m) a
|
||||
append Nil ys = ys
|
||||
append (x :: xs) ys = x :: append xs ys
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
### Lean 4: theorem as type
|
||||
```lean
|
||||
-- 매 proposition: ∀ n : ℕ, n + 0 = n
|
||||
theorem add_zero (n : Nat) : n + 0 = n := by
|
||||
induction n with
|
||||
| zero => rfl
|
||||
| succ k ih => rw [Nat.succ_add, ih]
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### TypeScript: conditional types (System Fω-ish)
|
||||
```typescript
|
||||
type IsArray<T> = T extends Array<any> ? true : false;
|
||||
type A = IsArray<number[]>; // true
|
||||
type B = IsArray<string>; // false
|
||||
|
||||
// 매 distributive
|
||||
type ToArray<T> = T extends any ? T[] : never;
|
||||
type C = ToArray<string | number>; // string[] | number[]
|
||||
```
|
||||
|
||||
### Rust: phantom type for state encoding
|
||||
```rust
|
||||
use std::marker::PhantomData;
|
||||
struct Connection<State> { _state: PhantomData<State> }
|
||||
struct Open; struct Closed;
|
||||
|
||||
impl Connection<Closed> {
|
||||
fn open(self) -> Connection<Open> { Connection { _state: PhantomData } }
|
||||
}
|
||||
impl Connection<Open> {
|
||||
fn send(&self, data: &[u8]) {}
|
||||
fn close(self) -> Connection<Closed> { Connection { _state: PhantomData } }
|
||||
}
|
||||
// 매 .send() on Closed 는 compile error
|
||||
```
|
||||
|
||||
### Haskell: refinement via Liquid Haskell
|
||||
```haskell
|
||||
{-@ type Pos = {v:Int | v > 0} @-}
|
||||
{-@ divPos :: Int -> Pos -> Int @-}
|
||||
divPos x y = x `div` y -- 매 SMT solver 가 y > 0 검증
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| Mathematical proof | Lean 4 / Rocq (Coq) |
|
||||
| Verified compiler / OS | Coq (CompCert) / Isabelle (seL4) |
|
||||
| Industrial typed FP | Haskell + GADT + TypeFamilies |
|
||||
| Practical dependent types | Idris 2 |
|
||||
| TypeScript-level type-level | conditional + mapped + template literal |
|
||||
| Compile-time state machine | Rust phantom types / typestate |
|
||||
|
||||
**기본값**: 매 application 은 Haskell/Rust/TS 의 expressive type system; 매 critical proof 는 Lean 4.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Type System]] · [[Lambda Calculus]] · [[Formal Methods]]
|
||||
- 변형: [[Dependent Types]] · [[Refinement Types]] · [[Linear Types]] · [[HoTT]]
|
||||
- 응용: [[Lean 4]] · [[Coq]] · [[Idris]] · [[Haskell GADT]]
|
||||
- Adjacent: [[Curry-Howard]] · [[System F]] · [[Calculus of Constructions]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 type system design 이해, advanced FP, formal verification, TS type-level wizardry.
|
||||
**언제 X**: 매 일반 application 작성 — overkill.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Type-level "abuse" in TS**: 매 IDE 가 5분 freeze — 단순 runtime check 가 나음.
|
||||
- **Dependent type 없는 곳 흉내**: 매 Haskell phantom type 으로 vector length 흉내 — 진짜 검증 안됨, runtime panic 가능.
|
||||
- **Curry-Howard 의 직접 응용 실수**: 매 Hindley-Milner type inference 는 type-level recursion 에 약함 — 매 explicit annotation 필요.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Pierce "Types and Programming Languages", Martin-Löf "Intuitionistic Type Theory", HoTT Book).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — type theory full content (Curry-Howard, GADT, dependent, Lean) |
|
||||
|
||||
@@ -2,102 +2,31 @@
|
||||
id: wiki-2026-0508-typescript-타입-시스템-및-인터페이스-설계
|
||||
title: TypeScript 타입 시스템 및 인터페이스 설계
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-9DE40A]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: typescript-types
|
||||
duplicate_of: "[[TypeScript Type System]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - TypeScript 타입 시스템 및 인터페이스 설계"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, typescript, interface]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[TypeScript 타입 시스템 및 인터페이스 설계]]
|
||||
# TypeScript 타입 시스템 및 인터페이스 설계
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> TypeScript의 타입 시스템은 객체의 실제 형태와 구조를 기준으로 호환성을 판단하는 구조적 타이핑([[Structural Typing]])을 근간으로 합니다 [1, 2]. 개발자는 시스템 설계 시 인터페이스와 타입 별칭을 전략적으로 선택하여 타입의 확장성과 컴파일러 성능을 최적화할 수 있습니다 [3-5]. 또한, 식별 가능한 유니온, 브랜디드 타입(Branded Types), `[[readonly]]` 및 `satisfies` 연산자 등의 고급 기능을 적극적으로 활용하여 런타임 에러를 방지하고 견고한 소프트웨어 아키텍처를 구축할 수 있습니다 [6-10].
|
||||
> **이 문서는 [[TypeScript Type System]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **구조적 타이핑과 집합론적 접근**
|
||||
TypeScript는 Java나 C#과 같은 명목적 타이핑(Nominal Typing)이 아닌, 객체의 구조가 일치하면 동일한 타입으로 간주하는 덕 타이핑(Duck Typing)을 채택하고 있습니다 [1, 11]. 집합론적 관점에서 타입은 '가능한 값들의 집합'으로 정의되며, `never`는 공집합, `unknown`은 모든 JS 값을 포함하는 전체집합으로 이해할 수 있습니다 [12-14]. 이러한 특성을 통해 상속이나 명시적 선언 없이도 타입 간의 호환성이 유연하게 결정됩니다 [2, 15].
|
||||
## 핵심 요약 (specialization aspects)
|
||||
- 매 interface 설계 측면 — `interface` vs `type alias`, declaration merging, `extends` chain.
|
||||
- 매 structural typing 의 핵심: shape match.
|
||||
|
||||
* **인터페이스(Interface)와 타입(Type) 설계 전략**
|
||||
인터페이스는 확장성과 성능 면에서 유리합니다. TypeScript 컴파일러는 인터페이스를 처리할 때 이름을 기준으로 캐싱하므로, 교집합(`&`)을 활용한 타입 별칭보다 `interface extends`를 사용하는 것이 대규모 프로젝트에서 성능 최적화에 도움이 됩니다 [5, 16-18]. 그러나 교집합, 유니온, 매핑된 타입 등 복잡한 타입 구성이 필요할 때는 타입 별칭을 활용해야 하며, 외부 확장 포인트를 제한하기 위해 의도적으로 인터페이스 대신 타입을 사용하는 경우도 존재합니다 [19, 20].
|
||||
## 🔗 Graph
|
||||
- 부모: [[TypeScript Type System]] (canonical)
|
||||
|
||||
* **과잉 속성 체크(EPC)와 `satisfies` 연산자**
|
||||
객체 리터럴이 타입이 지정된 변수에 직접 할당될 때, TypeScript는 초과 속성이 들어오는 것을 방어하기 위해 과잉 속성 체크를 실행합니다 [2, 21-24]. 하지만 간접 할당 과정에서는 이 수비 기제가 작동하지 않을 수 있는데, 이를 극복하기 위해 `satisfies` 연산자를 활용할 수 있습니다 [10, 21, 25]. `satisfies`는 객체가 특정 타입의 형태를 충족하는지 검사하면서도 구체적인 리터럴 타입의 정보를 잃지 않게 하여 타입 안전성을 보장합니다 [10, 26-28].
|
||||
|
||||
* **식별 가능한 유니온([[Discriminated Unions]])과 완전성 검사**
|
||||
복잡한 비즈니스 상태를 설계할 때는 식별 가능한 유니온이 핵심적인 역할을 합니다. 공통된 리터럴 속성(예: `kind`, `type`)을 태그로 사용하여 합집합 내의 타입을 좁혀(Narrowing) 안전하게 다룰 수 있습니다 [6, 29-31]. 특히 `never` 타입을 활용한 완전성 검사(Exhaustiveness Checking)를 구현하면, 처리되지 않은 누락된 상태가 있을 경우 컴파일 에러를 발생시켜 빈틈없는 수비 체계를 갖출 수 있습니다 [31, 32].
|
||||
|
||||
* **불변성과 브랜디드 타입(Branded Types)을 통한 데이터 오염 방지**
|
||||
`readonly` 수식어는 객체나 배열이 런타임 성능 저하 없이 컴파일 시점에 불변성을 유지하도록 보장하여 의도치 않은 상태 변경을 차단합니다 [8, 33-35]. 또한, 구조적 타이핑의 한계인 "기본 타입에의 집착(Primitive Obsession)"을 해결하기 위해 고유한 표식(`__brand`)을 부여하는 브랜디드 타입 기법을 적용할 수 있습니다 [7, 9, 36, 37]. 이는 ID와 일반 문자열이 혼용되는 것을 컴파일러 수준에서 강력히 차단합니다 [9, 37, 38].
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** 구조적 타이핑 (Structural Typing), 식별 가능한 유니온 (Discriminated Unions), Branded Types, [[satisfies 연산자]]
|
||||
- **Projects/Contexts:** [[도메인 기반 설계 (DDD)]], SOLID 원칙 및 인터페이스 분리 원칙 (ISP)
|
||||
- **Contradictions/Notes:** TypeScript 공식 문서와 성능 가이드는 컴파일 최적화를 위해 상속 시 `interface extends`를 권장합니다[16-18]. 하지만 일부 개발 팀들은 인터페이스 선언 병합(Declaration Merging)으로 인한 예기치 않은 부작용을 원천 차단하기 위해 모든 객체 정의에 대해 `Type` 별칭(alias)만 사용하도록 규칙을 강제하기도 합니다[19, 39, 40].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -2,102 +2,32 @@
|
||||
id: wiki-2026-0508-typescript-타입-시스템을-활용한-내부-로직-보호-
|
||||
title: TypeScript 타입 시스템을 활용한 내부 로직 보호 및 데이터 검증
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-2609F8]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: typescript-타입-시스템-및-인터페이스-설계
|
||||
duplicate_of: "[[TypeScript 타입 시스템 및 인터페이스 설계]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - TypeScript 타입 시스템을 활용한 내부 로직 보호 및 데이터 검증"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, typescript, type-safety]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[TypeScript 타입 시스템을 활용한 내부 로직 보호 및 데이터 검증]]
|
||||
# TypeScript 타입 시스템을 활용한 내부 로직 보호 및 데이터 검증
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> TypeScript의 타입 시스템은 컴파일 시점에 내부 로직을 보호하고 데이터 무결성을 검증하는 강력한 수비 기제를 제공합니다. 구조적 타이핑의 유연성에서 오는 한계점을 과잉 속성 체크([[Excess Property Checking]])와 `satisfies` 연산자로 보완하며, 브랜디드 타입(Branded Types)과 식별 가능한 유니온([[Discriminated Unions]])을 활용하여 잘못된 상태와 데이터 오염을 원천 차단합니다. 또한, 시스템 경계에서 "검증하지 말고 파싱하라(Parse, don't validate)" 원칙을 적용함으로써 런타임 환경에서도 예측 가능하고 견고한 애플리케이션 구조를 확립할 수 있습니다.
|
||||
> **이 문서는 [[TypeScript 타입 시스템 및 인터페이스 설계]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **구조적 타이핑과 `satisfies` 연산자를 활용한 경계 방어**
|
||||
TypeScript는 객체의 구조가 일치하면 동일한 타입으로 취급하는 구조적 타이핑([[Structural Typing]])을 사용합니다 [1, 2]. 이 특성은 유연하지만 의도치 않은 잉여 속성이 포함될 수 있는 약점이 있습니다 [3-5]. 객체 리터럴 직접 할당 시에는 과잉 속성 체크(EPC)가 작동하지만 변수를 거칠 경우 이를 우회할 수 있습니다 [5-7]. 이를 막기 위해 `satisfies` 연산자를 사용하면, 객체의 리터럴 형태나 추가적인 메타데이터 구조를 잃지 않으면서도 타입 요구사항을 엄격히 검증하여 안전성을 보장합니다 [5, 8-10].
|
||||
## 핵심 요약 (specialization aspects)
|
||||
- 내부 로직 보호: branded types · readonly · private 도메인 invariant.
|
||||
- 데이터 검증: compile-time (structural) + runtime (Zod / Effect Schema) 매 결합.
|
||||
|
||||
* **식별 가능한 유니온(Discriminated Unions)과 불가능한 상태의 차단**
|
||||
식별 가능한 유니온은 공통된 리터럴 속성(예: `kind`, `type`)을 태그로 사용하여 여러 객체 타입을 구별하는 패턴입니다 [11-13]. 이 기법은 TypeScript가 타입을 안전하게 좁히도록(Narrowing) 유도하여 유효하지 않은 상태의 표현을 코드로 불가능하게 만듭니다 [13-15]. 또한, `never` 타입을 반환하는 완전성 검사(Exhaustiveness Checking) 함수를 스위치(switch) 문 등에 결합하면, 추후 새로운 상태가 추가되었을 때 누락된 분기 처리를 컴파일 에러로 포착해 로직의 빈틈을 막아줍니다 [13, 15-17].
|
||||
## 🔗 Graph
|
||||
- 부모: [[TypeScript 타입 시스템 및 인터페이스 설계]] (canonical)
|
||||
- Adjacent: [[Zod 파싱과 브랜디드 타입을 결합한 런타임 데이터 검증]] · [[브랜디드 타입 (Branded Types)]]
|
||||
|
||||
* **브랜디드 타입(Branded Types)을 통한 명목적 타이핑 구현 및 데이터 오염 방지**
|
||||
사용자의 식별자(ID)와 일반 문자열은 모두 `string` 타입이지만 도메인 의미는 다릅니다. 이들을 혼용하는 실수(원시 타입 집착)를 막기 위해, 컴파일 타임에만 존재하는 고유한 가상의 속성(브랜드)을 교집합(`&`)으로 결합하는 브랜디드 타입이 사용됩니다 [18-21]. 이는 고유한 신분증을 부여하는 것과 같아서, `UserId`가 필요한 곳에 `OrderId`나 일반 문자열이 유입되는 것을 컴파일러 수준에서 철저히 차단합니다 [5, 22, 23].
|
||||
|
||||
* **"검증하지 말고 파싱하라 (Parse, Don't Validate)" 전략**
|
||||
비즈니스 로직 전반에 흩어진 데이터 유효성 검사 코드는 관리를 어렵게 만듭니다. 대신 시스템의 경계(API 통신 등)에서 알 수 없는(`unknown`) 데이터를 안전한 타입의 구조로 한 번에 "파싱"해야 합니다 [24-26]. Zod와 같은 검증 라이브러리와 브랜디드 타입을 함께 결합하면, 경계를 통과한 데이터는 시스템 내부에서 항상 유효하고 안전한 데이터(`SanitizedString` 등)로 취급받을 수 있습니다 [26-28].
|
||||
|
||||
* **`[[readonly]]`를 통한 불변성(Immutability) 확립**
|
||||
데이터 무결성을 보호하기 위해 `readonly` 수식어를 사용하여 컴파일 타임에 속성값의 변경을 원천적으로 막을 수 있습니다 [29-31]. 얕은 수준(Shallow)의 보호를 넘어서기 위해 재귀적 유틸리티 타입인 `[[DeepReadonly]]`를 적용하면, 복잡하게 중첩된 객체 트리 구조 내부의 모든 상태가 예기치 않게 오염되는 것을 완벽히 차단할 수 있습니다 [31-33].
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** 구조적 타이핑 (Structural Typing), 식별 가능한 유니온 (Discriminated Unions), [[브랜디드 타입 (Branded Types)]], [[satisfies 연산자]], Parse, Don't Validate
|
||||
- **Projects/Contexts:** Zod를 활용한 런타임 데이터 파싱 및 검증, Toss Front SDK의 Facade 패턴 설계 및 안전성 확보
|
||||
- **Contradictions/Notes:** TypeScript의 구조적 타이핑은 매우 유연하여 덕 타이핑의 이점을 제공하지만, "의도하지 않은 초과 데이터의 유입"이라는 치명적인 보안적 허점을 만듭니다 [4, 21]. 이를 방어하기 위해 개발자들은 오히려 구조적 타이핑의 반대 개념인 명목적 타이핑(Nominal Typing) 특성을 강제로 모방한 브랜디드 타입을 사용하여 데이터를 격리해야 하는 역설적이지만 필수적인 설계 패턴을 따르게 됩니다 [21, 34, 35]. 또한, `any` 타입의 사용은 이러한 모든 타입 시스템의 보호막을 무력화시키므로 지양해야 하며, 출처를 알 수 없는 외부 데이터는 반드시 `unknown` 타입으로 선언 후 타입 가드를 거치도록 강제해야 합니다 [36-38].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -2,102 +2,32 @@
|
||||
id: wiki-2026-0508-typescript의-제어-흐름-분석-및-상태-관리-패턴
|
||||
title: TypeScript의 제어 흐름 분석 및 상태 관리 패턴
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-348B57]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: typescript-types
|
||||
duplicate_of: "[[TypeScript Type System]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - TypeScript의 제어 흐름 분석 및 상태 관리 패턴"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, typescript, narrowing, discriminated-union]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[TypeScript의 제어 흐름 분석 및 상태 관리 패턴]]
|
||||
# TypeScript의 제어 흐름 분석 및 상태 관리 패턴
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> TypeScript의 제어 흐름 분석과 상태 관리 패턴은 컴파일러가 런타임의 코드 흐름을 추론하여 타입을 안전하고 구체적으로 좁혀나가는(Narrowing) 메커니즘을 핵심으로 합니다 [1, 2]. 특히 '식별 가능한 유니온([[Discriminated Unions]])' 패턴을 활용하면 복잡한 조건부 분기를 간결하게 처리하고, 유효하지 않은 상태(Invalid [[State]])가 발생하는 것을 원천적으로 방지할 수 있습니다 [3-5]. 이 패턴은 완전성 검사(Exhaustiveness Checking)와 결합되어 복잡한 상태 머신 모델링이나 React 애플리케이션 등에서 시스템의 아키텍처적 안정성을 크게 높이는 데 기여합니다 [4, 6, 7].
|
||||
> **이 문서는 [[TypeScript Type System]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **제어 흐름 분석과 타입 좁히기 (Type Narrowing)**
|
||||
TypeScript는 런타임의 코드 흐름과 조건문을 분석하여 변수의 타입을 보다 구체적으로 추론합니다 [8]. `typeof`, `instanceof`, `in` 연산자 및 커스텀 타입 가드(Type Predicates)와 같은 기법을 통해 유니온 타입의 값을 안전하게 특정 타입으로 좁힐 수 있습니다 [1, 9]. TypeScript의 제어 흐름 분석은 조건문 블록 내부에서 이렇게 좁혀진 타입을 자동으로 인식하여 타입 안전성을 보장합니다 [1, 2].
|
||||
## 핵심 요약 (specialization aspects)
|
||||
- 매 control flow analysis 측면 — type narrowing (`typeof`, `instanceof`, `in`, custom type guards).
|
||||
- 매 discriminated union 의 state machine pattern: `type State = { kind: 'idle' } | { kind: 'loading' } | { kind: 'error', err: Error }`.
|
||||
|
||||
* **식별 가능한 유니온 (Discriminated Unions/Tagged Unions)**
|
||||
상태 관리에서 가장 강력한 무기 중 하나로, 유니온 타입의 각 멤버에 공통된 리터럴 속성(예: `kind`, `type`, `status`)을 식별자(Discriminant)로 두어 타입을 구별하는 패턴입니다 [2, 10-12]. TypeScript는 `switch`나 `if` 제어문에서 이 식별자의 값을 확인하여, 개발자가 다루고 있는 현재 분기의 타입을 자동으로 좁혀줍니다 [2, 10].
|
||||
## 🔗 Graph
|
||||
- 부모: [[TypeScript Type System]] (canonical)
|
||||
- 변형: [[Discriminated Union]] · [[Type Guard]]
|
||||
|
||||
* **유효하지 않은 상태 방지 및 상태 머신 모델링**
|
||||
이 패턴의 가장 큰 장점은 개발자가 잘못된 조합의 상태를 표현하는 것을 타입 시스템 차원에서 불가능하게 만든다는 것입니다 [3-5]. 이는 명확한 상태 전이가 필요한 '상태 머신(State Machine)'을 모델링할 때 매우 효과적이며, 비동기 데이터 로딩(`FETCH_START`, `FETCH_SUCCESS`, `FETCH_FAILURE` 등)이나 여러 단계로 이루어진 폼(Wizard/Multi-Step Forms)의 상태 등을 관리할 때 필수적입니다 [4, 7, 13].
|
||||
|
||||
* **완전성 검사 (Exhaustiveness Checking)**
|
||||
개발자가 유니온 타입의 모든 가능한 상태를 분기문에서 처리했는지 컴파일 타임에 검증하는 기법입니다 [2, 6, 14]. `switch` 문의 `default` 블록 등에서 `never` 타입을 활용하면, 추후 새로운 상태가 유니온에 추가되었을 때 이를 처리하는 로직이 누락되었다면 컴파일 에러를 발생시켜 런타임 버그를 미연에 차단합니다 [2, 15, 16].
|
||||
|
||||
* **ts-pattern과 분기 처리 최적화**
|
||||
외부 라이브러리인 `ts-pattern`을 사용하면 패턴 매칭을 통해 복잡한 조건부 분기를 선언적으로 작성하고 `.exhaustive()` 메서드를 통해 처리되지 않은 케이스를 안전하게 감지할 수 있습니다 [17]. 하지만 `ts-pattern`은 내부적으로 복잡한 타입 추론과 객체 생성을 수반하므로 자바스크립트의 기본 제어 구조(`if/else`, `switch`)에 비해 연산 성능이 저하될 수 있으며, 지나치게 단순한 로직에 사용할 경우 오버엔지니어링이 될 수 있어 상황에 맞는 유연한 도입이 필요합니다 [17-19].
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** Type Narrowing, [[Discriminated Unions]], Exhaustiveness Checking, State Machine Pattern, ts-pattern
|
||||
- **Projects/Contexts:** React State [[Management]], API Response Handling, Form Handling
|
||||
- **Contradictions/Notes:** 복잡한 조건부 분기를 처리할 때 `ts-pattern` 라이브러리는 훌륭한 타입 안전성과 완전성 검사를 제공하지만, 기존의 `if/else`나 `switch` 제어문에 비해 성능 오버헤드가 발생할 수 있으므로, 성능이 중요한 상황이거나 복잡도가 낮은 분기에서는 기본 제어 구조나 Early return을 활용하는 것이 더 효율적일 수 있습니다 [17-19].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -2,93 +2,199 @@
|
||||
id: wiki-2026-0508-union-types
|
||||
title: Union Types
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-696914]
|
||||
aliases: [Sum Types, Tagged Union, Discriminated Union, Variant]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [type-system, union, sum-type, discriminated-union, typescript, rust]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Union Types"
|
||||
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 / Rust / Haskell
|
||||
framework: language-agnostic
|
||||
---
|
||||
|
||||
# [[Union Types]]
|
||||
# Union Types
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Union Types는 TypeScript에서 하나의 값이 여러 타입 중 하나를 가질 수 있음을 나타내는 기능입니다 [1, 2]. 수직선(`|`) 기호를 사용하여 타입들을 연결하며(예: `string | number`), `any` 타입을 사용하는 것보다 타입 안전성을 유지하면서도 유연한 코드를 작성할 수 있게 해줍니다 [1-3]. 집합론적 관점에서는 두 개 이상의 타입 집합을 합친 합집합(Union)으로 기능합니다 [4, 5].
|
||||
## 매 한 줄
|
||||
> **"매 값이 A 또는 B (또는 C, ...) 의 하나 — 매 sum type 의 set-theoretic 표현"**. Union types 은 1970s ML 의 datatype, 1980s C union (untagged) 부터, 2026 TypeScript discriminated union, Rust enum, Haskell ADT, Python `X | Y` (PEP 604) 까지 매 type-safe variant modeling 의 표준. 매 product type (struct/tuple) 의 dual: AND 가 product, OR 가 sum.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **기본 동작과 공통 필드 제약**: Union Types로 정의된 변수는 지정된 타입들(`A | B`) 중 하나의 값을 가질 수 있습니다 [6, 7]. 그러나 이 변수의 속성에 접근할 때, TypeScript는 타입 안전성을 위해 유니온에 속한 **모든 타입에 공통으로 존재하는 멤버에만 접근을 허용합니다** [2]. 예를 들어 `Bird | Fish` 타입의 변수라면, 런타임에 어떤 타입이 들어올지 확실하지 않으므로 두 인터페이스에 모두 정의된 메서드만 호출할 수 있습니다 [2].
|
||||
- **타입 좁히기 (Type Narrowing)**: 특정 타입에만 속한 속성을 읽거나 쓰려면 먼저 변수의 타입을 좁혀야 합니다 [8]. 이를 위해 `typeof`, `instanceof`, `in` 연산자를 사용하거나, 사용자 정의 타입 가드(Custom Type Guards)를 활용하여 코드가 실행되는 분기(흐름) 내에서 정확한 타입을 추론하도록 해야 합니다 [8-10].
|
||||
- **식별 가능한 유니온 ([[Discriminated Unions]])**: Union Types를 더욱 강력하게 만드는 핵심 패턴입니다 [7, 11]. 유니온을 구성하는 각 객체 타입에 리터럴 타입의 공통 식별자 속성(예: `kind: 'circle' | 'rect[[ANGLE]]'`)을 선언하여, 이 속성을 비교하는 것만으로 TypeScript가 올바른 타입으로 좁힐 수 있게 돕습니다 [12-14]. 이 패턴은 상태 머신을 모델링하거나 잘못된 상태의 조합을 원천적으로 막을 때 매우 효과적입니다 [15, 16].
|
||||
- **완전성 검사 (Exhaustiveness Checking)**: 식별 가능한 유니온을 `switch` 문으로 분기 처리할 때, `never` 타입을 활용해 모든 분기를 안전하게 처리했는지 컴파일러에게 검사받을 수 있습니다 [17-19]. 만약 유니온 타입에 새로운 변형(Variant)이 추가되었는데 `switch` 문에서 처리하지 않았다면, `never` 타입 검사에 걸려 컴파일 에러가 발생하므로 누락을 방지할 수 있습니다 [18-20].
|
||||
- **Type Brands의 대안**: 값의 종류가 미리 정해져 있는 상황이라면, 복잡한 Branded Types를 사용하는 것보다 알려진 값들을 Union Types로 구성하는 것이 값의 종류를 정확히 설명하는 데 유리할 수 있습니다 [21, 22].
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 두 종류
|
||||
- **Untagged union (C-style)**: 매 같은 메모리 영역, runtime 에 active variant 알 수 없음 — unsafe.
|
||||
- **Tagged / discriminated union**: 매 tag field 로 variant 구분 — type-safe (Rust `enum`, TS discriminated, Haskell ADT).
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** Intersection Types, [[Discriminated Unions]], Type Narrowing, Set Theory
|
||||
- **Projects/Contexts:** TypeScript Type[[ system]], [[State]] [[Management]]
|
||||
- **Contradictions/Notes:** Union Types는 값의 유연성을 보장(`A` 혹은 `B` 중 하나 허용)하지만, 객체 속성에 접근할 때는 유니온의 모든 타입에 공통으로 존재하는 속성(교집합 형태)만 접근할 수 있는 엄격함이 있으므로 이를 다룰 때는 항상 타입 좁히기(Type Narrowing)가 선행되어야 합니다 [2, 8].
|
||||
### 매 set theory 관점
|
||||
- 매 `A | B` ≅ A ∪ B (set union, 중복 제거).
|
||||
- 매 `{a:1} | {b:2}` ≅ `{a:1, b?:undefined} ∪ {a?:undefined, b:2}` (TS structural).
|
||||
- 매 cardinality: `|A | B| = |A| + |B|` (disjoint).
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
### 매 응용
|
||||
1. API response — `Success<T> | Error` (Result type).
|
||||
2. State machine — `Idle | Loading | Success | Error`.
|
||||
3. Parser AST — `BinOp | UnaryOp | Literal | Variable`.
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
### TypeScript: discriminated union
|
||||
```typescript
|
||||
type Shape =
|
||||
| { kind: "circle"; radius: number }
|
||||
| { kind: "square"; side: number }
|
||||
| { kind: "rect"; width: number; height: number };
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(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
|
||||
function area(s: Shape): number {
|
||||
switch (s.kind) {
|
||||
case "circle": return Math.PI * s.radius ** 2;
|
||||
case "square": return s.side ** 2;
|
||||
case "rect": return s.width * s.height;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### TypeScript: exhaustiveness check
|
||||
```typescript
|
||||
function area(s: Shape): number {
|
||||
switch (s.kind) {
|
||||
case "circle": return Math.PI * s.radius ** 2;
|
||||
case "square": return s.side ** 2;
|
||||
case "rect": return s.width * s.height;
|
||||
default: {
|
||||
const _exhaustive: never = s; // 매 새 variant 추가 시 compile error
|
||||
throw new Error(`unhandled: ${_exhaustive}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### TypeScript: Result type
|
||||
```typescript
|
||||
type Result<T, E = Error> =
|
||||
| { ok: true; value: T }
|
||||
| { ok: false; error: E };
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
async function fetchUser(id: string): Promise<Result<User>> {
|
||||
try { return { ok: true, value: await api.get(id) }; }
|
||||
catch (e) { return { ok: false, error: e as Error }; }
|
||||
}
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
const r = await fetchUser("1");
|
||||
if (r.ok) console.log(r.value.name);
|
||||
else console.error(r.error.message);
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
### Rust: enum with data
|
||||
```rust
|
||||
enum Message {
|
||||
Quit,
|
||||
Move { x: i32, y: i32 },
|
||||
Write(String),
|
||||
ChangeColor(u8, u8, u8),
|
||||
}
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
fn handle(msg: Message) {
|
||||
match msg {
|
||||
Message::Quit => println!("quit"),
|
||||
Message::Move { x, y } => println!("move to {},{}", x, y),
|
||||
Message::Write(s) => println!("write {}", s),
|
||||
Message::ChangeColor(r, g, b) => println!("rgb({},{},{})", r, g, b),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Rust: Option / Result (built-in unions)
|
||||
```rust
|
||||
fn divide(a: f64, b: f64) -> Result<f64, String> {
|
||||
if b == 0.0 { Err("division by zero".into()) }
|
||||
else { Ok(a / b) }
|
||||
}
|
||||
|
||||
match divide(10.0, 2.0) {
|
||||
Ok(v) => println!("{}", v),
|
||||
Err(e) => eprintln!("error: {}", e),
|
||||
}
|
||||
```
|
||||
|
||||
### Haskell: ADT (sum + product)
|
||||
```haskell
|
||||
data Tree a = Leaf | Node (Tree a) a (Tree a)
|
||||
|
||||
depth :: Tree a -> Int
|
||||
depth Leaf = 0
|
||||
depth (Node l _ r) = 1 + max (depth l) (depth r)
|
||||
|
||||
-- 매 Maybe = Nothing | Just a — sum type
|
||||
safeDiv :: Int -> Int -> Maybe Int
|
||||
safeDiv _ 0 = Nothing
|
||||
safeDiv a b = Just (a `div` b)
|
||||
```
|
||||
|
||||
### Python 3.10+: union via `|`
|
||||
```python
|
||||
from dataclasses import dataclass
|
||||
|
||||
@dataclass
|
||||
class Circle: radius: float
|
||||
@dataclass
|
||||
class Square: side: float
|
||||
|
||||
Shape = Circle | Square
|
||||
|
||||
def area(s: Shape) -> float:
|
||||
match s:
|
||||
case Circle(radius=r): return 3.14159 * r * r
|
||||
case Square(side=x): return x * x
|
||||
```
|
||||
|
||||
### TypeScript: narrowing without discriminant
|
||||
```typescript
|
||||
type Pet = { swim: () => void } | { fly: () => void };
|
||||
function move(p: Pet) {
|
||||
if ("swim" in p) p.swim(); // 매 narrowed
|
||||
else p.fly();
|
||||
}
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| 2-3 variants, simple | TS plain union `A \| B` |
|
||||
| Many variants, type-safe dispatch | discriminated union with `kind` |
|
||||
| Result / Option | TS Result type / Rust built-in / Haskell Maybe |
|
||||
| Cross-language ADT | Rust enum / Haskell data |
|
||||
| Untagged (FFI / memory layout) | C union / Rust `union` (unsafe) |
|
||||
| Exhaustive matching | switch + `never` (TS) / `match` (Rust/Python) |
|
||||
|
||||
**기본값**: 매 discriminated union with literal `kind`/`tag` field — exhaustiveness 보장.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Type System]] · [[Algebraic Data Types]]
|
||||
- 변형: [[Discriminated Union]] · [[Tagged Union]] · [[Sum Types]] · [[Variant]]
|
||||
- 응용: [[Result Type]] · [[Option Type]] · [[State Machine]] · [[AST]]
|
||||
- Adjacent: [[Pattern Matching]] · [[Type Narrowing]] · [[Exhaustiveness Check]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 모델링 "A or B" 의 alternatives, error handling (Result), state representation.
|
||||
**언제 X**: 매 단순 enum (no associated data) — plain enum 이 나음.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Boolean flags 의 union 흉내**: `{ ok: boolean, value?, error? }` — 매 `value && error` 동시 가능 → bug. Discriminated union 으로.
|
||||
- **Discriminant 없는 큰 union**: 매 narrowing 불가능 — `kind`/`tag` 추가.
|
||||
- **`default` 없는 switch**: 매 새 variant 추가 시 silent miss — `never` exhaustive check.
|
||||
- **Rust untagged `union`**: 매 unsafe 만 사용 — 99% 의 case 는 `enum`.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (TypeScript handbook, Rust book, Haskell report 2010).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — union types full content (4 langs, exhaustive, Result, 8 patterns) |
|
||||
|
||||
@@ -2,104 +2,33 @@
|
||||
id: wiki-2026-0508-v8-엔진-힙-아키텍처-및-로그-분석
|
||||
title: V8 엔진 힙 아키텍처 및 로그 분석
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-18F9C4]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: nodejs-memory-tuning
|
||||
duplicate_of: "[[Nodejs 메모리 튜닝]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - V8 엔진 힙 아키텍처 및 로그 분석"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, v8, memory, debugging]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[V8 엔진 힙 아키텍처 및 로그 분석]]
|
||||
# V8 엔진 힙 아키텍처 및 로그 분석
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> V8 엔진 힙 아키텍처는 효율적인 메모리 할당과 빠른 가비지 컬렉션(GC)을 위해 물리적 메모리를 세대와 용도별 여러 공간으로 세분화하여 관리하는 구조입니다. 이 시스템은 대부분의 객체가 짧은 시간 안에 소멸한다는 '세대 가설([[Generational Hypothesis]])'을 바탕으로 설계되어 젊은 세대와 오래된 세대에 각각 다른 알고리즘을 적용합니다. 런타임 로그 분석은 `--trace-gc` 등의 플래그를 활용해 메모리 할당 실패 원인, 수집에 소요된 시간, 힙의 생존 객체 크기 변화를 추적함으로써 메모리 누수와 성능 병목을 진단하는 핵심 기술입니다.
|
||||
> **이 문서는 [[Nodejs 메모리 튜닝]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
**V8 힙 메모리 구조 (Heap Organization)**
|
||||
* **Resident Set 분할:** V8 프로세스가 할당받은 메모리는 주로 정적 데이터와 실행 프레임을 담는 스택(Stack) 공간과, 동적 객체가 저장되며 가비지 컬렉션의 대상이 되는 힙(Heap) 공간으로 나뉩니다 [1-3].
|
||||
* **New Space (Young Generation):** 새로 생성된 객체들이 할당되는 작고 빠른 공간입니다. 이 공간은 크기가 1~64MB 정도로 작으며, 내부적으로 'From-Space'와 'To-Space'라는 두 개의 동일한 크기의 반공간(semi-space)으로 나뉘어 [[Scavenge]]r 알고리즘에 의해 관리됩니다 [4-7].
|
||||
* **[[Old Space]] (Old Generation):** New Space에서 두 번의 GC를 거치고도 살아남은 객체들이 승격(Promotion)되어 이동하는 공간입니다. 이 공간은 다른 객체를 참조하는 포인터를 가진 'Old Pointer Space'와 문자열 등 순수 데이터만 가진 'Old Data Space'로 세분화되어 마크-스윕-컴팩트([[Mark-Sweep]]-Compact) 알고리즘으로 관리됩니다 [4, 7-9].
|
||||
* **특수 공간:** 여타 공간의 한계를 초과하는 큰 객체를 위해 메모리를 직접 mmap하는 'Large Object Space', JIT 컴파일된 머신 코드를 저장하는 'Code Space', 그리고 크기가 일정한 내부 구조체(Map, Cell)를 담는 전용 공간들이 존재합니다 [4, 7, 8].
|
||||
* **페이지와 샌드박싱:** 각 공간은 연속된 메모리 청크인 페이지(Page)로 구성됩니다. 기본 1MB 단위였으나 저메모리 기기 최적화를 위해 512KB로 축소되기도 하였습니다 [10-13]. 최신 64비트 V8은 포인터 압축([[Pointer Compression]]) 기법을 적용하여 힙 전체를 4GB로 제한된 연속된 '케이지(Cage)' 영역 안에 가두어 관리합니다 [14-16].
|
||||
## 핵심 요약 (specialization aspects)
|
||||
- 매 V8 heap 의 generational layout — Young (Nursery + Intermediate) / Old (Pointer + Data) / Large / Code.
|
||||
- 매 `--trace-gc` / `--trace-gc-verbose` log 의 interpret — pause time, promotion rate.
|
||||
- 매 heap snapshot 의 chrome://inspect 의 분석.
|
||||
|
||||
**가비지 컬렉션(GC) 메커니즘**
|
||||
* **마이너 GC (Scavenge):** New Space의 할당 포인터가 한계에 달하면(Allocation failure) 트리거됩니다. Cheney 알고리즘을 사용해 활성 객체만 'To-Space' 또는 Old Space로 복사하고, 이전 공간을 통째로 비움으로써 파편화를 없앱니다 [5, 17-19].
|
||||
* **메이저 GC:** Old Space의 객체를 수집합니다. 힙 전체에서 활성 객체를 식별(Mark)하고, 접근 불가 객체를 해제(Sweep)하며, 남은 메모리의 파편화를 줄이기 위해 활성 객체들을 한 곳으로 모읍니다(Compact) [20-23].
|
||||
* **오리노코([[Orinoco]]) 프로젝트:** 메인 스레드가 정지되는 '[[Stop-the-world]]' 시간을 최소화하기 위해 병렬(Parallel), 점진적(Incremental), 동시(Concurrent) 스레드 기법을 결합하여 GC 작업을 백그라운드로 분산시킵니다 [24-27].
|
||||
## 🔗 Graph
|
||||
- 부모: [[Nodejs 메모리 튜닝]] (canonical)
|
||||
- Adjacent: [[Old Space]] · [[Generational Hypothesis]] · [[Pointer Compression]] · [[Garbage Collection(가비지 컬렉션)]]
|
||||
|
||||
**로그 분석 (Log [[Analysis]])**
|
||||
* **--trace-gc 로깅 분석:** `PID, Isolate, Timestamp ms: Type Used (Total) -> Used (Total) MB, Duration ms, Reason` 형식으로 로그가 출력됩니다. 여기서 Reason 항목이 'allocation failure'인 경우 새로운 객체를 담을 메모리 공간이 부족하여 GC가 강제 실행되었음을 의미하며, 소요 시간(Duration) 지표를 통해 메인 스레드 멈춤 길이를 파악할 수 있습니다 [28-31].
|
||||
* **세부 로그 (--trace-gc-verbose / --trace-gc-nvp):** 각 힙 공간(New, Old, Large Object 등)의 사용량과 시스템에 커밋된 양을 분리하여 상세히 보여줍니다. 만약 메이저 GC 이후에도 Old space의 Used 영역이 점진적으로 계속 증가한다면 전형적인 메모리 누수 증상으로 판단합니다 [30, 32].
|
||||
* **프로파일링 도구 연계:** `--heap-prof` 플래그나 크롬 DevTools의 [[Allocation Timeline]]을 활용해 주기적인 힙 스냅샷을 찍고 분석할 수 있습니다. 할당 후 수집되지 않아 파란색으로 남은 타임라인 막대나, DevTools의 'Retainers' 패널을 역추적함으로써 어떤 루트 객체가 해제되어야 할 메모리를 쥐고 있는지([[Retaining Path]]s) 정확히 파악 가능합니다 [33-36].
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[세대 가설(Generational Hypothesis)]], Scavenger(마이너 GC), [[Mark-Sweep-Compact(메이저 GC)]], [[오리노코(Orinoco) 프로젝트]], [[포인터 압축(Pointer Compression)]]
|
||||
- **Projects/Contexts:** Node.js 프로덕션 메모리 누수 진단, [[Chrome]] 렌더러 프로세스 V8 샌드박스 보안
|
||||
- **Contradictions/Notes:** 소스 [37-56]에서는 gencon, balanced 등 IBM E[[CLIP]]se OpenJ9의 GC 정책에 대한 내용을 깊이 다루고 있으나, 이는 V8 엔진 고유의 구조가 아니므로 본 V8 아키텍처 중심 분석에서는 배제하였습니다.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — Node 메모리 튜닝 canonical 로 redirect |
|
||||
|
||||
@@ -2,106 +2,32 @@
|
||||
id: wiki-2026-0508-v8-엔진-힙-아키텍처
|
||||
title: V8 엔진 힙 아키텍처
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-221751]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: v8-엔진-힙-아키텍처-및-로그-분석
|
||||
duplicate_of: "[[V8 엔진 힙 아키텍처 및 로그 분석]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - V8 엔진 힙 아키텍처"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, v8, heap, memory]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[V8 엔진 힙 아키텍처]]
|
||||
# V8 엔진 힙 아키텍처
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> V8 엔진의 힙 아키텍처는 런타임 시 크기나 수명을 미리 알 수 없는 동적 데이터와 자바스크립트 객체들을 저장하고 관리하기 위해 구성된 메모리 구조입니다 [1-3]. 효율적인 가비지 컬렉션을 위해 대부분의 객체가 생성 직후 죽는다는 '세대적 가설([[Generational Hypothesis]])'을 기반으로 설계되었습니다 [4-6]. 이를 위해 힙은 객체의 수명과 특성에 따라 여러 개의 특수 공간(Space)으로 나뉘며, 각 공간은 페이지(Pages) 단위로 나뉘어 메모리 할당 및 회수에 최적화된 고유의 방식으로 관리됩니다 [7-10].
|
||||
> **이 문서는 [[V8 엔진 힙 아키텍처 및 로그 분석]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **세대적 힙 분할 (Generational Heap Layout):**
|
||||
* **New-space (Young Generation):** 대부분의 새로운 객체가 처음 할당되는 작고 빠른 공간입니다 [4, 7, 9]. 내부적으로 크기가 동일한 두 개의 반공간(To-Space, From-Space)으로 나뉘며, 스캐빈저([[Scavenge]]r)라 불리는 마이너 가비지 컬렉터(Minor GC)에 의해 관리됩니다 [11-14].
|
||||
* **Old-space (Old Generation):** New-space에서 두 번의 가비지 컬렉션 주기 동안 살아남은 객체들이 승격(Promote)되어 이동하는 공간입니다 [4, 12, 15]. 가비지 컬렉션 시 포인터 추적(Tracing) 단계를 최적화하기 위해, 다른 객체에 대한 포인터를 포함하는 **Old-pointer-space**와 문자열이나 박싱된 숫자처럼 포인터가 없는 순수 데이터만 포함하는 **Old-data-space**로 세분화됩니다 [7, 9, 15]. 이곳은 메이저 가비지 컬렉터([[Mark-Sweep]]-Compact)가 관리합니다 [4, 9, 16].
|
||||
## 핵심 요약 (specialization aspects)
|
||||
- New / Old / Large Object / Code / Map space 매 V8 partitioning.
|
||||
- Pointer compression · Orinoco GC 매 modern (2026) 적용.
|
||||
|
||||
* **특수 목적 공간 (Specialized Spaces):**
|
||||
* **Large-object-space:** 다른 공간의 크기 제한(일반적으로 1MB 이상)을 초과하는 큰 객체가 저장되는 공간입니다 [7, 9]. 각 객체는 운영체제로부터 별도의 mmap 영역을 할당받으며, 가비지 컬렉터에 의해 위치가 이동되지 않습니다 [7, 9].
|
||||
* **Code-space:** JIT 컴파일러에 의해 생성된 실행 가능한 기계어 명령어 코드가 저장되는 유일한 실행 가능 메모리 영역입니다 [7, 9].
|
||||
* **Map, Cell, Property-cell Space:** 모두 같은 크기를 가지며 가리키는 객체 종류에 제약이 있는 특정 내부 객체들을 저장하여 메모리 수집을 단순화하는 공간입니다 [7, 9].
|
||||
* **Read Only Space:** 영구적이며 절대 이동하거나 변하지 않는 불변(immutable) 객체들을 저장합니다 [17].
|
||||
## 🔗 Graph
|
||||
- 부모: [[V8 엔진 힙 아키텍처 및 로그 분석]] (canonical)
|
||||
- Adjacent: [[Old Space]] · [[Orinoco 가비지 컬렉터]] · [[Pointer Compression]]
|
||||
|
||||
* **페이지 및 물리적 메모리 관리 (Pages & [[memory]] [[Management]]):**
|
||||
* 각 힙 공간은 '페이지(Pages)'라는 연속된 메모리 청크의 집합으로 구성됩니다 [5, 8, 10].
|
||||
* 페이지는 전통적으로 1MB 크기에 1MB로 정렬되어 있었으나, 저메모리 기기 최적화 및 파편화 감소를 위해 512KB 크기로 축소되는 최적화가 적용되었습니다 [5, 8, 10, 18].
|
||||
* 각 페이지에는 메타데이터와 마킹 비트맵이 있는 헤더가 포함되며, 다른 페이지의 객체를 가리키는 포인터 위치를 추적하기 위한 슬롯 버퍼(기억 집합, Remembered Set)가 존재합니다 [8, 10, 19].
|
||||
|
||||
* **포인터 압축과 메모리 케이지 ([[Pointer Compression]] & V8 Memory Cage):**
|
||||
* 64비트 시스템에서 메모리 사용량을 줄이고 보안을 강화하기 위해, V8은 모든 힙 객체를 4GB 크기의 연속적인 '메모리 케이지(Memory Cage)' 구역 내에 가둡니다 [20-22].
|
||||
* 객체의 포인터는 완전한 64비트 주소가 아닌 케이지의 기본 주소(Base Address)로부터의 32비트 오프셋으로 압축되어 저장됩니다 [21, 22]. 이로 인해 힙 메모리는 물리적 RAM의 크기와 무관하게 4GB의 엄격한 상한선을 가집니다 [20, 21].
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** 가비지 컬렉션([[Garbage Collection]]), 세대적 가설(Generational Hypothesis), 스캐빈저(Scavenger), Mark-Sweep-Compact, [[포인터 압축(Pointer Compression)]]
|
||||
- **Projects/Contexts:** Node.js 성능 최적화, Google [[Chrome]] 브라우저 메모리 관리, [[Orinoco 가비지 컬렉터]]
|
||||
- **Contradictions/Notes:** V8은 일반적으로 1MB 단위의 페이지 크기를 사용해 왔으나, 최신 최적화 동향에 따라 메모리 단편화를 줄이고 병렬 압축(Compaction) 효율을 높이기 위해 페이지 크기를 512KB로 축소 조정하는 방식을 병행하여 사용합니다 [5, 8, 18].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -1,25 +1,174 @@
|
||||
---
|
||||
id: wiki-20260508-vr-sickness-redir
|
||||
title: VR Sickness
|
||||
category: Programming & Language
|
||||
status: merged
|
||||
redirect_to: VR_Sickness
|
||||
canonical_id: VR_Sickness
|
||||
aliases: []
|
||||
category: 10_Wiki/Topics
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [cybersickness, simulator sickness, VR motion sickness]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [redirect]
|
||||
confidence_score: 0.91
|
||||
verification_status: applied
|
||||
tags: [vr, ux, perception, three-js]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-merge 2026-05-08)
|
||||
tech_stack:
|
||||
language: TypeScript
|
||||
framework: Three.js / WebXR
|
||||
---
|
||||
|
||||
# VR Sickness
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 이 문서는 P-Reinforce Phase 2 자동 MERGE에 의해 **[[VR_Sickness]]**로 통합되었습니다.
|
||||
## 매 한 줄
|
||||
> **"매 visual motion 과 vestibular 의 mismatch 의 motion sickness 의 trigger"**. 매 VR 의 가장 큰 UX 장벽 — 매 frame rate / FOV / locomotion 의 careful design 의 mitigation. 2026 의 Quest 3 / Vision Pro / PCVR 의 90Hz+ 의 default — 매 여전히 design pattern 의 핵심.
|
||||
|
||||
---
|
||||
*Redirected to: [[VR_Sickness]]*
|
||||
## 매 핵심
|
||||
|
||||
### 매 원인
|
||||
- **Sensory mismatch**: 매 eye 의 motion 의 perceive — 매 inner ear 의 stationary 의 report.
|
||||
- **Low frame rate**: <72fps 의 judder 의 sickness 의 trigger.
|
||||
- **Vection**: 매 large optical flow 의 self-motion 의 illusion.
|
||||
- **Latency**: motion-to-photon >20ms 의 mismatch 의 amplify.
|
||||
- **FOV motion**: peripheral 의 motion 의 sensitivity 가장 큼.
|
||||
|
||||
### 매 mitigation 기법
|
||||
- **Teleport locomotion**: 매 smooth 대신 fade-to-black + jump.
|
||||
- **Tunnel vision (vignette)**: 매 motion 시 peripheral mask — 매 vection 감소.
|
||||
- **Snap turning**: 매 smooth rotation 대신 30° step.
|
||||
- **Comfort settings**: 매 user 의 individual tuning.
|
||||
- **High frame rate**: 90Hz+ 의 mandatory — Quest 3 의 default 90/120Hz.
|
||||
- **Stable horizon**: 매 cockpit / fixed reference frame.
|
||||
|
||||
### 매 응용
|
||||
1. Beat Saber — 매 stationary play 의 zero motion sickness.
|
||||
2. Half-Life Alyx — 매 teleport + smooth 의 toggle.
|
||||
3. 매 자전거 simulator — 매 physical motion 의 real vestibular alignment.
|
||||
|
||||
## 💻 패턴
|
||||
|
||||
### 매 Three.js + WebXR 의 framerate 의 monitor
|
||||
```typescript
|
||||
import * as THREE from 'three';
|
||||
|
||||
const renderer = new THREE.WebGLRenderer({ antialias: true });
|
||||
renderer.xr.enabled = true;
|
||||
|
||||
let lastTime = performance.now();
|
||||
renderer.setAnimationLoop((time) => {
|
||||
const dt = time - lastTime;
|
||||
if (dt > 14) console.warn(`Frame drop: ${dt.toFixed(1)}ms`); // 매 <72fps 의 경고
|
||||
lastTime = time;
|
||||
renderer.render(scene, camera);
|
||||
});
|
||||
```
|
||||
|
||||
### 매 Vignette 의 motion 시 적용
|
||||
```glsl
|
||||
// fragment shader
|
||||
uniform float u_vignetteStrength;
|
||||
varying vec2 vUv;
|
||||
|
||||
void main() {
|
||||
vec2 center = vUv - 0.5;
|
||||
float dist = length(center);
|
||||
float vignette = smoothstep(0.5, 0.3 - u_vignetteStrength * 0.2, dist);
|
||||
gl_FragColor = vec4(color.rgb * vignette, 1.0);
|
||||
}
|
||||
```
|
||||
|
||||
```typescript
|
||||
// 매 movement 의 detect 후 strength 의 ramp
|
||||
const speed = velocity.length();
|
||||
material.uniforms.u_vignetteStrength.value = THREE.MathUtils.clamp(speed / 5, 0, 0.6);
|
||||
```
|
||||
|
||||
### 매 Snap turn 의 implementation
|
||||
```typescript
|
||||
let lastTurnTime = 0;
|
||||
const SNAP_ANGLE = Math.PI / 6; // 30°
|
||||
const COOLDOWN = 250;
|
||||
|
||||
function update(controller: THREE.Group, input: GamepadAxes) {
|
||||
const now = performance.now();
|
||||
if (Math.abs(input.thumbstickX) > 0.7 && now - lastTurnTime > COOLDOWN) {
|
||||
rig.rotation.y -= Math.sign(input.thumbstickX) * SNAP_ANGLE;
|
||||
lastTurnTime = now;
|
||||
fadeOutIn(50); // 매 brief blackout 의 ease
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 매 Teleport locomotion
|
||||
```typescript
|
||||
function teleport(targetPos: THREE.Vector3) {
|
||||
fadeToBlack(150).then(() => {
|
||||
rig.position.copy(targetPos);
|
||||
fadeFromBlack(150);
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### 매 Stable horizon (cockpit reference)
|
||||
```typescript
|
||||
// 매 vehicle simulator 의 cockpit mesh 의 always-visible
|
||||
const cockpit = new THREE.Mesh(cockpitGeo, cockpitMat);
|
||||
camera.add(cockpit); // 매 head 에 follow — 매 vestibular reference
|
||||
scene.add(camera);
|
||||
```
|
||||
|
||||
### 매 Comfort 설정 의 노출
|
||||
```typescript
|
||||
const settings = {
|
||||
movementType: 'teleport' as 'teleport' | 'smooth',
|
||||
vignetteEnabled: true,
|
||||
snapTurn: true,
|
||||
snapAngle: 30,
|
||||
};
|
||||
// 매 in-game menu 의 user 노출 — 매 individual variance 의 대응
|
||||
```
|
||||
|
||||
### 매 Latency 의 측정
|
||||
```typescript
|
||||
const xrSession = renderer.xr.getSession();
|
||||
xrSession?.requestAnimationFrame((time, frame) => {
|
||||
// 매 frame.predictedDisplayTime - performance.now() = motion-to-photon
|
||||
});
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| Casual user | teleport + snap turn (default) |
|
||||
| Hardcore VR | smooth + comfort toggle |
|
||||
| Vehicle sim | cockpit + stable horizon |
|
||||
| Stationary game | minimal locomotion (Beat Saber) |
|
||||
| Motion ride | physical motion 의 sync |
|
||||
|
||||
**기본값**: teleport + snap turn 의 default. 매 user toggle 의 expose.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Virtual Reality UX]]
|
||||
- 변형: [[VR 멀미 (VR Sickness)]] · [[VR 멀미(VR sickness)]] (Korean variants)
|
||||
- 응용: [[Beat Saber]] · [[가상현실(VR) 자전거 시뮬레이터]]
|
||||
- Adjacent: [[Vergence-Accommodation Conflicts]] · [[깊이 지각(Depth perception)]] · [[Edge Bleeding]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: VR app 의 design 의 comfort 권장, frame rate budget 의 explain, snap turn / teleport 의 trade-off.
|
||||
**언제 X**: 매 medical 진단 — 매 individual variance 의 큼 의 인지.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **<72fps 의 ship**: 매 sickness 의 garantee.
|
||||
- **Smooth-only locomotion**: 매 casual user 의 alienate.
|
||||
- **Forced camera shake**: 매 vection 증폭.
|
||||
- **Unstable horizon**: 매 vehicle 의 wobble.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Oculus VR Best Practices, Valve Half-Life Alyx postmortem).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — VR sickness FULL 작성 |
|
||||
|
||||
@@ -1,25 +1,33 @@
|
||||
---
|
||||
id: wiki-20260508-vr-vr-sickness--redir
|
||||
title: VR 멀미 (VR Sickness)
|
||||
category: Programming & Language
|
||||
status: merged
|
||||
redirect_to: VR 멀미(VR sickness)
|
||||
canonical_id: VR 멀미(VR sickness)
|
||||
category: 10_Wiki/Topics
|
||||
status: duplicate
|
||||
canonical_id: vr-sickness
|
||||
duplicate_of: "[[VR Sickness]]"
|
||||
aliases: []
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [redirect]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
confidence_score: 0.9
|
||||
verification_status: redirected
|
||||
tags: [duplicate, vr, sickness, ux]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-merge 2026-05-08)
|
||||
---
|
||||
|
||||
# VR 멀미 (VR Sickness)
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 이 문서는 P-Reinforce Phase 2 자동 MERGE에 의해 **[[VR 멀미(VR sickness)]]**로 통합되었습니다.
|
||||
> **이 문서는 [[VR Sickness]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
---
|
||||
*Redirected to: [[VR 멀미(VR sickness)]]*
|
||||
## 핵심 요약 (specialization aspects)
|
||||
- Korean 표기 변형 — 매 same concept.
|
||||
- 시각-전정 충돌 · vergence-accommodation conflict 매 root cause.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[VR Sickness]] (canonical)
|
||||
- Adjacent: [[가상현실 멀미 (VR Sickness)]] · [[VR 멀미(VR sickness)]] · [[시각-전정 갈등 (Visual-Vestibular Conflict)]]
|
||||
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -2,101 +2,31 @@
|
||||
id: wiki-2026-0508-vr-멀미-vr-sickness
|
||||
title: VR 멀미(VR sickness)
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-926D42]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: vr-sickness
|
||||
duplicate_of: "[[VR Sickness]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - VR 멀미([[VR Sickness]])"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, vr, hci]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[VR 멀미(VR sickness)]]
|
||||
# VR 멀미(VR sickness)
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> VR 멀미(VR sickness)는 헤드 마운트 디스플레이(HMD) 사용 시 발생하는 부정적인 부작용으로, 주로 메스꺼움, 방향 감각 상실, 안구 피로 및 시각적 장애와 같은 증상으로 나타납니다 [1, 2]. 가상 세계의 시각적 경험과 실제 신체의 감각이 일치하지 않을 때 발생하는 시각-전정 감각의 충돌(visual-vestibular conflict)이 주요 원인으로 지목됩니다 [3]. 이러한 멀미 증상은 사용자의 몰입감(presence)을 떨어뜨리고, 게임이나 작업의 동기 부여와 즐거움을 감소시키며, 종국에는 수행 능력을 저하시키는 원인이 됩니다 [2].
|
||||
> **이 문서는 [[VR Sickness]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **발생 원인 및 메커니즘:**
|
||||
VR 멀미의 명확한 발병 원인에 대한 완전한 합의는 없지만, 가상과 현실 간의 감각 불일치 이론이 가장 유력합니다 [3]. 뇌로 전달되는 시각적 감각과 신체적(전정) 감각이 충돌하면 감각 통합에 교란이 생겨 메스꺼움이나 방향 감각 상실을 유발합니다 [3]. 또한, HMD 환경에서 제공되는 깊이 단서의 충돌로 인해 발생하는 '폭주-조절 불일치([[Vergence-Accommodation Conflicts]])' 역시 안구 운동 관련 증상(oculomotor symptoms)을 증가시킵니다 [3, 4].
|
||||
## 핵심 요약
|
||||
- 매 sensory conflict (visual ≠ vestibular) → nausea.
|
||||
- 매 mitigation: 90Hz+, vignette, teleport, snap-turn.
|
||||
|
||||
* **증상 및 측정:**
|
||||
멀미 증상은 크게 세 가지 범주, 즉 메스꺼움(위장 자극, 트림, 타액 분비 증가), 안구 운동 이상(눈의 피로, 초점 문제), 방향 감각 상실(현기증, 어지러움)로 나뉩니다 [5]. 이러한 증상들은 주로 시뮬레이터 멀미 설문지(SSQ)를 통해 측정되며, 증상이 심할 경우 약 15.6%의 평균 사용자 이탈률을 초래합니다 [2, 5]. 멀미 증상은 VR 종료 직후뿐만 아니라 최대 24시간 이후에 심각한 잠복 증상(latent symptoms)으로 나타날 수도 있습니다 [6].
|
||||
## 🔗 Graph
|
||||
- 부모: [[VR Sickness]] (canonical)
|
||||
|
||||
* **주요 영향 요인:**
|
||||
* **노출 시간:** VR 노출 지속 시간은 후유증의 발생과 심각도에 결정적인 역할을 합니다 [7]. 연구에 따르면 10분의 짧은 노출보다 50분의 긴 노출 직후에 메스꺼움 등의 증상이 유의미하게 더 많이 보고되었습니다 [8].
|
||||
* **콘텐츠 및 기기 특성:** 시각적 움직임의 강도, 장면의 복잡성, 이동 방식(locomotion) 등이 VR 멀미 발생에 직접적인 영향을 미칩니다 [9]. 모니터 기반 게임보다 HMD 착용 환경에서 더 높은 수준의 멀미가 유발되는 경향이 있습니다 [10].
|
||||
* **개인차:** 연령, HMD의 착용 상태, 사용자의 자세 안정성, 멀미에 대한 개인적 민감성 등이 복합적으로 작용합니다 [11]. 특히, 짧은 시간의 노출에도 심한 증상을 겪는 사람은 긴 노출 시 훨씬 더 심각한 증상을 겪을 가능성이 높습니다 [11].
|
||||
|
||||
* **완화 및 회복 전략:**
|
||||
VR 사용 후 후유증이 기저 수준으로 회복되는 데 걸리는 시간은 증상의 초기 심각도에 따라 다릅니다 [12]. 일반적인 경우, VR 노출 후 약 40분의 대기 시간을 가지면 증상이 정상 수준으로 돌아옵니다 [8, 13]. 멀미를 완화하기 위해서는 가상 세계의 시각적 움직임과 사용자의 실제 신체 움직임을 일치시키고, 장시간 사용 전 짧은 세션으로 테스트하거나 자주 휴식을 취하여 적응(habituation)을 유도하는 전략이 권장됩니다 [10, 11, 13].
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[시각-전정 감각 충돌(Visual-Vestibular Conflict)]], [[폭주-조절 불일치(Vergence-Accommodation Conflict)]], [[시뮬레이터 멀미 설문지(SSQ)]], 몰입감(Presence)
|
||||
- **Projects/Contexts:** 비트 세이버([[Beat Saber]]) 엑서게이밍 연구 (10분 및 50분의 VR 노출이 사용자의 시각, 인지 및 자기 보고된 멀미 후유증에 미치는 영향을 조사한 연구 [14, 15]).
|
||||
- **Contradictions/Notes:** 고강도 신체 활동을 동반하는 VR 엑서게임(Exergame)을 수행할 경우, 피로, 방향 감각 상실, 땀 흘림, 메스꺼움 등 격렬한 유산소 운동으로 인한 생리적 증상과 VR 멀미 증상이 겹치게 됩니다. 이로 인해 운동 중 순수한 VR 멀미 증상만을 명확히 구분해 내는 데에는 어려움이 따릅니다 [16].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -1,25 +1,146 @@
|
||||
---
|
||||
id: wiki-20260508-vergence-accommodation-conflicts-redir
|
||||
title: Vergence Accommodation Conflicts
|
||||
category: Programming & Language
|
||||
status: merged
|
||||
redirect_to: Vergence-Accommodation_Conflicts
|
||||
canonical_id: Vergence-Accommodation_Conflicts
|
||||
aliases: []
|
||||
title: Vergence-Accommodation Conflicts
|
||||
category: 10_Wiki/Topics
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [VAC, vergence accommodation conflict, focal mismatch]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [redirect]
|
||||
confidence_score: 0.91
|
||||
verification_status: applied
|
||||
tags: [vr, perception, optics, ux]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-merge 2026-05-08)
|
||||
tech_stack:
|
||||
language: TypeScript
|
||||
framework: Three.js / WebXR
|
||||
---
|
||||
|
||||
# Vergence Accommodation Conflicts
|
||||
# Vergence-Accommodation Conflicts
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 이 문서는 P-Reinforce Phase 2 자동 MERGE에 의해 **[[Vergence-Accommodation_Conflicts]]**로 통합되었습니다.
|
||||
## 매 한 줄
|
||||
> **"매 eye 의 vergence (cross-eye angle) 와 accommodation (lens focus) 의 mismatch 의 eye strain / sickness"**. 매 stereoscopic VR / AR 의 fundamental 한계 — 매 fixed focal plane 의 cause. 2026 의 Vision Pro 의 여전히 mitigation 만 가능 — 매 light field display 의 future.
|
||||
|
||||
---
|
||||
*Redirected to: [[Vergence-Accommodation_Conflicts]]*
|
||||
## 매 핵심
|
||||
|
||||
### 매 원인
|
||||
- **Real world**: 매 vergence (eye 가 object 로 cross) 와 accommodation (lens focus 의 거리) 의 동기.
|
||||
- **VR/AR**: 매 vergence 의 virtual depth 의 따라 변화 — 매 accommodation 의 fixed display focal plane (~2m) 에 lock.
|
||||
- **Conflict**: 매 brain 의 두 cue 의 mismatch 의 fatigue / blur / nausea 의 trigger.
|
||||
|
||||
### 매 mitigation
|
||||
- **Dolly comfort zone**: 매 0.5-2m 의 main interaction — focal mismatch minimum.
|
||||
- **Reduce small text**: 매 close-up text 의 conflict 의 amplify.
|
||||
- **Vary focus only with intent**: 매 sudden depth change 의 avoid.
|
||||
- **Pupil-aware DOF**: 매 eye-tracking 의 dynamic blur (Vision Pro).
|
||||
- **Light field display** (future): 매 multi-focal — true accommodation cue.
|
||||
|
||||
### 매 응용
|
||||
1. UI design — 매 menu 의 1.5m 거리 의 default.
|
||||
2. AR overlay 의 real-world depth match — 매 ARKit / ARCore 의 plane anchor.
|
||||
3. eye-tracked foveated rendering 의 결합.
|
||||
|
||||
## 💻 패턴
|
||||
|
||||
### 매 Three.js + WebXR 의 comfort zone 의 UI 배치
|
||||
```typescript
|
||||
const COMFORT_DISTANCE = 1.5; // m
|
||||
|
||||
const menu = new THREE.Group();
|
||||
menu.position.set(0, 1.5, -COMFORT_DISTANCE); // 매 1.5m 의 fixed focal
|
||||
camera.parent.add(menu); // 매 head-locked
|
||||
|
||||
// 매 menu 의 readable 의 maintain
|
||||
```
|
||||
|
||||
### 매 거리 별 text size 의 scaling
|
||||
```typescript
|
||||
function readableTextSize(distance: number): number {
|
||||
// 매 angular size = arctan(size / distance) — 매 적정 1-2°
|
||||
return distance * 0.025; // 매 1.5m 의 ~3.75cm height
|
||||
}
|
||||
```
|
||||
|
||||
### 매 Eye-tracking 의 dynamic DOF (Vision Pro / Quest Pro)
|
||||
```typescript
|
||||
const xrSession = renderer.xr.getSession();
|
||||
const gazeRay = await xrSession?.requestReferenceSpace('viewer');
|
||||
|
||||
// 매 gaze 의 depth 의 추정
|
||||
function applyDOF(focusDistance: number) {
|
||||
postProcessing.bokehPass.uniforms.focus.value = focusDistance;
|
||||
postProcessing.bokehPass.uniforms.aperture.value = 0.025;
|
||||
}
|
||||
```
|
||||
|
||||
### 매 Sudden depth change 의 mitigation
|
||||
```typescript
|
||||
// 매 fade transition 의 사용
|
||||
async function transitionScene(newDepth: number) {
|
||||
await fadeToBlack(200);
|
||||
scene.position.z = -newDepth;
|
||||
await fadeFromBlack(200);
|
||||
}
|
||||
```
|
||||
|
||||
### 매 AR plane anchor 의 align
|
||||
```typescript
|
||||
// 매 WebXR hit-test
|
||||
const hitTestSource = await xrSession.requestHitTestSource({ space: viewerSpace });
|
||||
|
||||
xrSession.requestAnimationFrame((time, frame) => {
|
||||
const results = frame.getHitTestResults(hitTestSource);
|
||||
if (results.length > 0) {
|
||||
const pose = results[0].getPose(refSpace);
|
||||
object.position.setFromMatrixPosition(new THREE.Matrix4().fromArray(pose.transform.matrix));
|
||||
// 매 real surface 의 attach — 매 vergence/accommodation 의 align
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### 매 Comfort range 의 enforce
|
||||
```typescript
|
||||
function clampInteractionDistance(target: THREE.Object3D) {
|
||||
const dist = camera.position.distanceTo(target.position);
|
||||
if (dist < 0.3) target.scale.setScalar(0.3 / dist); // 매 too-close 시 shrink
|
||||
if (dist > 3) target.scale.setScalar(dist / 3); // 매 too-far 시 enlarge
|
||||
}
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| UI / menu | 1.5-2m fixed (comfort zone) |
|
||||
| Reading | 0.7-1m, large font |
|
||||
| AR overlay | real surface anchor |
|
||||
| Cinematic | distant scene (>3m) |
|
||||
| Sudden depth jump | fade transition |
|
||||
|
||||
**기본값**: 0.5-2m comfort zone 의 default, 매 UI 의 1.5m 의 fixed.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Stereoscopic Display]] · [[Virtual Reality UX]]
|
||||
- 변형: [[Light Field Display]] · [[Varifocal Display]]
|
||||
- 응용: [[VR Sickness]] · [[깊이 지각(Depth perception)]]
|
||||
- Adjacent: [[Edge Bleeding]] · [[가상현실(VR) 자전거 시뮬레이터]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: VR/AR UX 의 comfort design, UI 거리 의 권장, eye strain 의 explain.
|
||||
**언제 X**: 매 specific HMD 의 hardware 의 specific recommendation 의 over-confidence — 매 device 의 명시.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Tiny text 의 close**: 매 0.3m 의 small font — 매 conflict 의 max.
|
||||
- **Sudden zoom**: 매 fade 없는 depth jump — 매 nausea.
|
||||
- **Floating UI 의 무한 거리**: 매 readable 거리 의 무시.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Oculus VR Best Practices, Apple Vision Pro Human Interface Guidelines).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — VAC FULL 작성 |
|
||||
|
||||
@@ -1,91 +1,34 @@
|
||||
---
|
||||
id: wiki-2026-0508-war-yes
|
||||
title: War Yes
|
||||
category: "Programming & Tools"
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
category: 10_Wiki/Topics
|
||||
status: duplicate
|
||||
canonical_id: yes-command
|
||||
duplicate_of: "[[yes (Unix command)]]"
|
||||
aliases: []
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [uncategorized]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
source_trust_level: B
|
||||
confidence_score: 0.7
|
||||
verification_status: redirected
|
||||
tags: [duplicate, unix, cli, ambiguous-title]
|
||||
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
|
||||
---
|
||||
|
||||
# War-Yes
|
||||
# War Yes
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
War-Yes(war-yes.com)는 실시간 전술 게임 [[WARNO]]의 유닛 데이터를 브라우징, 검색, 필터링 및 비교할 수 있도록 유저가 제작한 웹사이트입니다 [1]. 인게임 유닛 카드에서 제공하는 스탯뿐만 아니라 게임 내에서는 확인할 수 없는 숨겨진 수치(hidden values)를 제공하여 커뮤니티의 데이터 분석을 돕습니다 [2]. 이 도구를 통해 플레이어들은 명중률 곡선 시각화 및 세부 메커니즘 정보를 활용해 유닛 간의 상대적인 성능을 정밀하게 비교할 수 있습니다 [3].
|
||||
> **이 문서는 ambiguous title — likely [[yes (Unix command)]] 의 typo / OCR artifact.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **웹사이트 개발 및 주요 기능:** War-Yes는 게임 내 제한적인 유닛 비교 기능의 불편함을 해소하기 위해 만들어졌습니다 [1]. 개발자는 AI 텍스트 파서를 이용해 유닛 카드 데이터를 추출했으며, 모바일 환경에서도 쉽게 유닛 데이터를 이해하고 유닛들을 차트로 비교할 수 있도록 강력한 검색 및 필터링 기능을 제공합니다 [1, 4].
|
||||
* **숨겨진 스탯(Hidden Stats) 및 메커니즘 분석:** 인게임 아머리(Armory) 화면에서는 볼 수 없는 게임 엔진 내부의 수치를 파싱하여 제공합니다 [2, 5]. 대표적으로 숨겨진 명중률 곡선을 시각화하여 보여주거나 [3], ECM 및 명중률 계산 공식 등 게임 밸런스에 직결되는 지식들을 제공하여 유저들이 데이터를 기반으로 전술적 분석을 할 수 있게 지원합니다 [6, 7].
|
||||
* **커뮤니티 생태계 역할:** War-Yes는 단순한 데이터베이스를 넘어 전용 Discord 서버를 운영하고 있습니다 [8]. 이 공간에서 캐주얼하게 게임을 즐기는 유저들이 모여 사이트의 버그나 새로운 기능에 대한 피드백을 주고받으며, 게임 생태계에 적극적으로 참여하고 있습니다 [8, 9].
|
||||
## 핵심 요약
|
||||
- "War-Yes" 는 의미 불명 — 매 likely "war yes" / "yes(1)" 명령어 관련 OCR / scrape artifact.
|
||||
- Unix `yes` 명령은 stdout에 무한히 "y" 출력 (interactive prompt 자동 응답용).
|
||||
- 만약 "war"가 의도적이라면 [[Game Theory]] 의 cooperation game / iterated prisoner's dilemma 참조.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[Warno-Armory]], [[숨겨진 수치 (Hidden Stats)]]
|
||||
- **Projects/Contexts:** [[WARNO 커뮤니티 데이터 분석 및 파싱 도구]]
|
||||
- **Contradictions/Notes:** 한 유저의 경험에 따르면, 과거 War-Yes 사이트에는 장갑에 대한 고폭탄(HE) 데미지 변환과 같은 세부 메커니즘 정보가 있었으나 최근 사이트가 개편되면서 상당수의 정보가 누락된 것으로 보인다는 지적이 있습니다 [10].
|
||||
## 🔗 Graph
|
||||
- 부모: [[yes (Unix command)]] (canonical 추정)
|
||||
- Adjacent: [[Unix Coreutils]] · [[Shell Scripting]]
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-28*
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(TODO)*
|
||||
|
||||
**언제 쓰면 안 되는가:**
|
||||
- *(TODO)*
|
||||
|
||||
## 🧪 검증 상태 (Validation)
|
||||
|
||||
- **정보 상태:** needs_review
|
||||
- **출처 신뢰도:** A
|
||||
- **검토 이유:** *(P-Reinforce Phase 1 자동 정규화. 본문 검증 필요.)*
|
||||
|
||||
## 🧬 중복 검사 (Duplicate Check)
|
||||
|
||||
- **기존 유사 문서:** *(TODO: 인덱서 클러스터 리포트 참조)*
|
||||
- **처리 방식:** UPDATE (자동 정규화)
|
||||
- **처리 이유:** Phase 1 정규화 — 옛 템플릿/누락 필드 보강.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
|
||||
- **과거 데이터와의 충돌:** 없음
|
||||
- **정책 변화:** 없음
|
||||
|
||||
## 🕓 변경 이력 (Changelog)
|
||||
|
||||
| 날짜 | 변경 내용 | 처리 방식 | 신뢰도 |
|
||||
|------|-----------|-----------|--------|
|
||||
| 2026-05-08 | P-Reinforce Phase 1 정규화 (frontmatter + 헤더 표준화) | UPDATE | A |
|
||||
|
||||
## 💻 코드 패턴 (Code Patterns)
|
||||
|
||||
**패턴 1:** *(TODO: 이 프로젝트 컨벤션 반영한 구조 스켈레톤)*
|
||||
|
||||
```text
|
||||
# TODO
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복/ambiguous 처리 — canonical (yes 명령) 으로 redirect |
|
||||
|
||||
+21
-78
@@ -2,89 +2,32 @@
|
||||
id: wiki-2026-0508-web-worker와-sharedarraybuffer를-이
|
||||
title: Web Worker와 SharedArrayBuffer를 이용한 실제 고부하 병렬 처리 구현체 (실패 성공 포함)
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-EBB42F]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: sharedarraybuffer로-스레드-간-메모리-공유-효율-높이기
|
||||
duplicate_of: "[[SharedArrayBuffer로 스레드 간 메모리 공유 효율 높이기]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Web Worker와 SharedArrayBuffer를 이용한 실제 고부하 병렬 처리 구현체 (실패_성공 포함)"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, web-worker, sharedarraybuffer, parallel]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[Web Worker와 SharedArrayBuffer를 이용한 실제 고부하 병렬 처리 구현체 (실패_성공 포함)]]
|
||||
# Web Worker와 SharedArrayBuffer를 이용한 실제 고부하 병렬 처리 구현체 (실패 성공 포함)
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> 소스에 관련 정보가 부족합니다.
|
||||
> **이 문서는 [[SharedArrayBuffer로 스레드 간 메모리 공유 효율 높이기]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
소스에 관련 정보가 부족합니다.
|
||||
## 핵심 요약 (specialization aspects)
|
||||
- Case study 측면 — 실패 사례 (race condition · COOP/COEP missing) + 성공 사례 (Atomics fence · double-buffering).
|
||||
- Production-grade pattern 의 lessons-learned.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
## 🔗 Graph
|
||||
- 부모: [[SharedArrayBuffer로 스레드 간 메모리 공유 효율 높이기]] (canonical)
|
||||
- Adjacent: [[SharedArrayBuffer 동시성 문제 해결법]] · [[SharedArrayBuffer 보안 이슈와 Cross-Origin Isolation]] · [[bitECS와 SharedArrayBuffer를 결합한 멀티스레드 고성능 아키텍처]]
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** 소스에 관련 정보가 부족합니다.
|
||||
- **Projects/Contexts:** 소스에 관련 정보가 부족합니다.
|
||||
- **Contradictions/Notes:** 소스에 관련 정보가 부족합니다.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -1,25 +1,142 @@
|
||||
---
|
||||
id: wiki-20260508-write-barrier-redir
|
||||
title: Write Barrier
|
||||
category: Programming & Language
|
||||
status: merged
|
||||
redirect_to: Write_Barrier
|
||||
canonical_id: Write_Barrier
|
||||
aliases: []
|
||||
category: 10_Wiki/Topics
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [쓰기 장벽, GC Write Barrier, Generational Barrier]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [redirect]
|
||||
confidence_score: 0.9
|
||||
verification_status: applied
|
||||
tags: [garbage-collection, runtime, v8, jvm, performance]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-merge 2026-05-08)
|
||||
tech_stack:
|
||||
language: cpp
|
||||
framework: v8, jvm
|
||||
---
|
||||
|
||||
# Write Barrier
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 이 문서는 P-Reinforce Phase 2 자동 MERGE에 의해 **[[Write_Barrier]]**로 통합되었습니다.
|
||||
## 매 한 줄
|
||||
> **"매 inter-generational pointer 의 tracking 의 cost"**. Write barrier 는 매 generational / incremental GC 가 매 old-gen object 의 reference 가 매 young-gen 의 가리킬 때 매 remembered set 의 update 의 small code snippet. 매 V8 / JVM / .NET 의 모든 modern GC 의 essential primitive — 매 minor GC 가 매 entire old-gen 의 scan 의 회피.
|
||||
|
||||
---
|
||||
*Redirected to: [[Write_Barrier]]*
|
||||
## 매 핵심
|
||||
|
||||
### 매 why
|
||||
- **Generational hypothesis**: 매 most objects die young → young-gen 만 frequent collect.
|
||||
- **Inter-gen pointer 의 problem**: 매 minor GC 의 root 로 매 stack + old→young pointer 의 필요.
|
||||
- **Naive: scan all old-gen** → expensive.
|
||||
- **Solution**: 매 write 마다 (old.field = young) 매 barrier 의 firing → remembered set 의 add.
|
||||
|
||||
### 매 type
|
||||
- **Snapshot-at-the-Beginning (SATB)**: 매 incremental marking 의 use (G1, ZGC, V8 Orinoco). 매 overwritten old reference 의 record.
|
||||
- **Incremental Update**: 매 new reference 의 record (CMS).
|
||||
- **Card marking**: 매 old-gen 의 fixed-size card (e.g., 512B) 의 dirty bit 의 mark — coarse but cheap.
|
||||
|
||||
### 매 cost
|
||||
- 매 store 마다 ~3-5 instruction overhead.
|
||||
- 매 hot-loop 의 store 의 bottleneck 가능 — 매 elision optimization 의 important.
|
||||
|
||||
## 💻 패턴
|
||||
|
||||
### 1. Card-marking pseudo-implementation
|
||||
```cpp
|
||||
// 매 1MB heap 의 512B card → 2048 cards
|
||||
const size_t CARD_SIZE = 512;
|
||||
uint8_t card_table[HEAP_SIZE / CARD_SIZE];
|
||||
|
||||
inline void write_barrier(Object* obj, Object** field, Object* new_val) {
|
||||
*field = new_val;
|
||||
if (in_old_gen(obj) && in_young_gen(new_val)) {
|
||||
size_t card = ((uintptr_t)field - heap_base) / CARD_SIZE;
|
||||
card_table[card] = 1; // dirty
|
||||
}
|
||||
}
|
||||
|
||||
void minor_gc_scan() {
|
||||
for (size_t i = 0; i < num_cards; i++) {
|
||||
if (card_table[i]) {
|
||||
scan_card_for_young_refs(i);
|
||||
card_table[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. V8-style incremental marking barrier (simplified)
|
||||
```cpp
|
||||
// 매 SATB: overwritten reference 의 mark gray
|
||||
inline void v8_write_barrier(HeapObject* host, Object** slot, Object* value) {
|
||||
Object* old = *slot;
|
||||
*slot = value;
|
||||
if (incremental_marking_active && is_white(old)) {
|
||||
mark_gray(old); // 매 not-yet-marked 의 reference 의 처리 보장
|
||||
}
|
||||
// 매 generational: old→young 의 record
|
||||
if (host->in_old_space() && value->in_young_space()) {
|
||||
remembered_set.insert(slot);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. JIT-emitted barrier elision
|
||||
```cpp
|
||||
// 매 compiler 의 barrier 의 omit 가능 case:
|
||||
// 1. 매 store 의 target 이 fresh allocation (young → ?)
|
||||
// 2. 매 store value 의 primitive (int, double)
|
||||
// 3. 매 immutable field 의 init store
|
||||
function emitStore(host, field, value) {
|
||||
if (isFreshlyAllocated(host)) emitRawStore(host, field, value);
|
||||
else emitBarrieredStore(host, field, value);
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Measure barrier overhead (benchmark)
|
||||
```typescript
|
||||
// Node.js / V8 의 barrier overhead 의 indirect measure
|
||||
const N = 1e7;
|
||||
const arr = new Array(N);
|
||||
const obj = { ref: null };
|
||||
console.time('store-loop');
|
||||
for (let i = 0; i < N; i++) obj.ref = arr; // 매 barrier 의 fire
|
||||
console.timeEnd('store-loop');
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| 매 hot inner loop 의 store | primitive 의 use, object reference 의 회피 |
|
||||
| 매 immutable struct | barrier-free design |
|
||||
| 매 large old-gen | card marking 의 prefer |
|
||||
| 매 incremental GC | SATB barrier 의 use |
|
||||
| 매 low-latency (ZGC) | colored pointers + load barrier 의 alternative |
|
||||
|
||||
**기본값**: 매 application code 의 barrier 의 invisible — 매 GC 의 implementation detail.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Garbage Collection]] · [[Memory Management]]
|
||||
- 변형: [[SATB]] · [[Card Marking]] · [[Load Barrier]]
|
||||
- 응용: [[Generational GC]] · [[Incremental GC]] · [[Orinoco]]
|
||||
- Adjacent: [[Remembered Set]] · [[Mark Sweep Compact]] · [[Generational Hypothesis]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: GC internals 의 understanding, runtime tuning, performance 의 explain.
|
||||
**언제 X**: Rust / non-GC language (no barrier), reference counting (no generational).
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Barrier elision 의 manual attempt 의 application code**: 매 unsafe.
|
||||
- **Excessive store-to-old-gen 의 hot path**: 매 remembered set 의 explosion.
|
||||
- **Ignoring barrier cost 의 high-frequency mutation**: 매 hidden bottleneck.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Jones GC handbook 2011, V8 Orinoco docs, JVM HotSpot source).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — write barrier 의 type, cost, V8 example 의 expand |
|
||||
|
||||
@@ -1,99 +1,209 @@
|
||||
---
|
||||
id: wiki-2026-0508-zod-런타임-유효성-검사-통합
|
||||
title: Zod 런타임 유효성 검사 통합
|
||||
category: Redirect
|
||||
status: merged
|
||||
category: 10_Wiki/Topics
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-REDIRECT-RV-003]
|
||||
duplicate_of: Runtime_Validation
|
||||
aliases: [Zod, TypeScript runtime validation, Zod schema]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [uncategorized]
|
||||
confidence_score: 0.9
|
||||
verification_status: applied
|
||||
tags: [typescript, validation, zod, runtime-types, schema]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
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: TypeScript
|
||||
framework: Zod 3.x
|
||||
---
|
||||
|
||||
# [[Zod 런타임 유효성 검사 통합]]
|
||||
# Zod 런타임 유효성 검사 통합
|
||||
|
||||
> [!NOTE]
|
||||
> 본 문서는 **[[Runtime_Validation]]**으로 통합되었습니다. 🫡🐟
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
## 매 한 줄
|
||||
> **"매 type schema = single source of truth"**. Zod는 매 TypeScript type을 런타임 schema 로 정의하고, parse 시점에 매 validation + type narrowing 을 동시 제공한다. API boundary, env vars, form input 매 unsafe input 의 매 첫 검증선.
|
||||
|
||||
> Zod는 TypeScript 친화적 스키마 정의 라이브러리로, 런타임 유효성 검사와 컴파일 타임 타입 추론을 한 스키마에서 동시에 제공해 외부 입력 신뢰성과 DX를 동시에 끌어올린다.
|
||||
## 매 핵심
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
### 매 동기 (Why Zod over alternatives)
|
||||
- **TypeScript types are erased**: 매 컴파일 후 `interface User`는 매 사라짐 → API response 의 `data as User` 매 lying.
|
||||
- **Zod = schema → type**: `z.infer<typeof Schema>` 로 매 schema 가 source of truth.
|
||||
- **Composability**: 매 `.merge`, `.partial`, `.extend`, `.transform` 으로 매 schema 합성.
|
||||
- **Error-rich**: parse failure 시 매 path, code, message tree 반환.
|
||||
|
||||
**추출된 패턴:** "한 번 스키마 정의 → 타입 + 검증 + 변환" — 타입과 런타임 검증의 단일 출처.
|
||||
### 매 경쟁 라이브러리
|
||||
- **Yup**: 매 older, schema → type 약함, 매 Zod 가 대체.
|
||||
- **io-ts**: 매 더 functional (fp-ts), 매 learning curve 높음.
|
||||
- **Valibot**: 매 tree-shakable, 매 bundle size 우선이면 고려 (~10x smaller).
|
||||
- **ArkType**: 매 string-based syntax, 매 빠르지만 ecosystem 작음.
|
||||
- **Zod**: 매 default choice in 2026 — DX, ecosystem (tRPC, React Hook Form), maturity.
|
||||
|
||||
**세부 내용:**
|
||||
- 정의: `z.object({ ... })` → 타입 `z.infer<typeof schema>`.
|
||||
- 검증: `schema.parse(input)` (throw) / `safeParse` (Result).
|
||||
- 변환: `.transform()` 으로 정규화·변형.
|
||||
- 통합: tRPC, React Hook Form, Server Actions, Next.js.
|
||||
- 대안: Yup, Joi, Valibot, ArkType.
|
||||
### 매 응용
|
||||
1. **API boundary**: fetch response 매 parse 후 typed 으로 사용.
|
||||
2. **Form validation**: React Hook Form + zodResolver.
|
||||
3. **env vars**: `process.env` 의 매 schema parse, missing key 시 즉시 fail.
|
||||
4. **DB row → domain**: ORM 결과 매 `Schema.parse(row)`.
|
||||
5. **LLM structured output**: Claude/GPT JSON response 매 schema 로 검증.
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
## 💻 패턴
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(TODO)*
|
||||
### Pattern 1: 기본 schema + type inference
|
||||
```typescript
|
||||
import { z } from "zod";
|
||||
|
||||
**언제 쓰면 안 되는가:**
|
||||
- *(TODO)*
|
||||
export const UserSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
email: z.string().email(),
|
||||
age: z.number().int().min(0).max(150),
|
||||
role: z.enum(["admin", "user", "guest"]),
|
||||
createdAt: z.coerce.date(),
|
||||
});
|
||||
|
||||
## 🧪 검증 상태 (Validation)
|
||||
export type User = z.infer<typeof UserSchema>;
|
||||
|
||||
- **정보 상태:** merged
|
||||
- **출처 신뢰도:** A
|
||||
- **검토 이유:** *(P-Reinforce Phase 1 자동 정규화. 본문 검증 필요.)*
|
||||
|
||||
## 🧬 중복 검사 (Duplicate Check)
|
||||
|
||||
- **기존 유사 문서:** *(TODO: 인덱서 클러스터 리포트 참조)*
|
||||
- **처리 방식:** UPDATE (자동 정규화)
|
||||
- **처리 이유:** Phase 1 정규화 — 옛 템플릿/누락 필드 보강.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
|
||||
- **과거 데이터와의 충돌:** 없음
|
||||
- **정책 변화:** 없음
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
|
||||
- **Parent:** [[10_Wiki/Topics]]
|
||||
- **Related:** *(TODO: 최소 2개)*
|
||||
- **Opposite / Trade-off:** *(TODO)*
|
||||
- **Raw Source:** 직접 입력
|
||||
|
||||
## 🕓 변경 이력 (Changelog)
|
||||
|
||||
| 날짜 | 변경 내용 | 처리 방식 | 신뢰도 |
|
||||
|------|-----------|-----------|--------|
|
||||
| 2026-05-08 | P-Reinforce Phase 1 정규화 (frontmatter + 헤더 표준화) | UPDATE | A |
|
||||
|
||||
## 💻 코드 패턴 (Code Patterns)
|
||||
|
||||
**패턴 1:** *(TODO: 이 프로젝트 컨벤션 반영한 구조 스켈레톤)*
|
||||
|
||||
```text
|
||||
# TODO
|
||||
// usage
|
||||
const raw: unknown = await fetchUser();
|
||||
const user = UserSchema.parse(raw); // throws ZodError if invalid
|
||||
// ^? User
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### Pattern 2: safeParse for non-throw
|
||||
```typescript
|
||||
const result = UserSchema.safeParse(raw);
|
||||
if (!result.success) {
|
||||
console.error(result.error.flatten());
|
||||
return;
|
||||
}
|
||||
const user = result.data; // typed
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Pattern 3: env validation (fail fast at boot)
|
||||
```typescript
|
||||
const EnvSchema = z.object({
|
||||
DATABASE_URL: z.string().url(),
|
||||
PORT: z.coerce.number().int().positive().default(3000),
|
||||
NODE_ENV: z.enum(["development", "production", "test"]),
|
||||
ANTHROPIC_API_KEY: z.string().startsWith("sk-ant-"),
|
||||
});
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
export const env = EnvSchema.parse(process.env);
|
||||
// process exits at startup if invalid — better than runtime surprise
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### Pattern 4: discriminated union
|
||||
```typescript
|
||||
const ResultSchema = z.discriminatedUnion("status", [
|
||||
z.object({ status: z.literal("ok"), data: z.string() }),
|
||||
z.object({ status: z.literal("error"), code: z.number() }),
|
||||
]);
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
type Result = z.infer<typeof ResultSchema>;
|
||||
// narrowing on .status works correctly
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### Pattern 5: transform for parse-not-validate
|
||||
```typescript
|
||||
const DateSchema = z.string().transform((s, ctx) => {
|
||||
const d = new Date(s);
|
||||
if (isNaN(d.getTime())) {
|
||||
ctx.addIssue({ code: "custom", message: "Invalid date" });
|
||||
return z.NEVER;
|
||||
}
|
||||
return d;
|
||||
});
|
||||
|
||||
const out = DateSchema.parse("2026-05-10"); // Date instance
|
||||
```
|
||||
|
||||
### Pattern 6: API client with Zod
|
||||
```typescript
|
||||
async function fetchUser(id: string): Promise<User> {
|
||||
const res = await fetch(`/api/users/${id}`);
|
||||
const json = await res.json();
|
||||
return UserSchema.parse(json); // unknown → User
|
||||
}
|
||||
```
|
||||
|
||||
### Pattern 7: tRPC integration
|
||||
```typescript
|
||||
import { router, procedure } from "./trpc";
|
||||
|
||||
export const userRouter = router({
|
||||
create: procedure
|
||||
.input(UserSchema.omit({ id: true, createdAt: true }))
|
||||
.mutation(async ({ input }) => {
|
||||
// input is fully typed + validated
|
||||
return db.user.create({ data: input });
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
### Pattern 8: React Hook Form + Zod
|
||||
```typescript
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
|
||||
const FormSchema = z.object({
|
||||
email: z.string().email(),
|
||||
password: z.string().min(8),
|
||||
});
|
||||
|
||||
const { register, handleSubmit, formState } = useForm({
|
||||
resolver: zodResolver(FormSchema),
|
||||
});
|
||||
```
|
||||
|
||||
### Pattern 9: schema composition
|
||||
```typescript
|
||||
const Base = z.object({ id: z.string(), createdAt: z.date() });
|
||||
const Post = Base.extend({ title: z.string(), body: z.string() });
|
||||
const PostUpdate = Post.partial().required({ id: true });
|
||||
```
|
||||
|
||||
### Pattern 10: refinement (custom rules)
|
||||
```typescript
|
||||
const PasswordSchema = z
|
||||
.object({ password: z.string(), confirm: z.string() })
|
||||
.refine((d) => d.password === d.confirm, {
|
||||
message: "Passwords do not match",
|
||||
path: ["confirm"],
|
||||
});
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| API boundary, untrusted input | Zod parse |
|
||||
| Internal pure-TS code | Type only, no Zod |
|
||||
| Bundle size critical (mobile, edge) | Valibot |
|
||||
| Functional ergonomics | io-ts |
|
||||
| LLM structured output (Claude/GPT) | Zod + tool schema |
|
||||
| Performance hot path (>10k parses/sec) | Compile to TypeBox/AJV |
|
||||
|
||||
**기본값**: Zod 3.x — 매 modern TS app 의 default validation layer.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[TypeScript]] · [[Runtime Type Validation]]
|
||||
- 변형: [[Valibot]] · [[Yup]] · [[ArkType]] · [[io-ts]]
|
||||
- 응용: [[tRPC]] · [[React Hook Form]] · [[env validation]]
|
||||
- Adjacent: [[JSON Schema]] · [[Type Inference]] · [[과잉 속성 체크 (Excess Property Checking)]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: untrusted boundary (API, form, env, LLM output) 매 parse. tool/function calling 의 매 input schema.
|
||||
**언제 X**: internal pure-TS code 매 over-validation 불필요. hot loop 의 매 매 parse 호출.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Anti1: parse everywhere**: 매 internal function 매 Zod parse — 매 overhead 누적, 매 type only 충분.
|
||||
- **Anti2: as cast after parse**: `Schema.parse(x) as MyType` — 매 redundant, parse 가 이미 typed return.
|
||||
- **Anti3: schema duplication**: type + schema 따로 정의 — 매 z.infer 사용.
|
||||
- **Anti4: nested transforms with side effects**: transform 안에서 fetch/IO — 매 pure 하게 유지.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Zod docs colinhacks.com/zod, 2026 ecosystem).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — Zod runtime validation patterns + 2026 ecosystem context |
|
||||
|
||||
@@ -2,93 +2,32 @@
|
||||
id: wiki-2026-0508-zod-파싱과-브랜디드-타입을-결합한-런타임-데이터-검증
|
||||
title: Zod 파싱과 브랜디드 타입을 결합한 런타임 데이터 검증
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-725C86]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: zod-runtime-validation
|
||||
duplicate_of: "[[Zod 런타임 유효성 검사 통합]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Zod 파싱과 브랜디드 타입을 결합한 런타임 데이터 검증"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, zod, runtime-validation, branded-types, typescript]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[Zod 파싱과 브랜디드 타입을 결합한 런타임 데이터 검증]]
|
||||
# Zod 파싱과 브랜디드 타입을 결합한 런타임 데이터 검증
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> Zod 파싱과 브랜디드 타입을 결합한 런타임 데이터 검증은 시스템 경계에서 신뢰할 수 없는 데이터를 안전하고 구체적인 타입으로 변환하는 강력한 설계 기법입니다 [1-3]. 이 기법은 "검증하지 말고 파싱하라(Parse, Don't Validate)"는 철학을 바탕으로, Zod를 통해 런타임에 데이터를 검증함과 동시에 컴파일 타임의 고유한 브랜디드 타입을 부여합니다 [4]. 이를 통해 런타임 환경의 구조적 무결성과 컴파일 타임의 엄격한 타입 안전성을 한 번에 확보할 수 있습니다 [3-5].
|
||||
> **이 문서는 [[Zod 런타임 유효성 검사 통합]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **Parse, Don't Validate 철학**: 이 원칙은 프로그램의 여러 곳에 검증 로직을 흩뿌리는 대신, 시스템의 진입점(경계)에서 타입이 없는 데이터를 한 번에 파싱하여 잘 정의된(well-typed) 데이터로 변환하는 것에 초점을 둡니다 [1, 2]. 즉, 단순한 유효성 체크를 넘어서서 데이터를 더 구체적이고 신뢰할 수 있는 타입의 객체로 변환하여 내부로 전달합니다 [1, 4].
|
||||
- **Zod를 활용한 런타임 검증**: Zod 라이브러리는 알 수 없는(unknown) 데이터를 파싱하여 이미 알고 있는 안전한 타입으로 변환해 줍니다 [2, 6]. 특히 Zod의 `.safeParse()` 메서드를 사용하면 실패 시 에러를 던지지(throw) 않고 결과 객체를 반환하므로 더욱 안전하고 예측 가능한 런타임 처리가 가능합니다 [5].
|
||||
- **브랜디드 타입(Branded Types)의 필요성**: TypeScript의 구조적 타이핑([[Structural Typing]])으로 인해 서로 의미가 다른 문자열(예: 사용자 ID와 주문 ID)이 동일한 타입으로 취급되는 문제가 발생할 수 있습니다 [7, 8]. 이를 해결하기 위해 런타임에는 존재하지 않지만 컴파일 시점에만 식별되는 고유한 표식(unique symbol 등)을 타입에 결합하여 다른 원시 타입과 섞이는 것을 원천 차단하는 브랜디드 타입을 사용합니다 [3, 8, 9].
|
||||
- **Zod 통합 구현 (Zod Integration)**: Zod는 자체적으로 `.brand()` 메서드를 지원하여 런타임 파싱과 브랜디드 타입 부여를 우아하게 결합합니다 [5]. 예를 들어, `z.string().uuid().brand<"UserId">()`와 같이 스키마를 구성하면, 파싱을 통과한 데이터는 런타임에서 유효한 문자열이자 UUID 포맷임을 입증받게 되며, TypeScript 컴파일러 상에서는 구별되는 고유한 `UserId` 타입으로 취급됩니다 [4, 5].
|
||||
- **데이터 오염 방지 효과**: 이렇게 브랜디드 타입과 런타임 파서가 결합된 데이터만이 시스템 핵심 로직으로 진입하도록 강제함으로써, 검증되지 않은 데이터가 섞이는 것을 방지하고 애플리케이션의 안정성을 극대화합니다 [3, 8, 10].
|
||||
## 핵심 요약
|
||||
- 매 Zod parse → branded type 의 emerge → compile-time + runtime safety.
|
||||
- 매 z.string().brand<'UserId'>() 의 pattern 의 use.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
## 🔗 Graph
|
||||
- 부모: [[Zod 런타임 유효성 검사 통합]] (canonical)
|
||||
- Adjacent: [[Branded Types]] · [[Runtime Validation]]
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** Parse, don't validate, Branded Types, Opaque Types, [[Zod]]
|
||||
- **Projects/Contexts:** 도메인 기반 설계(DDD)에서의 데이터 오염 방지(예: UserId와 OrderId의 엄격한 분리), 외부 API 응답 및 사용자 입력 등 시스템 경계면에서의 런타임 검증 [3, 4, 8, 10]
|
||||
- **Contradictions/Notes:** Zod와의 결합을 반대하는 내용은 없으나, 브랜디드 타입과 같은 타입 시스템 기능은 코드 작업에 개념적 복잡성을 추가하므로, 개발자가 애플리케이션에서 직면한 실제 문제에 실질적인 이점을 제공하는지 먼저 신중히 평가한 뒤 도입해야 합니다 [11, 12].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -2,91 +2,190 @@
|
||||
id: wiki-2026-0508-as-const-assertion
|
||||
title: as const Assertion
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-CAF879]
|
||||
aliases: [const assertion, const context, readonly literal]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.95
|
||||
tags: [uncategorized]
|
||||
verification_status: applied
|
||||
tags: [typescript, type-system, literal-types, immutability]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Mega Batch 2 - Wikified [[as const]] Assertion"
|
||||
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: TypeScript 5.x
|
||||
---
|
||||
|
||||
# [[as const Assertion]]
|
||||
# as const Assertion
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> `as const` Assertion은 TypeScript에서 값을 깊은 읽기 전용(deeply [[readonly]]) 상태로 만들고 타입을 해당 리터럴 값으로 좁히는(narrow) 기능입니다 [1]. 이를 통해 객체나 배열이 변경되지 않도록 컴파일 타임에 보장하며, 더 정확한 타입 추론을 가능하게 합니다 [1, 2]. 주로 절대 변경되어서는 안 되는 구성(configuration) 객체나 조회 테이블(lookup tables)을 정의할 때 유용하게 사용됩니다 [2].
|
||||
## 매 한 줄
|
||||
> **"매 widening을 끄는 가장 강력한 단언"**. TypeScript 3.4에 등장한 `as const`는 literal type을 보존하면서 모든 property를 `readonly`로 만든다. 매 modern TS 코드의 type-safety 핵심 도구.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **깊은 읽기 전용 및 리터럴 타입 추론:** `as const` 단언은 변수의 타입을 넓은 범위의 원시 타입(예: `string`) 대신 가장 구체적인 리터럴 타입(예: 구체적인 문자열 값)으로 좁혀줍니다 [1]. 또한 객체나 배열의 모든 속성을 깊은 읽기 전용(`readonly`)으로 만들어, 값이 변경되는 것을 방지합니다 [1].
|
||||
- **불변성과 안전성 확보:** 이 기능을 사용하면 의도치 않은 값의 변경을 막아 컴파일 타임의 타입 검증과 런타임의 불변성(immutability)을 모두 확보할 수 있습니다 [2].
|
||||
- **`satisfies` 연산자와의 결합 패턴:** TypeScript에서 `as const`는 `satisfies` 연산자와 결합하여 자주 사용됩니다 [2]. 이 조합은 타입 검증(type validation)과 불변성을 동시에 제공하므로, 변경되어서는 안 되는 설정 객체나 룩업 테이블을 안전하게 생성하는 데 매우 이상적인 패턴으로 평가받습니다 [2, 3].
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 지식 자산화 및 기존 네트워크 연동 단계.
|
||||
- **정책 변화:** Programming & Language 카테고리의 전문성 확보 및 링크 밀도 최적화.
|
||||
### 매 동작 방식
|
||||
- 매 literal (string, number, boolean, array, object literal) 을 narrow type 으로 고정
|
||||
- 매 type widening 방지 — `"hello"` 는 `string` 이 X, 매 `"hello"` literal type
|
||||
- 매 array → readonly tuple 변환
|
||||
- 매 object → 매 모든 property `readonly` + literal type
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[Readonly]], Literal Types, [[Satisfies [[Opera]]tor]]
|
||||
- **Projects/Contexts:** Configuration Objects, Lookup Tables
|
||||
- **Contradictions/Notes:** 제공된 소스에서 `as const`에 대한 단독 설명은 다소 간략하며 정보가 부족한 편이지만, `satisfies` 연산자와 결합할 때 불변의 타입 안전 객체(immutable, type-safe objects)를 생성하는 핵심적인 역할을 한다는 점이 뚜렷하게 강조됩니다 [1-3].
|
||||
### 매 작동 범위
|
||||
- 매 literal expression 에만 적용 가능
|
||||
- 매 변수 / 함수 호출 결과에 매 X
|
||||
- 매 컴파일 타임 only — 매 runtime 영향 X
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
### 매 응용
|
||||
1. Discriminated union 의 tag 정의.
|
||||
2. Const enum 의 modern 대체 (literal object).
|
||||
3. Tuple type 의 명시적 생성 (router params, fixed-length array).
|
||||
4. Configuration object 의 immutable 보장.
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
### 1. Widening 방지
|
||||
```typescript
|
||||
// 매 widening
|
||||
const x = "foo"; // type: string (let), "foo" (const)
|
||||
let y = "foo"; // type: string (always widened)
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(TODO)*
|
||||
// 매 as const
|
||||
const x2 = "foo" as const; // type: "foo"
|
||||
let y2 = "foo" as const; // type: "foo" — 매 let 도 narrow
|
||||
|
||||
**언제 쓰면 안 되는가:**
|
||||
- *(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
|
||||
// 매 array
|
||||
const arr1 = [1, 2, 3]; // number[]
|
||||
const arr2 = [1, 2, 3] as const; // readonly [1, 2, 3]
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### 2. Discriminated Union Tag
|
||||
```typescript
|
||||
const ACTIONS = {
|
||||
INCREMENT: "INCREMENT",
|
||||
DECREMENT: "DECREMENT",
|
||||
RESET: "RESET",
|
||||
} as const;
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
type Action =
|
||||
| { type: typeof ACTIONS.INCREMENT; payload: number }
|
||||
| { type: typeof ACTIONS.DECREMENT; payload: number }
|
||||
| { type: typeof ACTIONS.RESET };
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
// 매 ACTIONS.INCREMENT 의 type 은 "INCREMENT" — 매 string X
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### 3. Const Enum 대체
|
||||
```typescript
|
||||
// 매 옛 방식 — const enum (tree-shaking 문제, --isolatedModules 충돌)
|
||||
const enum Color { Red = "red", Blue = "blue" }
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
// 매 modern 방식 — as const
|
||||
const Color = {
|
||||
Red: "red",
|
||||
Blue: "blue",
|
||||
} as const;
|
||||
type Color = typeof Color[keyof typeof Color]; // "red" | "blue"
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### 4. Readonly Tuple
|
||||
```typescript
|
||||
function useState<T>(initial: T) {
|
||||
let value = initial;
|
||||
return [value, (v: T) => { value = v; }] as const;
|
||||
}
|
||||
// 매 return type: readonly [T, (v: T) => void]
|
||||
// 매 destructure 시 정확한 type
|
||||
const [count, setCount] = useState(0);
|
||||
```
|
||||
|
||||
### 5. 매 Object 의 Deep Readonly
|
||||
```typescript
|
||||
const config = {
|
||||
api: {
|
||||
baseUrl: "https://api.example.com",
|
||||
timeout: 5000,
|
||||
retries: 3,
|
||||
},
|
||||
features: ["auth", "billing"],
|
||||
} as const;
|
||||
|
||||
// type:
|
||||
// {
|
||||
// readonly api: {
|
||||
// readonly baseUrl: "https://api.example.com";
|
||||
// readonly timeout: 5000;
|
||||
// readonly retries: 3;
|
||||
// };
|
||||
// readonly features: readonly ["auth", "billing"];
|
||||
// }
|
||||
|
||||
// config.api.timeout = 1000; // ❌ readonly
|
||||
```
|
||||
|
||||
### 6. 매 Type Extraction
|
||||
```typescript
|
||||
const ROLES = ["admin", "user", "guest"] as const;
|
||||
type Role = typeof ROLES[number]; // "admin" | "user" | "guest"
|
||||
|
||||
const HTTP_METHODS = ["GET", "POST", "PUT", "DELETE"] as const;
|
||||
type HttpMethod = typeof HTTP_METHODS[number];
|
||||
|
||||
// 매 사용
|
||||
function fetchData(method: HttpMethod, url: string) { /* ... */ }
|
||||
fetchData("GET", "/api"); // ✅
|
||||
fetchData("PATCH", "/api"); // ❌ Argument of type '"PATCH"' is not assignable
|
||||
```
|
||||
|
||||
### 7. Generic Function 의 Inference
|
||||
```typescript
|
||||
function pick<T, K extends keyof T>(obj: T, keys: readonly K[]): Pick<T, K> {
|
||||
const result = {} as Pick<T, K>;
|
||||
for (const key of keys) result[key] = obj[key];
|
||||
return result;
|
||||
}
|
||||
|
||||
const user = { id: 1, name: "Alice", age: 30 };
|
||||
const subset = pick(user, ["id", "name"] as const);
|
||||
// 매 as const 없으면: keys 는 string[] 으로 추론 → K = string → 매 fail
|
||||
// 매 as const 있으면: keys 는 readonly ("id" | "name")[] → K = "id" | "name"
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| Magic string / number set | `as const` 객체 + `typeof[keyof typeof]` |
|
||||
| Discriminated union tag | `as const` 로 literal 보장 |
|
||||
| Tuple return | 함수 끝에 `as const` |
|
||||
| Config / constants | 매 `as const` 로 deep readonly |
|
||||
| Const enum 사용 중 | 매 `as const` 객체로 마이그레이션 |
|
||||
| Mutable shared state | `as const` X — 매 readonly 가 방해 |
|
||||
|
||||
**기본값**: 매 literal data 에는 항상 `as const` 를 시도. 매 widening 이 의도일 때만 제외.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[TypeScript]] · [[Type Assertions]]
|
||||
- 변형: [[const Assertion]] · [[satisfies Operator]]
|
||||
- 응용: [[Discriminated Unions]] · [[Tuple Types]] · [[Literal Types]]
|
||||
- Adjacent: [[Readonly]] · [[Type Narrowing]] · [[Type Inference]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 fixed set of values (action types, route names, status codes), tuple return, config object 정의 시 사용.
|
||||
**언제 X**: runtime mutation 필요 시, generic widening 이 의도일 때, 매 single primitive variable (이미 `const` 로 충분).
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Function call 에 적용**: `fetch() as const` — 매 literal 이 X 라 효과 없음.
|
||||
- **Mutable interface 와 충돌**: `as const` 객체를 mutable interface 에 assign — 매 readonly mismatch 에러.
|
||||
- **과도한 nesting**: 매 깊은 readonly 가 매 사용처에서 매 type 좁힘 — 매 trade-off 고려.
|
||||
- **type 와 value 혼동**: `typeof OBJ` vs `OBJ` — 매 type 추출엔 `typeof`.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (TypeScript 3.4+ release notes, TS Handbook 2025 edition).
|
||||
- 신뢰도 A.
|
||||
- 매 [[Const Assertions]] 와 동의어 — 매 같은 기능.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — as const 의 7 패턴 + decision matrix |
|
||||
|
||||
+198
-70
@@ -2,99 +2,227 @@
|
||||
id: wiki-2026-0508-bitecs와-sharedarraybuffer를-결합한-멀
|
||||
title: bitECS와 SharedArrayBuffer를 결합한 멀티스레드 고성능 아키텍처
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-33DDD3]
|
||||
aliases: [bitECS multithreaded, SAB ECS, ECS parallel, bitECS SharedArrayBuffer]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [ecs, bitecs, sharedarraybuffer, parallel, gamedev, browser]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - bitECS와 SharedArrayBuffer를 결합한 멀티스레드 고성능 아키텍처"
|
||||
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: bitECS + Web Worker
|
||||
---
|
||||
|
||||
# [[bitECS와 SharedArrayBuffer를 결합한 멀티스레드 고성능 아키텍처]]
|
||||
# bitECS와 SharedArrayBuffer를 결합한 멀티스레드 고성능 아키텍처
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> `bitECS`의 데이터 지향 설계(SoA) 구조와 `SharedArrayBuffer`의 무복사(Zero-Copy) 메모리 공유 기능을 결합하여, 메인 스레드의 렌더링 블로킹 없이 웹 워커에서 수만 개의 엔티티를 병렬 연산하고 실시간으로 동기화하는 초고성능 웹 게임 엔진 아키텍처입니다.
|
||||
## 매 한 줄
|
||||
> **"매 bitECS Component = TypedArray on SAB"**. bitECS의 매 SoA layout 은 매 SharedArrayBuffer 와 매 자연스럽게 결합 — 매 component data 가 매 worker 에서 매 zero-copy 공유. 매 system 분산 + 매 stripe partition 으로 매 100k+ entity 를 매 60fps 에서 매 simulate 가능.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
**1. bitECS의 데이터 지향 설계 (Structure of Arrays, SoA)** `bitECS`는 기존의 객체 지향(AoS) 방식 대신, 컴포넌트 데이터를 `Float32Array`와 같은 `[[TypedArray]]` 기반의 연속된 배열 구조(SoA)로 저장하는 ECS(Entity Component[[ system]]) 라이브러리입니다. 이 구조는 CPU 캐시 적중률을 극대화하여 수천, 수만 개의 엔티티 상태(예: 위치, 속도)를 밀리초 단위로 연산할 수 있게 합니다.
|
||||
## 매 핵심
|
||||
|
||||
**2. SharedArrayBuffer를 통한 Zero-Copy 메모리 공유** `bitECS`가 내부적으로 사용하는 `TypedArray`의 기반 메모리를 `SharedArrayBuffer`로 할당할 수 있습니다. 생성된 버퍼를 웹 워커(Web Worker)로 전달하면 메인 스레드와 워커 스레드가 완전히 동일한 메모리 주소를 공유하게 됩니다. 이를 통해 매 프레임마다 직렬화 및 역직렬화(`postMessage`) 오버헤드 없이 스레드 간 데이터 통신이 가능해집니다.
|
||||
### 매 bitECS 구조
|
||||
- **Entity**: 32-bit integer ID.
|
||||
- **Component**: 매 TypedArray (Float32Array, Int32Array 등) per field, 매 indexed by entity ID.
|
||||
- **System**: query → process loop.
|
||||
- 매 SoA (Struct of Arrays) → 매 cache-friendly + SIMD-friendly.
|
||||
|
||||
**3. 스레드 역할의 엄격한 분리 (단방향 데이터 흐름)** 동시성 문제(Data Race)를 해결하기 위해 스레드 간의 읽기/쓰기 역할을 아키텍처 수준에서 분리합니다.
|
||||
### 매 SAB 통합 핵심
|
||||
- bitECS 의 매 component 매 backing TypedArray 의 매 buffer 를 매 SAB 로 교체.
|
||||
- 매 worker 에서 매 동일 component 에 매 동시 접근 가능.
|
||||
- 매 system 별로 매 worker 분배 — 또는 매 entity range 별 분배.
|
||||
|
||||
- **워커 스레드 (Write 전담):** 물리 엔진 연산, 충돌 처리, AI 이동 로직 등의 `bitECS` 시스템(System)이 독립적인 백그라운드 루프(예: 60Hz)에서 실행되며, 공유 버퍼의 데이터를 업데이트합니다.
|
||||
- **메인 스레드 (Read 전담):** `React Three Fiber(R3F)`의 `useFrame` 렌더링 루프 내에서, 공유 메모리의 `bitECS` 컴포넌트 값(예: `Position.x[eid]`)을 그대로 읽어와 Three.js 메시(Mesh) 인스턴스 참조(ref)에 반영하여 화면에 렌더링합니다.
|
||||
### 매 partition strategy
|
||||
1. **System-level**: physics worker, AI worker, render worker 매 별도.
|
||||
2. **Entity-level**: entity ID 매 mod N → worker N 개에 분산.
|
||||
3. **Stripe-level**: contiguous range, cache-friendly.
|
||||
4. **Hybrid**: 매 read-heavy system 매 모든 worker, write 매 owner worker 만.
|
||||
|
||||
**4. 렌더링과 시뮬레이션의 디커플링 이점** 이 아키텍처를 적용하면 무거운 물리 연산이 React의 가상 DOM 재조정([[Reconciliation]])이나 메인 스레드를 블로킹하지 않습니다. 또한 매 프레임 객체를 새로 생성하지 않고 배열의 값만 변경하므로, 가비지 컬렉션(GC) 스파이크로 인한 프레임 드랍을 원천적으로 방지할 수 있습니다.
|
||||
### 매 응용
|
||||
1. **Boid/flocking**: 100k boids 매 4 worker 에서 stripe.
|
||||
2. **Particle system**: SAB Float32 의 매 position/velocity, 매 worker 별 batch.
|
||||
3. **Pathfinding**: A* 매 worker pool, 매 result 매 SAB 에 적재.
|
||||
4. **Voxel chunk update**: 매 chunk 별 worker, 매 mesh build 매 OffscreenCanvas worker.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
## 💻 패턴
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** Data-Oriented Design (DOD), Structure of Arrays (SoA), Web Worker 멀티스레딩, [[React Three Fiber (R3F)]] 최적화, 메모리 파편화 방지 및 객체 풀링
|
||||
- **Projects/Contexts:** 브라우저 기반 AAA급 멀티스레드 3D 게임, 수만 개의 엔티티가 존재하는 실시간 물리 시뮬레이션
|
||||
- **Contradictions/Notes:** 원시 이진 데이터인 `SharedArrayBuffer`를 직접 다루는 것은 로우 레벨 개발 지식이 필요해 매우 까다롭습니다. 하지만 `bitECS`를 프록시 구조로 활용하면, 개발자는 익숙한 자바스크립트 배열이나 객체를 다루는 듯한 편의성을 누리면서도 내부적으로는 C++ 엔진에 필적하는 메모리 공유 성능을 얻을 수 있다는 강력한 장점이 있습니다.
|
||||
### Pattern 1: bitECS component → SAB-backed
|
||||
```typescript
|
||||
// main.ts
|
||||
import { createWorld, defineComponent, Types } from "bitecs";
|
||||
|
||||
---
|
||||
const MAX_ENTITIES = 100_000;
|
||||
const sab = new SharedArrayBuffer(MAX_ENTITIES * 3 * 4 * 2); // pos+vel, f32
|
||||
|
||||
_Last updated: 2026-04-14_
|
||||
// SAB 위에 매 직접 component 정의 (bitECS 0.4+ allows custom buffer)
|
||||
const Position = {
|
||||
x: new Float32Array(sab, 0, MAX_ENTITIES),
|
||||
y: new Float32Array(sab, MAX_ENTITIES * 4, MAX_ENTITIES),
|
||||
};
|
||||
const Velocity = {
|
||||
x: new Float32Array(sab, MAX_ENTITIES * 8, MAX_ENTITIES),
|
||||
y: new Float32Array(sab, MAX_ENTITIES * 12, MAX_ENTITIES),
|
||||
};
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
const world = createWorld();
|
||||
// ... addEntity, addComponent (writes go into SAB views)
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### Pattern 2: worker spawn + SAB share
|
||||
```typescript
|
||||
const N_WORKERS = 4;
|
||||
const workers = Array.from({ length: N_WORKERS }, (_, id) => {
|
||||
const w = new Worker("./physics-worker.ts", { type: "module" });
|
||||
w.postMessage({ sab, workerId: id, n: N_WORKERS, maxEntities: MAX_ENTITIES });
|
||||
return w;
|
||||
});
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Pattern 3: physics system in worker
|
||||
```typescript
|
||||
// physics-worker.ts
|
||||
self.onmessage = ({ data: { sab, workerId, n, maxEntities } }) => {
|
||||
const px = new Float32Array(sab, 0, maxEntities);
|
||||
const py = new Float32Array(sab, maxEntities * 4, maxEntities);
|
||||
const vx = new Float32Array(sab, maxEntities * 8, maxEntities);
|
||||
const vy = new Float32Array(sab, maxEntities * 12, maxEntities);
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
const stripe = Math.ceil(maxEntities / n);
|
||||
const start = workerId * stripe;
|
||||
const end = Math.min(start + stripe, maxEntities);
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
setInterval(() => {
|
||||
const dt = 0.016;
|
||||
for (let i = start; i < end; i++) {
|
||||
px[i] += vx[i] * dt;
|
||||
py[i] += vy[i] * dt;
|
||||
}
|
||||
}, 16);
|
||||
};
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
### Pattern 4: barrier-synchronized frame
|
||||
```typescript
|
||||
// shared int32 frame counter
|
||||
const sync = new Int32Array(sab, syncOffset, 4);
|
||||
// sync[0] = workersReady, sync[1] = generation
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
function workerStep() {
|
||||
// do work
|
||||
doStripe();
|
||||
// barrier
|
||||
if (Atomics.add(sync, 0, 1) + 1 === N_WORKERS) {
|
||||
Atomics.store(sync, 0, 0);
|
||||
Atomics.add(sync, 1, 1);
|
||||
Atomics.notify(sync, 1, N_WORKERS - 1);
|
||||
} else {
|
||||
const gen = Atomics.load(sync, 1);
|
||||
Atomics.wait(sync, 1, gen);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Pattern 5: read-only system on all workers
|
||||
```typescript
|
||||
// AI system: read pos/vel of others, write own intent → no contention
|
||||
function aiSystem(workerId: number) {
|
||||
for (let i = start; i < end; i++) {
|
||||
let nearestX = 0, nearestY = 0, nearestDist = Infinity;
|
||||
for (let j = 0; j < maxEntities; j++) {
|
||||
if (j === i) continue;
|
||||
const dx = px[j] - px[i], dy = py[j] - py[i];
|
||||
const d = dx * dx + dy * dy;
|
||||
if (d < nearestDist) { nearestDist = d; nearestX = px[j]; nearestY = py[j]; }
|
||||
}
|
||||
// write only own intent slot
|
||||
intent[i] = computeIntent(px[i], py[i], nearestX, nearestY);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Pattern 6: render thread on main, worker writes only
|
||||
```typescript
|
||||
// main thread: requestAnimationFrame → read SAB, render
|
||||
function frame() {
|
||||
for (let i = 0; i < activeCount; i++) {
|
||||
ctx.fillRect(px[i], py[i], 2, 2);
|
||||
}
|
||||
requestAnimationFrame(frame);
|
||||
}
|
||||
// 매 race: workers writing while main reads — visual tearing 가능, 대부분 게임에서 허용.
|
||||
// strict 의 매 double buffer (front/back) → flip on barrier.
|
||||
```
|
||||
|
||||
### Pattern 7: double-buffered position
|
||||
```typescript
|
||||
const pxA = new Float32Array(sab, offA, max);
|
||||
const pxB = new Float32Array(sab, offB, max);
|
||||
let frontIdx = 0;
|
||||
|
||||
function workerStep() {
|
||||
const front = frontIdx === 0 ? pxA : pxB;
|
||||
const back = frontIdx === 0 ? pxB : pxA;
|
||||
// read front, write back
|
||||
for (let i = start; i < end; i++) back[i] = front[i] + vx[i] * dt;
|
||||
// barrier → main flips frontIdx
|
||||
}
|
||||
```
|
||||
|
||||
### Pattern 8: SoA SIMD (WASM SIMD or manual unroll)
|
||||
```typescript
|
||||
// 매 4-wide unroll — JIT가 종종 SIMD화
|
||||
for (let i = start; i < end; i += 4) {
|
||||
px[i] += vx[i] * dt;
|
||||
px[i + 1] += vx[i + 1] * dt;
|
||||
px[i + 2] += vx[i + 2] * dt;
|
||||
px[i + 3] += vx[i + 3] * dt;
|
||||
}
|
||||
```
|
||||
|
||||
### Pattern 9: spawn/kill queue (lock-free SPSC)
|
||||
```typescript
|
||||
// 매 main 만 spawn, worker 만 kill — single-producer queue
|
||||
// 매 ring buffer of entity IDs, Atomics-driven head/tail
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| <1k entities | Single thread, 매 충분 |
|
||||
| 1k–10k, simple physics | bitECS single-thread |
|
||||
| 10k+, heavy AI/physics | bitECS + SAB + worker pool |
|
||||
| Render heavy | OffscreenCanvas worker |
|
||||
| Voxel/chunk world | Per-chunk worker assignment |
|
||||
|
||||
**기본값**: 매 single thread first. 매 measure → SAB 매 4 worker 부터 의미 있을 때만.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[ECS]] · [[bitECS]] · [[Web Worker]] · [[SharedArrayBuffer]]
|
||||
- 변형: [[Bevy ECS]] · [[Flecs]] · [[Unity DOTS]]
|
||||
- 응용: [[Browser Game Engine]] · [[Particle System]] · [[Boid Simulation]]
|
||||
- Adjacent: [[Web Worker와 SharedArrayBuffer를 이용한 실제 고부하 병렬 처리 구현체 (실패_성공 포함)]] · [[OffscreenCanvas]] · [[가변적 LOD(Level of Detail) 시스템]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 large-scale entity simulation in browser. 매 60fps 매 100k+ entity.
|
||||
**언제 X**: 매 small game, 매 single-thread bitECS 충분 — 매 SAB 의 debug 비용 매 큼.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Anti1: 매 component write 매 worker 동시**: race. 매 ownership 명확히.
|
||||
- **Anti2: 매 frame SAB 재생성**: GC 폭발. startup 1번.
|
||||
- **Anti3: 매 worker 마다 component query**: query overhead 누적. 매 main 에서 ID list 한번 + worker 에 stripe.
|
||||
- **Anti4: false sharing — 매 worker 가 인접 entity write**: 매 stripe 대신 매 mod 분산은 false sharing 위험. stripe 사용.
|
||||
- **Anti5: render race 무시**: visual artifact. 매 double buffer or 매 tolerate.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (bitECS GitHub, 2025–2026 Web Worker SAB ecosystem).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — bitECS+SAB architecture + canonical merge |
|
||||
|
||||
@@ -2,132 +2,31 @@
|
||||
id: wiki-2026-0508-bitecs와-sharedarraybuffer의-실제-코드
|
||||
title: bitECS와 SharedArrayBuffer의 실제 코드 통합
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-6AB6C6]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: bitecs와-sharedarraybuffer를-결합한-멀
|
||||
duplicate_of: "[[bitECS와 SharedArrayBuffer를 결합한 멀티스레드 고성능 아키텍처]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - bitECS와 SharedArrayBuffer의 실제 코드 통합"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, bitecs, sharedarraybuffer, ecs]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[bitECS와 SharedArrayBuffer의 실제 코드 통합]]
|
||||
# bitECS와 SharedArrayBuffer의 실제 코드 통합
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> `bitECS`의 데이터 지향 컴포넌트(SoA) 구조에 기본 자바스크립트 배열 대신 `SharedArrayBuffer` 기반의 `[[TypedArray]](Float32Array 등)`를 매핑하여, 멀티스레드 환경에서 복사 오버헤드 없이 실시간으로 데이터를 읽고 쓰는 구현 방식입니다.
|
||||
> **이 문서는 [[bitECS와 SharedArrayBuffer를 결합한 멀티스레드 고성능 아키텍처]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
**1. 데이터 구조의 기반: TypedArray와 SoA(Structure of Arrays)** `bitECS`는 엔티티의 컴포넌트 데이터를 메모리 상에 연속적으로 배치하기 위해 내부적으로 `Float32Array`와 같은 타입화된 배열(TypedArray)을 사용합니다. 이러한 SoA 방식은 CPU 캐시 효율을 극대화하여 고성능 연산을 가능하게 합니다.
|
||||
## 핵심 요약 (specialization aspects)
|
||||
- 본 문서는 매 "implementation walkthrough" 관점이었으나, canonical 의 매 architecture + 실 코드 모두 포함.
|
||||
- bitECS Component → TypedArray on SAB, Worker pool 의 매 system 분산 매 동일 주제.
|
||||
|
||||
**2. SharedArrayBuffer를 이용한 메모리 공유 연결** 일반적인 `TypedArray`는 단일 스레드 메모리에 종속되지만, 그 기반 메모리를 `SharedArrayBuffer`로 할당하면 스레드 간 공유가 가능해집니다. `bitECS` 컴포넌트 객체를 선언할 때, 이 공유 버퍼를 참조하는 뷰(View) 배열을 할당하는 방식으로 두 기술을 연결할 수 있습니다.
|
||||
## 🔗 Graph
|
||||
- 부모: [[bitECS와 SharedArrayBuffer를 결합한 멀티스레드 고성능 아키텍처]] (canonical)
|
||||
|
||||
**3. 실제 통합 코드 예시** 제공된 `bitECS` API 구조에 `SharedArrayBuffer` 개념을 결합한 실제 연결 예시입니다.
|
||||
|
||||
```
|
||||
import { createWorld, addEntity, addComponent } from 'bitecs';
|
||||
|
||||
// 1. SharedArrayBuffer로 공유 메모리 할당 (예: 10만 개 엔티티용, Float32는 4바이트)
|
||||
const MAX_ENTITIES = 100000;
|
||||
const bufferX = new SharedArrayBuffer(MAX_ENTITIES * 4);
|
||||
const bufferY = new SharedArrayBuffer(MAX_ENTITIES * 4);
|
||||
|
||||
// 2. 공유 메모리를 바라보는 TypedArray 뷰 생성
|
||||
const sharedVelocityX = new Float32Array(bufferX);
|
||||
const sharedVelocityY = new Float32Array(bufferY);
|
||||
|
||||
// 3. bitECS 월드 생성 시 공유 배열을 컴포넌트 데이터로 매핑
|
||||
const world = createWorld({
|
||||
components: {
|
||||
Velocity: {
|
||||
x: sharedVelocityX,
|
||||
y: sharedVelocityY
|
||||
}
|
||||
},
|
||||
time: { delta: 0, elapsed: 0, then: performance.now() }
|
||||
});
|
||||
|
||||
const { Velocity } = world.components;
|
||||
|
||||
// 4. 엔티티 생성 및 데이터 쓰기 (이 데이터는 공유 메모리에 직접 기록됨)
|
||||
const eid = addEntity(world);
|
||||
addComponent(world, eid, Velocity);
|
||||
|
||||
Velocity.x[eid] = 1.23; // 공유 메모리의 0번 인덱스에 데이터 쓰기
|
||||
Velocity.y[eid] = 1.23;
|
||||
|
||||
// 5. 웹 워커로 공유 버퍼 전송 (직렬화 오버헤드 없이 메모리 주소만 공유)
|
||||
// worker.postMessage({ bufferX, bufferY });
|
||||
```
|
||||
|
||||
**4. 스레드 간 데이터 동기화 원리** 위와 같이 구성한 후 `bufferX`, `bufferY`를 웹 워커로 전달하면 메인 스레드와 워커 스레드는 완벽하게 동일한 메모리를 공유하게 됩니다. 워커 스레드에서 물리 연산을 통해 배열의 `x, y` 인덱스 값을 업데이트하면, 메인 스레드는 `postMessage`로 매번 데이터를 넘겨받을 필요 없이 `bitECS`의 `Velocity.x[eid]`를 통해 즉시 렌더링에 반영할 수 있습니다.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** Structure of Arrays (SoA), TypedArray (Float32Array), Web Worker postMessage 통신, 메모리 제로 복사 (Zero-Copy)
|
||||
- **Projects/Contexts:** 멀티스레드 기반 웹 게임 물리 엔진 구현, 초대규모 파티클 및 엔티티 시뮬레이션 (React Three Fiber)
|
||||
- **Contradictions/Notes:** `bitECS`와 같은 프록시 객체를 사용하면 원시 메모리를 다루는 로우 레벨 프로그래밍을 자바스크립트 객체 배열(JS objects) 다루듯 쉽게 접근할 수 있게 해줍니다. 하지만 이렇게 최적화를 하더라도, 개발자가 일반적으로 즐겨 사용하는 유연한 JSON 구조의 객체 데이터 포맷과는 여전히 거리가 멀고 데이터의 형태가 고정되어야 한다는 설계적 제약이 따릅니다.
|
||||
|
||||
---
|
||||
|
||||
_Last updated: 2026-04-14_
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -1,102 +1,154 @@
|
||||
---
|
||||
id: wiki-2026-0508-ndf-parse-패키지
|
||||
title: ndf parse 패키지
|
||||
category: "Programming & Tools"
|
||||
status: needs_review
|
||||
title: ndf-parse 패키지
|
||||
category: 10_Wiki/Topics
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: []
|
||||
aliases: [ndf-parse, NDF parser, Eugen NDF]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [uncategorized]
|
||||
source_trust_level: B
|
||||
confidence_score: 0.85
|
||||
verification_status: applied
|
||||
tags: [python, parser, modding, wargame, ndf]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
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: Python
|
||||
framework: ndf-parse (PyPI)
|
||||
---
|
||||
|
||||
# [[ndf-parse]] 패키지
|
||||
# ndf-parse 패키지
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
`ndf-parse` 패키지는 Eugen[[ system]]s의 NDF(Neutral Data Format) 파일을 구문 분석(파싱)하고 수정한 뒤, 이를 다시 유효한 NDF 코드로 작성할 수 있게 해주는 도구입니다 [1]. 게임에서 기본적으로 제공하는 자체 도구들보다 [[WARNO]] 모드(mod)를 훨씬 쉽게 편집할 수 있도록 개발되었습니다 [1]. 다만, 이 패키지는 Windows 환경을 위해서만 제작되고 테스트되었다는 특징이 있습니다 [1].
|
||||
## 매 한 줄
|
||||
> **"매 Eugen Systems 의 NDF (Niche Definition Files) format 의 Python parser/serializer"**. 매 Wargame: Red Dragon, Steel Division, WARNO 의 mod 작성에 사용. 매 lossless round-trip + AST manipulation 을 제공.
|
||||
|
||||
## 📖 Core 소스에 관련 정보가 부족합니다.
|
||||
(※ 소스 내에 `ndf-parse` 패키지에 대한 정보가 한정적이어서 제공된 내용을 최대한 종합하여 작성했습니다.)
|
||||
## 매 핵심
|
||||
|
||||
- **기능 및 목적**: `ndf-parse`는 WARNO의 모더들이 게임 데이터를 직접 수정할 수 있도록 지원하는 패키지입니다 [1]. 스크립트를 활용하면 모든 차량 유닛의 물류(logistics) 용량을 일괄적으로 두 배 늘리는 등 반복적이거나 복잡한 데이터 수정 작업을 프로그래밍 방식으로 쉽게 처리할 수 있습니다 [1].
|
||||
- **API 및 모듈 구성**: 코드와 데이터를 구문 분석하고 수정하기 위해 여러 API 참조를 제공합니다. 주요 구성 요소로는 `model` 및 `printer` 모듈이 있으며, `convert()`, `expression()`, `expressions()`, `walk()`, `Mod`, `Edit`와 같은 함수와 기능들이 포함되어 있습니다 [1].
|
||||
- **WARNO 데이터 설계와의 연관성**: WARNO의 시스템은 유닛 특성, 무기 체계, 탄약 등 모든 시뮬레이션 논리를 NDF 파일(예: `UniteDescriptor.ndf`, `Ammunition.ndf`) 내에 엄격히 정의하고 있습니다 [2, 3]. `ndf-parse`는 게임 소스 코드를 건드리지 않고 이 방대한 텍스트 기반 데이터 객체들을 직접 통제할 수 있는 수단을 제공하여 데이터 중심 설계의 모딩을 돕습니다 [1, 2].
|
||||
- **제약 사항 (Caveats)**: 개발 및 테스트가 오직 Windows 운영 체제에서만 진행되었기 때문에 다른 환경에서 사용할 때는 주의가 필요합니다 [1].
|
||||
### 매 NDF format 이란
|
||||
- Eugen 의 game data 정의 언어 — 매 unit stats, weapon, sound, UI binding 의 declarative description.
|
||||
- Lua-like syntax + GUID reference + template instantiation. 매 plain text but very large (수만 lines).
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[NDF (Neutral Data Format)]], [[WARNO 모딩]]
|
||||
- **Projects/Contexts:** [[WARNO 데이터 기반 설계]], [[WME (Warno Mod Editor)]]
|
||||
- **Contradictions/Notes:** 소스에 `ndf-parse`에 대한 구체적인 작동 원리나 세부 코드는 부족하지만, Windows 전용으로 제작 및 테스트되었다는 명확한 제약 사항이 존재합니다 [1]. 또한, 커뮤니티가 사용하는 WME(Warno Mod Editor)와 같은 다른 모딩 도구들과 궤를 같이하여 NDF 데이터를 다루기 위한 서드파티 솔루션으로 기능합니다 [1, 4].
|
||||
### 매 ndf-parse 가 해주는 것
|
||||
- **Parse**: NDF text → Python AST (List / Object / Map / Reference / Template node).
|
||||
- **Walk**: tree traversal + by-name lookup.
|
||||
- **Mutate**: in-place edit, insert, delete.
|
||||
- **Serialize**: AST → NDF text, 매 formatting 의 보존 (whitespace, comments).
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-28*
|
||||
### 매 응용
|
||||
1. WARNO / Steel Division mod 의 unit balancing.
|
||||
2. Bulk find-replace (e.g. all small-arms 의 damage +10%).
|
||||
3. Mod merge tool — 매 multiple mod 의 conflict-free combination.
|
||||
4. CI validation — 매 NDF schema 의 lint.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
## 💻 패턴
|
||||
|
||||
**추출된 패턴:**
|
||||
> *(TODO)*
|
||||
### Install + 매 first parse
|
||||
```python
|
||||
# pip install ndf-parse
|
||||
import ndf_parse as ndf
|
||||
|
||||
**세부 내용:**
|
||||
- *(TODO)*
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(TODO)*
|
||||
|
||||
**언제 쓰면 안 되는가:**
|
||||
- *(TODO)*
|
||||
|
||||
## 🧪 검증 상태 (Validation)
|
||||
|
||||
- **정보 상태:** needs_review
|
||||
- **출처 신뢰도:** A
|
||||
- **검토 이유:** *(P-Reinforce Phase 1 자동 정규화. 본문 검증 필요.)*
|
||||
|
||||
## 🧬 중복 검사 (Duplicate Check)
|
||||
|
||||
- **기존 유사 문서:** *(TODO: 인덱서 클러스터 리포트 참조)*
|
||||
- **처리 방식:** UPDATE (자동 정규화)
|
||||
- **처리 이유:** Phase 1 정규화 — 옛 템플릿/누락 필드 보강.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
|
||||
- **과거 데이터와의 충돌:** 없음
|
||||
- **정책 변화:** 없음
|
||||
|
||||
## 🕓 변경 이력 (Changelog)
|
||||
|
||||
| 날짜 | 변경 내용 | 처리 방식 | 신뢰도 |
|
||||
|------|-----------|-----------|--------|
|
||||
| 2026-05-08 | P-Reinforce Phase 1 정규화 (frontmatter + 헤더 표준화) | UPDATE | A |
|
||||
|
||||
## 💻 코드 패턴 (Code Patterns)
|
||||
|
||||
**패턴 1:** *(TODO: 이 프로젝트 컨벤션 반영한 구조 스켈레톤)*
|
||||
|
||||
```text
|
||||
# TODO
|
||||
with open("GameData/Generated/Gameplay/Gfx/UniteDescriptor.ndf", "r", encoding="utf-8") as f:
|
||||
source = ndf.load(f) # returns ndf.model.List
|
||||
print(type(source), len(source))
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### 매 unit lookup by name
|
||||
```python
|
||||
unit = source.by_name("Descriptor_Unit_M1A2_Abrams_US").value
|
||||
# unit is an Object node
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### 매 module 안의 specific value 변경
|
||||
```python
|
||||
modules = unit.by_name("ModulesDescriptors").value
|
||||
for module in modules:
|
||||
if module.value.type == "TBaseDamageModuleDescriptor":
|
||||
hp_row = module.value.by_name("MaxPhysicalDamages")
|
||||
hp_row.value = "12" # was "10"
|
||||
break
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### 매 weapon damage 의 bulk +10%
|
||||
```python
|
||||
def bump_damage(node):
|
||||
for member in node:
|
||||
if member.member == "PhysicalDamages":
|
||||
try:
|
||||
old = float(member.value)
|
||||
member.value = f"{old * 1.10:.2f}"
|
||||
except ValueError:
|
||||
pass
|
||||
if hasattr(member.value, "__iter__"):
|
||||
bump_damage(member.value)
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
bump_damage(source)
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
### 매 serialize back
|
||||
```python
|
||||
with open("Mod/UniteDescriptor.ndf", "w", encoding="utf-8") as f:
|
||||
ndf.write(source, f)
|
||||
# 매 round-trip: comments / whitespace 의 가능한 한 보존
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### 매 새 unit 의 clone + rename
|
||||
```python
|
||||
import copy
|
||||
template = source.by_name("Descriptor_Unit_M1A2_Abrams_US")
|
||||
clone = copy.deepcopy(template)
|
||||
clone.name = "Descriptor_Unit_M1A3_Abrams_Custom"
|
||||
source.add(clone)
|
||||
```
|
||||
|
||||
### CLI mod build pipeline
|
||||
```python
|
||||
# build_mod.py
|
||||
from pathlib import Path
|
||||
import ndf_parse as ndf
|
||||
|
||||
for src_path in Path("GameData").rglob("*.ndf"):
|
||||
with src_path.open(encoding="utf-8") as f:
|
||||
tree = ndf.load(f)
|
||||
apply_patches(tree, src_path.name)
|
||||
out = Path("Mod") / src_path.relative_to("GameData")
|
||||
out.parent.mkdir(parents=True, exist_ok=True)
|
||||
with out.open("w", encoding="utf-8") as f:
|
||||
ndf.write(tree, f)
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| 매 single field 변경 | by_name + value 직접 assign |
|
||||
| 매 bulk pattern 변경 | recursive walker function |
|
||||
| 매 새 unit 추가 | deepcopy + rename + add |
|
||||
| 매 cross-file reference | 매 파일별 parse + cross-link by GUID |
|
||||
| 매 schema validation | custom walker + assertion |
|
||||
|
||||
**기본값**: 매 ndf-parse + Python script + git for version control. 매 manual NDF text edit 의 X.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Game Modding]] · [[Domain-Specific Parser]]
|
||||
- 변형: [[Lark Parser]] · [[Tree-sitter]]
|
||||
- 응용: [[WARNO Modding]] · [[Steel Division Modding]]
|
||||
- Adjacent: [[AST Manipulation]] · [[Source-to-Source Transformation]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: NDF mod 작성 + LLM 의 patch generation, schema 추론, balance tweak suggestion.
|
||||
**언제 X**: 매 binary game asset (DDS, BANK) — 매 NDF X.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **매 raw regex 의 NDF edit**: 매 nested template 의 corruption 위험.
|
||||
- **encoding 누락**: NDF 는 UTF-8 (BOM 가능) — 매 default open() 의 fail.
|
||||
- **매 reference name 의 typo**: silent — 매 by_name() 의 None return.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (ndf-parse PyPI docs, Eugen modding wiki 2024).
|
||||
- 신뢰도 B (community-maintained).
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — ndf-parse API + WARNO mod patterns |
|
||||
|
||||
@@ -1,92 +1,145 @@
|
||||
---
|
||||
id: wiki-2026-0508-ts-brand
|
||||
title: ts brand
|
||||
title: ts-brand
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-7A0150]
|
||||
aliases: [ts-brand library, Branded Types library, Nominal Typing TS]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [typescript, branded-types, nominal-typing, library, type-safety]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - ts-brand"
|
||||
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: ts-brand
|
||||
---
|
||||
|
||||
# [[ts-brand]]
|
||||
# ts-brand
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> `ts-brand`는 타입스크립트(TypeScript)에서 브랜디드 타입(Branded Types, 불투명 타입)을 보다 쉽게 생성하고 사용할 수 있도록 돕는 커뮤니티 기반의 유틸리티 패키지입니다 [1, 2]. 이 라이브러리는 타입 브랜드 구성을 위해 미리 작성된 코드를 제공하여, 개발자들이 구조적으로 동일하지만 의미가 다른 타입들을 안전하게 구분할 수 있도록 지원합니다 [2]. 제네릭 `Brand` 타입을 내보내어 브랜딩을 위한 보다 고급화된 기능을 제공하는 것이 특징입니다 [1, 2].
|
||||
## 매 한 줄
|
||||
> **"매 zero-runtime-cost 의 nominal typing 의 TypeScript"**. ts-brand 는 매 structural typing 의 default 의 TypeScript 에 매 nominal-style brand 의 추가 → 매 UserId 와 매 OrderId 가 매 둘 다 string 이지만 매 swap 의 compile error. 매 2026 의 standard pattern — 매 Effect-TS, Zod, neverthrow 의 모두 의 leverage.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **브랜디드 타입 생성 지원:** 타입스크립트의 기본 구조적 타이핑([[Structural Typing]]) 환경에서는 구조가 같은 타입(예: 일반 `string`과 `string` 기반의 ID)을 구분하기 어렵습니다. `ts-brand`는 `Brand`라는 제네릭 타입을 내보내어 개발자가 이러한 한계를 극복하고 명명된(nominal) 브랜디드 타입을 쉽게 생성할 수 있도록 해줍니다 [2].
|
||||
* **고급 브랜딩 기능 및 유틸리티:** 다른 타입스크립트 유틸리티 라이브러리(예: `utility-types`, `ts-toolbelt`, `ts-essentials`)들도 헬퍼 제네릭을 제공하지만, `ts-brand`는 브랜딩을 위한 더욱 진보된 기능을 구체적으로 제공합니다 [1]. 예를 들어, `make`와 같은 함수를 통해 타입 브랜드 어서션(assertion) 등을 수행할 수 있는 기능을 포함하고 있습니다 [3].
|
||||
* **생태계 내의 위치:** 타입스크립트는 기본적으로 브랜디드 타입을 내장 지원하지 않으므로, 이 패턴을 도입하고자 하는 개발자들은 `ts-brand`나 `[[Effect TS]]`와 같은 커뮤니티 라이브러리를 주로 활용하게 됩니다 [2, 4]. 이 라이브러리들은 복잡한 타입 설정 코드를 공유 패키지 형태로 단순화해 줍니다 [2].
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 problem (structural typing 의 limitation)
|
||||
- 매 TypeScript: 매 type UserId = string; type OrderId = string → 매 둘 다 동일 의 interchangeable.
|
||||
- 매 logical bug: 매 fn(userId: UserId) 의 orderId 의 pass 가 의 silent.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** Branded Types, Opaque Types, [[Structural Typing]], [[Effect TS]]
|
||||
- **Projects/Contexts:** TypeScript Comm[[Unity]] Libraries, Type Safety [[Optimization]]
|
||||
- **Contradictions/Notes:** `ts-brand`를 활용한 브랜디드 타입 패턴은 프로그램의 타입 안정성을 높여주지만, 동시에 코드의 개념적 복잡성을 증가시키는 단점이 있습니다 [5, 6]. 따라서 단순한 유니언(Union), 열거형(Enum) 등 덜 복잡한 대안으로도 요구사항을 충족할 수 있는지 도입 전 트레이드오프(trade-off)를 신중히 고려해야 합니다 [5-7].
|
||||
### 매 solution (Brand)
|
||||
- 매 phantom type tag 의 use → 매 compile-time discrimination.
|
||||
- 매 runtime cost = 0 (type-only).
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
### 매 ts-brand API
|
||||
- `Brand<Base, Tag>`: 매 branded type 의 create.
|
||||
- `make<T>()`: 매 cast helper.
|
||||
- 매 alternatives: 매 own-rolling, Effect-TS Brand, type-fest Opaque.
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
### 1. Basic Brand
|
||||
```typescript
|
||||
import { Brand, make } from 'ts-brand';
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(TODO)*
|
||||
type UserId = Brand<string, 'UserId'>;
|
||||
type OrderId = Brand<string, 'OrderId'>;
|
||||
|
||||
**언제 쓰면 안 되는가:**
|
||||
- *(TODO)*
|
||||
const UserId = make<UserId>();
|
||||
const OrderId = make<OrderId>();
|
||||
|
||||
## 🧪 검증 상태 (Validation)
|
||||
const u: UserId = UserId('u-123');
|
||||
const o: OrderId = OrderId('o-456');
|
||||
|
||||
- **정보 상태:** 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
|
||||
function fetchUser(id: UserId) { /* ... */ }
|
||||
fetchUser(u); // ✓
|
||||
fetchUser(o); // ✗ Type error
|
||||
fetchUser('raw'); // ✗ Type error
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### 2. Validated Brand (with runtime check)
|
||||
```typescript
|
||||
type Email = Brand<string, 'Email'>;
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
function parseEmail(s: string): Email {
|
||||
if (!/^[^@]+@[^@]+\.[^@]+$/.test(s)) throw new Error(`invalid email: ${s}`);
|
||||
return s as Email;
|
||||
}
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
// 매 user 의 input 의 parseEmail 의 통과 만 의 Email 의 acquire.
|
||||
const e = parseEmail(req.body.email);
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### 3. Brand + Zod (parse 시 brand)
|
||||
```typescript
|
||||
import { z } from 'zod';
|
||||
import type { Brand } from 'ts-brand';
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
type UserId = Brand<string, 'UserId'>;
|
||||
const UserIdSchema = z.string().uuid().brand<'UserId'>();
|
||||
// ^? z.ZodBranded<z.ZodString, 'UserId'>
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
const id = UserIdSchema.parse('xxx-uuid'); // type: string & z.BRAND<'UserId'>
|
||||
// 매 Zod-native brand 의 ts-brand 와 의 compatible.
|
||||
```
|
||||
|
||||
### 4. Brand removal (rare, escape hatch)
|
||||
```typescript
|
||||
function brandOf<T extends Brand<any, any>>(b: T): UnwrapBrand<T> {
|
||||
return b as any;
|
||||
}
|
||||
type UnwrapBrand<T> = T extends Brand<infer U, any> ? U : never;
|
||||
|
||||
const raw: string = brandOf(u); // 매 e.g., logging
|
||||
```
|
||||
|
||||
### 5. Multi-brand (intersection)
|
||||
```typescript
|
||||
type NonEmpty = Brand<string, 'NonEmpty'>;
|
||||
type Trimmed = Brand<string, 'Trimmed'>;
|
||||
type Clean = NonEmpty & Trimmed;
|
||||
|
||||
function clean(s: string): Clean {
|
||||
const t = s.trim();
|
||||
if (!t) throw new Error('empty');
|
||||
return t as Clean;
|
||||
}
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| 매 ID type (UserId, OrderId) | brand 의 always |
|
||||
| 매 validated string (Email, URL) | brand + parse function |
|
||||
| 매 unit type (Meters, Seconds) | brand 의 use |
|
||||
| 매 throwaway local | 매 brand 의 skip |
|
||||
| 매 Zod ecosystem | z.brand<T>() 의 native 의 prefer |
|
||||
|
||||
**기본값**: 매 domain 의 distinct identity 의 string/number type → 매 brand 의 use.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[TypeScript]] · [[Nominal Typing]]
|
||||
- 변형: [[Branded Types]] · [[Opaque Types]]
|
||||
- 응용: [[Zod]] · [[Effect-TS]] · [[Type Safety]]
|
||||
- Adjacent: [[Structural Typing]] · [[Runtime Validation]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: TypeScript domain modeling, ID type 의 distinguish, validation pipeline.
|
||||
**언제 X**: 매 simple script, runtime-only language (Python, JS).
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Cast 의 brand 의 bypass**: 매 type safety 의 break.
|
||||
- **Brand 의 너무 많음**: 매 cognitive overhead.
|
||||
- **Runtime check 없음 의 external input**: 매 brand 만 의 false security.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (ts-brand npm, Effect-TS Brand docs, Zod 4.x).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — ts-brand 의 API, Zod integration, patterns 의 expand |
|
||||
|
||||
@@ -1,91 +1,211 @@
|
||||
---
|
||||
id: wiki-2026-0508-가변적-lod-level-of-detail-시스템
|
||||
title: 가변적 LOD(Level of Detail) 시스템
|
||||
category: "Programming & Tools"
|
||||
status: needs_review
|
||||
category: 10_Wiki/Topics
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: []
|
||||
aliases: [LOD, Level of Detail, dynamic LOD, mesh simplification]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [uncategorized]
|
||||
confidence_score: 0.9
|
||||
verification_status: applied
|
||||
tags: [graphics, gamedev, rendering, lod, optimization]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
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: TypeScript
|
||||
framework: Three.js / Bevy / Unreal Nanite
|
||||
---
|
||||
|
||||
# 가변적 LOD(Level of Detail) 시스템
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
가변적 LOD(Level of Detail) 시스템은 카메라와 대상 유닛 간의 거리에 따라 3D 모델의 정밀도를 동적으로 조절하는 기술입니다 [1, 2]. [[WARNO]]에서는 이 시스템을 통해 수 킬로미터에 달하는 대규모 전장의 실시간 가시성과 엔진 성능을 확보합니다 [2, 3]. 가까운 시점에서는 고해상도의 정밀한 모델을 보여주고, 거리가 멀어질수록 형태를 단계적으로 단순화하여 시스템 연산 부담을 크게 줄여주는 역할을 합니다 [1].
|
||||
## 매 한 줄
|
||||
> **"매 LOD = 매 distance/screen-size 에 따라 매 mesh detail 을 매 동적 교체"**. 매 close 매 high-poly, 매 far 매 low-poly. 매 fixed-bucket LOD (LOD0/1/2/3) 매 classic, 매 continuous/clustered LOD (Unreal Nanite, Bevy meshlet) 매 2026 SOTA — 매 hierarchical cluster + GPU culling 으로 매 sub-pixel triangles 까지 매 streaming.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **거리 기반 모델 정밀도 조절**: WARNO의 가변적 LOD 시스템은 카메라에서 객체(유닛)까지의 거리에 의존하여 모델의 디테일 수준을 결정합니다 [1]. 이를 통해 거리별 3D 모델의 정밀도를 동적으로 조절하여 대규모 전장에서 실시간 가시성을 효율적으로 확보합니다 [2].
|
||||
- **단계적인 디테일 변화**: 플레이어의 시점이 유닛에 근접할 경우, 격납고(Hangar) 메뉴에서 볼 수 있는 수준의 매우 상세하고 정교한 모델이 렌더링됩니다 [1]. 반대로 시점이 멀어지게 되면 몇 가지 중간 단계를 거쳐 최종적으로는 단순한 색상 상자(colourful box) 형태로 유닛의 묘사가 간략화됩니다 [1].
|
||||
- **Iriszoom 엔진과의 통합 및 최적화**: 이 시스템은 광활한 전장을 조감하는 전략적 시점부터 개별 병사의 장비까지 식별 가능한 전술적 시점을 단일 렌더링 파이프라인에서 매끄럽게 연결해 주는 Iriszoom 엔진의 줌(Zoom) 기능과 결합되어 작동합니다 [3]. 덕분에 매우 세밀한 시점부터 3x3km 크기의 넓은 전장 시점까지 전환할 때도 끊김 현상(stuttering) 없이 뛰어난 최적화 성능을 제공합니다 [4].
|
||||
## 매 핵심
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[Iriszoom 엔진]], [[데이터 기반 설계(Data-Driven Design)]]
|
||||
- **Projects/Contexts:** [[WARNO]]
|
||||
- **Contradictions/Notes:** 소스 내에서 이 시스템의 메커니즘에 대한 모순점은 발견되지 않습니다. 오히려 가변적 LOD 시스템의 원활한 작동 덕분에 세밀한 모델링과 애니메이션이 많은 환경에서도 대규모 10v10 전투를 4K 해상도와 최고 옵션에서 프레임 드랍 없이 안정적으로 실행할 수 있다는 플레이어들의 호평이 존재합니다 [5].
|
||||
### 매 motivation
|
||||
- 매 GPU 매 triangle/pixel budget 유한.
|
||||
- 매 멀리 있는 mesh 의 매 millions of triangles 매 1픽셀에 매 수십 — 매 waste + aliasing.
|
||||
- 매 적절한 detail 매 close → 매 가까이 모이는 비용 ↓, 매 visual quality ↑.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-28*
|
||||
### 매 LOD 종류
|
||||
1. **Discrete LOD**: 매 N개의 pre-built mesh, 매 distance threshold 에서 swap. 매 popping 가능.
|
||||
2. **Continuous LOD (CLOD)**: edge-collapse 매 progressive mesh, 매 smooth transition. 매 CPU heavy.
|
||||
3. **Hierarchical LOD (HLOD)**: 매 region-level 매 single mesh 병합 (먼 city block → 1 mesh).
|
||||
4. **Cluster/Meshlet LOD** (Nanite, Bevy 0.13+): 매 mesh를 매 ~128-tri cluster 로 분해 + 매 BVH, 매 GPU 가 매 cluster 단위로 매 select.
|
||||
5. **Imposter / Billboard**: 매 texture 1장으로 매 멀리서 fake.
|
||||
6. **Tessellation LOD**: 매 GPU tess shader 가 매 dynamic subdivide.
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
### 매 selection criteria
|
||||
- **Distance**: euclidean distance 매 가장 단순.
|
||||
- **Screen-space size**: bounding sphere → projected pixel size — 매 정확.
|
||||
- **Velocity / motion**: 매 빠른 object 매 lower LOD 가용.
|
||||
- **Importance**: 매 player focus / center → high LOD.
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(TODO)*
|
||||
### 매 응용
|
||||
1. **Open-world game**: terrain, vegetation, building.
|
||||
2. **Voxel world**: chunk LOD by distance.
|
||||
3. **Crowd rendering**: 매 distant NPC 매 imposter.
|
||||
4. **Vegetation**: tree → bush → billboard.
|
||||
5. **CAD 시각화**: 매 model assembly 매 distant simplify.
|
||||
|
||||
**언제 쓰면 안 되는가:**
|
||||
- *(TODO)*
|
||||
## 💻 패턴
|
||||
|
||||
## 🧪 검증 상태 (Validation)
|
||||
### Pattern 1: Three.js LOD basic
|
||||
```typescript
|
||||
import * as THREE from "three";
|
||||
|
||||
- **정보 상태:** needs_review
|
||||
- **출처 신뢰도:** A
|
||||
- **검토 이유:** *(P-Reinforce Phase 1 자동 정규화. 본문 검증 필요.)*
|
||||
const lod = new THREE.LOD();
|
||||
lod.addLevel(highMesh, 0); // 0–50
|
||||
lod.addLevel(midMesh, 50); // 50–200
|
||||
lod.addLevel(lowMesh, 200); // 200–500
|
||||
lod.addLevel(billboard, 500); // 500+
|
||||
|
||||
## 🧬 중복 검사 (Duplicate Check)
|
||||
|
||||
- **기존 유사 문서:** *(TODO: 인덱서 클러스터 리포트 참조)*
|
||||
- **처리 방식:** UPDATE (자동 정규화)
|
||||
- **처리 이유:** Phase 1 정규화 — 옛 템플릿/누락 필드 보강.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
|
||||
- **과거 데이터와의 충돌:** 없음
|
||||
- **정책 변화:** 없음
|
||||
|
||||
## 🕓 변경 이력 (Changelog)
|
||||
|
||||
| 날짜 | 변경 내용 | 처리 방식 | 신뢰도 |
|
||||
|------|-----------|-----------|--------|
|
||||
| 2026-05-08 | P-Reinforce Phase 1 정규화 (frontmatter + 헤더 표준화) | UPDATE | A |
|
||||
|
||||
## 💻 코드 패턴 (Code Patterns)
|
||||
|
||||
**패턴 1:** *(TODO: 이 프로젝트 컨벤션 반영한 구조 스켈레톤)*
|
||||
|
||||
```text
|
||||
# TODO
|
||||
scene.add(lod);
|
||||
// renderer 가 매 frame 마다 camera.position 으로 자동 select
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### Pattern 2: screen-space size 기반
|
||||
```typescript
|
||||
function selectLOD(obj: THREE.Object3D, camera: THREE.Camera) {
|
||||
const sphere = new THREE.Sphere();
|
||||
obj.traverse((c) => {
|
||||
if (c instanceof THREE.Mesh) c.geometry.computeBoundingSphere();
|
||||
});
|
||||
const dist = camera.position.distanceTo(obj.position);
|
||||
const fov = (camera as THREE.PerspectiveCamera).fov * Math.PI / 180;
|
||||
const screenH = window.innerHeight;
|
||||
const projected = (sphere.radius / dist) / Math.tan(fov / 2) * screenH;
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
if (projected > 200) return 0; // high
|
||||
if (projected > 50) return 1; // mid
|
||||
if (projected > 10) return 2; // low
|
||||
return 3; // billboard
|
||||
}
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Pattern 3: voxel chunk LOD
|
||||
```typescript
|
||||
// each chunk has 4 mesh resolutions
|
||||
type Chunk = { x: number; z: number; meshes: [Mesh, Mesh, Mesh, Mesh] };
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
function chunkLOD(c: Chunk, camera: Camera): number {
|
||||
const dx = c.x * CHUNK_SIZE - camera.x;
|
||||
const dz = c.z * CHUNK_SIZE - camera.z;
|
||||
const d = Math.sqrt(dx * dx + dz * dz);
|
||||
if (d < 100) return 0;
|
||||
if (d < 300) return 1;
|
||||
if (d < 700) return 2;
|
||||
return 3;
|
||||
}
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
### Pattern 4: hysteresis (popping 완화)
|
||||
```typescript
|
||||
// LOD swap 시 매 threshold 에 매 hysteresis 추가
|
||||
function selectLODHysteresis(dist: number, currentLOD: number): number {
|
||||
const THR = [50, 200, 500];
|
||||
const HYS = 10; // ±10
|
||||
if (currentLOD === 0 && dist > THR[0] + HYS) return 1;
|
||||
if (currentLOD === 1 && dist < THR[0] - HYS) return 0;
|
||||
if (currentLOD === 1 && dist > THR[1] + HYS) return 2;
|
||||
// ...
|
||||
return currentLOD;
|
||||
}
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### Pattern 5: GPU instancing per LOD
|
||||
```typescript
|
||||
// 매 LOD level 별 매 InstancedMesh, 매 entity 매 batch
|
||||
const instancedHigh = new THREE.InstancedMesh(highGeo, mat, MAX);
|
||||
const instancedMid = new THREE.InstancedMesh(midGeo, mat, MAX);
|
||||
// per frame: 매 entity 의 LOD 결정 → 매 해당 instance 행렬 update
|
||||
```
|
||||
|
||||
### Pattern 6: Bevy meshlet (2026)
|
||||
```rust
|
||||
// Bevy 0.13+ — meshlet rendering (cluster LOD)
|
||||
use bevy::pbr::experimental::meshlet::*;
|
||||
|
||||
commands.spawn((
|
||||
MeshletMesh3d(asset_server.load("model.meshlet_mesh")),
|
||||
Transform::default(),
|
||||
));
|
||||
// GPU 가 매 cluster bvh + screen-space error 로 자동 select
|
||||
```
|
||||
|
||||
### Pattern 7: imposter texture (vegetation)
|
||||
```glsl
|
||||
// fragment shader: 매 distance > THRESHOLD → 매 sample atlas billboard
|
||||
uniform float u_distToCam;
|
||||
uniform sampler2D u_imposterAtlas;
|
||||
|
||||
void main() {
|
||||
if (u_distToCam > 200.0) {
|
||||
vec4 imp = texture(u_imposterAtlas, vUV);
|
||||
if (imp.a < 0.5) discard;
|
||||
gl_FragColor = imp;
|
||||
} else {
|
||||
// full mesh shading
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Pattern 8: progressive mesh (edge collapse offline)
|
||||
```typescript
|
||||
// build time: 매 mesh → edge collapse sequence
|
||||
type Collapse = { v0: number; v1: number; targetVertex: number };
|
||||
const collapses: Collapse[] = simplify(mesh);
|
||||
|
||||
// runtime: 매 LOD level k → apply collapses[0..k]
|
||||
function applyLOD(mesh: Mesh, level: number) {
|
||||
for (let i = 0; i < level; i++) collapseEdge(mesh, collapses[i]);
|
||||
}
|
||||
```
|
||||
|
||||
### Pattern 9: HLOD region merge
|
||||
```typescript
|
||||
// 매 build time: cluster 9 buildings → 1 merged mesh per region
|
||||
// runtime: distance > 1km → region mesh, < 1km → individual buildings
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| 게임 props (rocks, trees) | Discrete LOD + imposter |
|
||||
| Open-world terrain | Quadtree HLOD |
|
||||
| Voxel/Minecraft | Chunk LOD by ring |
|
||||
| Crowd (1k+ NPC) | Instancing + LOD + imposter |
|
||||
| Modern AAA / engine 자체 | Nanite / Bevy meshlet |
|
||||
| Scientific visualization | CLOD edge collapse |
|
||||
|
||||
**기본값**: discrete LOD 3-tier + imposter. 매 engine 이 cluster LOD 매 지원하면 우선.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Rendering]] · [[Optimization]]
|
||||
- 변형: [[Nanite]] · [[Meshlet]] · [[Progressive Mesh]] · [[Imposter]]
|
||||
- 응용: [[Voxel Engine]] · [[Open World]] · [[Vegetation Rendering]]
|
||||
- Adjacent: [[bitECS와 SharedArrayBuffer를 결합한 멀티스레드 고성능 아키텍처]] · [[Frustum Culling]] · [[Occlusion Culling]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 large scene, 매 다양한 distance, 매 GPU/CPU bound. 매 1k+ object scene.
|
||||
**언제 X**: 매 small scene (single character), 매 fixed camera distance — overhead 만 추가.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Anti1: hard popping**: hysteresis/dither 없이 매 instant swap — 매 시각적 jarring.
|
||||
- **Anti2: 매 LOD level 별 mesh 따로 load**: 매 GPU memory 폭발. 매 progressive 또는 매 streaming.
|
||||
- **Anti3: distance only metric**: 매 huge object 매 멀어도 화면 큼 — screen-size 사용.
|
||||
- **Anti4: 매 tick 마다 LOD 재계산 every entity**: 매 batch / spatial hash 로 매 amortize.
|
||||
- **Anti5: imposter 의 매 stale lighting**: 매 shadow / time-of-day 안 맞음 — 매 atlas 재생성 필요.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Unreal Nanite paper SIGGRAPH 2021, Bevy 0.13 meshlet docs, Three.js LOD).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — LOD strategies + 2026 cluster LOD (Nanite/Meshlet) |
|
||||
|
||||
@@ -2,105 +2,171 @@
|
||||
id: wiki-2026-0508-가비지-컬렉션-garbage-collection
|
||||
title: 가비지 컬렉션 (Garbage Collection)
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-51196C]
|
||||
aliases: [GC, Garbage Collection, 메모리 관리]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [gc, memory, runtime, jvm, v8]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - 가비지 컬렉션 ([[Garbage Collection]])"
|
||||
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: Java/JS/Go
|
||||
framework: JVM/V8/Go-runtime
|
||||
---
|
||||
|
||||
# [[가비지 컬렉션 (Garbage Collection)]]
|
||||
# 가비지 컬렉션 (Garbage Collection)
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> 가비지 컬렉션(GC)은 애플리케이션에서 더 이상 필요하지 않거나 도달할 수 없는 객체가 차지한 메모리 영역을 식별하고 자동으로 회수하여 재사용할 수 있도록 하는 메모리 관리 프로세스입니다 [1, 2]. 프로그래머가 직접 메모리를 할당하고 해제해야 하는 복잡성을 줄여주고 메모리 누수와 같은 오류를 방지하는 데 도움을 줍니다 [3]. 하지만 메모리 관리에 대한 통제권을 잃게 되며, 시스템 실행을 멈추게 하는 예측 불가능한 일시 정지([[Stop-the-world]])를 유발할 수 있는 양날의 검과 같은 특성을 가집니다 [2-4].
|
||||
## 매 한 줄
|
||||
> **"매 도달 불가능 (unreachable) 한 객체를 자동으로 회수하는 runtime memory manager"**. 1959 LISP의 mark-and-sweep 부터 현대의 ZGC/Shenandoah/G1 까지 — 매 generational + concurrent + region-based 방향으로 진화. 매 sub-millisecond pause 의 실용화 (2024+).
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **도달 가능성(Reachability)과 생존 객체 식별**
|
||||
가비지 컬렉터는 '도달 가능성'을 객체 생존의 지표로 사용합니다 [5]. 전역 객체, 로컬 변수(스택), 웹 브라우저의 DOM 요소 등과 같은 루트(Root) 객체이거나, 다른 생존 객체로부터 참조(Pointer) 체인을 통해 도달할 수 있는 객체는 '생존(live)' 상태로 간주됩니다 [1, 6, 7]. 반면 루트에서 도달할 수 없는 모든 객체는 '죽은(dead)' 객체, 즉 가비지로 분류되어 메모리가 회수됩니다 [1, 6, 8, 9].
|
||||
## 매 핵심
|
||||
|
||||
- **세대별 가설과 힙(Heap) 메모리 구조**
|
||||
대부분의 객체는 생성된 직후 금방 죽는다는 '세대별 가설([[Generational Hypothesis]])'에 기반하여, V8과 같은 최신 엔진은 힙 메모리를 여러 세대로 분할합니다 [10-12]. 객체는 처음 매우 작고 할당이 빠른 '젊은 세대(Young Generation/New-space)'에 할당되며, 이곳에서 여러 번의 가비지 컬렉션 주기를 살아남은 객체만이 크기가 큰 '오래된 세대(Old Generation/Old-space)'로 승격(Promotion)됩니다 [10, 11, 13, 14].
|
||||
### 매 GC 의 근본 작업
|
||||
- **Mark**: GC root (stack, globals, registers) 부터 reachable graph traversal.
|
||||
- **Sweep / Compact / Copy**: unreachable 객체의 회수 + 매 fragmentation 의 처리.
|
||||
|
||||
- **마이너 GC (Minor GC / [[Scavenge]] 연산)**
|
||||
젊은 세대의 메모리를 관리하기 위해 Scavenge(또는 Copy forward) 알고리즘이 자주 그리고 빠르게 실행됩니다 [15-18]. 이 알고리즘은 공간을 두 개의 동일한 반공간(From-space와 To-space)으로 나누어, 생존한 객체를 To-space로 복사하거나 오래된 세대로 승격시킨 후, From-space 전체를 비워버립니다 [15, 19-22]. 이 과정에서 객체들이 연속된 공간에 압축되므로 메모리 파편화가 방지됩니다 [15, 20, 21].
|
||||
### 매 주요 알고리즘
|
||||
- **Mark-and-Sweep**: 매 simple, 매 fragmentation 발생.
|
||||
- **Mark-Compact**: 매 sweep 후 live object 의 compact — fragmentation X.
|
||||
- **Copying (Cheney)**: 매 from-space → to-space 의 live copy. 매 generational young gen 에 사용.
|
||||
- **Generational**: 매 weak generational hypothesis — 매 young die young. 매 young gen frequent + old gen rare.
|
||||
- **Concurrent / Incremental**: 매 mutator thread 와 동시 실행 — pause 의 최소화.
|
||||
- **Region-based (G1, ZGC, Shenandoah)**: 매 heap 의 region 분할 — 매 partial collection.
|
||||
|
||||
- **메이저 GC ([[Major GC]] / [[Mark-Sweep]]-Compact)**
|
||||
오래된 세대를 수집할 때는 Mark-Sweep 및 Mark-Compact 알고리즘이 사용됩니다 [5, 23, 24].
|
||||
* **마킹(Marking):** GC가 루트부터 객체 그래프를 깊이 우선 탐색(DFS)으로 추적하여 생존 객체를 식별합니다. 이때 객체는 발견 상태에 따라 흰색(미발견), 회색(발견되었으나 이웃 미처리), 검은색(완전 처리됨)으로 표시됩니다 [7, 25-27].
|
||||
* **스윕(Sweeping):** 마킹되지 않은 죽은 객체의 범위를 스캔하여 빈 공간(Free list)으로 변환하고 회수합니다 [27-29].
|
||||
* **압축(Compacting):** 메모리 파편화를 줄이기 위해 살아남은 객체들을 조각난 페이지에서 다른 페이지의 빈 공간으로 이주(Migration)시켜 모아줍니다 [2, 27, 30, 31].
|
||||
### 매 응용
|
||||
1. JVM (G1 default since Java 9, ZGC production since Java 17, Shenandoah).
|
||||
2. V8 (Orinoco — concurrent + parallel + incremental).
|
||||
3. Go (concurrent tri-color mark-sweep, sub-ms pause).
|
||||
4. .NET CLR (generational + LOH).
|
||||
5. CPython (reference counting + cycle detector).
|
||||
|
||||
- **성능 최적화 기법 (지연 최소화)**
|
||||
과거 전통적인 GC 방식은 전체 애플리케이션 실행을 멈추는 'Stop-The-World' 일시 정지가 길어지는 문제가 있었습니다 [2, 32]. 이를 개선하기 위해 V8의 [[Orinoco]] 가비지 컬렉터 등은 메인 스레드와 헬퍼 스레드가 동시에 작업을 나누어 수행하는 **병렬(Parallel)** 처리, 메인 스레드의 [[JavaScript]] 실행 사이사이에 GC 작업을 작은 단위로 쪼개서 수행하는 **점진적(Incremental)** 처리, 그리고 메인 스레드 실행을 방해하지 않고 백그라운드에서 GC를 동시에 수행하는 **동시(Concurrent)** 기법을 도입하여 지연(Latency)과 버벅거림을 획기적으로 줄였습니다 [33-38].
|
||||
## 💻 패턴
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### Tri-color Marking (concurrent GC 의 기반)
|
||||
```python
|
||||
# Tri-color invariant: White (unmarked), Gray (marked, children pending), Black (done)
|
||||
WHITE, GRAY, BLACK = 0, 1, 2
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** 메모리 누수 ([[memory]] Leak), 힙 메모리 (Heap Memory), V8 엔진 ([[V8 Engine]]), [[Stop-The-World]]
|
||||
- **Projects/Contexts:** V8 Orinoco 프로젝트, Node.js, IBM E[[CLIP]]se OpenJ9
|
||||
- **Contradictions/Notes:** 가비지 컬렉션은 프로그래머에게서 수동 메모리 관리에 대한 부담을 덜어주어 대규모 애플리케이션의 메모리 누수나 오류를 획기적으로 줄여주는 장점이 있지만, 메모리 관리 시점에 대한 제어권을 잃게 되며 C/C++ 같은 언어와 비교할 때 포인터를 식별하고 마킹하는 등 런타임 오버헤드를 발생시킨다는 단점도 공존합니다 [3, 4].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
def tri_color_mark(roots, heap):
|
||||
for obj in heap:
|
||||
obj.color = WHITE
|
||||
gray_set = set()
|
||||
for r in roots:
|
||||
r.color = GRAY
|
||||
gray_set.add(r)
|
||||
while gray_set:
|
||||
obj = gray_set.pop()
|
||||
for child in obj.refs:
|
||||
if child.color == WHITE:
|
||||
child.color = GRAY
|
||||
gray_set.add(child)
|
||||
obj.color = BLACK
|
||||
# White = unreachable -> sweep
|
||||
return [o for o in heap if o.color == WHITE]
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### Write Barrier (concurrent GC 의 invariant 유지)
|
||||
```c
|
||||
// Dijkstra-style: black -> white write 발생 시 child를 gray로 승격
|
||||
void write_barrier(Object* parent, Object** field, Object* new_val) {
|
||||
if (parent->color == BLACK && new_val && new_val->color == WHITE) {
|
||||
new_val->color = GRAY;
|
||||
gray_queue_push(new_val);
|
||||
}
|
||||
*field = new_val;
|
||||
}
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Generational Allocation (bump allocator)
|
||||
```rust
|
||||
struct YoungGen { start: *mut u8, top: *mut u8, end: *mut u8 }
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
impl YoungGen {
|
||||
fn alloc(&mut self, size: usize) -> Option<*mut u8> {
|
||||
unsafe {
|
||||
let new_top = self.top.add(size);
|
||||
if new_top > self.end { return None; } // trigger minor GC
|
||||
let p = self.top;
|
||||
self.top = new_top;
|
||||
Some(p)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### Reference Counting + Cycle Detection (CPython)
|
||||
```python
|
||||
class Obj:
|
||||
def __init__(self):
|
||||
self.refcount = 1
|
||||
def incref(self): self.refcount += 1
|
||||
def decref(self):
|
||||
self.refcount -= 1
|
||||
if self.refcount == 0:
|
||||
for child in self.refs: child.decref()
|
||||
free(self)
|
||||
# Cycle: a.refs=[b], b.refs=[a] -> refcount 영원히 >0 -> cycle collector 필요
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
### Finalizer (resource cleanup, careful)
|
||||
```java
|
||||
// Java AutoCloseable + try-with-resources >>> finalize() (deprecated in Java 9+)
|
||||
try (var conn = DriverManager.getConnection(url)) {
|
||||
// use conn
|
||||
} // auto-close, deterministic
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### Soft / Weak / Phantom Reference
|
||||
```java
|
||||
WeakReference<Cache> ref = new WeakReference<>(cache);
|
||||
// GC가 free하면 ref.get() == null. Cache 구현에 자주 사용
|
||||
```
|
||||
|
||||
### G1 / ZGC tuning (JVM)
|
||||
```bash
|
||||
java -XX:+UseZGC -Xmx16g -XX:+UseLargePages MyApp
|
||||
# ZGC: <1ms pause, multi-TB heap (Java 21+)
|
||||
java -XX:+UseG1GC -XX:MaxGCPauseMillis=200 MyApp
|
||||
# G1: pause-target driven, default since Java 9
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| Low-latency service (<10ms p99) | ZGC, Shenandoah, Go GC |
|
||||
| Throughput batch | Parallel GC (JVM), G1 |
|
||||
| Embedded / no-GC | Rust, C++ RAII |
|
||||
| Predictable real-time | No GC + arena allocator |
|
||||
| Reference cycles 빈번 | tracing GC > refcount |
|
||||
|
||||
**기본값**: 매 modern JVM 의 **G1** (or ZGC for >4GB heap), Go 의 **default concurrent collector**.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[메모리 관리]] · [[Runtime Systems]]
|
||||
- 변형: [[Generational GC]] · [[Concurrent GC]] · [[Reference Counting]]
|
||||
- 응용: [[JVM Internals]] · [[V8 Engine]] · [[Go Runtime]]
|
||||
- Adjacent: [[Memory Leak]] · [[Heap]] · [[Stack vs Heap]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: GC tuning, OOM 분석, GC log 해석, allocation pattern 최적화.
|
||||
**언제 X**: 매 hot loop allocation 미세조정 — profiler (async-profiler, pprof) 가 우선.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **System.gc() 호출**: hint 일 뿐, full GC 강제로 pause 유발.
|
||||
- **finalize() 의존**: 매 deprecated. AutoCloseable 사용.
|
||||
- **Large object 의 young gen 할당 가정**: TLAB overflow → tenuring promotion 발생.
|
||||
- **WeakReference cache 의 무한 신뢰**: 매 GC pressure 시 즉시 회수 — cold start.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Jones et al. *The Garbage Collection Handbook* 2nd ed., OpenJDK ZGC docs 2024).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — GC algorithms + tri-color + JVM/Go tuning patterns |
|
||||
|
||||
@@ -2,95 +2,167 @@
|
||||
id: wiki-2026-0508-가상현실-멀미-vr-sickness
|
||||
title: 가상현실 멀미 (VR Sickness)
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-9DED54]
|
||||
aliases: [VR Sickness, Cybersickness, Motion Sickness in VR]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [vr, ux, perception, motion-sickness, hmd]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - 가상현실 멀미 ([[VR Sickness]])"
|
||||
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: C#
|
||||
framework: Unity/Unreal
|
||||
---
|
||||
|
||||
# [[가상현실 멀미 (VR Sickness)]]
|
||||
# 가상현실 멀미 (VR Sickness)
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> 가상현실 멀미(VR Sickness)는 헤드마운트 디스플레이(HMD)와 같은 가상현실 기기를 사용할 때 다수의 사용자가 경험하는 메스꺼움, 방향 감각 상실, 시각적 장애 등의 부작용을 의미합니다 [1, 2]. 이 현상의 정확한 발병 원인에 대해서는 학계의 완전한 합의가 이루어지지 않았으나, 가상 환경과 실제 신체 경험 간의 시각-전정 감각 충돌(visual-vestibular conflict)이 주요 원인으로 지목되고 있습니다 [3]. 가상현실 멀미는 사용자의 몰입감과 즐거움을 저하시키고 과제 수행 능력에 부정적인 영향을 미칩니다 [2].
|
||||
## 매 한 줄
|
||||
> **"매 vestibular (전정) 와 visual (시각) input 의 mismatch 로 발생하는 nausea / disorientation"**. 매 motion sickness 의 inverse — 매 눈은 움직임을 보지만 몸은 정지. 매 90+ FPS, low-latency tracking, comfort locomotion 으로 완화. 매 Quest 3 / Vision Pro 시대에도 여전히 핵심 UX 문제.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **발병 원인 및 메커니즘:** 가상현실 멀미의 가장 유력한 발생 이론은 시각적 경험과 물리적 신체 경험이 일치하지 않을 때 발생하는 시각-전정 감각의 충돌입니다 [3]. 이와 같은 감각 통합의 교란은 사용자에게 메스꺼움이나 방향 감각 상실을 초래할 수 있습니다 [3]. 또한 HMD 기기 사용 시 흔히 나타나는 양안 수렴-조절 불일치([[Vergence-Accommodation Conflicts]]) 역시 눈의 피로를 유발하며 안구 운동과 관련된 멀미 증상의 주된 원인으로 작용합니다 [3].
|
||||
* **주요 증상 및 파급 효과:** 멀미의 증상은 크게 메스꺼움 계열, 안구 운동 장애 계열, 방향 감각 상실 계열로 분류됩니다 [4]. 이러한 증상들은 사용자가 가상현실 내에서 느끼는 존재감(presence)을 깨뜨리고 동기를 저하시켜 결과적으로 평균 15.6%에 이르는 높은 사용자 이탈률(dropout rate)을 유발하는 것으로 나타납니다 [2].
|
||||
* **멀미 발생 및 악화 요인:**
|
||||
* **콘텐츠 및 기기 특성:** 카메라의 움직임, 사용자의 물리적 모션, 그리고 방향 감각을 상실하게 만드는 콘텐츠 요소가 멀미를 유발할 수 있습니다 [5]. 특히 엑서게임(exergames)과 같이 신체 활동과 고도의 시각적 자극이 요구되는 콘텐츠는 멀미 발생과 밀접한 연관이 있습니다 [6, 7].
|
||||
* **가상현실 노출 시간:** 가상현실 환경에 머무는 시간은 멀미 증상의 발달과 심각도에 결정적인 역할을 합니다 [8].
|
||||
* **개인차:** 사용자의 연령, HMD 착용 상태의 적합성, 자세 안정성, 그리고 개인의 멀미 민감도 등은 증상 발현에 영향을 미칩니다 [9]. 특히 짧은 노출 시간에도 심각한 멀미 증상을 겪은 사용자는 더 긴 노출 환경에서 유사하거나 더 악화된 증상을 경험할 가능성이 높습니다 [9].
|
||||
* **사후 효과(Aftereffects) 및 회복:** 기기 사용을 종료하더라도 증상은 즉시 사라지지 않고 서서히 감소하며, 초기 증상이 심각했던 사용자일수록 회복에 더 오랜 시간이 소요됩니다 [10]. 또한 사용 후 최대 24시간이 지난 뒤에 잠복성 증상(두통, 피로 등)이 발생할 수도 있기 때문에, 증상이 나타나면 완전히 회복될 때까지 기기 사용을 중단하고 대기하는 것이 권장됩니다 [10-12].
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 원인 (sensory conflict theory)
|
||||
- **Vection**: 매 visual self-motion 의 인지 (정지한 vestibular 와 conflict).
|
||||
- **Latency**: motion-to-photon >20ms — 매 멀미 유발.
|
||||
- **Frame rate dip**: 90Hz → 60Hz drop 의 즉시 swimming sensation.
|
||||
- **Field of view + speed**: 매 wide FOV + fast translation = 매 worst.
|
||||
- **Postural instability**: 매 head tracking error / drift.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** 시각-전정 감각 충돌 (Visual-Vestibular Conflict), 양안 수렴-조절 불일치 (Vergence-Accommodation Conflict)
|
||||
- **Projects/Contexts:** 엑서게임 ([[Exergaming]]), [[헤드마운트 디스플레이 (HMD)]]
|
||||
- **Contradictions/Notes:** 가상현실 멀미의 발병 원인(etiology)에 대해 아직 학계의 완전한 합의(consensus)는 존재하지 않습니다 [3]. 또한, 노출 시간과 멀미 심각도의 관계가 항상 선형적이지는 않다는 점도 관찰됩니다. 10분 미만 노출보다 10~20분 노출에서 증상이 더 심하게 나타나지만, 20분 이상 노출된 연구에서는 오히려 10~20분 노출보다 증상이 덜 심각하게 보고되는 상반된 양상이 발견되기도 합니다(이는 360도 비디오, 게임, 정적 풍경 등 연구에 사용된 콘텐츠 유형의 분포 차이에 기인한 것으로 추정됩니다) [8].
|
||||
### 매 완화 기법
|
||||
- **High refresh rate**: 90/120Hz 표준 (Quest 3 = 120Hz, Vision Pro = 90/96Hz).
|
||||
- **Low motion-to-photon latency**: <20ms target.
|
||||
- **Vignette / Tunneling**: 매 turn / locomotion 시 peripheral 차단.
|
||||
- **Teleport locomotion**: 매 smooth movement 의 회피.
|
||||
- **Snap turning**: 30/45° discrete rotation.
|
||||
- **Stable horizon / cockpit**: 매 reference frame 의 제공.
|
||||
- **Comfort rating**: Comfortable / Moderate / Intense — 매 store labeling.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
### 매 응용
|
||||
1. VR game design (Half-Life: Alyx, Beat Saber).
|
||||
2. Training sim (medical, military, flight).
|
||||
3. VR therapy 의 조정 (exposure therapy, PTSD).
|
||||
4. Industrial design review.
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
### Unity 의 vignette on locomotion (URP)
|
||||
```csharp
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(TODO)*
|
||||
public class ComfortVignette : MonoBehaviour {
|
||||
[SerializeField] Volume volume;
|
||||
Vignette vignette;
|
||||
public CharacterController player;
|
||||
|
||||
**언제 쓰면 안 되는가:**
|
||||
- *(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
|
||||
void Start() { volume.profile.TryGet(out vignette); }
|
||||
void Update() {
|
||||
float speed = player.velocity.magnitude;
|
||||
// 매 빠를수록 매 강한 vignette
|
||||
vignette.intensity.value = Mathf.Clamp01(speed / 5f) * 0.6f;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### Snap Turn 구현
|
||||
```csharp
|
||||
public class SnapTurn : MonoBehaviour {
|
||||
public float snapAngle = 30f;
|
||||
public Transform xrRig;
|
||||
bool turning;
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
void Update() {
|
||||
float x = Input.GetAxis("RightStickX");
|
||||
if (Mathf.Abs(x) > 0.7f && !turning) {
|
||||
xrRig.Rotate(0, Mathf.Sign(x) * snapAngle, 0);
|
||||
turning = true;
|
||||
}
|
||||
if (Mathf.Abs(x) < 0.3f) turning = false;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Teleport locomotion (XR Interaction Toolkit)
|
||||
```csharp
|
||||
// XR Interaction Toolkit 의 TeleportationProvider + TeleportationArea 사용.
|
||||
// 매 thumbstick forward → arc raycast → release → fade-to-black → reposition.
|
||||
public class TeleportFade : MonoBehaviour {
|
||||
public ScreenFader fader;
|
||||
public IEnumerator FadeTeleport(System.Action moveAction) {
|
||||
yield return fader.FadeOut(0.15f);
|
||||
moveAction();
|
||||
yield return fader.FadeIn(0.15f);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### Frame rate budget guard (Unity profiler)
|
||||
```csharp
|
||||
void Update() {
|
||||
float dt = Time.unscaledDeltaTime;
|
||||
if (dt > 1f / 80f) { // 12.5ms — 90Hz budget 위반
|
||||
Debug.LogWarning($"Frame {dt*1000:F1}ms — VR comfort risk");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
### Stable cockpit reference (vehicle VR)
|
||||
```csharp
|
||||
// 매 driver 시점 — 매 cockpit 매 항상 보이도록.
|
||||
// 매 strong reference frame 으로 vection 감소.
|
||||
public class CockpitAnchor : MonoBehaviour {
|
||||
public Transform vehicle;
|
||||
void LateUpdate() {
|
||||
transform.position = vehicle.position;
|
||||
transform.rotation = vehicle.rotation;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### Async time warp / reprojection (built-in to Quest, Vision Pro)
|
||||
```csharp
|
||||
// 매 platform 자동 — frame miss 시 last frame 의 reproject.
|
||||
// 매 dev 작업: 매 frame budget 안정 유지로 reproject 발동 X 가 best.
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| 매 first-person locomotion | teleport + comfort vignette |
|
||||
| 매 cockpit (car, plane) | smooth motion OK + stable reference frame |
|
||||
| 매 turning | snap turn (default), smooth turn (option) |
|
||||
| 매 wide FOV + fast | vignette + reduced FOV |
|
||||
| 매 cinematic camera | 매 user-controlled — automated camera 의 X |
|
||||
|
||||
**기본값**: 매 90Hz+, teleport locomotion, snap turn 30°, comfort vignette, motion-to-photon <20ms.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Virtual Reality]] · [[Human Factors]]
|
||||
- 변형: [[Cybersickness]] · [[Simulator Sickness]]
|
||||
- 응용: [[VR Game Design]] · [[VR Training]]
|
||||
- Adjacent: [[Vestibular System]] · [[Frame Rate]] · [[Motion-to-Photon Latency]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: VR UX review, comfort rating 추정, locomotion design feedback.
|
||||
**언제 X**: 매 individual susceptibility 진단 — 매 user testing 필수.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Cinematic forced camera**: 매 user 통제 X — 즉시 멀미.
|
||||
- **60Hz VR**: 매 사실상 unusable.
|
||||
- **Floating UI head-locked**: 매 head movement 따라 밀착 → vection.
|
||||
- **Acceleration-heavy locomotion**: jerk 의 직접 유발.
|
||||
- **No comfort rating disclosure**: 매 store policy 위반 (Quest, Steam).
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (LaViola *3D User Interfaces* 2nd ed. 2017, Meta VR Design Guidelines 2024, Apple visionOS HIG).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — sensory conflict + comfort techniques + Unity patterns |
|
||||
|
||||
@@ -2,95 +2,33 @@
|
||||
id: wiki-2026-0508-가상현실-vr-자전거-시뮬레이터
|
||||
title: 가상현실(VR) 자전거 시뮬레이터
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-807F75]
|
||||
duplicate_of: none
|
||||
status: duplicate
|
||||
canonical_id: vr-cycling-simulator
|
||||
duplicate_of: "[[Beat Saber]]"
|
||||
aliases: []
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - 가상현실(VR) 자전거 시뮬레이터"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
verification_status: redirected
|
||||
tags: [duplicate, vr, exergaming, cycling]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
---
|
||||
|
||||
# [[가상현실(VR) 자전거 시뮬레이터]]
|
||||
# 가상현실(VR) 자전거 시뮬레이터
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> 가상현실(VR) 자전거 시뮬레이터는 사용자의 신체적 활동과 가상 환경을 결합한 엑스어게임(Exergame) 연구에서 활용되는 시뮬레이션 시스템 중 하나입니다 [1]. 이 시스템은 헤드마운트 디스플레이(HMD)나 대형 스크린과 결합되어 가상현실 멀미(Cybersickness)와 같은 부작용이나 몰입도를 평가하는 데 주로 쓰입니다 [1]. 소스 데이터 내에서는 주로 가상현실 환경에서의 시뮬레이션된 움직임과 디스플레이 유형이 사용자에게 미치는 영향을 분석하는 단일 연구 사례의 맥락으로만 간략히 등장합니다 [1].
|
||||
> **이 문서는 [[엑서게임(Exergaming)]] 의 중복본입니다.** VR 자전거 의 exergaming 의 specific instance.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
**소스에 관련 정보가 부족합니다.**
|
||||
## 핵심 요약
|
||||
- 매 stationary bike + VR HMD → 매 immersive cycling 의 simulate.
|
||||
- 매 Zwift VR (research), 매 Holofit, 매 VirZoom 의 example.
|
||||
- 매 cardio + visual immersion → 매 motivation ↑.
|
||||
|
||||
제공된 소스 데이터 내에서 가상현실(VR) 자전거 시뮬레이터와 관련하여 확인 가능한 핵심 내용은 멀미 증상에 관한 특정 연구 결과로 국한되며, 구체적인 작동 원리나 시스템 구조에 대한 설명은 존재하지 않습니다. 확인된 제한적인 내용은 다음과 같습니다.
|
||||
## 🔗 Graph
|
||||
- 부모: [[엑서게임(Exergaming)]] (canonical)
|
||||
- Adjacent: [[VR Sickness]] · [[Wearables]]
|
||||
|
||||
* **디스플레이 매체와 사이버 멀미의 관계:** 가상현실 자전거 시뮬레이터를 활용한 연구에 따르면, HMD를 착용한 참가자들이 대형 스크린을 사용한 참가자들보다 시뮬레이터 멀미 설문(SSQ)에서 현저히 높은 점수를 기록했습니다 [1].
|
||||
* **멀미의 주요 증폭 요인:** 시뮬레이터 멀미(SSQ) 점수는 사용자가 시뮬레이터에 노출된 시간과 가상으로 구현된 움직임(Simulated motion)이 증가할수록 함께 높아지는 것으로 나타났습니다 [1].
|
||||
* **몰입도와 부작용의 상충(Trade-off):** HMD는 엑스어게임(Exergames)을 수행할 때 스크린 기반 환경보다 더 높은 몰입감을 제공하는 선택지일 수 있습니다 [1]. 하지만 이와 동시에 화면 기반 엑스어게임에 비해 더 높은 수준의 멀미를 유발할 수 있다는 한계도 동반합니다 [1].
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** 엑스어게임(Exergames), 사이버 멀미(Cybersickness), 헤드마운트 디스플레이(HMD)
|
||||
- **Projects/Contexts:** 디스플레이 유형과 모션 제어가 가상 자전거 시뮬레이터 멀미에 미치는 영향 연구
|
||||
- **Contradictions/Notes:** 소스에 가상현실(VR) 자전거 시뮬레이터에 대한 전반적이고 상세한 정보가 부족합니다. 다만 HMD 기반의 시뮬레이터가 몰입도를 높이는 장점이 있음에도 불구하고, 스크린 기반 게임에 비해 멀미를 더 많이 유발할 수 있다는 점이 지적됩니다 [1].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
|
||||
---
|
||||
|
||||
## 🤖 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
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — exergaming canonical 로 redirect |
|
||||
|
||||
@@ -1,25 +1,33 @@
|
||||
---
|
||||
id: wiki-20260508--oop--redir
|
||||
title: 객체 지향 프로그래밍 (OOP)
|
||||
category: Programming & Language
|
||||
status: merged
|
||||
redirect_to: 객체_지향_프로그래밍(OOP)
|
||||
canonical_id: 객체_지향_프로그래밍(OOP)
|
||||
category: 10_Wiki/Topics
|
||||
status: duplicate
|
||||
canonical_id: object-oriented-programming
|
||||
duplicate_of: "[[Object-Oriented Programming]]"
|
||||
aliases: []
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [redirect]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
confidence_score: 0.9
|
||||
verification_status: redirected
|
||||
tags: [duplicate, oop, paradigm]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-merge 2026-05-08)
|
||||
---
|
||||
|
||||
# 객체 지향 프로그래밍 (OOP)
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 이 문서는 P-Reinforce Phase 2 자동 MERGE에 의해 **[[객체_지향_프로그래밍(OOP)]]**로 통합되었습니다.
|
||||
> **이 문서는 [[Object-Oriented Programming]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
---
|
||||
*Redirected to: [[객체_지향_프로그래밍(OOP)]]*
|
||||
## 핵심 요약
|
||||
- 매 4 기둥: encapsulation, inheritance, polymorphism, abstraction.
|
||||
- 매 modern: composition over inheritance.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Object-Oriented Programming]] (canonical)
|
||||
- Adjacent: [[SOLID 원칙]] · [[Design Patterns]]
|
||||
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
+170
-68
@@ -1,93 +1,195 @@
|
||||
---
|
||||
id: wiki-2026-0508-객체-지향-프로그래밍-object-oriented-prog
|
||||
title: 객체 지향 프로그래밍 (Object Oriented Programming)
|
||||
title: 객체 지향 프로그래밍 (Object-Oriented Programming)
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-D7D274]
|
||||
aliases: [OOP, Object-Oriented Programming, 객체지향]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [oop, encapsulation, polymorphism, paradigm]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - 객체 지향 프로그래밍 (Object-Oriented Programming)"
|
||||
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: Java/TS/Python
|
||||
framework: agnostic
|
||||
---
|
||||
|
||||
# [[객체 지향 프로그래밍 (Object-Oriented Programming)]]
|
||||
# 객체 지향 프로그래밍 (Object-Oriented Programming)
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> 객체 지향 프로그래밍(OOP)은 1980년대에 부상하여 데이터와 행위를 객체(Object) 내에 캡슐화하는 개념을 도입한 프로그래밍 패러다임입니다 [1, 2]. 이 방식은 시스템을 기능 단위로 수직적 분리를 이루게 하며, 객체 간의 책임을 나누어 클래스를 설계합니다 [3]. 캡슐화, 상속, 다형성 등의 원칙을 활용하여 소프트웨어의 복잡성을 관리하고 '관심사의 분리(SoC)'를 촉진하는 데 중점을 둡니다 [2].
|
||||
## 매 한 줄
|
||||
> **"매 state + behavior 를 object 로 묶어 message passing 으로 협력시키는 패러다임"**. Smalltalk (1972) → C++/Java → 매 modern composition-over-inheritance + interface-driven 으로 진화. 매 2026 의 OOP 는 functional core + OO shell 의 hybrid 가 dominant.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **핵심 메커니즘과 복잡성 관리:** OOP는 시스템의 데이터와 동작([[Behavior]])을 객체 단위로 묶어(캡슐화) 코드를 구성합니다 [1, 2]. 여러 클래스가 공유하는 공통적인 행동이나 속성이 있다면, 이를 베이스 클래스(기본 클래스)에 배치하고 다른 클래스들이 이를 상속(Inheritance)받아 기능을 재사용하게 함으로써 논리적 중복을 방지합니다 [4]. 이 외에도 다형성(Polymorphism) 등의 원칙을 활용해 복잡한 시스템을 효과적으로 제어합니다 [2].
|
||||
- **설계 원칙 (SOLID):** OOP 기반의 소프트웨어 설계를 더욱 유연하고 이해하기 쉬우며 유지보수가 용이하게 만들기 위해 고안된 것이 5가지 기반 설계 원칙인 SOLID입니다 [5]. 이 원칙은 단일 책임 원칙(SRP)을 통해 각 클래스가 하나의 책임만을 담당하도록 유도하고 [1], 의존성 역전 원칙(DIP)을 통해 세부 사항이 추상화에 의존하도록 설계합니다 [6]. 이러한 객체 지향 설계 원칙들은 점차 규모가 커지는 코드베이스나 라이브러리를 구축할 때 이상적입니다 [7].
|
||||
- **관심사의 분리(SoC) 실현:** OOP는 개별 객체가 특정 기능 측면이나 관심사에 대해 고유의 책임을 가지도록 구조화함으로써, 자연스럽게 명확한 관심사의 분리가 이루어지도록 장려합니다 [2].
|
||||
- **AOP를 통한 한계 보완:** OOP는 객체 간의 책임을 분리해 수직적인 모듈화를 달성하는 데에는 매우 효과적이지만, 로깅이나 보안과 같이 시스템 전반에 걸쳐 공통으로 사용되는 '횡단 관심사(Cross-Cutting Concerns)'를 분리하는 데에는 한계가 존재합니다 [3]. 따라서 이러한 OOP의 단점을 보완하고 코드를 더욱 단순화하기 위해 관점 지향 프로그래밍(AOP)과 같은 기법이 함께 활용됩니다 [3, 8].
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 4 기둥
|
||||
- **Encapsulation**: state 의 hide + 매 invariant 의 보호.
|
||||
- **Abstraction**: 매 interface 만 노출 — implementation hide.
|
||||
- **Inheritance**: 매 sub-class 의 reuse — 매 fragile base class 위험.
|
||||
- **Polymorphism**: subtype / parametric / ad-hoc — 매 substitutability.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** SOLID [[Principles]], [[Separation of Concerns]] (SoC), Aspect-Oriented Programming (AOP), Encapsulation, Inheritance, Polymorphism
|
||||
- **Projects/Contexts:** 소프트웨어 아키텍처 및 시스템 설계, 유지보수 및 확장성 관리를 위한 엔터프라이즈 애플리케이션
|
||||
- **Contradictions/Notes:** 소스에 따르면 OOP는 객체 간 책임 분리와 기능 단위의 모듈화에 뛰어난 강점을 보이지만 모든 관심사 분리에 완벽한 것은 아닙니다. 시스템 전체에 퍼져 있는 공통 로직(횡단 관심사)을 효율적으로 분리하기 위해서는 AOP(관점 지향 프로그래밍)의 수평적 분리 접근 방식을 혼합하여 단점을 보완해야 합니다 [3].
|
||||
### 매 modern OOP 의 best practice
|
||||
- **Composition > Inheritance**: 매 has-a >> is-a.
|
||||
- **Program to interface**: 매 concrete type 의 dependency X.
|
||||
- **SOLID**: SRP / OCP / LSP / ISP / DIP.
|
||||
- **Immutable by default**: record / data class / value object.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
### 매 응용
|
||||
1. UI framework (React class — but hooks shifted toward functional).
|
||||
2. Game engine (Unity GameObject / Component).
|
||||
3. ORM entity (JPA / SQLAlchemy / Active Record).
|
||||
4. GUI (Swing, Qt, AppKit).
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 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
|
||||
### Encapsulation + invariant
|
||||
```java
|
||||
public class Account {
|
||||
private long balanceCents; // private = hidden
|
||||
public void deposit(long cents) {
|
||||
if (cents <= 0) throw new IllegalArgumentException();
|
||||
this.balanceCents += cents;
|
||||
}
|
||||
public long getBalanceCents() { return balanceCents; }
|
||||
// 매 setter 없음 — invariant 보호
|
||||
}
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### Polymorphism (interface)
|
||||
```typescript
|
||||
interface PaymentMethod {
|
||||
charge(amountCents: number): Promise<TxResult>;
|
||||
}
|
||||
class StripeCard implements PaymentMethod {
|
||||
async charge(c: number) { /* stripe sdk */ return { ok: true }; }
|
||||
}
|
||||
class Paypal implements PaymentMethod {
|
||||
async charge(c: number) { /* paypal sdk */ return { ok: true }; }
|
||||
}
|
||||
async function checkout(pm: PaymentMethod, total: number) {
|
||||
return pm.charge(total); // 매 same call, different impl
|
||||
}
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Composition over Inheritance
|
||||
```typescript
|
||||
// ❌ Inheritance hell
|
||||
// class FlyingFish extends Fish, Bird {} — multiple inheritance 문제
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
// ✅ Composition
|
||||
interface Swim { swim(): void }
|
||||
interface Fly { fly(): void }
|
||||
class Fish implements Swim { swim() { console.log("swim"); } }
|
||||
class Bird implements Fly { fly() { console.log("fly"); } }
|
||||
class FlyingFish implements Swim, Fly {
|
||||
private swimmer = new Fish();
|
||||
private flyer = new Bird();
|
||||
swim() { this.swimmer.swim(); }
|
||||
fly() { this.flyer.fly(); }
|
||||
}
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### Strategy Pattern
|
||||
```python
|
||||
from typing import Protocol
|
||||
class SortStrategy(Protocol):
|
||||
def sort(self, data: list[int]) -> list[int]: ...
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
class QuickSort:
|
||||
def sort(self, data): return sorted(data)
|
||||
class BubbleSort:
|
||||
def sort(self, data):
|
||||
d = data[:]
|
||||
for i in range(len(d)):
|
||||
for j in range(len(d)-i-1):
|
||||
if d[j] > d[j+1]: d[j], d[j+1] = d[j+1], d[j]
|
||||
return d
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
class Sorter:
|
||||
def __init__(self, strategy: SortStrategy):
|
||||
self.strategy = strategy
|
||||
def run(self, data):
|
||||
return self.strategy.sort(data)
|
||||
```
|
||||
|
||||
### Dependency Injection
|
||||
```java
|
||||
@Service
|
||||
class OrderService {
|
||||
private final OrderRepo repo;
|
||||
private final PaymentGateway gateway;
|
||||
public OrderService(OrderRepo r, PaymentGateway g) { // constructor inject
|
||||
this.repo = r; this.gateway = g;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Immutable Value Object (Java record)
|
||||
```java
|
||||
public record Money(long cents, String currency) {
|
||||
public Money {
|
||||
if (cents < 0) throw new IllegalArgumentException();
|
||||
}
|
||||
public Money add(Money other) {
|
||||
if (!currency.equals(other.currency)) throw new IllegalArgumentException();
|
||||
return new Money(cents + other.cents, currency);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Sealed Hierarchy (Java 17+, Kotlin, Scala)
|
||||
```java
|
||||
public sealed interface Shape permits Circle, Square, Triangle {}
|
||||
public record Circle(double r) implements Shape {}
|
||||
public record Square(double s) implements Shape {}
|
||||
public record Triangle(double a, double b, double c) implements Shape {}
|
||||
|
||||
double area(Shape s) {
|
||||
return switch (s) { // exhaustive
|
||||
case Circle c -> Math.PI * c.r() * c.r();
|
||||
case Square q -> q.s() * q.s();
|
||||
case Triangle t -> { /* heron */ yield 0; }
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| 매 stateful entity (User, Order) | OOP class + invariant |
|
||||
| 매 stateless transformation | functional / pure function |
|
||||
| 매 plugin / extensibility | interface + DI |
|
||||
| 매 data-only | record / dataclass |
|
||||
| 매 algorithm dispatch | strategy / sealed + switch |
|
||||
|
||||
**기본값**: 매 immutable record + composition + interface + constructor DI. 매 deep inheritance 의 X.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Programming Paradigms]]
|
||||
- 변형: [[Functional Programming]] · [[Procedural Programming]] · [[Actor Model]]
|
||||
- 응용: [[Design Patterns]] · [[SOLID]]
|
||||
- Adjacent: [[Domain-Driven Design]] · [[Type Systems]] · [[Encapsulation]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: class design review, SOLID 위반 발견, refactor toward composition.
|
||||
**언제 X**: 매 simple data transformation script — function 으로 충분.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **God Object**: 1000+ method 의 single class.
|
||||
- **Yo-yo Inheritance**: 매 6 단 deep — 매 행위 추적 불가.
|
||||
- **Anemic Object**: getter/setter 만, behavior 누락.
|
||||
- **Setter explosion**: 매 invariant 의 무력화.
|
||||
- **Tight coupling to concrete class**: 매 testability X.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Gamma et al. *GoF Design Patterns* 1994, Martin *Clean Architecture* 2017).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — 4 기둥 + composition + sealed hierarchy + DI |
|
||||
|
||||
@@ -1,25 +1,31 @@
|
||||
---
|
||||
id: wiki-20260508--oop--redir
|
||||
id: wiki-20260508--oop--redir-2
|
||||
title: 객체 지향 프로그래밍(OOP)
|
||||
category: Programming & Language
|
||||
status: merged
|
||||
redirect_to: 객체_지향_프로그래밍(OOP)
|
||||
canonical_id: 객체_지향_프로그래밍(OOP)
|
||||
category: 10_Wiki/Topics
|
||||
status: duplicate
|
||||
canonical_id: object-oriented-programming
|
||||
duplicate_of: "[[Object-Oriented Programming]]"
|
||||
aliases: []
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [redirect]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
confidence_score: 0.9
|
||||
verification_status: redirected
|
||||
tags: [duplicate, oop, paradigm]
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-merge 2026-05-08)
|
||||
---
|
||||
|
||||
# 객체 지향 프로그래밍(OOP)
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 이 문서는 P-Reinforce Phase 2 자동 MERGE에 의해 **[[객체_지향_프로그래밍(OOP)]]**로 통합되었습니다.
|
||||
> **이 문서는 [[Object-Oriented Programming]] 의 중복본입니다.** Canonical 문서로 redirect.
|
||||
|
||||
---
|
||||
*Redirected to: [[객체_지향_프로그래밍(OOP)]]*
|
||||
## 핵심 요약
|
||||
- 매 spacing 만 다른 동일 concept.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Object-Oriented Programming]] (canonical)
|
||||
|
||||
## 🕓 변경 이력
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | 중복 처리 — canonical 문서로 redirect |
|
||||
|
||||
@@ -2,94 +2,215 @@
|
||||
id: wiki-2026-0508-견고한-도메인-모델-및-api-계약-설계
|
||||
title: 견고한 도메인 모델 및 API 계약 설계
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-E5BF95]
|
||||
aliases: [Domain Model Design, API Contract Design, DDD]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [ddd, domain-model, api-design, contract, type-driven]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - 견고한 도메인 모델 및 API 계약 설계"
|
||||
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/Java
|
||||
framework: Zod/Pydantic/OpenAPI
|
||||
---
|
||||
|
||||
# [[견고한 도메인 모델 및 API 계약 설계]]
|
||||
# 견고한 도메인 모델 및 API 계약 설계
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> 견고한 도메인 모델 및 API 계약 설계는 TypeScript의 정적 타입 시스템을 활용하여 유효하지 않은 상태를 원천 차단하고 예측 가능한 애플리케이션 구조를 만드는 과정입니다. 이를 위해 식별 가능한 유니온, 브랜디드 타입, 불변성 제약, 그리고 "검증하지 말고 파싱하라"와 같은 설계 철학을 결합하여, 경계면에서부터 데이터의 무결성을 보장하는 안전한 계약을 수립합니다.
|
||||
## 매 한 줄
|
||||
> **"매 type-driven domain model + 매 versioned API contract 의 결합으로 매 invalid state 를 unrepresentable 로 만든다"**. 매 DDD aggregate + value object + Zod/Pydantic schema + OpenAPI contract — 매 2024 modern stack.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **"검증하지 말고 파싱하라 (Parse, don't validate)":** 시스템 경계(API 진입점이나 출구)에서 타입이 지정되지 않은 데이터를 수동으로 검증하기만 하는 대신, 잘 정의된 타입의 데이터로 파싱하여 변환해야 합니다 [1, 2]. Zod와 같은 런타임 검증 라이브러리를 브랜디드 타입과 결합하면, 알 수 없는 데이터를 명확한 타입으로 좁히고 시스템 내부에서 정적 분석의 이점을 온전히 누릴 수 있습니다 [3, 4].
|
||||
* **식별 가능한 유니온([[Discriminated Unions]])과 완전성 검사:** 객체의 공통 리터럴 속성을 식별자로 사용하는 유니온 타입을 통해, 런타임에 유효하지 않은 상태가 아예 표현될 수 없도록 도메인을 모델링합니다 [5-7]. 여기에 `never` 타입을 활용한 완전성 검사(Exhaustiveness checking)를 더하면, 새로운 API 응답 상태나 도메인 로직이 추가될 때 처리되지 않은 케이스를 컴파일 에러로 즉각 잡아낼 수 있습니다 [6, 8-10].
|
||||
* **브랜디드 타입(Branded Types)을 통한 명목적 타이핑:** TypeScript의 구조적 타이핑이 갖는 한계(기본 타입에의 집착)를 극복하기 위해, 식별용 가상 속성이나 `unique symbol`을 교집합으로 추가하여 고유한 불투명 타입(Opaque Types)을 생성합니다 [11-14]. 이를 통해 사용자 ID와 주문 ID처럼 구조가 동일한 문자열이나 숫자일지라도 서로 섞여 API 계약을 위반하는 치명적인 버그를 컴파일 타임에 차단합니다 [3, 15, 16].
|
||||
* **`satisfies` 연산자를 활용한 엄격한 계약 강제:** 변수를 거친 간접 할당 과정에서는 타입스크립트의 과잉 속성 체크([[Excess Property Checking]])가 작동하지 않을 수 있습니다 [17, 18]. 백엔드 API 응답을 프론트엔드 모델로 매핑할 때 `satisfies` 연산자를 사용하면, 추가된 초과 속성을 엄격하게 에러로 잡아내면서도 구체적인 리터럴 타입 추론을 그대로 유지하여 계약의 엄격성과 유연성을 동시에 달성합니다 [19-22].
|
||||
* **불변성(Immutability) 확립:** 객체와 배열의 무분별한 상태 변경을 막고 데이터 무결성을 보장하기 위해 `[[readonly]]` 수식어와 `[[DeepReadonly]]` 재귀적 유틸리티 타입을 적용합니다 [23-25]. 식별자, 설정 객체, API 응답 등 절대 변경되어서는 안 되는 핵심 데이터에 컴파일 타임의 강력한 보호막을 제공합니다 [25, 26].
|
||||
* **도메인 방어 및 예외 처리 설계:** 비즈니스 로직에서 예상 가능한 실패를 처리할 때 단순히 `throw`로 예외를 발생시키는 대신, `Result` 타입을 명시적으로 반환합니다 [27-30]. 이를 통해 함수 시그니처 자체를 견고한 계약으로 만들어, API의 가능한 모든 결과(오류 포함)를 소비자가 안전하고 철저하게 처리하도록 강제합니다 [28, 29, 31].
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 도메인 모델 의 견고함
|
||||
- **Value Object**: 매 immutable + equality by value (Money, Email, OrderId).
|
||||
- **Entity / Aggregate Root**: 매 identity + lifecycle + invariant 보호.
|
||||
- **Make illegal states unrepresentable**: 매 sum type / discriminated union 사용.
|
||||
- **Smart Constructor**: 매 raw type → validated branded type 의 single entry.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** Parse, don't validate, 식별 가능한 유니온 (Discriminated Unions), [[브랜디드 타입 (Branded Types)]], [[Satisfies 연산자]], [[불변성 (Immutability)]], Result 타입
|
||||
- **Projects/Contexts:** Zod를 활용한 런타임 데이터 검증, API 응답 처리 및 상태 머신 모델링
|
||||
- **Contradictions/Notes:** 소스에 따르면 교집합(`&`)과 타입 별칭(`type`)만으로도 객체를 조합할 수 있지만, 대규모 프로젝트의 성능과 컴파일러 캐싱 최적화를 고려할 때 핵심 도메인 객체 선언에는 인터페이스 상속(`interface extends`)을 우선시하는 것이 권장됩니다 [32-34]. 또한 비즈니스 흐름 제어를 위해 전통적인 예외(`Exception`) 투척보다는 `Result` 패턴을 활용하는 방식이 더욱 안전한 설계로 제시됩니다 [28, 30, 35].
|
||||
### 매 API 계약 의 견고함
|
||||
- **Schema-first**: OpenAPI / JSON Schema / GraphQL SDL — 매 source of truth.
|
||||
- **Backward compat**: additive change only, 매 deprecation header, version in URL/header.
|
||||
- **Idempotency key**: 매 mutation 의 retry-safe 화.
|
||||
- **Pagination + filter + sort 표준화**: cursor-based >>> offset-based.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
### 매 응용
|
||||
1. e-commerce checkout (Money, Cart, Order aggregate).
|
||||
2. Banking (Account, Transaction, immutable ledger).
|
||||
3. Multi-tenant SaaS (Tenant 의 invariant 격리).
|
||||
4. Public API (Stripe-style versioned contract).
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
### 매 Branded type (TS) — primitive obsession 의 회피
|
||||
```typescript
|
||||
type Brand<T, B> = T & { __brand: B };
|
||||
type Email = Brand<string, "Email">;
|
||||
type UserId = Brand<string, "UserId">;
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(TODO)*
|
||||
const parseEmail = (s: string): Email => {
|
||||
if (!/^[^@]+@[^@]+$/.test(s)) throw new Error("Invalid email");
|
||||
return s as Email;
|
||||
};
|
||||
|
||||
**언제 쓰면 안 되는가:**
|
||||
- *(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
|
||||
function send(to: Email, msg: string) { /* ... */ }
|
||||
send("not-email" as Email, "x"); // unsafe cast 만 통과 — 매 explicit
|
||||
send(parseEmail("a@b.com"), "x"); // safe path
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### Value Object (Money)
|
||||
```typescript
|
||||
class Money {
|
||||
private constructor(readonly amount: bigint, readonly currency: string) {}
|
||||
static of(amount: number, currency: string) {
|
||||
if (!Number.isFinite(amount)) throw new Error("non-finite");
|
||||
return new Money(BigInt(Math.round(amount * 100)), currency);
|
||||
}
|
||||
add(other: Money) {
|
||||
if (this.currency !== other.currency) throw new Error("currency mismatch");
|
||||
return new Money(this.amount + other.amount, this.currency);
|
||||
}
|
||||
equals(other: Money) {
|
||||
return this.amount === other.amount && this.currency === other.currency;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### 매 illegal state unrepresentable (TS discriminated union)
|
||||
```typescript
|
||||
type OrderState =
|
||||
| { kind: "draft"; cart: CartLine[] }
|
||||
| { kind: "placed"; orderId: OrderId; placedAt: Date }
|
||||
| { kind: "shipped"; orderId: OrderId; tracking: string }
|
||||
| { kind: "cancelled"; reason: string };
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
function summary(o: OrderState) {
|
||||
switch (o.kind) {
|
||||
case "draft": return `Draft (${o.cart.length} items)`;
|
||||
case "placed": return `Placed ${o.orderId}`;
|
||||
case "shipped": return `Shipped ${o.tracking}`;
|
||||
case "cancelled": return `Cancelled: ${o.reason}`;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### Zod schema (runtime + static type)
|
||||
```typescript
|
||||
import { z } from "zod";
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
const CreateOrderSchema = z.object({
|
||||
customerId: z.string().uuid(),
|
||||
items: z.array(z.object({
|
||||
sku: z.string().min(1),
|
||||
qty: z.number().int().positive().max(1000)
|
||||
})).min(1),
|
||||
idempotencyKey: z.string().uuid()
|
||||
});
|
||||
type CreateOrderReq = z.infer<typeof CreateOrderSchema>;
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
app.post("/orders", (req, res) => {
|
||||
const parsed = CreateOrderSchema.safeParse(req.body);
|
||||
if (!parsed.success) return res.status(400).json({ errors: parsed.error.issues });
|
||||
// parsed.data is fully typed
|
||||
});
|
||||
```
|
||||
|
||||
### Aggregate Root (invariant protection)
|
||||
```typescript
|
||||
class Order {
|
||||
private constructor(
|
||||
readonly id: OrderId,
|
||||
private state: OrderState,
|
||||
private lines: OrderLine[]
|
||||
) {}
|
||||
|
||||
addLine(line: OrderLine) {
|
||||
if (this.state.kind !== "draft") throw new Error("cannot modify placed order");
|
||||
if (this.lines.length >= 50) throw new Error("max 50 lines");
|
||||
this.lines.push(line);
|
||||
}
|
||||
place(): void {
|
||||
if (this.lines.length === 0) throw new Error("empty cart");
|
||||
this.state = { kind: "placed", orderId: this.id, placedAt: new Date() };
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### OpenAPI 의 versioned contract
|
||||
```yaml
|
||||
# openapi.yaml
|
||||
openapi: 3.1.0
|
||||
info: { title: Orders API, version: "2026-05-01" }
|
||||
paths:
|
||||
/v1/orders:
|
||||
post:
|
||||
parameters:
|
||||
- in: header
|
||||
name: Idempotency-Key
|
||||
required: true
|
||||
schema: { type: string, format: uuid }
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: '#/components/schemas/CreateOrder' }
|
||||
responses:
|
||||
'201': { $ref: '#/components/responses/Order' }
|
||||
'409': { description: Idempotency conflict }
|
||||
```
|
||||
|
||||
### Cursor pagination
|
||||
```typescript
|
||||
type Page<T> = { items: T[]; nextCursor: string | null };
|
||||
async function listOrders(cursor?: string): Promise<Page<OrderDto>> {
|
||||
const rows = await db.query(
|
||||
"SELECT * FROM orders WHERE id > $1 ORDER BY id LIMIT 51",
|
||||
[cursor ?? ""]
|
||||
);
|
||||
const hasMore = rows.length === 51;
|
||||
const items = rows.slice(0, 50);
|
||||
return {
|
||||
items: items.map(toDto),
|
||||
nextCursor: hasMore ? items[items.length - 1].id : null
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| 매 simple CRUD | DTO + validator (Zod/Pydantic) — DDD overkill |
|
||||
| 매 complex domain (banking, scheduling) | Aggregate + VO + invariant |
|
||||
| 매 public API | OpenAPI contract-first + version |
|
||||
| 매 internal RPC | gRPC / tRPC + protobuf / TS infer |
|
||||
| 매 event-driven | event schema (Avro/protobuf) + registry |
|
||||
|
||||
**기본값**: 매 schema-first (Zod / OpenAPI) + branded ID + idempotency + cursor pagination.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Domain-Driven Design]] · [[API Design]]
|
||||
- 변형: [[Hexagonal Architecture]] · [[Event Sourcing]] · [[CQRS]]
|
||||
- 응용: [[Stripe API]] · [[Shopify API]]
|
||||
- Adjacent: [[Type-Driven Development]] · [[OpenAPI]] · [[gRPC]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: schema generation, contract review, illegal-state 발견, migration 전략.
|
||||
**언제 X**: 매 internal throwaway script — 매 over-engineering.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Primitive Obsession**: string everywhere — UserId 와 OrderId 의 swap silent.
|
||||
- **Anemic Domain**: getter/setter 만, business logic 의 service 누설.
|
||||
- **Shared Mutable Aggregate**: 매 invariant 의 broken.
|
||||
- **Breaking change in v1 endpoint**: 매 client 의 parallel 운영 X.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Evans *DDD* 2003, Vernon *Implementing DDD* 2013, Stripe API design guide 2024).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — branded types + Zod + OpenAPI + aggregate patterns |
|
||||
|
||||
@@ -2,97 +2,151 @@
|
||||
id: wiki-2026-0508-계층화-아키텍처-layered-architecture
|
||||
title: 계층화 아키텍처 (Layered Architecture)
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-1EAECE]
|
||||
aliases: [Layered Architecture, N-tier, Tiered Architecture]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [architecture, layering, separation-of-concerns, n-tier]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - 계층화 아키텍처 (Layered [[Architecture]])"
|
||||
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: agnostic
|
||||
framework: Spring/.NET/Django
|
||||
---
|
||||
|
||||
# [[계층화 아키텍처 (Layered Architecture)]]
|
||||
# 계층화 아키텍처 (Layered Architecture)
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> 계층화 아키텍처(Layered Architecture)는 시스템을 특정 책임을 가진 여러 수평적 계층(Layer)으로 나누어 구성하는 전통적이고 영향력 있는 소프트웨어 설계 패턴입니다 [1]. 각 계층은 사용자 인터페이스, 비즈니스 로직, 데이터 접근 등 특정 관심사(Concern)만을 전담하여 엄격한 관심사의 분리(SoC)를 강제합니다 [1, 2]. 이를 통해 각 계층은 주로 인접한 계층과만 소통하게 되며, 결과적으로 시스템의 결합도를 낮추고 유지보수성, 확장성 및 테스트 용이성을 크게 향상시키는 것을 목표로 합니다 [1, 3].
|
||||
## 매 한 줄
|
||||
> **"매 application 을 horizontal layer (presentation / business / persistence / data) 의 stack 으로 조직"**. 매 가장 흔한 default architecture — 매 simple, 매 onboarding 쉬움. 매 large-scale 에서 coupling/performance 한계 발생 → microservice/hexagonal 로 진화.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **개념 및 핵심 목표:** n-tier 아키텍처라고도 불리는 이 패턴은 애플리케이션의 기능적 영역을 수평적으로 격리합니다 [1]. 이를 통해 개발자는 다른 계층에 영향을 주지 않고 특정 계층의 코드를 수정하거나 테스트할 수 있으며, 이는 관심사의 분리(SoC)를 실무에 적용하는 가장 대표적인 방법론입니다 [1, 2].
|
||||
* **'뇌와 팔다리의 분리' 관점의 적용:** 계층화 아키텍처에서 하위 계층(인프라, 데이터베이스 등 팔다리 역할)은 구체적인 기술적 세부 사항을 담당하며, 상위 계층(핵심 비즈니스 로직 등 뇌 역할)에 대해 전혀 알지 못하는 상태로 필요한 서비스를 제공합니다 [4-6]. 이 구조는 시스템의 핵심적인 '사고(비즈니스 규칙)' 영역이 외부의 잦은 기술적 변화로부터 오염되지 않고 순수성을 유지할 수 있도록 보호합니다 [7, 8].
|
||||
* **전형적인 3계층 구조 (3-Tier Structure):** 현대 웹 애플리케이션 등에서 가장 흔히 볼 수 있는 계층 분리 방식은 다음과 같습니다.
|
||||
* **프레젠테이션 계층 (Presentation Layer):** 사용자 인터페이스(UI)와 사용자 경험(UX) 로직을 전담하며, 화면 렌더링 및 사용자 입력을 캡처하는 최상단 계층입니다 [2, 9].
|
||||
* **비즈니스 로직 계층 ([[business]] [[Logic]] Layer / Domain Layer):** 애플리케이션의 핵심 업무 규칙과 프로세싱을 처리합니다. 프레젠테이션 계층과 독립적으로 존재하며 시스템의 동작을 제어합니다 [2, 9].
|
||||
* **데이터 액세스 계층 (Data Access Layer / Persistence Layer):** 데이터베이스와의 통신(CRUD 작업 등)을 전담합니다. 다른 계층이 데이터가 어떻게 저장되거나 조회되는지 그 세부 사항을 알 수 없도록 완벽하게 격리합니다 [2, 9].
|
||||
* **성공적인 구현을 위한 공학적 원칙:**
|
||||
* **엄격한 통신 규칙 강제:** 시스템의 관리를 용이하게 하려면, 특정 계층은 바로 아래에 있는 인접한 계층과만 소통해야 합니다 [2, 3].
|
||||
* **인터페이스와 의존성 주입(DI) 활용:** 상위 계층이 하위 계층의 구체적인 구현에 의존하지 않도록 명확한 인터페이스를 정의하고 의존성 주입을 활용해야 합니다. 이를 통해 데이터베이스나 프레임워크가 변경되더라도 상위 계층의 코드는 수정할 필요가 없게 됩니다 [3, 4, 10].
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 표준 layer
|
||||
- **Presentation**: UI / REST controller / GraphQL resolver. 매 input 의 validation + serialization.
|
||||
- **Business / Service**: domain logic, transaction boundary, orchestration.
|
||||
- **Persistence / Repository**: ORM, query, cache.
|
||||
- **Data**: DB, file, message broker.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[응집도와 결합도 (Cohesion and Coupling)]], [[단일 책임 원칙 (SRP)]], [[의존성 역전 원칙 (DIP)]], [[클린 아키텍처 (Clean Architecture)]]
|
||||
- **Projects/Contexts:** [[웹 애플리케이션의 3계층 구조]], [[엔터프라이즈 애플리케이션 설계]]
|
||||
- **Contradictions/Notes:** 소스는 계층화 아키텍처가 시스템의 복잡성을 줄이고 관심사를 성공적으로 격리한다고 긍정적으로 평가하지만, 동시에 지나친 관심사 분리(과도한 계층화 및 추상화)는 여러 계층을 거쳐야 하는 성능 오버헤드를 유발하거나, 오히려 코드를 추적하기 어렵게 만드는 '인디렉션의 저주(Curse of Indirection)'를 발생시킬 수 있다고 경고합니다 [11-13].
|
||||
### 매 strict vs relaxed
|
||||
- **Strict layering**: 매 layer N 은 layer N-1 만 호출 가능. 매 testability 좋음.
|
||||
- **Relaxed**: layer skip 가능 (e.g. controller → repository 직접). 매 anti-pattern 으로 간주.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
### 매 응용
|
||||
1. Spring Boot 의 @Controller / @Service / @Repository.
|
||||
2. Django 의 view / business / model.
|
||||
3. Clean Architecture 의 adapter ring 변형.
|
||||
4. .NET 의 N-tier WebAPI / BLL / DAL.
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
### Spring Boot 의 표준 3-layer
|
||||
```java
|
||||
@RestController
|
||||
@RequestMapping("/orders")
|
||||
public class OrderController {
|
||||
private final OrderService service;
|
||||
public OrderController(OrderService s) { this.service = s; }
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(TODO)*
|
||||
@PostMapping
|
||||
public OrderDto create(@RequestBody @Valid CreateOrderReq req) {
|
||||
return service.create(req);
|
||||
}
|
||||
}
|
||||
|
||||
**언제 쓰면 안 되는가:**
|
||||
- *(TODO)*
|
||||
@Service
|
||||
public class OrderService {
|
||||
private final OrderRepo repo;
|
||||
@Transactional
|
||||
public OrderDto create(CreateOrderReq req) {
|
||||
Order o = Order.from(req);
|
||||
return OrderDto.from(repo.save(o));
|
||||
}
|
||||
}
|
||||
|
||||
## 🧪 검증 상태 (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
|
||||
@Repository
|
||||
public interface OrderRepo extends JpaRepository<Order, Long> {}
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### DTO ↔ Domain 매 boundary
|
||||
```java
|
||||
// 매 controller 는 DTO 만, service 는 domain entity 만 다룬다.
|
||||
public record CreateOrderReq(String sku, int qty) {}
|
||||
public record OrderDto(Long id, String sku, int qty, String status) {
|
||||
public static OrderDto from(Order o) {
|
||||
return new OrderDto(o.getId(), o.getSku(), o.getQty(), o.getStatus().name());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Repository abstraction (testability)
|
||||
```java
|
||||
public interface OrderRepo {
|
||||
Order save(Order o);
|
||||
Optional<Order> findById(Long id);
|
||||
}
|
||||
// 매 unit test 의 Stub repository 의 inject:
|
||||
class StubOrderRepo implements OrderRepo { /* in-memory */ }
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### 매 cross-cutting (logging / tx / auth) 의 AOP
|
||||
```java
|
||||
@Aspect
|
||||
@Component
|
||||
class AuditAspect {
|
||||
@Around("@annotation(Audited)")
|
||||
public Object audit(ProceedingJoinPoint pjp) throws Throwable {
|
||||
long t0 = System.nanoTime();
|
||||
Object result = pjp.proceed();
|
||||
log.info("{} took {}ns", pjp.getSignature(), System.nanoTime() - t0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### Layer 의 dependency rule (안티: upward call)
|
||||
```java
|
||||
// ❌ Service 가 Controller 호출 X
|
||||
// ❌ Repository 가 Service 호출 X
|
||||
// ✅ 매 한 방향: presentation → service → persistence
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| CRUD-heavy MVP | 매 layered (default 선택) |
|
||||
| 매 complex domain logic | hexagonal / clean architecture |
|
||||
| 매 high decoupling 필요 | event-driven / CQRS |
|
||||
| 매 large team / bounded context | microservice |
|
||||
| 매 simple script | 매 layer X — single file |
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
**기본값**: 매 small/medium app 은 **3-layer (controller / service / repository)** + DI + DTO boundary.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Software Architecture]]
|
||||
- 변형: [[Hexagonal Architecture]] · [[Clean Architecture]] · [[Onion Architecture]]
|
||||
- 응용: [[Spring Boot]] · [[Django]] · [[ASP.NET Core]]
|
||||
- Adjacent: [[Separation of Concerns]] · [[Dependency Injection]] · [[Repository Pattern]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: scaffolding generation, layer 위반 review, refactor towards layered.
|
||||
**언제 X**: 매 trivial CRUD — boilerplate overhead.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Anemic Service**: 매 service 가 단순 repo passthrough — domain logic 누락.
|
||||
- **Smart Controller**: business logic 의 controller 누수.
|
||||
- **Layer skip**: controller 가 repo 직접 호출.
|
||||
- **God Service**: 매 service class 가 5000+ lines — bounded context 분할 필요.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Richards *Software Architecture Patterns* 2nd ed. 2022).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — layered patterns + Spring example + anti-patterns |
|
||||
|
||||
@@ -2,92 +2,145 @@
|
||||
id: wiki-2026-0508-과잉-속성-체크-excess-property-checkin
|
||||
title: 과잉 속성 체크 (Excess Property Checking)
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-9B5810]
|
||||
aliases: [Excess Property Checking, EPC, TS Excess Property]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [typescript, type-system, structural-typing, epc]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - 과잉 속성 체크 ([[Excess Property Checking]])"
|
||||
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: TS 5.x
|
||||
---
|
||||
|
||||
# [[과잉 속성 체크 (Excess Property Checking)]]
|
||||
# 과잉 속성 체크 (Excess Property Checking)
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> TypeScript의 과잉 속성 체크(Excess Property Checking, EPC)는 객체 리터럴이 다른 변수에 직접 할당되거나 함수의 인자로 전달될 때, 대상 타입에 정의되지 않은 속성이 포함되어 있는지를 엄격하게 검사하는 기능이다[1-4]. 이는 구조적 타이핑([[Structural Typing]])의 유연함으로 인해 속성 이름의 오타나 잘못된 데이터가 유입되어 발생하는 런타임 오류를 컴파일 시점에 방지하는TypeScript의 핵심 방어 기제로 작동한다[5-7].
|
||||
## 매 한 줄
|
||||
> **"매 object literal 을 직접 assign / pass 할 때만 발동하는 TS 의 추가 strictness rule"**. 매 structural typing 의 원칙적으론 OK 인 extra property 를 매 fresh object literal 에 한해 error 로 잡아 typo 방지. 매 변수 경유 시 자동 비활성화.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **도입 배경 및 목적**: TypeScript는 기본적으로 객체의 형태(구조)가 일치하면 타입의 호환성을 인정하는 구조적 타이핑(덕 타이핑) 원칙을 따른다[7-9]. 그러나 대상 타입의 속성을 충족하더라도 오타(예: `color` 대신 `colour`를 입력)와 같은 실수로 잉여 속성이 포함되면 의도치 않은 런타임 동작이 발생할 수 있다[5, 6]. 이러한 한계를 보완하기 위해 TypeScript는 객체 리터럴에 대해 예외적으로 더 엄격한 잣대를 들이대는 '과잉 속성 체크'를 수행한다[1, 5].
|
||||
- **동작 방식과 한계 (우회 현상)**: 과잉 속성 체크는 객체 리터럴이 변수에 직접 할당되거나 인자로 전달되는 특수한 경우에만 작동한다[3, 5]. 만약 변수를 먼저 선언한 후 이를 다른 타입에 간접적으로 할당하거나 제네릭 타입 매개변수를 사용하는 경우, 두 객체 사이에 최소 하나의 공통 속성만 존재한다면 과잉 속성 체크가 작동하지 않는다[10-12]. 이는 시스템이 "최소 요건 충족"이라는 구조적 타이핑의 기본 원칙으로 되돌아가기 때문이다[12]. (단, 선택적 속성만 가진 '약한 타입(Weak Type)'의 경우에는 공통 속성이 아예 없으면 에러를 발생시키는 약한 타입 탐지가 작동한다[13, 14].)
|
||||
- **우회로 인한 부작용**: 간접 할당 등을 통해 과잉 속성 체크가 우회되면, 예상치 못한 잉여 데이터가 객체 내부에 숨어들 수 있다[12]. 이는 React 컴포넌트 등에서 유효하지 않은 속성이 DOM으로 넘어가 경고를 발생시키거나, 불필요한 리렌더링을 유발하고 런타임 시 보안 유출의 원인이 되기도 한다[12, 15].
|
||||
- **`satisfies` 연산자를 통한 방비**: `as` 키워드를 이용한 타입 캐스팅([[Type Casting]])은 과잉 속성 체크를 수행하지 않아 잠재적인 에러를 유발할 수 있다[16]. 이 같은 취약점을 보완하기 위해 TypeScript 4.9에 도입된 `satisfies` 연산자는 객체가 특정 인터페이스나 타입을 만족하는지 엄격히 검사하여 과잉 속성의 유입을 컴파일 단계에서 차단한다[17, 18]. 더불어 객체의 구체적인 값(리터럴 타입 등)을 유지해 정밀한 타입 추론과 타입 좁히기(Narrowing)를 돕는 혁신적인 수비 전략으로 활용된다[18-20].
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
|
||||
### 매 작동 방식
|
||||
- TS 의 **structural / duck typing** 은 매 extra property OK.
|
||||
- 그러나 매 **object literal 을 fresh 하게 assign 시** TS 는 추가로 surplus key 를 error 로 보고.
|
||||
- 매 변수에 한 번 alias 하면 fresh 신호가 사라져 EPC 우회.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** 구조적 타이핑 (Structural Typing), [[satisfies 연산자]], [[타입 캐스팅 (Type Casting)]], [[약한 타입 탐지 (Weak Type Detection)]]
|
||||
- **Projects/Contexts:** 철벽 수비대" - TypeScript 타입 시스템 (인터페이스 설계), [[React 컴포넌트 Props 검증]]
|
||||
- **Contradictions/Notes:** 객체 리터럴을 직접 할당할 때는 과잉 속성 체크가 발동되어 에러를 반환하지만, 중간 변수를 통해 간접 할당될 때는 구조적 타이핑 원칙이 적용되어 과잉 속성이 존재해도 에러가 발생하지 않는 모순적 동작을 보인다[1, 3, 5, 12]. 또한 `as` 연산자는 과잉 속성을 무시하고 할당을 허용하지만, `satisfies` 연산자는 초과된 속성에 대해 엄격한 검증을 강제한다[16, 21].
|
||||
### 매 발동 조건
|
||||
- 매 object literal 의 직접 assignment / argument / return.
|
||||
- 매 contextual type 이 존재.
|
||||
- 매 변수 경유, type assertion (`as`), spread 시 비활성화.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
### 매 응용
|
||||
1. Component prop typo 방지 (React).
|
||||
2. API request body 의 surplus field 차단.
|
||||
3. Config object 의 misnamed key 발견.
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
### 매 EPC 발동 (error)
|
||||
```typescript
|
||||
interface User { name: string; age: number }
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(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
|
||||
const u: User = { name: "Lee", age: 30, emial: "x" };
|
||||
// ^^^^^ 매 EPC: 'emial' does not exist on User
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### 매 변수 경유 우회 (error 사라짐)
|
||||
```typescript
|
||||
const raw = { name: "Lee", age: 30, emial: "x" };
|
||||
const u: User = raw; // ✅ OK — fresh 아니라 EPC 비활성
|
||||
// 매 structural compatibility 만 본다 (User 의 모든 prop 충족 → OK)
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### 매 함수 인자 EPC
|
||||
```typescript
|
||||
function greet(u: User) { console.log(u.name); }
|
||||
greet({ name: "A", age: 1, extra: 1 }); // ❌ EPC error
|
||||
const x = { name: "A", age: 1, extra: 1 };
|
||||
greet(x); // ✅ OK
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### 매 index signature 의 escape hatch
|
||||
```typescript
|
||||
interface Loose {
|
||||
name: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
const l: Loose = { name: "A", whatever: 123, deep: { x: 1 } }; // ✅ OK
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### 매 union type 의 EPC quirk
|
||||
```typescript
|
||||
type A = { kind: "a"; a: number };
|
||||
type B = { kind: "b"; b: number };
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
const x: A | B = { kind: "a", a: 1, b: 2 };
|
||||
// ❌ EPC: 'b' is not in A; not in B 의 fresh form
|
||||
// 매 변수 경유 시 통과 — 의도치 않은 leakage 가능
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### 매 의도적 우회 (type assertion — 위험)
|
||||
```typescript
|
||||
const u: User = { name: "A", age: 1, emial: "x" } as User;
|
||||
// ⚠ 매 작동하지만 매 typo 의 silent — 매 강력히 X
|
||||
```
|
||||
|
||||
### 매 React component prop typo 방지
|
||||
```typescript
|
||||
type ButtonProps = { label: string; onClick: () => void };
|
||||
const Button = (p: ButtonProps) => <button onClick={p.onClick}>{p.label}</button>;
|
||||
|
||||
<Button labl="Hi" onClick={() => {}} />; // ❌ EPC: 'labl' typo 발견
|
||||
```
|
||||
|
||||
### 매 satisfies operator (TS 4.9+) — 매 EPC 유지 + inference
|
||||
```typescript
|
||||
const config = {
|
||||
port: 8080,
|
||||
host: "localhost",
|
||||
// typoKey: 1 // ❌ EPC error if uncomment
|
||||
} satisfies { port: number; host: string };
|
||||
// 매 config.port: number 의 narrow type 유지 + EPC 활성
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| 매 strict typo 검출 | 매 object literal 직접 assign + EPC 활용 |
|
||||
| 매 동적 key 다수 | index signature 추가 |
|
||||
| 매 narrow + EPC 동시 | `satisfies` operator |
|
||||
| 매 변수 경유 필요 | type annotation 변수 + literal 사용 |
|
||||
| 매 EPC 의도적 회피 | 매 보통 X — type 의 재설계 |
|
||||
|
||||
**기본값**: 매 object literal 의 직접 assign + `satisfies` 또는 explicit type — 매 변수 경유 의 무의식적 우회 X.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[TypeScript]] · [[구조적 타이핑(Structural Typing)]]
|
||||
- 변형: [[Strict Mode (TS)]] · [[satisfies operator]]
|
||||
- 응용: [[React Props]] · [[API Contract]]
|
||||
- Adjacent: [[Index Signature]] · [[Type Narrowing]] · [[Discriminated Union]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: TS error 디버깅 ("excess property"), refactor 시 EPC 의도 검증.
|
||||
**언제 X**: 매 runtime validation — 매 EPC 는 컴파일타임만.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **as Type 으로 EPC 회피**: 매 typo 의 silent.
|
||||
- **변수 경유 의 우회**: 매 의도면 OK, 매 실수면 위험.
|
||||
- **EPC 비활성화 의 흔한 오해**: 매 spread `{ ...x, extra: 1 }` 의 fresh — EPC 발동.
|
||||
- **runtime 신뢰**: EPC 는 매 compile-time only — 매 런타임 검증 X.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (TypeScript Handbook — Object Types, TS 5.x source).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — EPC 발동 조건 + 우회 + satisfies |
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user