
# 캐싱 및 최소화

파이프라인의 마지막 부분에는 운영 환경과 관련된 세 가지 고려 사항이 있습니다. 동일한 입력을 다시 컴파일하지 않고, 요청마다 컴파일러를 새로 구성하는 비용을 피하며, 생성된 CSS의 크기를 줄이는 것입니다. 이 세 가지는 모두 컴파일러를 감싸는 PHP 측 헬퍼입니다.

## 캐싱

CSS 생성은 호출할 때마다 전체 파이프라인을 실행합니다. 요청 사이에 콘텐츠가 바뀌지 않는 경우 파일 기반 캐시는 결과를 디스크에 저장해 다음 호출부터 제공합니다.

`tw::generate()`에 `cache`을 전달하세요. 기본 디렉터리를 사용하려면 `true`를, 사용자 지정 디렉터리를 사용하려면 경로 문자열을 지정합니다.

```php
use TailwindPHP\tw;

// Cache to the default directory: sys_get_temp_dir() . '/tailwindphp'
$css = tw::generate([
    'content' => '<div class="flex p-4">Hello</div>',
    'cache' => true,
]);

// Cache to a custom directory
$css = tw::generate([
    'content' => '<div class="flex p-4">Hello</div>',
    'cache' => '/path/to/cache',
]);

// With a time-to-live (seconds)
$css = tw::generate([
    'content' => '<div class="flex p-4">Hello</div>',
    'cache' => true,
    'cacheTtl' => 3600, // expire after 1 hour
]);
```

캐시 디렉터리가 없으면 자동으로 생성됩니다.

### 캐시 키

키는 **콘텐츠**, **CSS 설정**, **minify** 플래그에서 파생되며 파일 이름 `tailwind_<hash>.css`로 해시됩니다. 마크업이나 CSS 입력이 변경되거나 최소화 여부가 달라지면 키도 달라져 별도의 파일이 생성됩니다.

키에 포함되는 CSS 설정은 인라인 `css`와 `importPaths`에 지정된 파일의 콘텐츠입니다. 중첩된 `@import`로 해당 파일 안에서 불러온 파일과 TailwindPHP 버전은 키에 포함되지 않습니다. 중첩된 가져오기 파일을 수정하거나 패키지를 업그레이드한 후 캐시를 비우지 않으면 이전 출력이 계속 제공됩니다.

### 유효 기간

`cacheTtl`는 수명(초)입니다. 캐시 적중 시 파일의 수정 시각을 현재 시각과 비교합니다. 파일이 `cacheTtl`보다 오래되면 캐시 미스로 처리해 다시 컴파일합니다. `cacheTtl`가 없으면 항목은 만료되지 않으므로 직접 비워야 합니다.

### 캐시 비우기

`tw::clearCache()`(또는 `clearCache()` 함수)는 캐시 디렉터리에서 `tailwind_*.css` 파일을 제거하고 삭제한 파일 수를 반환합니다.

```php
use TailwindPHP\tw;
use function TailwindPHP\clearCache;

$deleted = tw::clearCache();                  // default directory
$deleted = tw::clearCache('/path/to/cache');  // custom directory
clearCache('/path/to/cache');                 // function form
```

## 컴파일러 상태 캐시

출력 캐시는 같은 콘텐츠가 다시 사용될 때만 도움이 됩니다. 호출할 때마다 콘텐츠가 바뀐다면 비용이 큰 작업은 컴파일러 자체를 구성하는 일입니다. `@import "tailwindcss"` 확인, 번들 리소스 파싱, 테마 누적이 여기에 포함됩니다. 이 단계는 입력 CSS에만 의존하므로 저장해 재사용할 수 있습니다.

`tw::compile()`(또는 `new TailwindCompiler($css, $options)`)에 `stateCacheFile`을 전달하세요.

```php
use TailwindPHP\tw;

$compiler = tw::compile($themeCss, [
    'stateCacheFile' => __DIR__ . '/cache/tailwind-state.php',
]);

$css = $compiler->generateExact($html, true);
```

처음 구성할 때 상태를 일반 PHP 파일로 해당 경로에 기록하면 OPcache가 요청 간에 공유할 수 있습니다. 이후 구성에서는 다시 파싱하지 않고 파일을 불러옵니다. 출력은 캐시를 사용하지 않은 컴파일러의 출력과 바이트 단위로 동일합니다.

