---
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]] · [[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]] · [[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 |
