
# 파일 워커

모든 Greph 모드(텍스트, AST, 재작성, 인덱싱된 텍스트, 인덱싱된 AST, 캐시된 AST, `rg` 래퍼, `sg` 래퍼)는 파일 트리를 탐색하고 `Greph\Walker\FileList`를 생성하는 것으로 시작합니다. 워커는 공유되므로 동일한 플래그와 동작이 모든 모드에 적용됩니다.

## 기본 동작

기본적으로 워커는 다음을 수행합니다.

- 지정된 경로 아래의 모든 디렉터리를 재귀적으로 탐색합니다.
- 모든 수준에서 중첩된 재정의와 부정 규칙을 포함해 `.gitignore` 및 `.grephignore` 규칙을 따릅니다.
- `.git` 디렉터리를 건너뜁니다.
- 숨김 파일과 디렉터리(`.`으로 시작하는 모든 항목)를 건너뜁니다.
- 바이너리 파일(파일의 첫 512바이트에 널 바이트가 있는지 확인해 감지)을 건너뜁니다.
- 10 MiB보다 큰 파일을 건너뜁니다.
- 심볼릭 링크를 따라가지 않습니다.

## 재정의 플래그

| 플래그 | 효과 |
|---|---|
| `--no-ignore` | `.gitignore` 및 `.grephignore`을 더 이상 따르지 않음 |
| `--hidden` | 숨김 파일 및 디렉터리 포함 |
| `--type NAME` | 지정된 유형 별칭과 일치하는 파일만 포함 |
| `--type-not NAME` | 지정된 유형 별칭과 일치하는 파일 제외 |
| `--glob GLOB` | 경로가 GLOB와 일치하는 파일만 포함. 반복 사용 가능. |

프로그래밍 방식으로 사용할 수 있도록 동일한 옵션이 `Greph\Walker\WalkOptions`을 통해 제공됩니다.

```php
use Greph\Greph;
use Greph\Walker\FileTypeFilter;
use Greph\Walker\WalkOptions;

$files = Greph::walk('src', new WalkOptions(
    respectIgnore: false,
    includeHidden: true,
    fileTypeFilter: new FileTypeFilter(['php']),
    globPatterns: ['src/**/*.php'],
));
```

## 파일 유형 별칭

Greph에는 이름이 지정된 파일 유형 몇 가지가 기본 제공됩니다. 각 별칭은 확장자 목록에 대응합니다.

| 별칭 | 확장자 |
|---|---|
| `css` | `css`, `sass`, `scss` |
| `html` | `htm`, `html`, `phtml` |
| `js` | `cjs`, `js`, `mjs` |
| `json` | `json` |
| `md` | `markdown`, `md` |
| `php` | `inc`, `php`, `php3`, `php4`, `php5`, `php7`, `php8`, `phpt`, `phtml` |
| `txt` | `txt` |
| `ts` | `ts`, `tsx` |
| `xml` | `xml` |
| `yaml` | `yaml`, `yml` |

전체 목록은 `Greph\Walker\FileTypeFilter::TYPE_MAP`에 있습니다.

## .gitignore 의미

Greph은 순수 PHP로 gitignore 일치 규칙을 구현합니다. 동작 방식은 `git check-ignore`에 맞춰져 있습니다.

- 패턴은 해당 패턴이 있는 디렉터리를 기준으로 평가됩니다.
- 중첩된 `.gitignore` 파일은 상위 규칙을 재정의합니다.
- 부정(`!pattern`)은 이전에 제외된 경로를 다시 포함합니다.
- 끝의 `/`는 패턴을 디렉터리로 제한합니다.
- 앞의 `/`는 패턴을 `.gitignore` 디렉터리에 고정합니다.
- `**`는 경로 세그먼트 수에 관계없이 일치합니다.

`.grephignore`은 동일한 구문을 사용하며 `.gitignore` 위에 계층화되어 있습니다. 버전 관리에 포함하지 않을 도구별 제외 규칙을 지정하기에 적합합니다.

구현은 `Greph\Walker\GitignoreFilter`에 있습니다.

## 바이너리 감지

워커는 모든 파일의 첫 512바이트에서 널 바이트를 확인합니다. 널 바이트가 있으면 파일을 바이너리로 간주해 건너뜁니다. 이렇게 하면 인덱싱된 디렉터리에 이미지, 아카이브 또는 컴파일된 산출물이 있는 일반적인 경우를 처리할 수 있습니다.

바이너리 파일도 검색하려면 해당 `Options` 객체에서 `skipBinaryFiles: false`을 설정하세요. 현재 CLI에서는 이 플래그를 제공하지 않으므로 파사드를 사용하세요.

## 심볼릭 링크

기본적으로 심볼릭 링크는 따라가지 않습니다. 링크를 따라가려면 `followSymlinks: true`을 설정하거나 `rg` 래퍼에서 `-L` / `--follow`를 전달하세요. 워커는 방문한 디렉터리를 추적하므로 심볼릭 링크 루프가 무한 재귀를 일으키지 않습니다.

## 최대 파일 크기

`maxFileSizeBytes`보다 큰 파일은 건너뜁니다(기본값 10 MiB). 이렇게 하면 실수로 1 GB 로그 파일을 메모리에 불러오는 일을 방지할 수 있습니다. 더 큰 입력을 처리해야 한다면 `Options` 객체에서 한도를 재정의하세요.

## 사용자 지정 워커를 사용하는 이유

Greph은 `glob()` 또는 `RecursiveDirectoryIterator`에 의존할 수 있지만, 둘 다 gitignore 의미를 구현하지 않고 `.grephignore`을 이해하지 못하며 작업자 풀과도 깔끔하게 통합되지 않습니다. 워커를 한 번 작성해 여러 모드에서 공유하면 모든 모드에 정확히 동일한 필터링 규칙을 적용할 수 있습니다. 이는 오라클 기반 테스트 전략에서 매우 중요합니다. `grep`, `ripgrep` 및 `ast-grep`와 비교하려면 해당 도구와 동일한 파일 집합을 탐색해야 합니다.
