
# 아키텍처

TailwindPHP는 1:1 포트입니다. 코드베이스는 TailwindCSS 자체 구조를 미러링합니다. 파일 이름과 구성은 동일하며, 직접 포트할 수 없는 부분(PHP에는 Rust도 V8도 없음)은 `src/_tailwindphp/` 아래에 분리합니다. 이 페이지에서는 컴파일 파이프라인, 소스 구성, `lightningcss` 재구현, 차이점을 문서화하는 규칙을 설명합니다.

## 파이프라인

CSS 생성은 여러 단계로 진행됩니다. 별도의 빌드 단계는 없으며, `tw::generate()`를 호출할 때마다 전체 파이프라인이 실행됩니다.

```
CSS input          (@import "tailwindcss"; @theme { … })
  │
  ▼
┌──────────────┐
│  Parse CSS   │  css-parser.php → ast.php nodes
└──────┬───────┘
       ▼  design system (theme, utilities, variants)
┌──────────────┐
│ Scan content │  candidate.php — extract class names from HTML
└──────┬───────┘
       ▼  candidates
┌──────────────┐
│   Compile    │  compile.php — candidate → AST, via design-system.php
└──────┬───────┘
       ▼  AST
┌──────────────┐
│   Optimize   │  _tailwindphp/LightningCss.php — nesting, @media, calc()
└──────┬───────┘
       ▼
┌──────────────┐
│  Serialize   │  ast.php toCss()   (minified when requested)
└──────┬───────┘
       ▼
CSS output
```

**파싱.** `css-parser.php`는 CSS 입력인 `@import`, `@theme`, `@utility`, `@layer` 및 원시 규칙을 스타일 규칙, at-rule, 선언 노드로 이루어진 `ast.php` 추상 구문 트리로 읽습니다. 가상 모듈(`tailwindcss`, `tailwindcss/preflight`, …)을 위한 `@import` 지시문과 파일 경로도 이 단계에서 확인하고 대체합니다.

**디자인 시스템 구성.** `theme.php`는 파싱된 `@theme` 블록과 기본값에서 테마 값(색상, 간격, 중단점)을 확인합니다. `design-system.php`는 `utilities.php` 및 `variants.php`에 정의된 테마와 유틸리티 및 변형 조회를 연결하는 중앙 레지스트리입니다.

**콘텐츠 스캔.** `candidate.php`는 제공된 콘텐츠(HTML, 템플릿)에서 클래스 이름 후보를 추출하고, 각 후보를 기본 유틸리티, 변형, 수정자, 임의 값, important 플래그로 나눠 파싱합니다.

**컴파일.** `compile.php`는 각 후보를 디자인 시스템에서 조회하고 변형과 수정자를 적용해 AST 노드로 변환합니다. 실제 유틸리티에 해당하지 않는 후보는 제외합니다.

**직렬화 및 최적화.** `ast.php`의 `toCss()`는 트리를 순회하고(`walk.php`의 헬퍼 사용) CSS 문자열을 출력합니다. `_tailwindphp/LightningCss.php`의 `lightningcss`에 해당하는 변환을 적용하므로, 출력은 TailwindCSS가 Rust 후처리 단계에서 생성하는 결과와 일치합니다.

