[๐Ÿ‡ฌ๐Ÿ‡ง English](./README.md) | [๐Ÿ‡จ๐Ÿ‡ณ ๆฑ‰่ฏญ](./README.zh.md) | [๐Ÿ‡ช๐Ÿ‡ธ espaรฑol](./README.es.md) | [๐Ÿ‡ฏ๐Ÿ‡ต ๆ—ฅๆœฌ่ชž](./README.ja.md) | [๐Ÿ‡ฆ๐Ÿ‡ช ุงู„ุนุฑุจูŠุฉ](./README.ar.md) | [๐Ÿ‡ท๐Ÿ‡บ ั€ัƒััะบะธะน](./README.ru.md) | [๐Ÿ‡ฉ๐Ÿ‡ช Deutsch](./README.de.md) | [๐Ÿ‡ซ๐Ÿ‡ท franรงais](./README.fr.md) | **๐Ÿ‡ฐ๐Ÿ‡ท ํ•œ๊ตญ์–ด** | [๐Ÿ‡ง๐Ÿ‡ท portuguรชs](./README.pt.md) # tzst [![codecov](https://codecov.io/gh/xixu-me/tzst/graph/badge.svg?token=2AIN1559WU)](https://codecov.io/gh/xixu-me/tzst) [![CodeQL](https://github.com/xixu-me/tzst/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/xixu-me/tzst/actions/workflows/github-code-scanning/codeql) [![CI/CD](https://github.com/xixu-me/tzst/actions/workflows/ci.yml/badge.svg)](https://github.com/xixu-me/tzst/actions/workflows/ci.yml) [![PyPI - Version](https://img.shields.io/pypi/v/tzst)](https://pypi.org/project/tzst/) [![GitHub License](https://img.shields.io/github/license/xixu-me/tzst)](LICENSE) [![Sponsor](https://img.shields.io/badge/Sponsor-violet)](https://xi-xu.me/#sponsorships) **tzst**๋Š” ์ตœ์‹  Zstandard ์••์ถ• ๊ธฐ์ˆ ์„ ํ™œ์šฉํ•˜์—ฌ ์šฐ์ˆ˜ํ•œ ์„ฑ๋Šฅ, ๋ณด์•ˆ ๋ฐ ์‹ ๋ขฐ์„ฑ์„ ์ œ๊ณตํ•˜๋Š” ์ฐจ์„ธ๋Œ€ Python ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. Python 3.12+ ์ „์šฉ์œผ๋กœ ์ œ์ž‘๋œ ์ด ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ๊ธ‰ ์†”๋ฃจ์…˜์€ ์›์ž์  ์ž‘์—…, ์ŠคํŠธ๋ฆฌ๋ฐ ํšจ์œจ์„ฑ ๋ฐ ์ •๊ตํ•˜๊ฒŒ ์„ค๊ณ„๋œ API๋ฅผ ๊ฒฐํ•ฉํ•˜์—ฌ `.tzst`/`.tar.zst` ์•„์นด์ด๋ธŒ๋ฅผ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์„ ์žฌ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ๐Ÿš€ ## โœจ ๊ธฐ๋Šฅ - **๐Ÿ—œ๏ธ ๊ณ ์••์ถ•๋ฅ **: ์šฐ์ˆ˜ํ•œ ์••์ถ•๋ฅ ๊ณผ ์†๋„๋ฅผ ์œ„ํ•œ Zstandard ์••์ถ• - **๐Ÿ“ Tar ํ˜ธํ™˜์„ฑ**: Zstandard๋กœ ์••์ถ•๋œ ํ‘œ์ค€ tar ์•„์นด์ด๋ธŒ ์ƒ์„ฑ - **๐Ÿ’ป ๋ช…๋ น์ค„ ์ธํ„ฐํŽ˜์ด์Šค**: ์ŠคํŠธ๋ฆฌ๋ฐ ์ง€์›๊ณผ ํฌ๊ด„์ ์ธ ์˜ต์…˜์„ ๊ฐ–์ถ˜ ์ง๊ด€์ ์ธ CLI - **๐Ÿ Python API**: ํ”„๋กœ๊ทธ๋žจ์  ์‚ฌ์šฉ์„ ์œ„ํ•œ ๊น”๋”ํ•˜๊ณ  Python ์Šคํƒ€์ผ์˜ API - **๐ŸŒ ํฌ๋กœ์Šค ํ”Œ๋žซํผ**: Windows, macOS, Linux์—์„œ ์ž‘๋™ - **๐Ÿ“‚ ๋‹ค์ค‘ ํ™•์žฅ์ž**: `.tzst` ๋ฐ `.tar.zst` ํ™•์žฅ์ž ๋ชจ๋‘ ์ง€์› - **๐Ÿ’พ ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์ **: ์ตœ์†Œ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ์œผ๋กœ ๋Œ€์šฉ๋Ÿ‰ ์•„์นด์ด๋ธŒ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅํ•œ ์ŠคํŠธ๋ฆฌ๋ฐ ๋ชจ๋“œ - **โšก ์›์ž์  ์ž‘์—…**: ์ค‘๋‹จ ์‹œ ์ž๋™ ์ •๋ฆฌ ๊ธฐ๋Šฅ์„ ํ†ตํ•œ ์•ˆ์ „ํ•œ ํŒŒ์ผ ์ž‘์—… - **๐Ÿ”’ ๊ธฐ๋ณธ ๋ณด์•ˆ**: ์ถ”์ถœ ์‹œ ์ตœ๋Œ€ ๋ณด์•ˆ์„ ์œ„ํ•ด 'data' ํ•„ํ„ฐ ์‚ฌ์šฉ - **๐Ÿšจ ํ–ฅ์ƒ๋œ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ**: ์œ ์šฉํ•œ ๋Œ€์•ˆ ์ œ์‹œ์™€ ํ•จ๊ป˜ ๋ช…ํ™•ํ•œ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ## ๐Ÿ“ฅ ์„ค์น˜ ### GitHub ๋ฆด๋ฆฌ์Šค์—์„œ Python ์„ค์น˜๊ฐ€ ํ•„์š” ์—†๋Š” ๋…๋ฆฝํ˜• ์‹คํ–‰ ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ: #### ์ง€์› ํ”Œ๋žซํผ | ํ”Œ๋žซํผ | ์•„ํ‚คํ…์ฒ˜ | ํŒŒ์ผ | |----------|-------------|------| | **๐Ÿง Linux** | x86_64 | `tzst-v{๋ฒ„์ „}-linux-x86_64.zip` | | **๐Ÿง Linux** | ARM64 | `tzst-v{๋ฒ„์ „}-linux-aarch64.zip` | | **๐ŸชŸ Windows** | x64 | `tzst-v{๋ฒ„์ „}-windows-amd64.zip` | | **๐ŸชŸ Windows** | ARM64 | `tzst-v{๋ฒ„์ „}-windows-arm64.zip` | | **๐ŸŽ macOS** | Intel | `tzst-v{๋ฒ„์ „}-macos-x86_64.zip` | | **๐ŸŽ macOS** | Apple Silicon | `tzst-v{๋ฒ„์ „}-macos-arm64.zip` | #### ๐Ÿ› ๏ธ ์„ค์น˜ ๋‹จ๊ณ„ 1. [์ตœ์‹  ๋ฆด๋ฆฌ์Šค ํŽ˜์ด์ง€](https://github.com/xixu-me/tzst/releases/latest)์—์„œ ํ”Œ๋žซํผ์— ๋งž๋Š” ์•„์นด์ด๋ธŒ **๐Ÿ“ฅ ๋‹ค์šด๋กœ๋“œ** 2. ์•„์นด์ด๋ธŒ๋ฅผ **๐Ÿ“ฆ ์ถ”์ถœ**ํ•˜์—ฌ `tzst` ์‹คํ–‰ ํŒŒ์ผ ํš๋“ (Windows๋Š” `tzst.exe`) 3. ์‹คํ–‰ ํŒŒ์ผ์„ PATH ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ๋””๋ ‰ํ„ฐ๋ฆฌ๋กœ **๐Ÿ“‚ ์ด๋™**: - **๐Ÿง Linux/macOS**: `sudo mv tzst /usr/local/bin/` - **๐ŸชŸ Windows**: `tzst.exe`๊ฐ€ ํฌํ•จ๋œ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ PATH ํ™˜๊ฒฝ ๋ณ€์ˆ˜์— ์ถ”๊ฐ€ 4. ์„ค์น˜ **โœ… ํ™•์ธ**: `tzst --help` #### ๐ŸŽฏ ๋ฐ”์ด๋„ˆ๋ฆฌ ์„ค์น˜์˜ ์žฅ์  - โœ… **Python ๋ถˆํ•„์š”** - ๋…๋ฆฝํ˜• ์‹คํ–‰ ํŒŒ์ผ - โœ… **๋น ๋ฅธ ์‹œ์ž‘** - Python ์ธํ„ฐํ”„๋ฆฌํ„ฐ ์˜ค๋ฒ„ํ—ค๋“œ ์—†์Œ - โœ… **์‰ฌ์šด ๋ฐฐํฌ** - ๋‹จ์ผ ํŒŒ์ผ ๋ฐฐํฌ - โœ… **์ผ๊ด€๋œ ๋™์ž‘** - ๋ฒˆ๋“ค๋ง๋œ ์˜์กด์„ฑ ### ๐Ÿ“ฆ PyPI์—์„œ ```bash pip install tzst ``` ### ๐Ÿ”ง ์†Œ์Šค์—์„œ ```bash git clone https://github.com/xixu-me/tzst.git cd tzst pip install . ``` ### ๐Ÿš€ ๊ฐœ๋ฐœ ์„ค์น˜ ์ตœ์‹  Python ํŒจํ‚ค์ง• ํ‘œ์ค€ ์‚ฌ์šฉ: ```bash git clone https://github.com/xixu-me/tzst.git cd tzst pip install -e .[dev] ``` ## ๐Ÿš€ ๋น ๋ฅธ ์‹œ์ž‘ ### ๐Ÿ’ป ๋ช…๋ น์ค„ ์‚ฌ์šฉ๋ฒ• > **์ฐธ๊ณ **: ์ตœ์ƒ์˜ ์„ฑ๋Šฅ๊ณผ Python ์˜์กด์„ฑ ์—†์ด ์‚ฌ์šฉํ•˜๋ ค๋ฉด [๋…๋ฆฝํ˜• ๋ฐ”์ด๋„ˆ๋ฆฌ](#github-๋ฆด๋ฆฌ์Šค์—์„œ)๋ฅผ ๋‹ค์šด๋กœ๋“œํ•˜์„ธ์š”. ๋˜๋Š” ์„ค์น˜ ์—†์ด ์‹คํ–‰ํ•˜๋ ค๋ฉด `uvx tzst`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. ์ž์„ธํ•œ ๋‚ด์šฉ์€ [uv ๋ฌธ์„œ](https://docs.astral.sh/uv/) ์ฐธ์กฐ. ```bash # ๐Ÿ“ ์•„์นด์ด๋ธŒ ์ƒ์„ฑ tzst a archive.tzst file1.txt file2.txt directory/ # ๐Ÿ“ค ์•„์นด์ด๋ธŒ ์ถ”์ถœ tzst x archive.tzst # ๐Ÿ“‹ ์•„์นด์ด๋ธŒ ๋‚ด์šฉ ๋ชฉ๋ก tzst l archive.tzst # ๐Ÿงช ์•„์นด์ด๋ธŒ ๋ฌด๊ฒฐ์„ฑ ํ…Œ์ŠคํŠธ tzst t archive.tzst ``` ### ๐Ÿ Python API ์‚ฌ์šฉ๋ฒ• ```python from tzst import create_archive, extract_archive, list_archive # ์•„์นด์ด๋ธŒ ์ƒ์„ฑ create_archive("archive.tzst", ["file1.txt", "file2.txt", "directory/"]) # ์•„์นด์ด๋ธŒ ์ถ”์ถœ extract_archive("archive.tzst", "output_directory/") # ์•„์นด์ด๋ธŒ ๋‚ด์šฉ ๋ชฉ๋ก contents = list_archive("archive.tzst", verbose=True) for item in contents: print(f"{item['name']}: {item['size']} bytes") ``` ## ๐Ÿ’ป ๋ช…๋ น์ค„ ์ธํ„ฐํŽ˜์ด์Šค ### ๐Ÿ“ ์•„์นด์ด๋ธŒ ์ž‘์—… #### โž• ์•„์นด์ด๋ธŒ ์ƒ์„ฑ ```bash # ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ• tzst a archive.tzst file1.txt file2.txt # ์••์ถ• ๋ ˆ๋ฒจ ์ง€์ • (1-22, ๊ธฐ๋ณธ๊ฐ’: 3) tzst a archive.tzst files/ -l 15 # ๋Œ€์ฒด ๋ช…๋ น์–ด tzst add archive.tzst files/ tzst create archive.tzst files/ ``` #### ๐Ÿ“ค ์•„์นด์ด๋ธŒ ์ถ”์ถœ ```bash # ์ „์ฒด ๋””๋ ‰ํ„ฐ๋ฆฌ ๊ตฌ์กฐ ์œ ์ง€ํ•˜๋ฉฐ ์ถ”์ถœ tzst x archive.tzst # ํŠน์ • ๋””๋ ‰ํ„ฐ๋ฆฌ๋กœ ์ถ”์ถœ tzst x archive.tzst -o output/ # ํŠน์ • ํŒŒ์ผ ์ถ”์ถœ tzst x archive.tzst file1.txt dir/file2.txt # ๋””๋ ‰ํ„ฐ๋ฆฌ ๊ตฌ์กฐ ์—†์ด ์ถ”์ถœ (ํ”Œ๋žซ) tzst e archive.tzst -o output/ # ๋Œ€์šฉ๋Ÿ‰ ์•„์นด์ด๋ธŒ์— ์ŠคํŠธ๋ฆฌ๋ฐ ๋ชจ๋“œ ์‚ฌ์šฉ tzst x archive.tzst --streaming -o output/ ``` #### ๐Ÿ“‹ ๋‚ด์šฉ ๋ชฉ๋ก ```bash # ๊ฐ„๋‹จํ•œ ๋ชฉ๋ก tzst l archive.tzst # ์ƒ์„ธ ์ •๋ณด ํฌํ•จ ๋ชฉ๋ก tzst l archive.tzst -v # ๋Œ€์šฉ๋Ÿ‰ ์•„์นด์ด๋ธŒ์— ์ŠคํŠธ๋ฆฌ๋ฐ ๋ชจ๋“œ ์‚ฌ์šฉ tzst l archive.tzst --streaming -v ``` #### ๐Ÿงช ๋ฌด๊ฒฐ์„ฑ ํ…Œ์ŠคํŠธ ```bash # ์•„์นด์ด๋ธŒ ๋ฌด๊ฒฐ์„ฑ ํ…Œ์ŠคํŠธ tzst t archive.tzst # ์ŠคํŠธ๋ฆฌ๋ฐ ๋ชจ๋“œ๋กœ ํ…Œ์ŠคํŠธ tzst t archive.tzst --streaming ``` ### ๐Ÿ“Š ๋ช…๋ น์–ด ์ฐธ์กฐ | ๋ช…๋ น์–ด | ๋ณ„์นญ | ์„ค๋ช… | ์ŠคํŠธ๋ฆฌ๋ฐ ์ง€์› | |---------|---------|-------------|-------------------| | `a` | `add`, `create` | ์•„์นด์ด๋ธŒ ์ƒ์„ฑ ๋˜๋Š” ์ถ”๊ฐ€ | N/A | | `x` | `extract` | ์ „์ฒด ๊ฒฝ๋กœ๋กœ ์ถ”์ถœ | โœ“ `--streaming` | | `e` | `extract-flat` | ๋””๋ ‰ํ„ฐ๋ฆฌ ๊ตฌ์กฐ ์—†์ด ์ถ”์ถœ | โœ“ `--streaming` | | `l` | `list` | ์•„์นด์ด๋ธŒ ๋‚ด์šฉ ๋ชฉ๋ก | โœ“ `--streaming` | | `t` | `test` | ์•„์นด์ด๋ธŒ ๋ฌด๊ฒฐ์„ฑ ํ…Œ์ŠคํŠธ | โœ“ `--streaming` | ### โš™๏ธ CLI ์˜ต์…˜ - `-v, --verbose`: ์ƒ์„ธ ์ถœ๋ ฅ ํ™œ์„ฑํ™” - `-o, --output DIR`: ์ถœ๋ ฅ ๋””๋ ‰ํ„ฐ๋ฆฌ ์ง€์ • (์ถ”์ถœ ๋ช…๋ น์–ด) - `-l, --level LEVEL`: ์••์ถ• ๋ ˆ๋ฒจ 1-22 ์„ค์ • (์ƒ์„ฑ ๋ช…๋ น์–ด) - `--streaming`: ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์  ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ์ŠคํŠธ๋ฆฌ๋ฐ ๋ชจ๋“œ ํ™œ์„ฑํ™” - `--filter FILTER`: ์ถ”์ถœ์„ ์œ„ํ•œ ๋ณด์•ˆ ํ•„ํ„ฐ (data/tar/fully_trusted) - `--no-atomic`: ์›์ž์  ํŒŒ์ผ ์ž‘์—… ๋น„ํ™œ์„ฑํ™” (๊ถŒ์žฅํ•˜์ง€ ์•Š์Œ) ### ๐Ÿ”’ ๋ณด์•ˆ ํ•„ํ„ฐ ```bash # ์ตœ๋Œ€ ๋ณด์•ˆ์œผ๋กœ ์ถ”์ถœ (๊ธฐ๋ณธ๊ฐ’) tzst x archive.tzst --filter data # ํ‘œ์ค€ tar ํ˜ธํ™˜์„ฑ์œผ๋กœ ์ถ”์ถœ tzst x archive.tzst --filter tar # ์™„์ „ ์‹ ๋ขฐ ๋ชจ๋“œ๋กœ ์ถ”์ถœ (์œ„ํ—˜ - ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ์•„์นด์ด๋ธŒ ์ „์šฉ) tzst x archive.tzst --filter fully_trusted ``` **๐Ÿ” ๋ณด์•ˆ ํ•„ํ„ฐ ์˜ต์…˜:** - `data` (๊ธฐ๋ณธ๊ฐ’): ๊ฐ€์žฅ ์•ˆ์ „. ์œ„ํ—˜ํ•œ ํŒŒ์ผ, ์ ˆ๋Œ€ ๊ฒฝ๋กœ, ์ถ”์ถœ ๋””๋ ‰ํ„ฐ๋ฆฌ ์™ธ๋ถ€ ๊ฒฝ๋กœ ์ฐจ๋‹จ - `tar`: ํ‘œ์ค€ tar ํ˜ธํ™˜์„ฑ. ์ ˆ๋Œ€ ๊ฒฝ๋กœ ๋ฐ ๋””๋ ‰ํ„ฐ๋ฆฌ ์ˆœํšŒ ์ฐจ๋‹จ - `fully_trusted`: ๋ณด์•ˆ ์ œํ•œ ์—†์Œ. ์™„์ „ํžˆ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ์•„์นด์ด๋ธŒ์—์„œ๋งŒ ์‚ฌ์šฉ ## ๐Ÿ Python API ### ๐Ÿ“ฆ TzstArchive ํด๋ž˜์Šค ```python from tzst import TzstArchive # ์ƒˆ ์•„์นด์ด๋ธŒ ์ƒ์„ฑ with TzstArchive("archive.tzst", "w", compression_level=5) as archive: archive.add("file.txt") archive.add("directory/", recursive=True) # ๊ธฐ์กด ์•„์นด์ด๋ธŒ ์ฝ๊ธฐ with TzstArchive("archive.tzst", "r") as archive: # ๋‚ด์šฉ ๋ชฉ๋ก contents = archive.list(verbose=True) # ๋ณด์•ˆ ํ•„ํ„ฐ ์ ์šฉ ์ถ”์ถœ archive.extract("file.txt", "output/", filter="data") # ๋ฌด๊ฒฐ์„ฑ ํ…Œ์ŠคํŠธ is_valid = archive.test() # ๋Œ€์šฉ๋Ÿ‰ ์•„์นด์ด๋ธŒ์— ์ŠคํŠธ๋ฆฌ๋ฐ ๋ชจ๋“œ ์‚ฌ์šฉ with TzstArchive("large_archive.tzst", "r", streaming=True) as archive: archive.extract(path="output/") ``` **โš ๏ธ ์ค‘์š”ํ•œ ์ œํ•œ ์‚ฌํ•ญ:** - **โŒ ์ถ”๊ฐ€ ๋ชจ๋“œ ๋ฏธ์ง€์›**: ์—ฌ๋Ÿฌ ์•„์นด์ด๋ธŒ ์ƒ์„ฑ ๋˜๋Š” ์ „์ฒด ์•„์นด์ด๋ธŒ ์žฌ์ƒ์„ฑ ํ•„์š” ### ๐ŸŽฏ ํŽธ์˜ ํ•จ์ˆ˜ #### ๐Ÿ“ create_archive() ```python from tzst import create_archive # ์›์ž์  ์ž‘์—…์œผ๋กœ ์ƒ์„ฑ (๊ธฐ๋ณธ๊ฐ’) create_archive( archive_path="backup.tzst", files=["documents/", "photos/", "config.txt"], compression_level=10 ) ``` #### ๐Ÿ“ค extract_archive() ```python from tzst import extract_archive # ๋ณด์•ˆ ์ถ”์ถœ (๊ธฐ๋ณธ๊ฐ’: 'data' ํ•„ํ„ฐ) extract_archive("backup.tzst", "restore/") # ํŠน์ • ํŒŒ์ผ ์ถ”์ถœ extract_archive("backup.tzst", "restore/", members=["config.txt"]) # ๋””๋ ‰ํ„ฐ๋ฆฌ ๊ตฌ์กฐ ํ‰ํƒ„ํ™” extract_archive("backup.tzst", "restore/", flatten=True) # ๋Œ€์šฉ๋Ÿ‰ ์•„์นด์ด๋ธŒ์— ์ŠคํŠธ๋ฆฌ๋ฐ ์‚ฌ์šฉ extract_archive("large_backup.tzst", "restore/", streaming=True) ``` #### ๐Ÿ“‹ list_archive() ```python from tzst import list_archive # ๊ฐ„๋‹จํ•œ ๋ชฉ๋ก files = list_archive("backup.tzst") # ์ƒ์„ธ ๋ชฉ๋ก files = list_archive("backup.tzst", verbose=True) # ๋Œ€์šฉ๋Ÿ‰ ์•„์นด์ด๋ธŒ์— ์ŠคํŠธ๋ฆฌ๋ฐ ์‚ฌ์šฉ files = list_archive("large_backup.tzst", streaming=True) ``` #### ๐Ÿงช test_archive() ```python from tzst import test_archive # ๊ธฐ๋ณธ ๋ฌด๊ฒฐ์„ฑ ํ…Œ์ŠคํŠธ if test_archive("backup.tzst"): print("์•„์นด์ด๋ธŒ๊ฐ€ ์œ ํšจํ•ฉ๋‹ˆ๋‹ค") # ์ŠคํŠธ๋ฆฌ๋ฐ์œผ๋กœ ํ…Œ์ŠคํŠธ if test_archive("large_backup.tzst", streaming=True): print("๋Œ€์šฉ๋Ÿ‰ ์•„์นด์ด๋ธŒ๊ฐ€ ์œ ํšจํ•ฉ๋‹ˆ๋‹ค") ``` ## ๐Ÿ”ง ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ ### ๐Ÿ“‚ ํŒŒ์ผ ํ™•์žฅ์ž ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์ง€๋Šฅ์ ์ธ ์ •๊ทœํ™”๋กœ ํŒŒ์ผ ํ™•์žฅ์ž๋ฅผ ์ž๋™ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค: - `.tzst` - tar+zstandard ์•„์นด์ด๋ธŒ์˜ ๊ธฐ๋ณธ ํ™•์žฅ์ž - `.tar.zst` - ๋Œ€์ฒด ํ‘œ์ค€ ํ™•์žฅ์ž - ๊ธฐ์กด ์•„์นด์ด๋ธŒ ์—ด ๋•Œ ์ž๋™ ๊ฐ์ง€ - ์•„์นด์ด๋ธŒ ์ƒ์„ฑ ์‹œ ์ž๋™ ํ™•์žฅ์ž ์ถ”๊ฐ€ ```python # ๋ชจ๋‘ ์œ ํšจํ•œ ์•„์นด์ด๋ธŒ ์ƒ์„ฑ create_archive("backup.tzst", files) # backup.tzst ์ƒ์„ฑ create_archive("backup.tar.zst", files) # backup.tar.zst ์ƒ์„ฑ create_archive("backup", files) # backup.tzst ์ƒ์„ฑ create_archive("backup.txt", files) # backup.tzst ์ƒ์„ฑ (์ •๊ทœํ™”๋จ) ``` ### ๐Ÿ—œ๏ธ ์••์ถ• ๋ ˆ๋ฒจ Zstandard ์••์ถ• ๋ ˆ๋ฒจ ๋ฒ”์œ„: 1 (๊ฐ€์žฅ ๋น ๋ฆ„) ~ 22 (์ตœ๋Œ€ ์••์ถ•): - **๋ ˆ๋ฒจ 1-3**: ๋น ๋ฅธ ์••์ถ•, ํŒŒ์ผ ํฌ๊ธฐ ํผ - **๋ ˆ๋ฒจ 3** (๊ธฐ๋ณธ๊ฐ’): ์†๋„์™€ ์••์ถ•๋ฅ ์˜ ๊ท ํ˜• - **๋ ˆ๋ฒจ 10-15**: ๋” ๋‚˜์€ ์••์ถ•, ๋А๋ฆผ - **๋ ˆ๋ฒจ 20-22**: ์ตœ๋Œ€ ์••์ถ•, ๋งค์šฐ ๋А๋ฆผ ### ๐ŸŒŠ ์ŠคํŠธ๋ฆฌ๋ฐ ๋ชจ๋“œ ๋Œ€์šฉ๋Ÿ‰ ์•„์นด์ด๋ธŒ์˜ ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์  ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด ์ŠคํŠธ๋ฆฌ๋ฐ ๋ชจ๋“œ ์‚ฌ์šฉ: **โœ… ์žฅ์ :** - ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ํ˜„์ €ํžˆ ๊ฐ์†Œ - ๋ฉ”๋ชจ๋ฆฌ์— ๋งž์ง€ ์•Š๋Š” ๋Œ€์šฉ๋Ÿ‰ ์•„์นด์ด๋ธŒ ์ฒ˜๋ฆฌ ์„ฑ๋Šฅ ํ–ฅ์ƒ - ๋ฆฌ์†Œ์Šค ์ž๋™ ์ •๋ฆฌ **๐ŸŽฏ ์‚ฌ์šฉ ์‹œ๊ธฐ:** - 100MB ์ด์ƒ์˜ ์•„์นด์ด๋ธŒ - ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ œํ•œ๋œ ํ™˜๊ฒฝ - ๋Œ€์šฉ๋Ÿ‰ ํŒŒ์ผ์ด ๋งŽ์€ ์•„์นด์ด๋ธŒ ์ฒ˜๋ฆฌ ```python # ์˜ˆ์ œ: ๋Œ€์šฉ๋Ÿ‰ ๋ฐฑ์—… ์•„์นด์ด๋ธŒ ์ฒ˜๋ฆฌ from tzst import extract_archive, list_archive, test_archive large_archive = "backup_500gb.tzst" # ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์  ์ž‘์—… is_valid = test_archive(large_archive, streaming=True) contents = list_archive(large_archive, streaming=True, verbose=True) extract_archive(large_archive, "restore/", streaming=True) ``` ### โšก ์›์ž์  ์ž‘์—… ๋ชจ๋“  ํŒŒ์ผ ์ƒ์„ฑ ์ž‘์—…์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์›์ž์  ํŒŒ์ผ ์ž‘์—…์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค: - ์ž„์‹œ ํŒŒ์ผ์— ๋จผ์ € ์ƒ์„ฑ ํ›„ ์›์ž์  ์ด๋™ - ํ”„๋กœ์„ธ์Šค ์ค‘๋‹จ ์‹œ ์ž๋™ ์ •๋ฆฌ - ์†์ƒ๋˜๊ฑฐ๋‚˜ ๋ถˆ์™„์ „ํ•œ ์•„์นด์ด๋ธŒ ์œ„ํ—˜ ์—†์Œ - ํฌ๋กœ์Šค ํ”Œ๋žซํผ ํ˜ธํ™˜์„ฑ ```python # ๊ธฐ๋ณธ์ ์œผ๋กœ ์›์ž์  ์ž‘์—… ํ™œ์„ฑํ™” create_archive("important.tzst", files) # ์ค‘๋‹จ์œผ๋กœ๋ถ€ํ„ฐ ์•ˆ์ „ # ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๋น„ํ™œ์„ฑํ™” ๊ฐ€๋Šฅ (๊ถŒ์žฅํ•˜์ง€ ์•Š์Œ) create_archive("test.tzst", files, use_temp_file=False) ``` ### ๐Ÿšจ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ ```python from tzst import TzstArchive from tzst.exceptions import ( TzstError, TzstArchiveError, TzstCompressionError, TzstDecompressionError, TzstFileNotFoundError ) try: with TzstArchive("archive.tzst", "r") as archive: archive.extract() except TzstDecompressionError: print("์•„์นด์ด๋ธŒ ์••์ถ• ํ•ด์ œ ์‹คํŒจ") except TzstFileNotFoundError: print("์•„์นด์ด๋ธŒ ํŒŒ์ผ์„ ์ฐพ์„ ์ˆ˜ ์—†์Œ") except KeyboardInterrupt: print("์‚ฌ์šฉ์ž์— ์˜ํ•ด ์ž‘์—… ์ค‘๋‹จ๋จ") # ์ž๋™์œผ๋กœ ์ •๋ฆฌ๋จ ``` ## ๐Ÿš€ ์„ฑ๋Šฅ ๋ฐ ๋น„๊ต ### ๐Ÿ’ก ์„ฑ๋Šฅ ํŒ 1. **๐Ÿ—œ๏ธ ์••์ถ• ๋ ˆ๋ฒจ**: ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ๋ ˆ๋ฒจ 3์ด ์ตœ์  2. **๐ŸŒŠ ์ŠคํŠธ๋ฆฌ๋ฐ**: 100MB ์ด์ƒ ์•„์นด์ด๋ธŒ์— ์‚ฌ์šฉ 3. **๐Ÿ“ฆ ์ผ๊ด„ ์ž‘์—…**: ๋‹จ์ผ ์„ธ์…˜์—์„œ ์—ฌ๋Ÿฌ ํŒŒ์ผ ์ถ”๊ฐ€ 4. **๐Ÿ“„ ํŒŒ์ผ ์œ ํ˜•**: ์ด๋ฏธ ์••์ถ•๋œ ํŒŒ์ผ์€ ์ถ”๊ฐ€ ์••์ถ•์ด ๊ฑฐ์˜ ์•ˆ๋จ ### ๐Ÿ†š ๋‹ค๋ฅธ ๋„๊ตฌ์™€ ๋น„๊ต **vs tar + gzip:** - โœ… ๋” ๋‚˜์€ ์••์ถ•๋ฅ  - โšก ๋” ๋น ๋ฅธ ์••์ถ• ํ•ด์ œ - ๐Ÿ”„ ํ˜„๋Œ€์ ์ธ ์•Œ๊ณ ๋ฆฌ์ฆ˜ **vs tar + xz:** - ๐Ÿš€ ํ˜„์ €ํžˆ ๋น ๋ฅธ ์••์ถ• - ๐Ÿ“Š ์œ ์‚ฌํ•œ ์••์ถ•๋ฅ  - โš–๏ธ ๋” ๋‚˜์€ ์†๋„/์••์ถ•๋ฅ  ๊ท ํ˜• **vs zip:** - ๐Ÿ—œ๏ธ ๋” ๋‚˜์€ ์••์ถ• - ๐Ÿ” Unix ๊ถŒํ•œ ๋ฐ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๋ณด์กด - ๐ŸŒŠ ๋” ๋‚˜์€ ์ŠคํŠธ๋ฆฌ๋ฐ ์ง€์› ## ๐Ÿ“‹ ์š”๊ตฌ ์‚ฌํ•ญ - ๐Ÿ Python 3.12 ์ด์ƒ - ๐Ÿ“ฆ zstandard >= 0.19.0 ## ๐Ÿ› ๏ธ ๊ฐœ๋ฐœ ### ๐Ÿš€ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์„ค์ • ์ตœ์‹  Python ํŒจํ‚ค์ง• ํ‘œ์ค€ ์‚ฌ์šฉ: ```bash git clone https://github.com/xixu-me/tzst.git cd tzst pip install -e .[dev] ``` ### ๐Ÿงช ํ…Œ์ŠคํŠธ ์‹คํ–‰ ```bash # ์ปค๋ฒ„๋ฆฌ์ง€ ํฌํ•จ ํ…Œ์ŠคํŠธ ์‹คํ–‰ pytest --cov=tzst --cov-report=html # ๋˜๋Š” ๊ฐ„๋‹จํ•œ ๋ช…๋ น์–ด ์‚ฌ์šฉ (์ปค๋ฒ„๋ฆฌ์ง€ ์„ค์ •์€ pyproject.toml์— ์žˆ์Œ) pytest ``` ### โœจ ์ฝ”๋“œ ํ’ˆ์งˆ ```bash # ์ฝ”๋“œ ํ’ˆ์งˆ ํ™•์ธ ruff check src tests # ์ฝ”๋“œ ํฌ๋งทํŒ… ruff format src tests ``` ## ๐Ÿค ๊ธฐ์—ฌ ๊ธฐ์—ฌ๋ฅผ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค! ๋‹ค์Œ ์‚ฌํ•ญ์„ ์œ„ํ•ด [๊ธฐ์—ฌ ๊ฐ€์ด๋“œ](CONTRIBUTING.md)๋ฅผ ์ฝ์–ด์ฃผ์„ธ์š”: - ๊ฐœ๋ฐœ ์„ค์ • ๋ฐ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ - ์ฝ”๋“œ ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ๋ผ์ธ ๋ฐ ๋ชจ๋ฒ” ์‚ฌ๋ก€ - ํ…Œ์ŠคํŠธ ์š”๊ตฌ ์‚ฌํ•ญ ๋ฐ ํ…Œ์ŠคํŠธ ์ž‘์„ฑ ๋ฐฉ๋ฒ• - ํ’€ ๋ฆฌํ€˜์ŠคํŠธ ํ”„๋กœ์„ธ์Šค ๋ฐ ๋ฆฌ๋ทฐ ์›Œํฌํ”Œ๋กœ ### ๐Ÿš€ ๊ธฐ์—ฌ์ž ๋น ๋ฅธ ์‹œ์ž‘ ```bash git clone https://github.com/xixu-me/tzst.git cd tzst pip install -e .[dev] python -m pytest tests/ ``` ### ๐ŸŽฏ ํ™˜์˜ํ•˜๋Š” ๊ธฐ์—ฌ ์œ ํ˜• - ๐Ÿ› **๋ฒ„๊ทธ ์ˆ˜์ •** - ๊ธฐ์กด ๊ธฐ๋Šฅ์˜ ๋ฌธ์ œ ํ•ด๊ฒฐ - โœจ **๊ธฐ๋Šฅ** - ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ ์ถ”๊ฐ€ - ๐Ÿ“š **๋ฌธ์„œ** - ๋ฌธ์„œ ๊ฐœ์„  ๋˜๋Š” ์ถ”๊ฐ€ - ๐Ÿงช **ํ…Œ์ŠคํŠธ** - ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€ ์ถ”๊ฐ€ ๋˜๋Š” ๊ฐœ์„  - โšก **์„ฑ๋Šฅ** - ๊ธฐ์กด ์ฝ”๋“œ ์ตœ์ ํ™” - ๐Ÿ”’ **๋ณด์•ˆ** - ๋ณด์•ˆ ์ทจ์•ฝ์  ํ•ด๊ฒฐ ## ๐Ÿ™ ๊ฐ์‚ฌ์˜ ๋ง - ์šฐ์ˆ˜ํ•œ ์••์ถ• ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ œ๊ณตํ•œ [Meta Zstandard](https://github.com/facebook/zstd) - Python ๋ฐ”์ธ๋”ฉ์„ ์ œ๊ณตํ•œ [python-zstandard](https://github.com/indygreg/python-zstandard) - ์˜๊ฐ๊ณผ ํ”ผ๋“œ๋ฐฑ์„ ์ค€ Python ์ปค๋ฎค๋‹ˆํ‹ฐ ## ๐Ÿ“„ ๋ผ์ด์„ ์Šค ์ €์ž‘๊ถŒ © 2025 [์‹œ ์‰ฌ](https://xi-xu.me). ๋ชจ๋“  ๊ถŒ๋ฆฌ ๋ณด์œ . [BSD 3-Clause](LICENSE) ๋ผ์ด์„ ์Šค๋กœ ์‚ฌ์šฉ์ด ํ—ˆ๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.