docs(10_Wiki): Topic_Business/General/Graphic/Programming을 Topics/ 하위로 이동
최상위 10_Wiki/Topic_*였던 4개 카테고리 폴더를 10_Wiki/Topics/Topic_* 로 재배치. 콘텐츠 변경 없음(순수 폴더 이동) — Topics/ 하위 나머지 폴더는 이미 지난 커밋에서 전부 정리된 상태(잔존 항목은 에이전트 운영 상태 및 사용자가 보존을 요청한 업데이트0615/무제 3.canvas 뿐).
This commit is contained in:
@@ -0,0 +1,351 @@
|
||||
---
|
||||
id: wiki-2026-0508-dsl
|
||||
title: Domain-Specific Languages (DSL)
|
||||
category: 10_Wiki/Topics
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [DSL, internal DSL, external DSL, fluent API, embedded DSL, NL-to-DSL]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
verification_status: applied
|
||||
tags: [dsl, programming-languages, abstraction, fluent-api, ddd, sql, regex, llm-dsl]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
tech_stack:
|
||||
language: any
|
||||
framework: ANTLR / PEG / Tree-sitter
|
||||
---
|
||||
|
||||
# DSL (Domain-Specific Language)
|
||||
|
||||
## 매 한 줄
|
||||
> **"매 specific domain 의 optimized 의 language"**. 매 SQL, regex, HTML, CSS 의 omnipresent. 매 internal (embedded) vs external. 매 modern: 매 LLM 의 NL → DSL 의 best interface. 매 IaC 의 Terraform / config DSL 의 boom.
|
||||
|
||||
## 매 핵심
|
||||
|
||||
### 매 type
|
||||
|
||||
#### External DSL
|
||||
- 매 own grammar.
|
||||
- 매 parser / compiler 필요.
|
||||
- 예: SQL, regex, CSS, GraphQL, Gherkin, HCL (Terraform).
|
||||
|
||||
#### Internal DSL (Embedded)
|
||||
- 매 host language 의 문법 안.
|
||||
- 매 fluent API.
|
||||
- 예: jQuery, RSpec, Gradle (Kotlin DSL), zod schema.
|
||||
|
||||
### 매 design principle
|
||||
1. **Domain-aligned terminology**.
|
||||
2. **Declarative over imperative** ("what" not "how").
|
||||
3. **Composable**.
|
||||
4. **Readable by domain expert**.
|
||||
5. **Constrained** (less Turing-complete = better verification).
|
||||
|
||||
### 매 famous DSL
|
||||
- **SQL**: 매 query.
|
||||
- **Regex**: 매 pattern.
|
||||
- **CSS**: 매 styling.
|
||||
- **HTML / JSX**: 매 markup.
|
||||
- **GraphQL**: 매 query.
|
||||
- **Cypher** (Neo4j): 매 graph.
|
||||
- **HCL** (Terraform): 매 IaC.
|
||||
- **Gherkin**: 매 BDD.
|
||||
- **Mermaid / PlantUML**: 매 diagram.
|
||||
- **dbt SQL**: 매 transformation.
|
||||
|
||||
### 매 modern (LLM era)
|
||||
|
||||
#### NL-to-DSL
|
||||
- 매 natural language → 매 SQL / regex / etc.
|
||||
- 매 GitHub Copilot regex helper.
|
||||
- 매 Text2SQL 의 mature.
|
||||
|
||||
#### LLM-driven DSL
|
||||
- 매 LLM 의 better understand 매 specific DSL.
|
||||
- 매 internal company DSL 의 valuable.
|
||||
|
||||
### 매 tooling
|
||||
- **ANTLR**: 매 parser generator.
|
||||
- **PEG.js / Peggy**: 매 PEG-based.
|
||||
- **Tree-sitter**: 매 modern incremental.
|
||||
- **Lark** (Python).
|
||||
- **MPS** (JetBrains): 매 projectional.
|
||||
|
||||
### 매 응용
|
||||
1. **Configuration** (Helm, Terraform).
|
||||
2. **Workflow** (Airflow, GitHub Actions YAML).
|
||||
3. **Test specification** (Gherkin, RSpec).
|
||||
4. **Build** (Gradle, Bazel).
|
||||
5. **Domain modeling** (DDD ubiquitous language).
|
||||
6. **Hardware** (Verilog, VHDL).
|
||||
7. **Math / AI** (TLA+, Lean).
|
||||
|
||||
## 💻 패턴
|
||||
|
||||
### Internal DSL (TypeScript fluent)
|
||||
```ts
|
||||
// 매 query builder
|
||||
class QueryBuilder<T> {
|
||||
private filters: Filter[] = [];
|
||||
private sort: Sort[] = [];
|
||||
private limitN = 100;
|
||||
|
||||
where(field: keyof T, op: Op, value: unknown): this {
|
||||
this.filters.push({ field, op, value });
|
||||
return this; // 매 chain
|
||||
}
|
||||
|
||||
orderBy(field: keyof T, dir: 'asc' | 'desc'): this {
|
||||
this.sort.push({ field, dir });
|
||||
return this;
|
||||
}
|
||||
|
||||
limit(n: number): this {
|
||||
this.limitN = n;
|
||||
return this;
|
||||
}
|
||||
|
||||
build(): SQL {
|
||||
return `SELECT * FROM ${this.table} WHERE ${this.filters} ORDER BY ${this.sort} LIMIT ${this.limitN}`;
|
||||
}
|
||||
}
|
||||
|
||||
// 매 use
|
||||
const query = new QueryBuilder<User>()
|
||||
.where('age', '>', 18)
|
||||
.where('country', '=', 'US')
|
||||
.orderBy('createdAt', 'desc')
|
||||
.limit(50);
|
||||
```
|
||||
|
||||
### Zod schema (DSL-like)
|
||||
```ts
|
||||
import { z } from 'zod';
|
||||
|
||||
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']),
|
||||
preferences: z.object({
|
||||
theme: z.enum(['light', 'dark']).default('light'),
|
||||
notifications: z.boolean().default(true),
|
||||
}).optional(),
|
||||
});
|
||||
|
||||
type User = z.infer<typeof UserSchema>;
|
||||
```
|
||||
|
||||
### External DSL (Lark in Python)
|
||||
```python
|
||||
from lark import Lark, Transformer
|
||||
|
||||
grammar = """
|
||||
start: rule+
|
||||
rule: NAME ":" condition "→" action
|
||||
condition: "if" CNAME comparison NUMBER
|
||||
comparison: ">" | "<" | "=="
|
||||
action: CNAME "(" CNAME ")"
|
||||
NUMBER: /\\d+/
|
||||
%import common.CNAME
|
||||
%import common.NAME
|
||||
%import common.WS
|
||||
%ignore WS
|
||||
"""
|
||||
|
||||
dsl = """
|
||||
high_score: if score > 90 → notify(student)
|
||||
warn: if attendance < 70 → email(student)
|
||||
"""
|
||||
|
||||
parser = Lark(grammar)
|
||||
tree = parser.parse(dsl)
|
||||
|
||||
class MyDSL(Transformer):
|
||||
def rule(self, items):
|
||||
name, cond, action = items
|
||||
return {'name': name, 'condition': cond, 'action': action}
|
||||
|
||||
print(MyDSL().transform(tree))
|
||||
```
|
||||
|
||||
### NL → SQL (LLM-driven)
|
||||
```python
|
||||
def nl_to_sql(query, schema):
|
||||
prompt = f"""You are a SQL expert.
|
||||
|
||||
Schema:
|
||||
{schema}
|
||||
|
||||
Convert this natural language to SQL:
|
||||
"{query}"
|
||||
|
||||
Return ONLY the SQL, no explanation."""
|
||||
sql = llm.generate(prompt)
|
||||
|
||||
# 매 validate
|
||||
if not is_safe(sql) or has_destructive(sql):
|
||||
raise ValueError('Unsafe SQL')
|
||||
|
||||
return sql
|
||||
```
|
||||
|
||||
### Gherkin (BDD)
|
||||
```gherkin
|
||||
Feature: User login
|
||||
|
||||
Scenario: Successful login with valid credentials
|
||||
Given a registered user with email "test@example.com"
|
||||
And the user's password is "password123"
|
||||
When the user submits the login form
|
||||
Then they are redirected to "/dashboard"
|
||||
And a session cookie is set
|
||||
```
|
||||
|
||||
```python
|
||||
from behave import given, when, then
|
||||
|
||||
@given('a registered user with email "{email}"')
|
||||
def step_user(context, email):
|
||||
context.user = create_user(email)
|
||||
|
||||
@when('the user submits the login form')
|
||||
def step_submit(context):
|
||||
context.response = client.post('/login', {...})
|
||||
|
||||
@then('they are redirected to "{path}"')
|
||||
def step_redirect(context, path):
|
||||
assert context.response.url.endswith(path)
|
||||
```
|
||||
|
||||
### Terraform HCL
|
||||
```hcl
|
||||
resource "aws_instance" "web" {
|
||||
ami = "ami-0c55b159cbfafe1f0"
|
||||
instance_type = var.environment == "prod" ? "t3.large" : "t3.micro"
|
||||
|
||||
tags = merge(var.common_tags, {
|
||||
Name = "web-${var.environment}"
|
||||
})
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
prevent_destroy = var.environment == "prod"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Custom config DSL (Python)
|
||||
```python
|
||||
class PipelineDSL:
|
||||
def __init__(self):
|
||||
self.steps = []
|
||||
|
||||
def fetch(self, source: str):
|
||||
self.steps.append(('fetch', source))
|
||||
return self
|
||||
|
||||
def transform(self, fn):
|
||||
self.steps.append(('transform', fn))
|
||||
return self
|
||||
|
||||
def store(self, dest: str):
|
||||
self.steps.append(('store', dest))
|
||||
return self
|
||||
|
||||
def run(self):
|
||||
# 매 execute
|
||||
...
|
||||
|
||||
# 매 use
|
||||
pipeline = (PipelineDSL()
|
||||
.fetch('s3://my-bucket/data.csv')
|
||||
.transform(lambda df: df.dropna())
|
||||
.store('postgres://localhost/clean'))
|
||||
```
|
||||
|
||||
### Tree-sitter (parse)
|
||||
```js
|
||||
const Parser = require('tree-sitter');
|
||||
const SQL = require('tree-sitter-sql');
|
||||
|
||||
const parser = new Parser();
|
||||
parser.setLanguage(SQL);
|
||||
|
||||
const tree = parser.parse('SELECT * FROM users WHERE id = 1');
|
||||
console.log(tree.rootNode.toString());
|
||||
```
|
||||
|
||||
### Validate DSL (LLM-friendly)
|
||||
```python
|
||||
def validate_dsl(text, grammar):
|
||||
"""매 LLM 의 generated DSL 의 validate."""
|
||||
try:
|
||||
parser.parse(text)
|
||||
return {'valid': True}
|
||||
except ParseError as e:
|
||||
# 매 LLM 의 fix 의 ask
|
||||
fixed = llm.generate(f'Fix this DSL parse error:\n{e}\n{text}')
|
||||
return {'valid': False, 'fixed_attempt': fixed}
|
||||
```
|
||||
|
||||
### DSL 의 evaluation
|
||||
```python
|
||||
class CompiledDSL:
|
||||
def __init__(self, ast):
|
||||
self.ast = ast
|
||||
|
||||
def execute(self, context):
|
||||
return self._eval(self.ast, context)
|
||||
|
||||
def _eval(self, node, ctx):
|
||||
if node.type == 'literal': return node.value
|
||||
if node.type == 'variable': return ctx[node.name]
|
||||
if node.type == 'binary_op':
|
||||
left = self._eval(node.left, ctx)
|
||||
right = self._eval(node.right, ctx)
|
||||
return apply_op(node.op, left, right)
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | DSL Type |
|
||||
|---|---|
|
||||
| Domain expert reads | External DSL |
|
||||
| Programmer power | Internal (fluent) |
|
||||
| Configuration | YAML / HCL / TOML |
|
||||
| Build | Make / Gradle / Bazel |
|
||||
| Test BDD | Gherkin |
|
||||
| LLM interface | NL → DSL |
|
||||
| Constrained safety | External w/ verifier |
|
||||
|
||||
**기본값**: 매 internal DSL (TypeScript / Python fluent) for code-heavy. 매 external for non-dev.
|
||||
|
||||
## 🔗 Graph
|
||||
- 변형: [[External-DSL]] · [[Internal-DSL]] · [[Fluent-API]]
|
||||
- 응용: [[SQL]] · [[Terraform]] · [[Diagrams_as_Code]]
|
||||
- Adjacent: [[Bounded Contexts (DDD)]] · [[Domain-Driven-Design]] · [[Articulateness]] · [[Be-Detailed]] · [[Container_Queries]] (CSS DSL)
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 internal API design. 매 NL-to-DSL system. 매 IaC. 매 BDD.
|
||||
**언제 X**: 매 simple imperative task.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **DSL 의 Turing-complete 의 force**: 매 verification lose.
|
||||
- **No documentation / examples**: 매 adoption fail.
|
||||
- **Premature DSL** (small project): 매 over-engineering.
|
||||
- **NL → DSL 의 unvalidated**: 매 destructive (e.g., DROP TABLE).
|
||||
- **DSL leak host language**: 매 loose abstraction.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Fowler "DSLs", PoEAA, ANTLR / Tree-sitter docs).
|
||||
- 신뢰도 A.
|
||||
- Related: [[Bounded Contexts (DDD)]] · [[Articulateness]] · [[Diagrams_as_Code]] · [[Custom-ESLint-Rules-Development]] · [[Be-Detailed]].
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — internal/external + 매 zod / Lark / Gherkin / NL-to-SQL / Terraform code |
|
||||
Reference in New Issue
Block a user