**최소화.** `minify`가 활성화되면 `toCss()`는 직렬화 중 최소화된 CSS를 출력합니다. 독립 실행형 `tw::minify()` 문자열 처리 단계는 `_tailwindphp/CssMinifier.php`를 기반으로 합니다. [캐싱 및 최소화](https://tailwindphp.inline0.dev/ko/docs/advanced/caching)를 참조하세요.

## 소스 구성

`src/`는 TailwindCSS를 미러링합니다. 구조상 달라진 점은 하나입니다. TailwindCSS의 `utilities.ts`는 6,000줄이 넘으므로, 유지 관리를 위해 범주별 파일 하나씩 `src/utilities/`로 나눕니다.

```
src/
├── _tailwindphp/                # PHP-specific — NOT part of the TailwindCSS port
│   ├── LightningCss.php         # CSS transforms (lightningcss Rust library equivalent)
│   ├── CssMinifier.php          # CSS minification
│   └── lib/                     # Companion library ports (TailwindPHP\Lib\*)
│       ├── clsx/                # clsx port
│       ├── tailwind-merge/      # tailwind-merge port
│       └── cva/                 # CVA port
│
├── plugin/                      # Plugin system
│   └── plugins/
│       ├── typography-plugin.php  # @tailwindcss/typography port
│       └── forms-plugin.php       # @tailwindcss/forms port
│
├── utilities/                   # Split from TailwindCSS utilities.ts (one file per category)
│   ├── accessibility.php        # sr-only, forced-colors
│   ├── backgrounds.php          # bg-*, gradient-*, from-*, via-*, to-*
│   ├── borders.php              # border-*, rounded-*, divide-*, outline-*
│   ├── effects.php              # shadow-*, opacity-*, mix-blend-*
│   ├── filters.php              # blur-*, brightness-*, contrast-*, …
│   ├── flexbox.php              # flex-*, grid-*, gap-*, justify-*, align-*
│   ├── interactivity.php        # cursor-*, scroll-*, touch-*, select-*
│   ├── layout.php               # display, position, z-*, overflow-*, …
│   ├── masks.php                # mask-linear-*, mask-radial-*, mask-conic-*
│   ├── sizing.php               # w-*, h-*, min-*, max-*, size-*
│   ├── spacing.php              # m-*, p-*, space-*
│   ├── svg.php                  # fill-*, stroke-*
│   ├── tables.php               # border-collapse, table-layout
│   ├── transforms.php           # translate-*, rotate-*, scale-*, skew-*
│   ├── transitions.php          # transition-*, duration-*, ease-*, delay-*
│   └── typography.php           # font-*, text-*, leading-*, tracking-*
│
├── utils/                       # Helper functions (ported from utils/)
│
├── index.php                    # Main entry — compile(), cn(), variants(), merge(), join()
├── ast.php                      # AST nodes and toCss()
├── candidate.php                # Candidate parsing (class name → parts)
├── compile.php                  # Candidate to CSS compilation
├── css-functions.php            # theme(), --theme(), --spacing(), --alpha()
├── css-parser.php               # CSS parsing
├── design-system.php            # Central registry for utilities/variants
├── plugin.php                   # Plugin system (PluginInterface, PluginAPI, PluginManager)
├── theme.php                    # Theme value resolution
├── utilities.php                # Utility registration and lookup
├── value-parser.php             # CSS value parsing
├── variants.php                 # Variant handling (hover, focus, responsive, …)
└── walk.php                     # AST traversal
```

## lightningcss에 해당하는 기능

TailwindCSS는 CSS 후처리(중첩, 미디어 쿼리 처리, 값 단순화)를 [lightningcss](https://lightningcss.dev/)에 위임합니다. 이 파서는 Rust로 작성된 파서/변환기/압축기입니다. PHP는 Rust 라이브러리를 로드할 수 없으므로 `src/_tailwindphp/LightningCss.php`는 TailwindPHP가 실제로 사용하는 변환을 재구현하여 테스트 스위트가 다루는 사례에서 바이트 단위로 동일한 출력을 생성합니다.

확인된 변환은 다음과 같습니다.

| 변환 | 설명 |
|-----------|--------------|
| 중첩 평탄화 | 참조 구현의 `:is(…)` 규칙에 따라 `&` 선택자를 처리하고 중첩 규칙을 평탄화합니다(`ast.php`의 `handleNesting()`는 TailwindCSS 단계의 포트임). `transformNesting`는 선언을 포함하는 첫 번째 수준 아래에 남은 중첩을 하위 수준으로 변환합니다. |
| 조건부 at-rule 평탄화 | 중첩된 `@media`, `@supports`, `@container`, `@starting-style`를 제자리에서 평탄화하고 소스 순서를 유지하며, 조건이 동일하고 바로 인접한 형제 항목만 병합합니다. |
| 선언 순서 정렬 | lightningcss의 선언 처리기 체인에 따라 선언 순서를 바꿔 속성이 참조 구현과 같은 순서(`reorderDeclarations`)로 출력되게 합니다. |
| `calc()` 단순화 | `calc()` 식을 단순화합니다(`simplifyCalcExpressions`). |
| 앞쪽 0 제거 | `0.5` → `.5` (`normalizeLeadingZeros`) |
| 변환 함수 간격 | 변환 함수 내부의 간격을 정규화합니다(`normalizeTransformFunctions`). |
| 그리드 값 정규화 | 범위 값의 `/` 주변에 공백을 추가하고, `grid-template-*`의 단독 정수를 px로 변환합니다(`normalizeGridValues`). |
| 색상 정규화 | 색상 구문을 정규화하고 `color-mix()`를 `oklab()`로 계산합니다(`normalizeColors`, `evaluateColorMix`). |
| URL 따옴표 처리 | `url(./x.jpg)` → `url("./x.jpg")` (`normalizeUrlQuoting`) |
| 공급업체 접두사 | Autoprefixer에 해당하는 접두사 처리를 수행합니다(`addVendorPrefixes`). |

이 파일은 의도적으로 `_tailwindphp/` 아래에 격리하고 `@port-deviation:replacement`로 표시했습니다. TailwindCSS 소스를 포트한 것이 아니라 외부 의존성을 대신합니다.

## 포트 차이점 표시

모든 구현 파일의 독스트링에는 `@port-deviation:*` 표시가 있으며, PHP 구현이 TypeScript 원본과 어디서 왜 달라지는지 설명합니다. 독자가 PHP와 TailwindCSS 소스를 비교할 때 차이가 의도적인지 추측하지 않도록 하는 것이 목적입니다.

| 표시 | 의미 |
|--------|---------|
| `@port-deviation:none` | 중요한 차이점이 없는 직접적인 1:1 포트 |
| `@port-deviation:async` | PHP는 async/await 대신 동기 코드를 사용함 |
| `@port-deviation:storage` | 데이터 구조가 다름(PHP 배열과 JS Map/Set) |
| `@port-deviation:types` | TypeScript 타입 대신 PHPDoc 주석 사용 |
| `@port-deviation:sourcemaps` | 소스 맵 추적 생략 |
| `@port-deviation:enum` | PHP 상수 대신 TypeScript 열거형 사용 |
| `@port-deviation:errors` | 오류 처리 방식이 다름 |
| `@port-deviation:replacement` | 외부 라이브러리(e.g. lightningcss)를 대체하는 PHP 구현 |
| `@port-deviation:helper` | 원본에는 없는 PHP 전용 헬퍼 |
| `@port-deviation:performance` | 동일한 출력을 유지하는 PHP 전용 최적화 |
| `@port-deviation:omitted` | 포트 범위 밖이라 포트되지 않은 모듈/기능 전체 |

`@port-deviation:performance` 표시와 동등성 보장 방법은 [성능 및 테스트](https://tailwindphp.inline0.dev/ko/docs/advanced/performance)를 참조하세요.
