# RTK Compression (ํ•œ๊ตญ์–ด) ๐ŸŒ **Languages:** ๐Ÿ‡บ๐Ÿ‡ธ [English](../../../../compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ช๐Ÿ‡น [am](../../../am/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ธ๐Ÿ‡ฆ [ar](../../../ar/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฆ๐Ÿ‡ฟ [az](../../../az/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ง๐Ÿ‡ฌ [bg](../../../bg/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ง๐Ÿ‡ฉ [bn](../../../bn/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡จ๐Ÿ‡ฟ [cs](../../../cs/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฉ๐Ÿ‡ฐ [da](../../../da/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฉ๐Ÿ‡ช [de](../../../de/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฌ๐Ÿ‡ท [el](../../../el/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ช๐Ÿ‡ธ [es](../../../es/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ช๐Ÿ‡ช [et](../../../et/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ท [fa](../../../fa/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ซ๐Ÿ‡ฎ [fi](../../../fi/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ซ๐Ÿ‡ท [fr](../../../fr/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ช [ga](../../../ga/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ณ [gu](../../../gu/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ณ๐Ÿ‡ฌ [ha](../../../ha/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ฑ [he](../../../he/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ณ [hi](../../../hi/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ญ๐Ÿ‡ท [hr](../../../hr/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ญ๐Ÿ‡บ [hu](../../../hu/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฆ๐Ÿ‡ฒ [hy](../../../hy/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ฉ [id](../../../id/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ณ๐Ÿ‡ฌ [ig](../../../ig/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฎ๐Ÿ‡น [it](../../../it/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฏ๐Ÿ‡ต [ja](../../../ja/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฌ๐Ÿ‡ช [ka](../../../ka/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฐ๐Ÿ‡ญ [km](../../../km/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ณ [kn](../../../kn/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฑ๐Ÿ‡น [lt](../../../lt/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฑ๐Ÿ‡ป [lv](../../../lv/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ณ [ml](../../../ml/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ณ [mr](../../../mr/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฒ๐Ÿ‡พ [ms](../../../ms/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฒ๐Ÿ‡น [mt](../../../mt/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฒ๐Ÿ‡ฒ [my](../../../my/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ณ๐Ÿ‡ต [ne](../../../ne/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ณ๐Ÿ‡ฑ [nl](../../../nl/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ณ๐Ÿ‡ด [no](../../../no/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ณ [or](../../../or/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ณ [pa](../../../pa/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ต๐Ÿ‡ญ [phi](../../../phi/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ต๐Ÿ‡ฑ [pl](../../../pl/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ต๐Ÿ‡น [pt](../../../pt/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ง๐Ÿ‡ท [pt-BR](../../../pt-BR/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ท๐Ÿ‡ด [ro](../../../ro/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ท๐Ÿ‡บ [ru](../../../ru/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฑ๐Ÿ‡ฐ [si](../../../si/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ธ๐Ÿ‡ฐ [sk](../../../sk/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ธ๐Ÿ‡ฎ [sl](../../../sl/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ท๐Ÿ‡ธ [sr](../../../sr/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ธ๐Ÿ‡ช [sv](../../../sv/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฐ๐Ÿ‡ช [sw](../../../sw/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ณ [ta](../../../ta/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ณ [te](../../../te/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡น๐Ÿ‡ญ [th](../../../th/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡น๐Ÿ‡ท [tr](../../../tr/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡บ๐Ÿ‡ฆ [uk-UA](../../../uk-UA/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ต๐Ÿ‡ฐ [ur](../../../ur/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡บ๐Ÿ‡ฟ [uz](../../../uz/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ป๐Ÿ‡ณ [vi](../../../vi/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡ณ๐Ÿ‡ฌ [yo](../../../yo/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡จ๐Ÿ‡ณ [zh-CN](../../../zh-CN/docs/compression/RTK_COMPRESSION.md) ยท ๐Ÿ‡น๐Ÿ‡ผ [zh-TW](../../../zh-TW/docs/compression/RTK_COMPRESSION.md) --- RTK ์••์ถ•์€ ํ„ฐ๋ฏธ๋„ ๋ฐ ๋„๊ตฌ ์ถœ๋ ฅ์„ ์œ„ํ•œ OmniRoute์˜ ๋ช…๋ น์–ด ์ธ์‹ ์••์ถ• ์—”์ง„์ž…๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ์ปจํ…์ŠคํŠธ ์ฆ๊ฐ€๊ฐ€ ํ…Œ์ŠคํŠธ ๋กœ๊ทธ, ๋นŒ๋“œ ์ถœ๋ ฅ, ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ์ž ๋…ธ์ด์ฆˆ, ์…ธ ๊ธฐ๋ก, Docker ์ถœ๋ ฅ, git ์ถœ๋ ฅ ๋ฐ ์Šคํƒ ํŠธ๋ ˆ์ด์Šค์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์ฝ”๋”ฉ ์—์ด์ „ํŠธ ์„ธ์…˜์„ ์œ„ํ•ด ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. RTK๋Š” `defaultMode: "rtk"`๋กœ ์ง์ ‘ ์‹คํ–‰ํ•˜๊ฑฐ๋‚˜ ์Šคํƒํ˜• ํŒŒ์ดํ”„๋ผ์ธ์˜ ์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ผ๋ฐ˜์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. ```txt rtk -> caveman ``` ์ด ์ˆœ์„œ๋Š” ๋จผ์ € ๋…ธ์ด์ฆˆ๊ฐ€ ๋งŽ์€ ๋จธ์‹  ์ถœ๋ ฅ์„ ์••์ถ•ํ•œ ๋‹ค์Œ, Caveman์ด ๋‚˜๋จธ์ง€ ์‚ฐ๋ฌธ์„ ์š”์•ฝํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ์—…์ŠคํŠธ๋ฆผ RTK๋Š” ๋ช…๋ น์–ด ์ถœ๋ ฅ์—์„œ `60-90%`์˜ ์ ˆ๊ฐ๋ฅ ์„ ๋ณด๊ณ ํ•ฉ๋‹ˆ๋‹ค. README์˜ ์ƒ˜ํ”Œ ์„ธ์…˜์—์„œ๋Š” ํ‘œ์ค€ ํ† ํฐ์ด `~118,000`๊ฐœ์—์„œ RTK ํ† ํฐ `~23,900`๊ฐœ๋กœ ์ค„์–ด๋“ค์–ด `79.7%`๊ฐ€ ์ ˆ๊ฐ๋ฉ๋‹ˆ๋‹ค(`~80%`). OmniRoute๋Š” Caveman ์ž…๋ ฅ ์••์ถ•๊ณผ ๊ฒฐํ•ฉํ•œ ์Šคํƒํ˜• ์ ˆ๊ฐ๋ฅ  ๊ณ„์‚ฐ์— ์ด ์—…์ŠคํŠธ๋ฆผ ํ‰๊ท ๊ฐ’์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ```txt RTK ํ‰๊ท : 80% ์ ˆ๊ฐ Caveman ์ž…๋ ฅ: 46% ์ ˆ๊ฐ ์Šคํƒํ˜•: 1 - (1 - 0.80) * (1 - 0.46) = 89.2% ์ ˆ๊ฐ ๋ฒ”์œ„: 1 - (1 - 0.60..0.90) * (1 - 0.46) = 78.4-94.6% ``` ## ์••์ถ• ๋Œ€์ƒ ํ˜„์žฌ ๊ธฐ๋ณธ ์ œ๊ณต ์นดํƒˆ๋กœ๊ทธ์—๋Š” ๋‹ค์Œ ์นดํ…Œ๊ณ ๋ฆฌ์— ๊ฑธ์ณ 49๊ฐœ์˜ ํ•„ํ„ฐ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. | ์นดํ…Œ๊ณ ๋ฆฌ | ์˜ˆ์‹œ | | --------- | ------------------------------------------------------------- | | `git` | `git status`, `git branch`, `git diff`, `git log` | | `test` | Vitest, Jest, Pytest, Playwright, Go ํ…Œ์ŠคํŠธ, Cargo ํ…Œ์ŠคํŠธ | | `build` | TypeScript, ESLint, Biome, Prettier, Vite, Webpack, Turbo, Nx | | `package` | `npm install`, `npm audit`, `pip`, `uv sync`, Poetry, Bundler | | `shell` | `ls`, `find`, `grep`, ์ผ๋ฐ˜ ์…ธ ๋กœ๊ทธ | | `docker` | `docker ps`, Docker ๋กœ๊ทธ | | `infra` | Terraform, OpenTofu, `systemctl status` | | `generic` | JSON ์ถœ๋ ฅ, ์Šคํƒ ํŠธ๋ ˆ์ด์Šค, ์ผ๋ฐ˜ ์ถœ๋ ฅ ํด๋ฐฑ | `open-sse/services/compression/engines/rtk/commandDetector.ts`์˜ ๊ฐ์ง€๊ธฐ๋Š” ํ•„ํ„ฐ๋ฅผ ์„ ํƒํ•˜๊ธฐ ์ „์— ์ถœ๋ ฅ์„ ๋ถ„๋ฅ˜ํ•ฉ๋‹ˆ๋‹ค. ๋ช…๋ น์–ด ํด๋ž˜์Šค๋งŒ์œผ๋กœ ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ํ•„ํ„ฐ๋Š” ๋ช…๋ น์–ด ํŒจํ„ด ๋˜๋Š” ์ถœ๋ ฅ ์ •๊ทœ์‹์œผ๋กœ๋„ ์ผ์น˜์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ## ํ•„ํ„ฐ ํ•ด์„ RTK๋Š” ๋‹ค์Œ ์ˆœ์„œ๋กœ ํ•„ํ„ฐ๋ฅผ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค. 1. ์‹ ๋ขฐ๋œ ๊ฒฝ์šฐ์—๋งŒ `.rtk/filters.toml` ๋ฐ `.rtk/filters.json`์˜ ํ”„๋กœ์ ํŠธ ํ•„ํ„ฐ. 2. `DATA_DIR/rtk/filters.toml` ๋ฐ `DATA_DIR/rtk/filters.json`์˜ ์ „์—ญ ํ•„ํ„ฐ. 3. `open-sse/services/compression/engines/rtk/filters/`์˜ ๊ธฐ๋ณธ ์ œ๊ณต ํ•„ํ„ฐ. ๊ฐ™์€ ๋ฒ”์œ„ ๋‚ด์—์„œ๋Š” RTK TOML ์Šคํ‚ค๋งˆ v1 ํ•„ํ„ฐ๊ฐ€ OmniRoute JSON ํ•„ํ„ฐ๋ณด๋‹ค ์šฐ์„ ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ€์ ธ์˜จ ๋ช…๋ น์–ด๋ณ„ ํ•„ํ„ฐ๊ฐ€ ํ•ด๋‹น ๋ฒ”์œ„์˜ ๋” ๊ด‘๋ฒ”์œ„ํ•œ ํ•„ํ„ฐ๋ฅผ ์žฌ์ •์˜ํ•  ์ˆ˜ ์žˆ๋„๋ก TOML `match_command` ํ‘œํ˜„์‹์€ ๋ช…๋ น์–ด ์œ ํ˜• ์ผ์น˜๋ณด๋‹ค ๋จผ์ € ํ™•์ธ๋ฉ๋‹ˆ๋‹ค. ํŒŒ์ผ ํ˜•์‹๊ณผ ๊ด€๊ณ„์—†์ด ํ”„๋กœ์ ํŠธ ๋ฒ”์œ„๊ฐ€ ์—ฌ์ „ํžˆ ์ „์—ญ ๋ฒ”์œ„๋ณด๋‹ค ์šฐ์„ ํ•ฉ๋‹ˆ๋‹ค. ์ •๊ทœ์‹ ํ•„ํ„ฐ๋Š” ๋„๊ตฌ ์ถœ๋ ฅ์ด ์—์ด์ „ํŠธ์—๊ฒŒ ํ‘œ์‹œ๋˜๋Š” ๋ฐฉ์‹์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ํ”„๋กœ์ ํŠธ ํ•„ํ„ฐ์—๋Š” ์˜๋„์ ์œผ๋กœ ์‹ ๋ขฐ ๊ฒ€์ฆ์ด ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ์ค‘ ํ•˜๋‚˜๊ฐ€ ์ฐธ์ด๋ฉด ํ”„๋กœ์ ํŠธ ํ•„ํ„ฐ ํŒŒ์ผ์ด ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค. - `rtkConfig.trustProjectFilters`๊ฐ€ `true`์ž…๋‹ˆ๋‹ค. - `OMNIROUTE_RTK_TRUST_PROJECT_FILTERS=1`์ด ์„ค์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. - `.rtk/trust.json`์— ํ”„๋กœ์ ํŠธ ํ•„ํ„ฐ ํŒŒ์ผ๊ณผ ์ผ์น˜ํ•˜๋Š” SHA-256 ํ•ด์‹œ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์‹ ๋ขฐ ํŒŒ์ผ ์˜ˆ์‹œ: ```json { "filtersSha256": "0123456789abcdef...", "filtersTomlSha256": "fedcba9876543210..." } ``` ํ•ด์‹œ๋Š” ๋ณ„๊ฐœ์ž…๋‹ˆ๋‹ค. `filtersSha256`๋Š” `.rtk/filters.json`์„ ์‹ ๋ขฐํ•˜๊ณ , `filtersTomlSha256`๋Š” `.rtk/filters.toml`์„ ์‹ ๋ขฐํ•ฉ๋‹ˆ๋‹ค. ์–ด๋А ํ•œ ํŒŒ์ผ์„ ํŽธ์ง‘ํ•˜๋ฉด ํ•ด๋‹น ํŒŒ์ผ์˜ ์‹ ๋ขฐ ํ•ญ๋ชฉ๋งŒ ๋ฌดํšจํ™”๋ฉ๋‹ˆ๋‹ค. ์ „์—ญ ํŒŒ์ผ์€ ๊ด€๋ฆฌ์ž๊ฐ€ ์„ค์น˜ํ•˜๋ฉฐ ๊ธฐ์กด ์ „์—ญ ํ•„ํ„ฐ ์‹ ๋ขฐ ๋™์ž‘์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ •์˜ ํ•„ํ„ฐ๋Š” ํ•˜๋‚˜์˜ ํ•„ํ„ฐ ๊ฐ์ฒด์ด๊ฑฐ๋‚˜ ํ•„ํ„ฐ ๊ฐ์ฒด์˜ ๋ฐฐ์—ด์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์œ ํšจํ•˜์ง€ ์•Š์€ ์‚ฌ์šฉ์ž ์ •์˜ ํ•„ํ„ฐ๋Š” ๊ฑด๋„ˆ๋›ฐ๋ฉฐ `/api/context/rtk/filters` ์ง„๋‹จ์—์„œ ๋ณด๊ณ ๋ฉ๋‹ˆ๋‹ค. ์œ ํšจํ•˜์ง€ ์•Š์€ ๊ธฐ๋ณธ ์ œ๊ณต ํ•„ํ„ฐ๋Š” ์ฆ‰์‹œ ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค. ## RTK TOML ์Šคํ‚ค๋งˆ v1 ํ˜ธํ™˜์„ฑ OmniRoute๋Š” RTK TOML ์Šคํ‚ค๋งˆ v1์„ ์‚ฌ์šฉํ•˜๋Š” ์„ ์–ธ์  ํ•„ํ„ฐ ํŒŒ์ผ์„ ํŒŒ์‹ฑํ•˜๊ณ , ๊ฒ€์ฆํ•˜๊ณ , ํ…Œ์ŠคํŠธํ•˜๊ณ , ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ง€์›๋˜๋Š” ํ•„๋“œ๋Š” `description`, `match_command`, `strip_ansi`, `filter_stderr`, `strip_lines_matching`, `keep_lines_matching`, `replace`, `match_output`, `truncate_lines_at`, `head_lines`, `tail_lines`, `max_lines`, `on_empty`, ๊ทธ๋ฆฌ๊ณ  `[[tests.]]` ์ธ๋ผ์ธ ํ…Œ์ŠคํŠธ์ž…๋‹ˆ๋‹ค. ์•Œ ์ˆ˜ ์—†๋Š” ํ•„๋“œ, ์œ ํšจํ•˜์ง€ ์•Š๊ฑฐ๋‚˜ ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ์ •๊ทœ์‹, ๋™์‹œ์— ์ง€์ •๋œ ์ œ๊ฑฐ/์œ ์ง€ ๊ทœ์น™, 1 MiB๋ฅผ ์ดˆ๊ณผํ•˜๋Š” ํŒŒ์ผ, ๊ทธ๋ฆฌ๊ณ  ์•Œ ์ˆ˜ ์—†๋Š” ํ•„ํ„ฐ์— ๋Œ€ํ•œ ์ฐธ์กฐ๋Š” ๊ฑฐ๋ถ€๋ฉ๋‹ˆ๋‹ค. ์ธ๋ผ์ธ ํ…Œ์ŠคํŠธ์— ์‹คํŒจํ•œ ํŒŒ์ผ์€ ๊ฒ€ํ† ๋ฅผ ์œ„ํ•ด ๊ฒ€์ฆํ•  ์ˆ˜๋Š” ์žˆ์ง€๋งŒ ์„ค์น˜ํ•˜๊ฑฐ๋‚˜ ๋กœ๋“œํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ง€์ • ํŒŒ์ผ ๋กœ๋“œ ์‹คํŒจ์—๋Š” ๊ณ„์†ํ•ด์„œ ํŽ˜์ผ ์˜คํ”ˆ์ด ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์œ ํšจํ•˜์ง€ ์•Š์€ ํŒŒ์ผ์€ ๊ฑด๋„ˆ๋›ฐ๋ฉฐ ๋‚˜๋จธ์ง€ ํ•„ํ„ฐ๋Š” ๊ณ„์† ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. OmniRoute๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ด๋ฏธ ์บก์ฒ˜ํ•œ ๋„๊ตฌ ์ถœ๋ ฅ์„ ์ˆ˜์‹ ํ•˜๋ฏ€๋กœ `filter_stderr = true`๋Š” ํ”„๋กœ์„ธ์Šค ์บก์ฒ˜๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด ํ•„๋“œ๋Š” ์•„๋ฌด ์ž‘์—…๋„ ํ•˜์ง€ ์•Š๋Š” ์˜ต์…˜์œผ๋กœ ํ—ˆ์šฉ๋˜๋ฉฐ, ๊ฒ€์ฆ ์‹œ ๊ฒฝ๊ณ ๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์˜๋„์ ์œผ๋กœ RTK ์‹คํ–‰ ํŒŒ์ผ, ์…ธ ํ›…, Rust ๋ช…๋ น ๊ตฌํ˜„ ๋˜๋Š” ์‹ ๋ขฐ ์ €์žฅ์†Œ ๋ ˆ์ด์•„์›ƒ๊ณผ์˜ ์™„์ „ํ•œ ํ˜ธํ™˜์„ฑ์ด ์•„๋‹ˆ๋ผ **RTK TOML ์Šคํ‚ค๋งˆ v1 ํ˜ธํ™˜์„ฑ**์œผ๋กœ ์„ค๋ช…๋ฉ๋‹ˆ๋‹ค. ๋Œ€์‹œ๋ณด๋“œ์˜ ๊ณ ๊ธ‰ RTK ๋ณด๊ธฐ๋Š” ๋ถ™์—ฌ๋„ฃ๊ฑฐ๋‚˜ ์—…๋กœ๋“œํ•œ TOML์„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ฒ€์ฆ์€ ์ฝ๊ธฐ ์ „์šฉ์ž…๋‹ˆ๋‹ค. ์„ค์น˜ ์‹œ ์ œํ•œ์ ์ธ ๊ถŒํ•œ์œผ๋กœ `DATA_DIR/rtk/filters.toml`์„ ์›์ž์ ์œผ๋กœ ์ž‘์„ฑํ•˜๊ณ , ์žฌ์‹œ์ž‘ ์—†์ด ์‹ค์‹œ๊ฐ„ ํ•„ํ„ฐ ์นดํƒˆ๋กœ๊ทธ๋ฅผ ์ƒˆ๋กœ ๊ณ ์นฉ๋‹ˆ๋‹ค. ๊ธฐ์กด ํŒŒ์ผ์„ ๊ต์ฒดํ•˜๋ ค๋ฉด ๋ช…์‹œ์ ์ธ `overwrite` ํ™•์ธ์ด ํ•„์š”ํ•˜๋ฉฐ, ๋จผ์ € `DATA_DIR/rtk/filters.toml.bak`์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ## ํ•„ํ„ฐ DSL ํ•„ํ„ฐ๋Š” [์••์ถ• ๊ทœ์น™ ํ˜•์‹](./COMPRESSION_RULES_FORMAT.md)์— ์„ค๋ช…๋œ JSON ์Šคํ‚ค๋งˆ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋Ÿฐํƒ€์ž„์€ ๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ ์ˆœ์„œ๋Œ€๋กœ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค. ```txt stripAnsi -> filterStderr -> replace -> matchOutput -> ์ค„ ์‚ญ์ œ/ํฌํ•จ -> truncateLineAt -> head/tail/maxLines -> onEmpty ``` ์ฃผ์š” ํ•„๋“œ: | ํ•„๋“œ | ๋ชฉ์  | | ---------------------------- | -------------------------------------------------------- | | `rules.stripAnsi` | ์ผ์น˜ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๊ธฐ ์ „์— ํ„ฐ๋ฏธ๋„ ์ƒ‰์ƒ/์ œ์–ด ์‹œํ€€์Šค ์ œ๊ฑฐ | | `rules.filterStderr` | ์ผ์น˜ ์—ฌ๋ถ€ ํ™•์ธ/ํ•„ํ„ฐ๋ง ์ „์— ์ผ๋ฐ˜์ ์ธ stderr ์ ‘๋‘์‚ฌ ์ •๊ทœํ™” | | `rules.replace` | ์ˆœ์„œ๋Œ€๋กœ ์ •๊ทœ์‹ ์น˜ํ™˜ ์ ์šฉ | | `rules.matchOutput` | ์ถœ๋ ฅ์ด ์•Œ๋ ค์ง„ ์กฐ๊ฑด๊ณผ ์ผ์น˜ํ•  ๋•Œ ๊ฐ„๊ฒฐํ•œ ์š”์•ฝ ๋ฐ˜ํ™˜ | | `rules.matchOutput[].unless` | ์˜ค๋ฅ˜/์‹คํŒจ ํŒจํ„ด์ด ์žˆ์„ ๋•Œ ๋‹จ์ถ• ์ฒ˜๋ฆฌ ๊ฑด๋„ˆ๋›ฐ๊ธฐ | | `rules.dropPatterns` | ๋ถˆํ•„์š”ํ•œ ์ค„ ์ œ๊ฑฐ | | `rules.includePatterns` | ์กฐ์น˜ ๊ฐ€๋Šฅํ•œ ์ค„ ์šฐ์„  ์œ ์ง€ | | `rules.collapsePatterns` | ์ผ์น˜ํ•˜๋Š” ๋ฐ˜๋ณต ์ค„ ์ถ•์•ฝ | | `rules.deduplicate` | ํ•„ํ„ฐ๋ณ„ ์˜ตํŠธ์ธ: ์—ฐ์†๋œ ์ค‘๋ณต ์ค„ ์ถ•์•ฝ | | `rules.truncateLineAt` | ์œ ๋‹ˆ์ฝ”๋“œ์— ์•ˆ์ „ํ•œ ์ค„๋ณ„ ์ž˜๋ผ๋‚ด๊ธฐ | | `rules.onEmpty` | ๋ชจ๋“  ์ค„์ด ํ•„ํ„ฐ๋ง๋œ ๊ฒฝ์šฐ ์‚ฌ์šฉํ•  ๋Œ€์ฒด ๋ฉ”์‹œ์ง€ | | `tests[]` | ๊ฒ€์ฆ ๊ฒŒ์ดํŠธ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ธ๋ผ์ธ ์ƒ˜ํ”Œ | ๊ธฐ๋ณธ ์ œ๊ณต ํ•„ํ„ฐ์—๋Š” ์ธ๋ผ์ธ `tests[]` ์ƒ˜ํ”Œ์ด ํฌํ•จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ง€์ • ํ•„ํ„ฐ์—๋„, ํŠนํžˆ ์—ฌ๋Ÿฌ ํ”„๋กœ์ ํŠธ์—์„œ ๊ณต์œ ๋˜๋Š” ๊ฒฝ์šฐ ์ธ๋ผ์ธ ์ƒ˜ํ”Œ์„ ํฌํ•จํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ## ๋ผ์ธ ์ค‘๋ณต ์ œ๊ฑฐ(๋‘ ๊ณ„์ธต) RTK๋Š” ์„œ๋กœ ๋…๋ฆฝ์ ์ธ ๋‘ ๊ณ„์ธต์—์„œ ์ค‘๋ณต ๋ผ์ธ์„ ์ถ•์•ฝํ•ฉ๋‹ˆ๋‹ค. 1. **ํ•„ํ„ฐ๋ณ„ `deduplicate`(์˜ตํŠธ์ธ, ๊ธฐ๋ณธ๊ฐ’ `false`).** ํ•„ํ„ฐ์—์„œ `rules.deduplicate: true`๋ฅผ ์„ค์ •ํ•˜๋ฉด ํ•ด๋‹น ํ•„ํ„ฐ๊ฐ€ ์ผ์น˜์‹œํ‚จ ์ถœ๋ ฅ ๋‚ด์—์„œ ์—ฐ์†๋œ ์ค‘๋ณต ๋ผ์ธ์„ ์ž˜๋ผ๋‚ด๊ธฐ ์ „์— ์ถ•์•ฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์ž‘์—…์€ `lineFilter.ts` ๋‚ด๋ถ€์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ๋ ˆ๊ฑฐ์‹œ ํ•„ํ„ฐ์˜ ๊ฒฝ์šฐ ํ•„ํ„ฐ์— `collapsePatterns`๊ฐ€ ์ •์˜๋˜์–ด ์žˆ์œผ๋ฉด ์ž๋™์œผ๋กœ ํ™œ์„ฑํ™”๋ฉ๋‹ˆ๋‹ค. ์Šคํ‚ค๋งˆ: `open-sse/services/compression/engines/rtk/filterSchema.ts`์˜ `deduplicate: z.boolean().default(false)`. 2. **์—”์ง„ ์ „์ฒด `deduplicateThreshold`(๊ธฐ๋ณธ๊ฐ’ `3`).** ๋ชจ๋“  ํ•„ํ„ฐ๊ฐ€ ์‹คํ–‰๋œ ํ›„ ์—”์ง„์€ ์ „์ฒด ๊ฒฐ๊ณผ์—์„œ ๋™์ผํ•œ ๋ผ์ธ์ด `deduplicateThreshold`๊ฐœ ์ด์ƒ ์—ฐ์†๋˜๋Š” ๋ชจ๋“  ๊ตฌ๊ฐ„์„ ์ถ•์•ฝํ•ฉ๋‹ˆ๋‹ค (`deduplicateRepeatedLines`, `engines/rtk/index.ts`์—์„œ ์ ์šฉ). ์ •๊ทœํ™” ์‹œ ๊ฐ’์€ 2โ€“100 ๋ฒ”์œ„๋กœ ์ œํ•œ๋ฉ๋‹ˆ๋‹ค. ํ•„ํ„ฐ๋ณ„ ์ฒ˜๋ฆฌ๋Š” ๋จผ์ € ํ•„ํ„ฐ ๋‚ด๋ถ€์—์„œ ์‹คํ–‰๋˜๊ณ , ์—”์ง„ ์ „์ฒด ์ฒ˜๋ฆฌ๋Š” ๊ฒฐํ•ฉ๋œ ์ถœ๋ ฅ ์ „์ฒด์— ๋Œ€ํ•ด ๋งˆ์ง€๋ง‰์— ์‹คํ–‰๋˜๋ฏ€๋กœ ๋‘ ์ฒ˜๋ฆฌ๊ฐ€ ์ค‘๋ณต ๊ณ„์‚ฐ ์—†์ด ํ•จ๊ป˜ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ## ๋ผ์ธ ๊ทธ๋ฃนํ™”(`enableGrouping`) `rtkConfig.enableGrouping`์ด `true`์ด๋ฉด(๊ธฐ๋ณธ๊ฐ’ `false`) RTK๋Š” ์ค‘๋ณต ์ œ๊ฑฐ ํ›„ ๊ฒฐ๊ณผ์— ์ถ”๊ฐ€๋กœ `groupSimilarLines` ์ฒ˜๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ๋ฐ”์ดํŠธ ๋‹จ์œ„๋กœ ๋™์ผํ•˜์ง€๋Š” ์•Š์ง€๋งŒ _๊ฑฐ์˜ ๋™๋“ฑํ•œ_ ์—ฐ์† ๋ผ์ธ ๊ตฌ๊ฐ„์„ ์ถ•์•ฝํ•ฉ๋‹ˆ๋‹ค. `rtkConfig.groupingThreshold`(๊ธฐ๋ณธ๊ฐ’ `3`)๋Š” ๊ทธ๋ฃนํ™”๋ฅผ ์‹คํ–‰ํ•˜๋Š” ์ตœ์†Œ ์—ฐ์† ๊ธธ์ด์ž…๋‹ˆ๋‹ค. ์ด๋Š” `deduplicateThreshold`์— ๊ตฌ์กฐ์ ์œผ๋กœ ๋Œ€์‘ํ•˜๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. ์ค‘๋ณต ์ œ๊ฑฐ๋Š” ์ •ํ™•ํžˆ ๊ฐ™์€ ๋ฐ˜๋ณต์„ ์ฒ˜๋ฆฌํ•˜๊ณ , ๊ทธ๋ฃนํ™”๋Š” "์ž‘์€ ์ฐจ์ด๊ฐ€ ์žˆ์ง€๋งŒ ํ˜•ํƒœ๊ฐ€ ๊ฐ™์€" ๋ผ์ธ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๋‘ ํ”Œ๋ž˜๊ทธ ๋ชจ๋‘ `key_value` ํ…Œ์ด๋ธ”์— ์ €์žฅ๋˜๋Š” `rtkConfig` JSON์˜ ์ผ๋ถ€์ด๋ฏ€๋กœ(์œ„์˜ ๊ตฌ์„ฑ ์ฐธ์กฐ) ์žฌ์‹œ์ž‘ ํ›„์—๋„ ์„ค์ •์ด ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. ## ์ฝ”๋“œ ์ฃผ์„ ์ œ๊ฑฐ(`stripCodeComments` / `preserveDocstrings`) `rtkConfig.applyToCodeBlocks`๊ฐ€ ํ™œ์„ฑํ™”๋œ ๊ฒฝ์šฐ RTK๋Š” ํŽœ์Šค ์ฝ”๋“œ ๋ธ”๋ก์—์„œ ์ฃผ์„๋„ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. - `stripCodeComments`(๊ธฐ๋ณธ๊ฐ’ `false`) โ€” ์˜ตํŠธ์ธ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. `true`์ด๋ฉด RTK๋Š” JavaScript ๋ฐ TypeScript ํŽœ์Šค ๋ธ”๋ก์—์„œ ์ฃผ์„์„ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. ๊ณผ๊ฑฐ์—๋Š” ์ด ํ”Œ๋ž˜๊ทธ๋ฅผ ์ฝ๊ธฐ๋งŒ ํ•˜๊ณ  ์‹ค์ œ๋กœ ์ ์šฉํ•˜์ง€ ์•Š์•˜์œผ๋ฏ€๋กœ, ์šด์˜ ํ™˜๊ฒฝ์—์„œ ์˜ˆ๊ณ  ์—†์ด ๋™์ž‘์ด ๋ณ€๊ฒฝ๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๊ธฐ๋ณธ๊ฐ’์€ "๋ณด์กด"์œผ๋กœ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. - `preserveDocstrings`(๊ธฐ๋ณธ๊ฐ’ `true`) โ€” ์ฃผ์„ ์ œ๊ฑฐ ์‹œ JSDoc/`/** โ€ฆ */` ๋ธ”๋ก ์ฃผ์„์€ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค(ํ•ด๋‹น ์ฃผ์„์€ ์ฐจ์ง€ํ•˜๋Š” ๋ฐ”์ดํŠธ๋ณด๋‹ค ๊ฐ€์น˜ ์žˆ๋Š” API ๋ฌธ์„œ๋ฅผ ๋‹ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค). ์ด๋Ÿฌํ•œ ์ฃผ์„๋„ ์ œ๊ฑฐํ•˜๋ ค๋ฉด `false`๋กœ ์„ค์ •ํ•˜์‹ญ์‹œ์˜ค. ์ฃผ์„ ์ œ๊ฑฐ๋Š” `open-sse/services/compression/engines/rtk/codeStripper.ts`์— ๊ตฌํ˜„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด, ํ…œํ”Œ๋ฆฟ ๋ฐ ์ •๊ทœ์‹ ๋ฆฌํ„ฐ๋Ÿด์„ ์ฃผ์„์œผ๋กœ ์ž˜๋ชป ์ธ์‹ํ•˜์ง€ ์•Š๋„๋ก ์ •๊ทœ์‹์ด ์•„๋‹Œ **TypeScript ํŒŒ์„œ**๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ, JSX๊ฐ€ ๊ฐ์ง€๋˜๋ฉด ์ฒ˜๋ฆฌ๋ฅผ ์™„์ „ํžˆ ์ค‘๋‹จํ•ฉ๋‹ˆ๋‹ค(๋”ฐ๋ผ์„œ JSX ํ‘œํ˜„์‹ ์ปจํ…Œ์ด๋„ˆ์˜ ์ฃผ์„์ด ์†์ƒ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค). ํ˜„์žฌ ์ฃผ์„ ์ œ๊ฑฐ๋Š” **JavaScript ๋ฐ TypeScript์—๋งŒ** ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ŠคํŠธ๋ฆฌํผ์˜ `CodeLanguage` ์ง‘ํ•ฉ์— ํฌํ•จ๋œ ๋‹ค๋ฅธ ์–ธ์–ด(Python, Rust, Go, Ruby, Java)๋Š” ๋นˆ ๋ผ์ธ ๋ฐ ๊ณต๋ฐฑ ์ถ•์•ฝ๋งŒ ์ˆ˜ํ–‰ํ•˜๋ฉฐ ์ฃผ์„์€ ์ œ๊ฑฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ฃผ์„์ด ์ œ๊ฑฐ๋œ ๋ธ”๋ก ์ฒ˜๋ฆฌ๋Š” `rulesApplied`์—์„œ `rtk:code-strip` ํƒœ๊ทธ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. > **์ฐธ๊ณ  โ€” GCF/ํ…Œ์ด๋ธ” ํ˜•์‹ ์ธ์ฝ”๋”ฉ์€ ๋ณ„๋„์˜ ์—”์ง„์ž…๋‹ˆ๋‹ค.** RTK์—๋Š” "GCF" > (Graph Compact Format) ํ…Œ์ด๋ธ”ํ˜•/์—ด ๊ธฐ๋ฐ˜ JSON ์ธ์ฝ”๋”๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์ง€ **์•Š์Šต๋‹ˆ๋‹ค**. ์ด์ „์˜ > `omni-tabular` ์ธ์ฝ”๋”๋ฅผ ๋Œ€์ฒดํ•œ ์ด ์ธ์ฝ”๋”๋Š” **headroom** ์—”์ง„์— ์žˆ์Šต๋‹ˆ๋‹ค > (`open-sse/services/compression/engines/headroom/`, ๋ฒค๋”๋ง๋œ ์ฝ”๋ฑ์€ > `headroom/gcf/` ์•„๋ž˜์— ์žˆ์Œ). ์ด๋Š” ์—ฌ๊ธฐ์—์„œ ์„ค๋ช…ํ•˜๋Š” RTK ํ•„ํ„ฐ ํŒŒ์ดํ”„๋ผ์ธ๊ณผ ๊ด€๋ จ์ด ์—†์Šต๋‹ˆ๋‹ค. ## ๊ตฌ์„ฑ ์ „์—ญ ์„ค์ •์€ `/api/settings/compression`์„ ํ†ตํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. RTK ์ „์šฉ ์„ค์ •์€ `/api/context/rtk/config`๋ฅผ ํ†ตํ•ด์„œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```json { "defaultMode": "stacked", "autoTriggerMode": "stacked", "autoTriggerTokens": 32000, "stackedPipeline": [ { "engine": "rtk", "intensity": "standard" }, { "engine": "caveman", "intensity": "full" } ], "rtkConfig": { "enabled": true, "intensity": "standard", "applyToToolResults": true, "applyToCodeBlocks": false, "applyToAssistantMessages": false, "enabledFilters": [], "disabledFilters": [], "maxLinesPerResult": 120, "maxCharsPerResult": 12000, "deduplicateThreshold": 3, "customFiltersEnabled": true, "trustProjectFilters": false, "rawOutputRetention": "never", "rawOutputMaxBytes": 1048576, "enableGrouping": false, "groupingThreshold": 3, "stripCodeComments": false, "preserveDocstrings": true } } ``` `enabledFilters`์™€ `disabledFilters`์—๋Š” ํ•„ํ„ฐ ID๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค(์˜ˆ: `test-vitest` ๋˜๋Š” `git-diff`). ์ „์ฒด `rtkConfig` ๊ตฌ์กฐ๋Š” `open-sse/services/compression/types.ts`์˜ `RtkConfig` / `DEFAULT_RTK_CONFIG`์— ์ •์˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ „์ฒด ๊ฐ์ฒด๋Š” SQLite `key_value` ํ…Œ์ด๋ธ”์— `namespace = "compression"`, `key = "rtkConfig"`๋กœ ํ•˜๋‚˜์˜ JSON ๊ฐ’์œผ๋กœ ์ €์žฅ๋˜๋ฉฐ (`src/lib/db/compression.ts`), ์ฝ์„ ๋•Œ `normalizeRtkConfig`๋ฅผ ํ†ตํ•ด ์ •๊ทœํ™”๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์•„๋ž˜์˜ ๋ชจ๋“  ํ•„๋“œ(์˜ˆ: `enableGrouping`, `groupingThreshold`, `stripCodeComments`, `preserveDocstrings`)๋Š” ๋™์ผํ•œ ์ €์žฅ์†Œ๋ฅผ ํ†ตํ•ด ์™•๋ณต ์ฒ˜๋ฆฌ๋˜๋ฉฐ ์žฌ์‹œ์ž‘ ํ›„์—๋„ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. | ํ‚ค | ๊ธฐ๋ณธ๊ฐ’ | ์šฉ๋„ | | ---------------------- | ------- | -------------------------------------------------------------- | | `deduplicateThreshold` | `3` | ์—”์ง„ ์ „์ฒด: ์ถ•์•ฝํ•  ์—ฐ์† ๋™์ผ ์ค„์˜ ์ตœ์†Œ ๊ฐœ์ˆ˜(2~100 ๋ฒ”์œ„) | | `enableGrouping` | `false` | ์˜ตํŠธ์ธ: ๊ฑฐ์˜ ๋™์ผํ•œ ์—ฐ์† ์ค„ ๋ฌถ์Œ์„ ์ถ•์•ฝ | | `groupingThreshold` | `3` | ๊ทธ๋ฃนํ™”๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•˜๋Š” ์œ ์‚ฌํ•œ ์—ฐ์† ์ค„ ๋ฌถ์Œ์˜ ์ตœ์†Œ ๊ฐœ์ˆ˜ | | `stripCodeComments` | `false` | ์˜ตํŠธ์ธ: ํŽœ์Šค ์ฝ”๋“œ ๋ธ”๋ก์—์„œ ์ฃผ์„ ์ œ๊ฑฐ(`applyToCodeBlocks` ํ•„์š”) | | `preserveDocstrings` | `true` | ์ฃผ์„์„ ์ œ๊ฑฐํ•  ๋•Œ JSDoc/`/** โ€ฆ */` ๋ธ”๋ก ์œ ์ง€ | ## API | ๊ฒฝ๋กœ | ๋ฉ”์„œ๋“œ | ์šฉ๋„ | | ---------------------------------- | ------ | ----------------------------------------- | | `/api/context/rtk/config` | GET | RTK ๊ตฌ์„ฑ ์ฝ๊ธฐ | | `/api/context/rtk/config` | PUT | RTK ๊ตฌ์„ฑ ์—…๋ฐ์ดํŠธ | | `/api/context/rtk/filters` | GET | ํ•„ํ„ฐ ์นดํƒˆ๋กœ๊ทธ ๋ฐ ๋กœ๋“œ ์ง„๋‹จ ๋ชฉ๋ก ์กฐํšŒ | | `/api/context/rtk/import` | POST | RTK TOML ์Šคํ‚ค๋งˆ v1 ํŒŒ์ผ ๊ฒ€์ฆ ๋˜๋Š” ์„ค์น˜ | | `/api/context/rtk/test` | POST | ๋‹จ์ผ ํ…์ŠคํŠธ ํŽ˜์ด๋กœ๋“œ์˜ RTK ์••์ถ• ๋ฏธ๋ฆฌ ๋ณด๊ธฐ | | `/api/context/rtk/raw-output/[id]` | GET | ๋ณด์กด๋œ ๋ฏผ๊ฐ ์ •๋ณด ์ œ๊ฑฐ ์›์‹œ ์ถœ๋ ฅ ์ฝ๊ธฐ | | `/api/compression/preview` | POST | ๋ชจ๋“  ์••์ถ• ๋ชจ๋“œ ๋ฏธ๋ฆฌ ๋ณด๊ธฐ | RTK ํ…Œ์ŠคํŠธ ํŽ˜์ด๋กœ๋“œ: ```json { "command": "npm test", "text": "FAIL tests/example.test.ts\nAssertionError: expected true\nTest Files 1 failed", "config": { "intensity": "standard" } } ``` ์••์ถ• ๋ฏธ๋ฆฌ ๋ณด๊ธฐ ํŽ˜์ด๋กœ๋“œ: ```json { "mode": "stacked", "messages": [ { "role": "tool", "content": "FAIL tests/example.test.ts\nAssertionError: expected true\nTest Files 1 failed" } ], "config": { "rtkConfig": { "rawOutputRetention": "failures" } } } ``` ๊ด€๋ฆฌ ๊ฒฝ๋กœ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋Œ€์‹œ๋ณด๋“œ ๊ด€๋ฆฌ ์ธ์ฆ ๋˜๋Š” ์ผ์น˜ํ•˜๋Š” API ํ‚ค ์ •์ฑ…์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. RTK TOML ๊ฒ€์ฆ ํŽ˜์ด๋กœ๋“œ: ```json { "action": "validate", "content": "schema_version = 1\n\n[filters.my-tool]\nmatch_command = \"^my-tool\\\\b\"\nmax_lines = 20\n" } ``` ๊ฒ€์ฆ๋œ ํŒŒ์ผ์„ ์ „์—ญ์œผ๋กœ ์„ค์น˜ํ•˜๋ ค๋ฉด `"action": "install"`์„ ์‚ฌ์šฉํ•˜์„ธ์š”. ๊ธฐ์กด ์ „์—ญ ํŒŒ์ผ์˜ ๊ต์ฒด๋ฅผ ๊ฒ€ํ† ํ•˜๊ณ  ํ™•์ธํ•œ ํ›„์—๋งŒ `"overwrite": true`๋ฅผ ์ถ”๊ฐ€ํ•˜์„ธ์š”. ## ์›์‹œ ์ถœ๋ ฅ ๋ณต๊ตฌ RTK๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์••์ถ•๋œ ํ…์ŠคํŠธ๋งŒ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋””๋ฒ„๊น…์„ ์œ„ํ•ด `rawOutputRetention`์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฏผ๊ฐ ์ •๋ณด๊ฐ€ ์‚ญ์ œ๋œ ์›์‹œ ์ถœ๋ ฅ์„ ๋ณด์กดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. | ๊ฐ’ | ๋™์ž‘ | | ---------- | -------------------------------------------------- | | `never` | ์›์‹œ ์ถœ๋ ฅ์„ ๋ณด์กดํ•˜์ง€ ์•Š์Œ | | `failures` | ์‹คํŒจํ–ˆ์„ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š” ์ถœ๋ ฅ๋งŒ ๋ณด์กด | | `always` | ๋ฏผ๊ฐ ์ •๋ณด ์‚ญ์ œ ํ›„ ์••์ถ•๋œ ๋ชจ๋“  RTK ์›์‹œ ์ถœ๋ ฅ์„ ๋ณด์กด | ๋ณด์กด๋œ ํŒŒ์ผ์€ ๋‹ค์Œ ๊ฒฝ๋กœ ์•„๋ž˜์— ๊ธฐ๋ก๋ฉ๋‹ˆ๋‹ค. ```txt DATA_DIR/rtk/raw-output/ ``` ์˜๊ตฌ ์ €์žฅ ์ „์— ์ผ๋ฐ˜์ ์ธ bearer token, API key, Slack token, AWS access key ๋ฐ ํ• ๋‹น ํ˜•์‹์˜ `token=...`, `secret=...`, `password=...` ๊ฐ’์„ ํฌํ•จํ•œ ๋น„๋ฐ€ ์ •๋ณด๊ฐ€ ์‚ญ์ œ๋ฉ๋‹ˆ๋‹ค. ๋ถ„์„ ๋ฐ์ดํ„ฐ์—๋Š” ํฌ์ธํ„ฐ ID, ํฌ๊ธฐ ๋ฐ ํ•ด์‹œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋งŒ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. ## ๊ฒ€์ฆ ๊ฒŒ์ดํŠธ ์ง‘์ค‘ ๊ฒ€์ฆ ๊ฒŒ์ดํŠธ๋Š” ์™ธ๋ถ€ ๋ช…๋ น์„ ์…ธ๋กœ ์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ  ๊ธฐ๋ณธ ์ œ๊ณต ์ธ๋ผ์ธ ํ•„ํ„ฐ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ```bash node --import tsx/esm --test tests/unit/compression/rtk-verify.test.ts ``` ๋” ๊ด‘๋ฒ”์œ„ํ•œ RTK ๊ฒŒ์ดํŠธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ```bash node --import tsx/esm --test \ tests/unit/compression/rtk-*.test.ts \ tests/unit/compression/pipeline-integration.test.ts \ tests/unit/compression/context-compression-api.test.ts ``` ๋ฆด๋ฆฌ์Šค ์ „์— ์ „์ฒด ์••์ถ• ๊ฒŒ์ดํŠธ๋ฅผ ์‹คํ–‰ํ•˜์„ธ์š”. ```bash node --import tsx/esm --test \ tests/unit/compression/*.test.ts \ tests/golden-set/*.test.ts \ tests/integration/compression-pipeline.test.ts \ tests/unit/api/compression/compression-api.test.ts ``` ## RTK ํ™•์žฅ 1. ํ•„ํ„ฐ JSON ํŒŒ์ผ์„ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค. 2. ์ค‘์š”ํ•œ ๋™์ž‘์„ ์ž…์ฆํ•˜๋Š” `tests[]` ์ƒ˜ํ”Œ์„ ํ•˜๋‚˜ ์ด์ƒ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. 3. ์ƒˆ๋กœ์šด ๋ช…๋ น ๊ณ„์—ด์˜ ๊ฒฝ์šฐ `tests/unit/compression/fixtures/rtk/` ์•„๋ž˜์— fixture๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. 4. ์ƒˆ๋กœ์šด ์ถœ๋ ฅ ํด๋ž˜์Šค๋ฅผ ๋„์ž…ํ•  ๋•Œ ๋ช…๋ น ๊ฐ์ง€ ์ปค๋ฒ„๋ฆฌ์ง€๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. 5. ๊ฒ€์ฆ ๊ฒŒ์ดํŠธ์™€ ๊ด‘๋ฒ”์œ„ํ•œ RTK ๊ฒŒ์ดํŠธ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. 6. ํ•„ํ„ฐ๊ฐ€ ํ”„๋กœ์ ํŠธ ๋กœ์ปฌ์ธ ๊ฒฝ์šฐ ๊ฒ€ํ†  ํ›„์—๋งŒ `.rtk/filters.json`์„ ์ปค๋ฐ‹ํ•˜๊ณ  `.rtk/trust.json`์„ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค. --- ## ๊ฐ•๋„ ์ˆ˜์ค€ (v3.8.16+) RTK๋Š” **์••์ถ•์˜ ๊ณต๊ฒฉ์„ฑ**๊ณผ **์•ˆ์ „์„ฑ** ์‚ฌ์ด์—์„œ ๊ท ํ˜•์„ ์กฐ์ ˆํ•˜๋Š” **3๊ฐ€์ง€ ๊ฐ•๋„ ์ˆ˜์ค€**์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์ˆ˜์ค€์€ ์—”์ง„ ๊ตฌ์„ฑ์˜ `config.intensity`๋ฅผ ํ†ตํ•ด ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ### 3๊ฐ€์ง€ ์ˆ˜์ค€ | ์ˆ˜์ค€ | ์ž˜๋ผ๋‚ด๊ธฐ ์ž„๊ณ„๊ฐ’ | ํ† ํฐ ์ ˆ๊ฐ๋ฅ  | ์œ„ํ—˜๋„ | ์ ํ•ฉํ•œ ์šฉ๋„ | | ------------------- | --------------- | ----------- | --------- | ------------------------------- | | `minimal` | ์„น์…˜๋‹น 24์ค„ | ~20-40% | ๋งค์šฐ ๋‚ฎ์Œ | ์ค‘์š”ํ•œ ์ปจํ…์ŠคํŠธ๊ฐ€ ์žˆ๋Š” ํ”„๋กœ๋•์…˜ | | `standard` (๊ธฐ๋ณธ๊ฐ’) | ์„น์…˜๋‹น 24์ค„ | ~50-70% | ๋‚ฎ์Œ | ์ผ์ƒ์ ์ธ ์ฝ”๋”ฉ ์„ธ์…˜ | | `aggressive` | ์„น์…˜๋‹น 16์ค„ | ~70-90% | ์ค‘๊ฐ„ | ๊ธด ์„ธ์…˜, ์ตœ๋Œ€ ์ ˆ๊ฐ | ### ์ž˜๋ผ๋‚ด๊ธฐ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์œ„์น˜ ์ž˜๋ผ๋‚ด๊ธฐ ์ž„๊ณ„๊ฐ’์€ `lineFilter.ts`์— ์˜ํ–ฅ์„ ์ค๋‹ˆ๋‹ค. ```ts // open-sse/services/compression/engines/rtk/index.ts:329-330์—์„œ ๋ฐœ์ทŒ config.intensity === "aggressive" ? 16 : 24, config.intensity === "aggressive" ? 16 : 24, ``` ๊ฐ ์„น์…˜์˜ **์•ž๋ถ€๋ถ„**๊ณผ **๋’ท๋ถ€๋ถ„**์€ ๋ชจ๋‘ ๋ณด์กด๋˜๋ฉฐ, ์ž˜๋ผ๋‚ด๊ธฐ๊ฐ€ ์‹œ์ž‘๋˜๋ฉด ์ค‘๊ฐ„ ์ฝ˜ํ…์ธ ๊ฐ€ ์ œ๊ฑฐ๋ฉ๋‹ˆ๋‹ค. ### ์œ ์ง€๋˜๋Š” ํ•ญ๋ชฉ๊ณผ ์ž˜๋ฆฌ๋Š” ํ•ญ๋ชฉ | ์ฝ˜ํ…์ธ  | minimal | standard | aggressive | | ---------------------- | ------- | -------- | ---------- | | ์˜ค๋ฅ˜ / ์Šคํƒ ์ถ”์  | โœ… ๋ณด์กด | โœ… ๋ณด์กด | โœ… ๋ณด์กด | | ํ…Œ์ŠคํŠธ ์‹คํŒจ | โœ… ๋ณด์กด | โœ… ๋ณด์กด | โœ… ๋ณด์กด | | ๋นŒ๋“œ ์˜ค๋ฅ˜ | โœ… ๋ณด์กด | โœ… ๋ณด์กด | โœ… ๋ณด์กด | | ํ…Œ์ŠคํŠธ ํ†ต๊ณผ(์ƒ์„ธ ์ถœ๋ ฅ) | โœ… ๋ณด์กด | ๐ŸŸก ์ถ•์•ฝ | ๐ŸŸก ์ถ•์•ฝ | | ์ผ๋ฐ˜ ์ถœ๋ ฅ(์ •๋ณด ๋กœ๊ทธ) | ๐ŸŸก ์ถ•์•ฝ | ๐ŸŸก ์ถ•์•ฝ | โŒ ์ œ๊ฑฐ | | ์ง„ํ–‰๋ฅ  ํ‘œ์‹œ์ค„ | ๐ŸŸก ์ถ•์•ฝ | โŒ ์ œ๊ฑฐ | โŒ ์ œ๊ฑฐ | | ๋ฐฐ๋„ˆ / ASCII ์•„ํŠธ | ๐ŸŸก ์ถ•์•ฝ | โŒ ์ œ๊ฑฐ | โŒ ์ œ๊ฑฐ | ### ์ ์ ˆํ•œ ๊ฐ•๋„ ์„ ํƒ ``` ์ปจํ…์ŠคํŠธ ์†์‹ค์ด ์น˜๋ช…์ ์ธ๊ฐ€? โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ ์˜ˆ ์•„๋‹ˆ์š” ํ™•์‹คํ•˜์ง€ ์•Š์Œ โ”‚ โ”‚ โ”‚ โ–ผ โ”‚ โ”‚ minimal โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ–ผ โ–ผ โ”‚ ์ฒ˜๋ฆฌ๋Ÿ‰์ด ์–ผ๋งˆ๋‚˜ ๋จผ์ € `standard` ์‹œ๋„ โ”‚ ์ค‘์š”ํ•œ๊ฐ€? (์‚ฌ๋ก€์˜ 80%์—์„œ โ”‚ โ”‚ ํšจ๊ณผ์ ) โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ โ”‚ ๋‚ฎ์Œ ๋†’์Œ โ”‚ โ”‚ โ”‚ โ”‚ โ–ผ โ–ผ โ”‚ standard aggressive โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` ### ๊ฐ•๋„ ๊ตฌ์„ฑ **์ฝค๋ณด๋ณ„**(์ฝค๋ณด ๊ตฌ์„ฑ ๋‚ด): ```json { "combo": "my-coding-combo", "routing": {/* ... */}, "compression": { "engine": "rtk", "intensity": "aggressive" } } ``` **ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹**: `rtkEngine` (`@omniroute/open-sse/services/compression/engines/rtk`)์€ `CompressionEngine`์ด๋ฉฐ `updateConfig` ๋ฉ”์„œ๋“œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋Œ€์‹  ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ ํ—ฌํผ๋ฅผ ํ†ตํ•ด ์—”์ง„ ๊ตฌ์„ฑ์„ ์—…๋ฐ์ดํŠธํ•˜์„ธ์š”. ```ts import { updateEngineConfig } from "@omniroute/open-sse/services/compression/engines/registry"; updateEngineConfig("rtk", { intensity: "aggressive" }); ``` ### ํšจ๊ณผ ๊ฒ€์ฆ **๊ฒ€์ฆ ๊ฒŒ์ดํŠธ**(์•„๋ž˜ ์ฐธ์กฐ)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„ ํƒํ•œ ๊ฐ•๋„์—์„œ ํ•„ํ„ฐ๊ฐ€ ์•ˆ์ „ํ•œ์ง€ ํ™•์ธํ•˜์„ธ์š”. ```ts import { runRtkFilterTests } from "omniroute/compression/engines/rtk/verify"; const result = runRtkFilterTests({ intensity: "aggressive" }); if (!result.passed) { console.error("๊ณต๊ฒฉ์  ๊ฐ•๋„์—์„œ ํ•„ํ„ฐ ์‹คํŒจ"); } ``` --- ## ์‚ฌ์šฉ์ž ์ง€์ • ํ•„ํ„ฐ ๊ฐœ๋ฐœ (v3.8.16+) `engines/rtk/filters/` ๋””๋ ‰ํ„ฐ๋ฆฌ์—๋Š” **49๊ฐœ ์ด์ƒ์˜ ๊ธฐ๋ณธ ์ œ๊ณต ํ•„ํ„ฐ JSON ํŒŒ์ผ**์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ํ•„ํ„ฐ์—์„œ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ์‚ฌ์šฉ์ž ์ง€์ • ๋„๊ตฌ์˜ ์ถœ๋ ฅ์„ ์••์ถ•ํ•˜๋ ค๋ฉด ์ž์ฒด ํ•„ํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ### ํ•„ํ„ฐ ์Šคํ‚ค๋งˆ (Zod) ```ts { "id": "string", // ํ•„์ˆ˜. ํ•„ํ„ฐ ์‹๋ณ„์ž(kebab-case, ์˜ˆ: "python-traceback") "label": "string", // ํ•„์ˆ˜. ์‚ฌ๋žŒ์ด ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ํ•„ํ„ฐ ์ด๋ฆ„ "description": "string", // ์„ ํƒ ์‚ฌํ•ญ(๊ธฐ๋ณธ๊ฐ’: ""). ํ•„ํ„ฐ๊ฐ€ ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์—…์— ๋Œ€ํ•œ ๊ฐ„๋‹จํ•œ ์„ค๋ช… "category": "git|test|build|shell|docker|package|infra|cloud|generic", "priority": number, // ์„ ํƒ ์‚ฌํ•ญ(0-100, ๊ธฐ๋ณธ๊ฐ’: 50). ์‹คํ–‰ ์ˆœ์„œ(๊ฐ’์ด ๋†’์„์ˆ˜๋ก ๋จผ์ € ์‹คํ–‰) "match": { "commands": ["string"], // ์ผ์น˜์‹œํ‚ฌ ๋ช…๋ น์–ด ์ด๋ฆ„(์˜ˆ: "python", "pytest") "patterns": ["string"], // ์ถœ๋ ฅ๊ณผ ์ผ์น˜์‹œํ‚ฌ ์ •๊ทœ์‹ ํŒจํ„ด "outputTypes": ["string"] // ๊ฐ์ง€๋œ ์ถœ๋ ฅ ํด๋ž˜์Šค(์˜ˆ: "test-failure") }, "rules": { "stripAnsi": boolean, // ์„ ํƒ ์‚ฌํ•ญ(๊ธฐ๋ณธ๊ฐ’: false). ANSI ์ƒ‰์ƒ ์ฝ”๋“œ ์ œ๊ฑฐ "replace": [ // ์ฐพ๊ธฐ ๋ฐ ๋ฐ”๊พธ๊ธฐ ๊ทœ์น™(๊ธฐ๋ณธ๊ฐ’: []) { "pattern": "regex", "replacement": "..." } ], "matchOutput": [ // ํŒจํ„ด์ด ์ผ์น˜ํ•˜๋ฉด ์ฆ‰์‹œ ์ฒ˜๋ฆฌ ์ข…๋ฃŒ(๊ธฐ๋ณธ๊ฐ’: []) { "pattern": "regex", "message": "short summary", "unless": "regex" // ์ด ํŒจํ„ด์ด ์ผ์น˜ํ•˜๋ฉด ๊ฑด๋„ˆ๋œ€ } ], "includePatterns": ["string"], // ์œ ์ง€ํ•  ์ค„(์ •๊ทœ์‹ ํŒจํ„ด, ๊ธฐ๋ณธ๊ฐ’: []) "dropPatterns": ["string"], // ์ œ๊ฑฐํ•  ์ค„(์ •๊ทœ์‹ ํŒจํ„ด, ๊ธฐ๋ณธ๊ฐ’: []) "collapsePatterns": ["string"], // ํ•˜๋‚˜์˜ ํ•ญ๋ชฉ์œผ๋กœ ์ถ•์•ฝํ•  ์ค„(๊ธฐ๋ณธ๊ฐ’: []) "deduplicate": boolean, // ์„ ํƒ ์‚ฌํ•ญ(๊ธฐ๋ณธ๊ฐ’: false). ์ค‘๋ณต๋œ ์ค„ ์ œ๊ฑฐ "truncateLineAt": number, // ์„ ํƒ ์‚ฌํ•ญ(๊ธฐ๋ณธ๊ฐ’: 0). ์ค„์„ ์ตœ๋Œ€ ๋ฌธ์ž ์ˆ˜๋กœ ์ž๋ฆ„ "maxLines": number, // ์„ ํƒ ์‚ฌํ•ญ(๊ธฐ๋ณธ๊ฐ’: 0). ์ „์ฒด ์ค„ ์ˆ˜์˜ ์ ˆ๋Œ€ ์ƒํ•œ "headLines": number, // ์„ ํƒ ์‚ฌํ•ญ(๊ธฐ๋ณธ๊ฐ’: 20). ์ผ์น˜ํ•œ ์ถœ๋ ฅ์˜ ์ฒ˜์Œ N๊ฐœ ์ค„ ์œ ์ง€ "tailLines": number, // ์„ ํƒ ์‚ฌํ•ญ(๊ธฐ๋ณธ๊ฐ’: 20). ์ผ์น˜ํ•œ ์ถœ๋ ฅ์˜ ๋งˆ์ง€๋ง‰ N๊ฐœ ์ค„ ์œ ์ง€ "onEmpty": "string", // ์„ ํƒ ์‚ฌํ•ญ(๊ธฐ๋ณธ๊ฐ’: ""). ๋ชจ๋“  ์ค„์ด ํ•„ํ„ฐ๋ง๋œ ๊ฒฝ์šฐ ์‚ฌ์šฉํ•  ๋Œ€์ฒด ๋ฉ”์‹œ์ง€ "filterStderr": boolean // ์„ ํƒ ์‚ฌํ•ญ(๊ธฐ๋ณธ๊ฐ’: false). stderr ์ถœ๋ ฅ๋„ ํ•„ํ„ฐ๋ง }, "preserve": { "errorPatterns": ["string"], // ํ•ญ์ƒ ๋ณด์กดํ•ด์•ผ ํ•˜๋Š” ํŒจํ„ด(๊ธฐ๋ณธ๊ฐ’: []) "summaryPatterns": ["string"] // ์ตœ์ข… ์š”์•ฝ ์ค„์˜ ํŒจํ„ด(๊ธฐ๋ณธ๊ฐ’: []) }, "tests": [ // ๊ฒ€์ฆ์šฉ ์ธ๋ผ์ธ ํ…Œ์ŠคํŠธ(๊ธฐ๋ณธ๊ฐ’: []) { "name": "string", // ํ•„์ˆ˜. ํ…Œ์ŠคํŠธ ์ด๋ฆ„ "input": "sample output", // ํ•„์ˆ˜. ์ƒ˜ํ”Œ ์ž…๋ ฅ ํ…์ŠคํŠธ "expected": "expected output", // ํ•„์ˆ˜. ์˜ˆ์ƒ ์••์ถ• ์ถœ๋ ฅ "command": "optional command" // ์„ ํƒ ์‚ฌํ•ญ. ๋ช…๋ น์–ด ์ปจํ…์ŠคํŠธ } ] } ``` ### ์˜ˆ์‹œ: Python ํŠธ๋ ˆ์ด์Šค๋ฐฑ ํ•„ํ„ฐ ```json { "id": "python-traceback", "label": "Python Traceback Filter", "description": "Compresses Python tracebacks to essential file/line locations and error type", "category": "test", "priority": 60, "match": { "commands": ["python", "python3", "pytest", "uv", "poetry"], "patterns": ["Traceback \\(most recent call last\\)", "Error", "Exception"], "outputTypes": ["error-traceback"] }, "rules": { "stripAnsi": true, "includePatterns": [ "Traceback \\(most recent call last\\)", "^\\s*File \".+\", line \\d+", "^\\s*[A-Z][a-zA-Z]+Error:", "^\\s*[A-Z][a-zA-Z]+Exception" ], "dropPatterns": ["site-packages/", "^\\s+[a-z_]+\\([^)]*\\)$"], "headLines": 5, "tailLines": 3, "maxLines": 25, "filterStderr": true }, "preserve": { "errorPatterns": ["Error:", "Exception:", "Traceback"], "summaryPatterns": ["^[A-Z][a-zA-Z]+(?:Error|Exception):"] }, "tests": [ { "name": "preserves-error-type-and-location", "input": "Traceback (most recent call last):\n File \"app.py\", line 42, in main\n do_thing()\n File \"lib/utils.py\", line 17, in helper\n return 1 / 0\nZeroDivisionError: division by zero", "expected": "Traceback (most recent call last):\n File \"app.py\", line 42, in main\n File \"lib/utils.py\", line 17, in helper\nZeroDivisionError: division by zero", "command": "python app.py" } ] } ``` ### ์‚ฌ์šฉ์ž ์ง€์ • ํ•„ํ„ฐ ๋กœ๋“œ ํŒŒ์ผ์„ ์ธ์‹๋˜๋Š” ์œ„์น˜์— ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค. ``` ~/.omniroute/rtk/filters/my-filter.json # ์‚ฌ์šฉ์ž ์ˆ˜์ค€ /.rtk/filters/my-filter.json # ํ”„๋กœ์ ํŠธ ์ˆ˜์ค€ ``` ํ•„ํ„ฐ๋Š” ์‹œ์ž‘ ์‹œ `open-sse/services/compression/engines/rtk/filterLoader.ts`์˜ `loadRtkFilters()`๋ฅผ ํ†ตํ•ด ์ž๋™์œผ๋กœ ๋กœ๋“œ๋ฉ๋‹ˆ๋‹ค. ๋กœ๋”๋Š” ๋‹ค์Œ ์œ„์น˜์—์„œ ํ•„ํ„ฐ๋ฅผ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค. - ๊ธฐ๋ณธ ์ œ๊ณต ์นดํƒˆ๋กœ๊ทธ: `open-sse/services/compression/engines/rtk/filters/` - ์‚ฌ์šฉ์ž ๋””๋ ‰ํ„ฐ๋ฆฌ: `~/.omniroute/rtk/filters/` - ํ”„๋กœ์ ํŠธ ๋””๋ ‰ํ„ฐ๋ฆฌ: `/.rtk/filters/` ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์œผ๋กœ ํ•„ํ„ฐ๋ฅผ ๋กœ๋“œํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ```ts import { loadRtkFilters } from "@omniroute/open-sse/services/compression/engines/rtk/filterLoader"; // ์˜ต์…˜: customFiltersEnabled(์‚ฌ์šฉ์ž/ํ”„๋กœ์ ํŠธ ํ•„ํ„ฐ ๋กœ๋“œ, ๊ธฐ๋ณธ์ ์œผ๋กœ ํ™œ์„ฑํ™”), // trustProjectFilters, refresh. const filters = loadRtkFilters({ customFiltersEnabled: true }); ``` ### ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ํ•„ํ„ฐ๋ฅผ ๋กœ๋“œํ•  ๋•Œ Zod ์Šคํ‚ค๋งˆ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์œ ํšจ์„ฑ์„ ๊ฒ€์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๊ตฌ์กฐ๊ฐ€ ์ž˜๋ชป๋œ ํ•„ํ„ฐ๋Š” ๋กœ๋“œ๋˜์ง€ ์•Š์œผ๋ฉฐ ์˜ค๋ฅ˜๊ฐ€ ๊ธฐ๋ก๋ฉ๋‹ˆ๋‹ค. ``` RTK_FILTER_LOADER: ํ•„ํ„ฐ "my-filter"์˜ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ์‹คํŒจ: - rules.replace.0.pattern: ์ž˜๋ชป๋œ ์ •๊ทœ์‹ - match.commands: ๋น„์–ด ์žˆ์œผ๋ฉด ์•ˆ ๋จ ``` ์„ค์น˜๋œ ๋ชจ๋“  ํ•„ํ„ฐ์˜ ์œ ํšจ์„ฑ์„ ๊ฒ€์‚ฌํ•˜๋ ค๋ฉด `open-sse/services/compression/engines/rtk/verify.ts`์—์„œ ๋‚ด๋ณด๋‚ด๋Š” `runRtkFilterTests()`๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ### ๋ชจ๋ฒ” ์‚ฌ๋ก€ 1. **ํ•ญ์ƒ `tests[]`๋ฅผ ํฌํ•จํ•˜์„ธ์š”** โ€” ํ•„ํ„ฐ๊ฐ€ ์ œ๋Œ€๋กœ ์ž‘๋™ํ•จ์„ ์ž…์ฆํ•˜๊ณ  ํšŒ๊ท€๋ฅผ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค 2. **๋‹จ์ถ• ์ฒ˜๋ฆฌ์—๋Š” `matchOutput`์„ ์‚ฌ์šฉํ•˜์„ธ์š”** โ€” ํ•œ ์ค„๋งŒ์œผ๋กœ ์ถฉ๋ถ„ํžˆ ์„ค๋ช…๋œ๋‹ค๋ฉด ์ „์ฒด ๋ธ”๋ก์„ ๋Œ€์ฒดํ•˜์„ธ์š” 3. **`strip`๋ณด๋‹ค `keep`์„ ์šฐ์„ ํ•˜์„ธ์š”** โ€” ๋ช…์‹œ์ ์ธ "ํ•ญ์ƒ ๋ณด์กด" ๊ทœ์น™์ด "ํ•ญ์ƒ ์ œ๊ฑฐ" ๊ทœ์น™๋ณด๋‹ค ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค 4. **3๊ฐ€์ง€ ๊ฐ•๋„ ์ˆ˜์ค€ ๋ชจ๋‘์—์„œ ํ…Œ์ŠคํŠธํ•˜์„ธ์š”** โ€” `minimal`์€ ์•„๋ฌด ์ž‘์—…๋„ ํ•˜์ง€ ์•Š์•„์•ผ ํ•˜๋ฉฐ, `aggressive`์—์„œ๋„ ์˜ค๋ฅ˜๋Š” ๋ณด์กด๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค 5. **`unless` ํ•„๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”** โ€” "X๊ฐ€ ์žˆ์œผ๋ฉด ํŠธ๋ฆฌ๊ฑฐํ•˜์ง€ ์•Š์Œ" ์กฐ๊ฑด์œผ๋กœ ๋‹จ์ถ• ์ฒ˜๋ฆฌ๋ฅผ ๋ณดํ˜ธํ•˜์„ธ์š” --- ## ์›์‹œ ์ถœ๋ ฅ ๋ณต๊ตฌ ๋ฐ ๊ฒ€์ฆ ๊ฒŒ์ดํŠธ RTK๊ฐ€ ์ถœ๋ ฅ์„ ๊ฐ•ํ•˜๊ฒŒ ์••์ถ•ํ•  ๋•Œ ๋””๋ฒ„๊น…, ๊ฐ์‚ฌ ๋˜๋Š” ์žฌ์‹คํ–‰์„ ์œ„ํ•ด **์›๋ณธ ํ…์ŠคํŠธ๋ฅผ ๋ณต๊ตฌ**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ### ์›์‹œ ์ถœ๋ ฅ ๋ณต๊ตฌ ์ž‘๋™ ๋ฐฉ์‹ ``` ์›๋ณธ ์ถœ๋ ฅ(10K ํ† ํฐ) โ”‚ โ–ผ RTK ์••์ถ•(rawOutput.enabled=true) โ”‚ โ”œโ”€โ–ถ ์••์ถ•๋œ ์ถœ๋ ฅ(2K ํ† ํฐ) โ”€โ”€โ–ถ LLM์œผ๋กœ ์ „๋‹ฌ โ”‚ โ””โ”€โ–ถ ์›๋ณธ ์ถœ๋ ฅ(10K ํ† ํฐ) โ”€โ”€โ–ถ DB์— ์ €์žฅ (request_id๋กœ ์—ฐ๊ฒฐ) ``` ### ์›์‹œ ์ถœ๋ ฅ ์ €์žฅ ํ™œ์„ฑํ™” **์š”์ฒญ๋ณ„ ์„ค์ •**(combo ๊ตฌ์„ฑ์—์„œ): ```json { "compression": { "engine": "rtk", "intensity": "aggressive", "rawOutput": { "enabled": true, "maxBytes": 1048576 // 1MB ์ œํ•œ } } } ``` **๊ธฐ๋ณธ๊ฐ’**: `rawOutput.enabled: false`(์ €์žฅ ๊ณต๊ฐ„ ์ ˆ์•ฝ). ### ์ €์žฅ ๋น„์šฉ | ์š”์ฒญ๋‹น | 1MB ์ œํ•œ | 10MB ์ œํ•œ | | --------------------- | ----------- | ------------ | | ํ‰๊ท  ์••์ถ• ์ถœ๋ ฅ | ~5KB | ~5KB | | ์ €์žฅ๋œ ์›์‹œ ์ถœ๋ ฅ | ~50-500KB | ~500KB-5MB | | ์ผ์ผ ์š”์ฒญ 1000๊ฑด ๊ธฐ์ค€ | 50-500MB/์ผ | 500MB-5GB/์ผ | > **๊ถŒ์žฅ ์‚ฌํ•ญ**: ์›์‹œ ์ถœ๋ ฅ์€ ํ•ญ์ƒ ํ™œ์„ฑํ™”ํ•˜์ง€ ๋ง๊ณ  **๋””๋ฒ„๊น… ์„ธ์…˜** ๋˜๋Š” **์ƒ˜ํ”Œ๋ง๋œ ๊ฐ์‚ฌ**์—๋งŒ ํ™œ์„ฑํ™”ํ•˜์„ธ์š”. ### ์›๋ณธ ๋ณต๊ตฌ ```ts import { readRtkRawOutput } from "omniroute/compression/engines/rtk/rawOutput"; const raw = readRtkRawOutput(pointerId); // ์••์ถ• ํ†ต๊ณ„์˜ pointerId if (raw) { console.log("์›๋ณธ ์ถœ๋ ฅ:", raw); } ``` `pointerId`๋Š” ์••์ถ• ํ›„ `CompressionStats.rtkRawOutputPointers[]`์— ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. ํ•จ์ˆ˜ ์‹œ๊ทธ๋‹ˆ์ฒ˜๋Š” `open-sse/services/compression/engines/rtk/rawOutput.ts:102`๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”. ### ๊ฒ€์ฆ ๊ฒŒ์ดํŠธ **RTK ํ•„ํ„ฐ ๊ฒ€์ฆ**(`open-sse/services/compression/engines/rtk/verify.ts`)์€ ๋ชจ๋“  ํ•„ํ„ฐ๋ฅผ ํ•ด๋‹น `tests[]`์— ๋Œ€ํ•ด ๊ฒ€์ฆํ•˜๊ณ , ์„ธ ๊ฐ€์ง€ ๊ฐ•๋„ ์ˆ˜์ค€ ๋ชจ๋‘์—์„œ ๋™์ž‘์ด ์˜ฌ๋ฐ”๋ฅธ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๊ฒ€์ฆ์„ ์‹คํ–‰ํ•˜๋ ค๋ฉด **`runRtkFilterTests()`๋ฅผ ํ˜ธ์ถœํ•˜์„ธ์š”**: ```ts import { runRtkFilterTests } from "open-sse/services/compression/engines/rtk/verify"; const result = runRtkFilterTests(); console.log(`ํ†ต๊ณผ: ${result.outcomes.filter((o) => o.passed).length}`); console.log(`์‹คํŒจ: ${result.outcomes.filter((o) => !o.passed).length}`); if (!result.passed) { console.error("ํ•„ํ„ฐ๊ฐ€ ๊ฒ€์ฆ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค"); result.outcomes .filter((o) => !o.passed) .forEach((o) => { console.error( ` - ${o.filterId} / ${o.testName}: ์˜ˆ์ƒ๊ฐ’ "${o.expected}", ์‹ค์ œ๊ฐ’ "${o.actual}"` ); }); } ``` **๊ฒ€์ฆ ํ•ญ๋ชฉ**: 1. ๋ชจ๋“  ํ•„ํ„ฐ๊ฐ€ ๋กœ๋“œ๋˜๊ณ  ์Šคํ‚ค๋งˆ ๊ฒ€์ฆ์„ ํ†ต๊ณผํ•˜๋Š”์ง€ ํ™•์ธ 2. ๋ชจ๋“  `tests[]` ํ•ญ๋ชฉ์ด ์˜ˆ์ƒ ์ถœ๋ ฅ์„ ์ƒ์„ฑํ•˜๋Š”์ง€ ํ™•์ธ 3. `minimal` ๊ฐ•๋„๊ฐ€ ์•„๋ฌด ์ž‘์—…๋„ ํ•˜์ง€ ์•Š๋Š”์ง€ ํ™•์ธ(์›๋ณธ์„ ๋ณด์กดํ•˜๊ณ  ๊ตฌ์กฐ์  ํ•„ํ„ฐ๋งŒ ์ ์šฉ) 4. `aggressive` ๊ฐ•๋„๊ฐ€ ์˜ค๋ฅ˜, ํ…Œ์ŠคํŠธ ์‹คํŒจ ๋ฐ ์Šคํƒ ์ถ”์ ์„ ๋ณด์กดํ•˜๋Š”์ง€ ํ™•์ธ 5. ์••์ถ•๋œ ์ถœ๋ ฅ์ด ์›๋ณธ ์ž…๋ ฅ๋ณด๋‹ค ์ ˆ๋Œ€ ํฌ์ง€ ์•Š์€์ง€ ํ™•์ธ - ์†Œ์Šค: `open-sse/services/compression/engines/rtk/`(63๊ฐœ ํŒŒ์ผ, ~70KB) - **ํ•„ํ„ฐ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๋ณ‘ํ•ฉํ•˜๊ธฐ ์ „** โ€” ํ•ญ์ƒ ํ…Œ์ŠคํŠธ ํ†ต๊ณผ ์—ฌ๋ถ€ ํ™•์ธ - **RTK ์—”์ง„์„ ์—…๊ทธ๋ ˆ์ด๋“œํ•œ ํ›„** โ€” ์Šคํ‚ค๋งˆ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์„ ์ˆ˜ ์žˆ์Œ - **๋ชจ๋‹ˆํ„ฐ๋ง ์ค‘ ์ •๊ธฐ์ ์œผ๋กœ** โ€” ํ…Œ์ŠคํŠธ ํ”ฝ์Šค์ฒ˜์˜ ๋“œ๋ฆฌํ”„ํŠธ ๋ฐฉ์ง€ - **์ƒˆ๋กœ์šด ๋„๊ตฌ/๋ช…๋ น ๊ณ„์—ด์„ ์ถ”๊ฐ€ํ•  ๋•Œ** โ€” ์ƒˆ ํ•„ํ„ฐ์˜ ์ •์ƒ ์ž‘๋™ ์ž…์ฆ --- ## ์ฐธ๊ณ  ์ž๋ฃŒ - [COMPRESSION_GUIDE.md](./COMPRESSION_GUIDE.md) โ€” ์ „์ฒด ์••์ถ• ํŒŒ์ดํ”„๋ผ์ธ ๊ฐœ์š” - [COMPRESSION_ENGINES.md](./COMPRESSION_ENGINES.md) โ€” ์—”์ง„ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ ๋ฐ ๋‚ด์žฅ ์—”์ง„ - [EXTENDING_COMPRESSION.md](./EXTENDING_COMPRESSION.md) โ€” ์‚ฌ์šฉ์ž ์ •์˜ ์—”์ง„, ์–ธ์–ด ํŒฉ, ์Šคํƒํ˜• ํŒŒ์ดํ”„๋ผ์ธ - ์†Œ์Šค: `open-sse/services/compression/engines/rtk/` (ํŒŒ์ผ 63๊ฐœ, ์•ฝ 70KB)