- 파일은 엔진 지문(TailwindPHP 소스 및 리소스의 크기와 수정 시각), 입력 CSS 및 `base`와 `importSearchPaths` 옵션에서 파생된 키, 그리고 입력에서 가져온 모든 파일의 크기와 수정 시각을 기준으로 검증됩니다. 일치하지 않으면 파일을 다시 구성하고 기록하므로 TailwindPHP를 업그레이드하거나 가져온 파일을 수정해도 별도 작업이 필요하지 않습니다.
- 경로는 직접 관리해야 합니다. 서로 다른 입력 CSS마다 파일 하나씩 사용하고 웹 서버가 쓸 수 있는 디렉터리에 두세요. 쓰기는 원자적으로 처리됩니다(임시 파일과 `rename()` 사용).
- 사용자 지정 `importResolver`를 사용하는 입력은 확인자 동작의 지문을 생성할 수 없으므로 캐시를 우회합니다.
- 하위 수준 `compile()` 배열 API에도 같은 캐시를 `TailwindPHP\StateCache\compileCssCached($css, $cacheFile, $options)`로 사용할 수 있습니다.

`tw::generate()`는 `stateCacheFile`을 받지 않으며 호출할 때마다 새 컴파일러를 만듭니다. 구성 비용이 중요하다면 컴파일러 인스턴스를 사용하세요.

## 최소화

최소화는 운영 환경용 출력의 크기를 줄입니다. `minify` 플래그는 직렬화 중에 최소화된 CSS를 바로 출력하므로 가장 빠르고 정확한 방법입니다. `tw::minify()`는 기존 CSS 문자열에 문자열 기반 최소화 도구(`src/_tailwindphp/CssMinifier.php`)를 실행합니다.

```php
use TailwindPHP\tw;

// Minify during generation (serializer path, preferred)
$css = tw::generate([
    'content' => '<div class="flex p-4">Hello</div>',
    'minify' => true,
]);

// Or minify an existing string (string-based post-pass)
$css = tw::generate('<div class="flex p-4">Hello</div>');
$minified = tw::minify($css);
```

두 경로는 구조는 동일하지만 바이트까지 같지는 않습니다. 직렬화기 경로는 문자열 처리 과정에서 하나로 합쳐지는 하위 `:not()` 선택자를 보존하므로, 생성된 출력에는 `minify` 플래그를 사용하고 문자열로 전달되는 CSS에는 `tw::minify()`를 사용하세요.

### 기능

두 경로 모두 동일한 크기 축소 작업을 수행합니다:

| 단계 | 효과 |
|------|--------|
| 주석 제거 | `/* … */` 블록을 제거합니다 |
| 공백 축소 | 연속된 공백을 하나로 줄이고 `{ } ; : ,` 및 선택자 결합자 주변의 공백을 제거합니다 |
| 16진수 색상 단축 | `#ffffff` → `#fff`, `#aabbcc` → `#abc` |
| 0 단위 제거 | `0px` → `0` (`0s`/`0ms` 시간 값은 보존합니다) |
| font-weight 단축 | `font-weight:normal` → `400`, `font-weight:bold` → `700` |
| 빈 규칙 제거 | 선언 블록이 비어 있는 선택자를 제거합니다 |

설계상 중복 선택자를 병합하거나 축약 속성을 결합하지 **않습니다**. 두 작업 모두 디버깅을 어렵게 하고 캐스케이드에 영향을 줄 수 있기 때문입니다.

### CLI: `--minify` 대 `--optimize`

[CLI](https://tailwindphp.inline0.dev/ko/docs/cli)는 두 플래그를 통해 직렬화기 축소 경로를 제공합니다:

```bash
# Optimize and minify (smallest output)
tailwindphp -i ./src/app.css -o ./dist/styles.css --minify   # or -m

# Meant to optimize without minifying
tailwindphp -i ./src/app.css -o ./dist/styles.css --optimize
```

현재 릴리스에서는 `--optimize`도 축소하므로 두 명령은 같은 바이트를 기록합니다([#9](https://github.com/inline0/tailwindphp/issues/9)). lightningcss에 해당하는 변환은 어느 쪽이든 모든 빌드에서 실행되므로, 플래그가 없는 일반 출력은 이미 최적화된 읽기 쉬운 형식입니다.

나머지 공개 API인 `tw::generate()`, `tw::compile()`, 검사 메서드 및 입력 형식은 [API 참고](https://tailwindphp.inline0.dev/ko/docs/api)를 확인하세요.
