# ๐Ÿ–ผ๏ธ ๊ณ ์„ฑ๋Šฅ ์ธํŽ˜์ธํŒ… ์„œ๋ฒ„ FastAPI์™€ ๋”ฅ๋Ÿฌ๋‹์„ ํ™œ์šฉํ•œ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ์ธํŽ˜์ธํŒ… ์„œ๋ฒ„์ž…๋‹ˆ๋‹ค. Simple LAMA, MIGAN, REMBG ๋ชจ๋ธ์„ TensorRT์™€ CUDA๋ฅผ ํ™œ์šฉํ•˜์—ฌ FP16 ๋ฐฉ์‹์œผ๋กœ ์ตœ์ ํ™”๋œ ์„œ๋ฒ„๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. **๐Ÿš€ Jetson Xavier (ARM64) ๋ฐ x86_64 ์‹œ์Šคํ…œ์„ ๋ชจ๋‘ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค!** **๐Ÿ”„ ๊ธฐ์กด ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์™€ 100% ํ˜ธํ™˜๋ฉ๋‹ˆ๋‹ค!** [![Python](https://img.shields.io/badge/Python-3.8+-blue.svg)](https://python.org) [![FastAPI](https://img.shields.io/badge/FastAPI-0.100+-green.svg)](https://fastapi.tiangolo.com) [![CUDA](https://img.shields.io/badge/CUDA-11.8+-orange.svg)](https://developer.nvidia.com/cuda-toolkit) [![License](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) ## โœจ ์ฃผ์š” ๊ธฐ๋Šฅ ### ๐ŸŽฏ AI ๋ชจ๋ธ ์ง€์› - **Simple LAMA**: ๋น ๋ฅด๊ณ  ์ •ํ™•ํ•œ ์ธํŽ˜์ธํŒ… - **MIGAN**: ๊ณ ํ’ˆ์งˆ ์ธํŽ˜์ธํŒ… - **REMBG**: ๋ฐฐ๊ฒฝ ์ œ๊ฑฐ (u2net, u2netp, silueta) ### ๐Ÿš€ ์„ฑ๋Šฅ ์ตœ์ ํ™” - **๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ**: ๋™์  ์›Œ์ปค ๊ด€๋ฆฌ๋กœ ์ตœ์ ์˜ ์„ฑ๋Šฅ ์ œ๊ณต - **GPU ๊ฐ€์†**: TensorRT์™€ CUDA FP16 ํ™œ์šฉ - **๋™์  ์Šค์ผ€์ผ๋ง**: VRAM ์‚ฌ์šฉ๋Ÿ‰์— ๋”ฐ๋ฅธ ์ž๋™ ์›Œ์ปค ์กฐ์ • - **์„ธ์…˜ ํ’€**: ๋ชจ๋ธ ๋กœ๋”ฉ ์‹œ๊ฐ„ ์ตœ์†Œํ™” ### ๐Ÿ“Š ์‹ค์‹œ๊ฐ„ ๋ชจ๋‹ˆํ„ฐ๋ง - **์›น ๋Œ€์‹œ๋ณด๋“œ**: ์‹ค์‹œ๊ฐ„ ์„œ๋ฒ„ ์ƒํƒœ ํ™•์ธ - **์„ฑ๋Šฅ ์ง€ํ‘œ**: CPU, GPU, ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋ฅ  - **API ํ†ต๊ณ„**: ์—”๋“œํฌ์ธํŠธ๋ณ„ ์š”์ฒญ/์‘๋‹ต ๋ถ„์„ - **์›Œ์ปค ๊ด€๋ฆฌ**: ์‹ค์‹œ๊ฐ„ ์›Œ์ปค ์ƒํƒœ ์ถ”์  ### ๐Ÿ”„ ๊ธฐ์กด ํด๋ผ์ด์–ธํŠธ ํ˜ธํ™˜์„ฑ - **100% ํ˜ธํ™˜**: ๊ธฐ์กด ์ฝ”๋“œ ์ˆ˜์ • ์—†์ด ์‚ฌ์šฉ ๊ฐ€๋Šฅ - **์ž๋™ ๊ธฐ๋ณธ๊ฐ’**: `model_name` ๋ˆ„๋ฝ ์‹œ ์ž๋™ ์ฒ˜๋ฆฌ - **๋ฐ”์ด๋„ˆ๋ฆฌ ์‘๋‹ต**: ๊ธฐ์กด PNG ๋ฐ”์ด๋„ˆ๋ฆฌ ์‘๋‹ต ์ง€์› - **์—๋Ÿฌ ์ฒ˜๋ฆฌ**: ๊ธฐ์กด ํด๋ผ์ด์–ธํŠธ ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ฐฉ์‹ ์œ ์ง€ ### ๐ŸŒ ๋‹ค์–‘ํ•œ ์‘๋‹ต ํ˜•์‹ - **Binary** (๊ธฐ๋ณธ๊ฐ’): ๋ฐ”์ด๋„ˆ๋ฆฌ ์ด๋ฏธ์ง€ (๊ธฐ์กด ํ˜ธํ™˜) - **JSON**: iopaint ํ˜ธํ™˜ JSON ์‘๋‹ต - **Stream**: ๋Œ€์šฉ๋Ÿ‰ ํŒŒ์ผ ์ŠคํŠธ๋ฆฌ๋ฐ ### ๐Ÿ–ผ๏ธ ๋‹ค์–‘ํ•œ ์ด๋ฏธ์ง€ ํฌ๋งท - **PNG** (๊ธฐ๋ณธ๊ฐ’): ๋ฌด์†์‹ค, ํˆฌ๋ช…๋„ ์ง€์› - **WebP**: 25-35% ์••์ถ•๋ฅ  ๊ฐœ์„  - **JPEG**: ์ตœ๊ณ  ํ˜ธํ™˜์„ฑ ## ๐Ÿ—๏ธ ์•„ํ‚คํ…์ฒ˜ ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ FastAPI โ”‚ โ”‚ ์›Œ์ปค ๋งค๋‹ˆ์ € โ”‚ โ”‚ ์„ธ์…˜ ํ’€ โ”‚ โ”‚ ์—”๋“œํฌ์ธํŠธ โ”‚โ—„โ”€โ”€โ–บโ”‚ (๋™์  ์Šค์ผ€์ผ๋ง) โ”‚โ—„โ”€โ”€โ–บโ”‚ (๋ชจ๋ธ ๊ด€๋ฆฌ) โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ–ผ โ–ผ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ ๋ชจ๋‹ˆํ„ฐ๋ง โ”‚ โ”‚ GPU ๋ชจ๋‹ˆํ„ฐ โ”‚ โ”‚ ๋ชจ๋ธ ์ธ์Šคํ„ด์Šค โ”‚ โ”‚ ๋Œ€์‹œ๋ณด๋“œ โ”‚ โ”‚ (VRAM ์ถ”์ ) โ”‚ โ”‚ (Simple LAMA, โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ MIGAN, REMBG) โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` ## ๐Ÿ“‹ ์‹œ์Šคํ…œ ์š”๊ตฌ์‚ฌํ•ญ ### Jetson Xavier (ARM64) - **OS**: Ubuntu 18.04 ์ด์ƒ - **Python**: 3.8 ์ด์ƒ - **CUDA**: 11.8 - **cuDNN**: 8 - **TensorRT**: 8.6 - **GCC**: 11 ์ด์ƒ (ONNX Runtime GPU ํ˜ธํ™˜์„ฑ์šฉ) - **RAM**: 4GB ์ด์ƒ ๊ถŒ์žฅ - **์ €์žฅ๊ณต๊ฐ„**: 10GB ์ด์ƒ > **์ค‘์š”**: Jetson Xavier์—์„œ GPU ๊ฐ€์†์„ ์œ„ํ•ด์„œ๋Š” GCC 11๊ณผ ํŠน๋ณ„ํ•œ ONNX Runtime ๋ฒ„์ „์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ž๋™ ์„ค์น˜ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์ด๋ฅผ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ### x86_64 ์‹œ์Šคํ…œ - **OS**: Ubuntu 18.04 ์ด์ƒ - **Python**: 3.8 ์ด์ƒ (3.10 ๊ถŒ์žฅ) - **GPU**: NVIDIA GPU (RTX 3060 12GB ์ด์ƒ ๊ถŒ์žฅ) - **CUDA**: 11.8 ์ด์ƒ - **RAM**: 8GB ์ด์ƒ ๊ถŒ์žฅ - **์ €์žฅ๊ณต๊ฐ„**: 10GB ์ด์ƒ #### RTX 3060 12GB ์ตœ์ ํ™” ์„ค์ • - **์›Œ์ปค ์ˆ˜**: 4-12๊ฐœ (์ž๋™ ์กฐ์ •) - **์„ธ์…˜ ํ’€**: Simple LAMA 4๊ฐœ, MIGAN 4๊ฐœ, REMBG 2๊ฐœ - **VRAM ๊ด€๋ฆฌ**: 85% ์‚ฌ์šฉ๋ฅ ๊นŒ์ง€ ํ—ˆ์šฉ, 25% ์ดํ•˜ ์‹œ ํ™•์žฅ - **์ด๋ฏธ์ง€ ํฌ๊ธฐ**: ์ตœ๋Œ€ 8K (8192x8192) ์ง€์› - **ํŒŒ์ผ ํฌ๊ธฐ**: ์ตœ๋Œ€ 100MB ์ง€์› ### GPU ์š”๊ตฌ์‚ฌํ•ญ - **Jetson Xavier**: ๋‚ด์žฅ Volta GPU (8GB VRAM) - **x86**: NVIDIA GPU (4GB ์ด์ƒ VRAM) ## ๐Ÿš€ ๋น ๋ฅธ ์‹œ์ž‘ ### 1. ํ”„๋กœ์ ํŠธ ํด๋ก  ```bash # ํ”„๋กœ์ ํŠธ ํด๋ก  git clone inpaintServer cd inpaintServer # ์‹คํ–‰ ๊ถŒํ•œ ๋ถ€์—ฌ chmod +x scripts/*.sh ``` ### 2. ๐Ÿš€ ์›ํด๋ฆญ ์ž๋™ ์„ค์น˜ (๊ถŒ์žฅ) #### ํ”Œ๋žซํผ ์ž๋™ ๊ฐ์ง€ ์„ค์น˜ ```bash # ๐ŸŽฏ ํ”Œ๋žซํผ ์ž๋™ ๊ฐ์ง€ ํ›„ ์ตœ์  ์„ค์น˜ bash scripts/install.sh ``` #### ํ”Œ๋žซํผ๋ณ„ ์ง์ ‘ ์„ค์น˜ **๐Ÿš€ Jetson Xavier (ARM64):** ```bash # Jetson Xavier ์ „์šฉ ์ตœ์ ํ™” ์„ค์น˜ bash scripts/setup_jetson.sh ``` **๐Ÿ–ฅ๏ธ x86-64 Desktop:** ```bash # x86-64 ๋ฐ์Šคํฌํ†ฑ ์ตœ์ ํ™” ์„ค์น˜ bash scripts/setup_x86.sh ``` ### ๐Ÿ“ ๊ฐ€์ƒํ™˜๊ฒฝ ์„ค์ • ๋ฐฉ์‹ ์ด ํ”„๋กœ์ ํŠธ๋Š” **์œ ์—ฐํ•œ ๊ฐ€์ƒํ™˜๊ฒฝ ์„ค์ •**์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค: #### ๋ฐฉ์‹ 1: ํ‘œ์ค€ venv ๋””๋ ‰ํ† ๋ฆฌ (๊ธฐ๋ณธ) ```bash python3 -m venv venv source venv/bin/activate ``` #### ๋ฐฉ์‹ 2: ํ”„๋กœ์ ํŠธ ์ž์ฒด๋ฅผ ๊ฐ€์ƒํ™˜๊ฒฝ์œผ๋กœ ์‚ฌ์šฉ ```bash # ํ”„๋กœ์ ํŠธ ๋””๋ ‰ํ† ๋ฆฌ์—์„œ ์ง์ ‘ ๊ฐ€์ƒํ™˜๊ฒฝ ์ƒ์„ฑ python3 -m venv . source bin/activate ``` > **๐Ÿ’ก ์Šค๋งˆํŠธ ๊ฐ์ง€**: ์„ค์น˜ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์ž๋™์œผ๋กœ ๊ฐ์ง€ํ•˜๊ณ  ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค > - `venv/` ๋””๋ ‰ํ† ๋ฆฌ ์กด์žฌ โ†’ ํ‘œ์ค€ venv ์‚ฌ์šฉ > - `pyvenv.cfg` ํŒŒ์ผ ์กด์žฌ โ†’ ํ”„๋กœ์ ํŠธ ์ž์ฒด๊ฐ€ ๊ฐ€์ƒํ™˜๊ฒฝ > - ๋‘˜ ๋‹ค ์—†์Œ โ†’ ์ƒˆ๋กœ์šด `venv/` ๋””๋ ‰ํ† ๋ฆฌ ์ƒ์„ฑ **์ž๋™ ์„ค์น˜๊ฐ€ ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์—…:** - โœ… ํ”Œ๋žซํผ ์ž๋™ ๊ฐ์ง€ (Jetson Xavier vs x86-64) - โœ… ๊ฐ€์ƒํ™˜๊ฒฝ ์ž๋™ ์ƒ์„ฑ/๊ฐ์ง€ - โœ… GPU ์ตœ์ ํ™” ์˜์กด์„ฑ ์„ค์น˜ - โœ… ONNX Runtime GPU ์„ค์น˜ (ํ”Œ๋žซํผ๋ณ„) - โœ… PyTorch CUDA ์„ค์น˜ - โœ… ๋ชจ๋ธ ํ˜ธํ™˜์„ฑ ํ™•์ธ - โœ… ์„ค์น˜ ๊ฒ€์ฆ ๋ฐ ํ…Œ์ŠคํŠธ ### 3. ์ˆ˜๋™ ์„ค์น˜ (๊ณ ๊ธ‰ ์‚ฌ์šฉ์ž)
์ˆ˜๋™ ์„ค์น˜ ๊ณผ์ • ๋ณด๊ธฐ #### ๊ฐ€์ƒํ™˜๊ฒฝ ์„ค์ • ```bash # ๊ฐ€์ƒํ™˜๊ฒฝ ์ƒ์„ฑ python -m venv venv # ๊ฐ€์ƒํ™˜๊ฒฝ ํ™œ์„ฑํ™” source venv/bin/activate # Linux/Mac ``` #### ์˜์กด์„ฑ ์„ค์น˜ ```bash # Jetson Xavier ./scripts/install_deps.sh --jetson-optimize # x86_64 ์‹œ์Šคํ…œ ./scripts/install_deps.sh # ์ˆ˜๋™ ์„ค์น˜ pip install -r requirements.txt ``` #### ํ™˜๊ฒฝ ์„ค์ • ```bash # ํ™˜๊ฒฝ ์„ค์ • ํŒŒ์ผ ๋ณต์‚ฌ ๋ฐ ์ˆ˜์ • cp .env.example .env ``` #### ์„œ๋ฒ„ ์‹œ์ž‘ ```bash # ๊ธฐ๋ณธ ์‹œ์ž‘ (๋ฉ”์ธ + ๋ชจ๋‹ˆํ„ฐ๋ง) ./scripts/start_server.sh # Jetson ์ตœ์ ํ™” ./scripts/start_server.sh --jetson-optimize # ํ”„๋กœ๋•์…˜ ๋ชจ๋“œ ./scripts/start_server.sh --production ```
## ๐ŸŒ ์„œ๋ฒ„ ์ ‘์† ์ •๋ณด ์„ค์น˜ ์™„๋ฃŒ ํ›„ ๋‹ค์Œ URL๋กœ ์ ‘์†ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: | ์„œ๋น„์Šค | URL | ์„ค๋ช… | |--------|-----|------| | **๋ฉ”์ธ API** | http://localhost:8000 | ์ธํŽ˜์ธํŒ…/๋ฐฐ๊ฒฝ์ œ๊ฑฐ API | | **API ๋ฌธ์„œ** | http://localhost:8000/docs | Swagger UI ๋ฌธ์„œ | | **๋ชจ๋‹ˆํ„ฐ๋ง** | http://localhost:8001 | ์‹ค์‹œ๊ฐ„ ๋Œ€์‹œ๋ณด๋“œ | | **ํ—ฌ์Šค ์ฒดํฌ** | http://localhost:8000/health | ์„œ๋ฒ„ ์ƒํƒœ ํ™•์ธ | ## ๐Ÿ”„ ๊ธฐ์กด ํด๋ผ์ด์–ธํŠธ 100% ํ˜ธํ™˜ ### โœ… ๊ธฐ์กด ์ฝ”๋“œ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅ! ๊ธฐ์กด ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๋ฅผ **ํ•œ ๊ธ€์ž๋„ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ ** ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: ```python def request_inpaint(self, image: np.ndarray, mask: np.ndarray) -> np.ndarray: try: # ์„œ๋ฒ„ ์ƒํƒœ ํ™•์ธ if not self.is_server_alive(self.inpaint_base_url): return None # ์ด๋ฏธ์ง€๋ฅผ base64๋กœ ์ธ์ฝ”๋”ฉ _, img_encoded = cv2.imencode('.png', image) _, mask_encoded = cv2.imencode('.png', mask) img_b64 = base64.b64encode(img_encoded).decode('utf-8') mask_b64 = base64.b64encode(mask_encoded).decode('utf-8') payload = { "image": img_b64, "mask": mask_b64 # model_name ๋ˆ„๋ฝ ์‹œ ์ž๋™์œผ๋กœ "simple-lama" ์‚ฌ์šฉ } response = requests.post(self.inpaint_api_url, json=payload, timeout=(5, 45)) if response.status_code != 200: return None # ๋ฐ”์ด๋„ˆ๋ฆฌ PNG ์‘๋‹ต ์ฒ˜๋ฆฌ (๊ธฐ์กด๊ณผ ๋™์ผ) nparr = np.frombuffer(response.content, np.uint8) result = cv2.imdecode(nparr, cv2.IMREAD_COLOR) return result except Exception as e: return None ``` ### ๐ŸŽฏ ํ˜ธํ™˜์„ฑ ๋ณด์žฅ ๊ธฐ๋Šฅ | ๊ธฐ๋Šฅ | ๊ธฐ์กด ๋™์ž‘ | ์„œ๋ฒ„ ์ฒ˜๋ฆฌ | ์ƒํƒœ | |------|-----------|-----------|------| | **model_name ๋ˆ„๋ฝ** | ํ•„๋“œ ์—†์Œ | ์ž๋™์œผ๋กœ ๊ธฐ๋ณธ๊ฐ’ ์‚ฌ์šฉ | โœ… ํ˜ธํ™˜ | | **๋ฐ”์ด๋„ˆ๋ฆฌ PNG ์‘๋‹ต** | `response.content` ์ง์ ‘ ์‚ฌ์šฉ | ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ฐ˜ํ™˜ | โœ… ํ˜ธํ™˜ | | **์—๋Ÿฌ ์ฒ˜๋ฆฌ** | `status_code != 200` ํ™•์ธ | ๋™์ผํ•œ HTTP ์ƒํƒœ ์ฝ”๋“œ | โœ… ํ˜ธํ™˜ | | **ํƒ€์ž„์•„์›ƒ** | `timeout=(5, 45)` | ์„œ๋ฒ„์—์„œ ์ ์ ˆํžˆ ์ฒ˜๋ฆฌ | โœ… ํ˜ธํ™˜ | ### ๐Ÿงช ํ˜ธํ™˜์„ฑ ํ…Œ์ŠคํŠธ ```bash # ๊ธฐ์กด ํด๋ผ์ด์–ธํŠธ ํ˜ธํ™˜์„ฑ ํ…Œ์ŠคํŠธ ์‹คํ–‰ python tests/scripts/test_compatibility.py # ์˜ˆ์ƒ ๊ฒฐ๊ณผ: # ๐ŸŽฏ ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ # ์„ฑ๊ณต: 2/2 # ์„ฑ๊ณต๋ฅ : 100.0% # ๐ŸŽ‰ ๋ชจ๋“  ํ…Œ์ŠคํŠธ๊ฐ€ ์„ฑ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค! ``` ## ๐Ÿ“ก API ์—”๋“œํฌ์ธํŠธ ### ๐ŸŽจ ์ธํŽ˜์ธํŒ… API #### ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ• (๊ธฐ์กด ํด๋ผ์ด์–ธํŠธ ํ˜ธํ™˜) ```http POST /api/v1/inpaint Content-Type: application/json { "image": "base64_encoded_image", "mask": "base64_encoded_mask" // model_name ์ƒ๋žต ์‹œ ์ž๋™์œผ๋กœ "simple-lama" ์‚ฌ์šฉ } # ์‘๋‹ต: ๋ฐ”์ด๋„ˆ๋ฆฌ PNG ์ด๋ฏธ์ง€ (๊ธฐ๋ณธ๊ฐ’) ``` #### ๊ณ ๊ธ‰ ์‚ฌ์šฉ๋ฒ• (์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ) ```http POST /api/v1/inpaint?response_format=json&image_format=webp Content-Type: application/json { "image": "base64_encoded_image", "mask": "base64_encoded_mask", "model_name": "migan", // ๋ชจ๋ธ ์„ ํƒ "sd_seed": 42, // ์‹œ๋“œ ์„ค์ • "prompt": "", // ํ”„๋กฌํ”„ํŠธ (ํ–ฅํ›„ ํ™•์žฅ) "negative_prompt": "", // ๋„ค๊ฑฐํ‹ฐ๋ธŒ ํ”„๋กฌํ”„ํŠธ "num_inference_steps": 20, // ์ถ”๋ก  ์Šคํ… "guidance_scale": 7.5, // ๊ฐ€์ด๋˜์Šค ์Šค์ผ€์ผ "strength": 1.0 // ์ธํŽ˜์ธํŒ… ๊ฐ•๋„ } # ์‘๋‹ต: JSON ํ˜•์‹ { "success": true, "image": "base64_encoded_result", "processing_time": 1.23 } ``` ### ๐Ÿ–ผ๏ธ ๋ฐฐ๊ฒฝ ์ œ๊ฑฐ API #### ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ• (๊ธฐ์กด ํด๋ผ์ด์–ธํŠธ ํ˜ธํ™˜) ```http POST /api/v1/remove_bg Content-Type: application/json { "image": "base64_encoded_image" // model_name ์ƒ๋žต ์‹œ ์ž๋™์œผ๋กœ "rembg" ์‚ฌ์šฉ } # ์‘๋‹ต: ๋ฐ”์ด๋„ˆ๋ฆฌ PNG ์ด๋ฏธ์ง€ (๊ธฐ๋ณธ๊ฐ’) ``` #### ๊ณ ๊ธ‰ ์‚ฌ์šฉ๋ฒ• (์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ) ```http POST /api/v1/remove_bg?response_format=json&image_format=webp Content-Type: application/json { "image": "base64_encoded_image", "model_name": "rembg" } # ์‘๋‹ต: JSON ํ˜•์‹ (์ด๋ฏธ์ง€ + ๋งˆ์Šคํฌ) { "success": true, "image": "base64_encoded_result", "mask": "base64_encoded_mask", "processing_time": 0.45 } ``` ### ๐Ÿ”ง ์‹œ์Šคํ…œ API ```http # ์„œ๋ฒ„ ์„ค์ • ์ •๋ณด GET /api/v1/server-config # ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ƒ˜ํ”Œ๋Ÿฌ ๋ชฉ๋ก GET /api/v1/samplers # ํ—ฌ์Šค ์ฒดํฌ GET /health ``` ## ๐ŸŽ›๏ธ ์‘๋‹ต ํ˜•์‹ ๋ฐ ์ด๋ฏธ์ง€ ํฌ๋งท ### ์‘๋‹ต ํ˜•์‹ ์„ ํƒ (`response_format`) | ํ˜•์‹ | ์„ค๋ช… | ์šฉ๋„ | ๊ธฐ๋ณธ๊ฐ’ | |------|------|------|--------| | `binary` | ๋ฐ”์ด๋„ˆ๋ฆฌ ์ด๋ฏธ์ง€ | ๊ธฐ์กด ํด๋ผ์ด์–ธํŠธ ํ˜ธํ™˜ | โœ… | | `json` | JSON ํ˜•์‹ | iopaint ํ˜ธํ™˜, ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ํฌํ•จ | | | `stream` | ์ŠคํŠธ๋ฆฌ๋ฐ | ๋Œ€์šฉ๋Ÿ‰ ํŒŒ์ผ, ์‹ค์‹œ๊ฐ„ ์ „์†ก | | ### ์ด๋ฏธ์ง€ ํฌ๋งท ์„ ํƒ (`image_format`) | ํฌ๋งท | ์••์ถ•๋ฅ  | ํ’ˆ์งˆ | ํˆฌ๋ช…๋„ | ํ˜ธํ™˜์„ฑ | ๊ถŒ์žฅ ์šฉ๋„ | |------|--------|------|--------|--------|-----------| | `png` | ๋‚ฎ์Œ | ๋ฌด์†์‹ค | โœ… | ์ตœ๊ณ  | ๊ธฐ์กด ํด๋ผ์ด์–ธํŠธ, ์ •ํ™•์„ฑ ์ค‘์š” | | `webp` | ๋†’์Œ | ๋ฌด์†์‹ค/์†์‹ค | โœ… | ์ข‹์Œ | ์ƒˆ ํด๋ผ์ด์–ธํŠธ, ๋Œ€์—ญํญ ์ ˆ์•ฝ | | `jpeg` | ๋†’์Œ | ์†์‹ค | โŒ | ์ตœ๊ณ  | ์‚ฌ์ง„, ํ˜ธํ™˜์„ฑ ์ค‘์š” | ### ์‚ฌ์šฉ ์˜ˆ์‹œ ```python # ๊ธฐ์กด ๋ฐฉ์‹ (๋ฐ”์ด๋„ˆ๋ฆฌ PNG) - ๊ธฐ๋ณธ๊ฐ’ response = requests.post("http://localhost:8000/api/v1/inpaint", json=payload) # WebP๋กœ 25-35% ์šฉ๋Ÿ‰ ์ ˆ์•ฝ response = requests.post("http://localhost:8000/api/v1/inpaint?response_format=binary&image_format=webp", json=payload) # JSON ์‘๋‹ต์œผ๋กœ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„ ์ •๋ณด ํฌํ•จ response = requests.post("http://localhost:8000/api/v1/inpaint?response_format=json", json=payload) data = response.json() print(f"์ฒ˜๋ฆฌ ์‹œ๊ฐ„: {data['processing_time']:.2f}์ดˆ") # ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต (๋Œ€์šฉ๋Ÿ‰ ํŒŒ์ผ) response = requests.post("http://localhost:8000/api/v1/inpaint?response_format=stream", json=payload) ``` ## ๐Ÿ“Š ์‹ค์‹œ๊ฐ„ ๋ชจ๋‹ˆํ„ฐ๋ง ๋Œ€์‹œ๋ณด๋“œ ### ์ ‘์† URL **http://localhost:8001** ### ์ฃผ์š” ๊ธฐ๋Šฅ #### โšก ์„ฑ๋Šฅ ์ง€ํ‘œ - **RPS**: ์ดˆ๋‹น ์š”์ฒญ ์ˆ˜ - **๋™์‹œ ์š”์ฒญ**: ํ˜„์žฌ/์ตœ๋Œ€ ๋™์‹œ ์š”์ฒญ ์ˆ˜ - **์‘๋‹ต ์‹œ๊ฐ„**: ์ตœ์†Œ/์ตœ๋Œ€/ํ‰๊ท  ์‘๋‹ต์‹œ๊ฐ„ - **๊ฐ€๋™์‹œ๊ฐ„**: ์„œ๋ฒ„ ๊ฐ€๋™ ์‹œ๊ฐ„ #### ๐ŸŒ ์—”๋“œํฌ์ธํŠธ ๋ถ„์„ - **API๋ณ„ ํ†ต๊ณ„**: ์ธํŽ˜์ธํŒ…, ๋ฐฐ๊ฒฝ์ œ๊ฑฐ ๊ฐ๊ฐ์˜ ์š”์ฒญ ์ˆ˜ - **์‘๋‹ต์‹œ๊ฐ„ ๋ถ„์„**: ์—”๋“œํฌ์ธํŠธ๋ณ„ ์„ฑ๋Šฅ ๋น„๊ต - **์ง„ํ–‰ ์ค‘์ธ ์š”์ฒญ**: ์‹ค์‹œ๊ฐ„ ์š”์ฒญ ์ถ”์  - **์„ฑ๊ณต๋ฅ **: ์„ฑ๊ณต/์‹คํŒจ ํ†ต๊ณ„ #### ๐Ÿ–ฅ๏ธ ์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ๋ง - **CPU**: ์‚ฌ์šฉ๋ฅ , ์˜จ๋„, ํด๋Ÿญ - **๋ฉ”๋ชจ๋ฆฌ**: RAM/SWAP ์‚ฌ์šฉ๋Ÿ‰ - **GPU**: ์‚ฌ์šฉ๋ฅ , VRAM, ์˜จ๋„ - **๋„คํŠธ์›Œํฌ**: I/O ํ†ต๊ณ„ - **๋””์Šคํฌ**: ์‚ฌ์šฉ๋Ÿ‰, I/O #### ๐Ÿ‘ฅ ์›Œ์ปค ๊ด€๋ฆฌ - **์›Œ์ปค ์ƒํƒœ**: ํ™œ์„ฑ/์œ ํœด/์—๋Ÿฌ ์›Œ์ปค ์ˆ˜ - **์ž‘์—… ํ**: ๋Œ€๊ธฐ ์ค‘์ธ ์ž‘์—… ์ˆ˜ - **์›Œ์ปค ํ†ต๊ณ„**: ์›Œ์ปค๋ณ„ ์ฒ˜๋ฆฌ ํ†ต๊ณ„ #### ๐ŸŽฏ ๋ชจ๋ธ ์„ธ์…˜ ํ’€ - **LAMA ์„ธ์…˜**: ์‚ฌ์šฉ ์ค‘/๋Œ€๊ธฐ ์ค‘ ์„ธ์…˜ - **MIGAN ์„ธ์…˜**: ์„ธ์…˜ ํ’€ ์ƒํƒœ - **REMBG ์„ธ์…˜**: ์„ธ์…˜ ํšจ์œจ์„ฑ - **๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ**: ์„ธ์…˜๋ณ„ VRAM ์‚ฌ์šฉ๋Ÿ‰ #### ๐Ÿšจ ์‹ค์‹œ๊ฐ„ ์•Œ๋ฆผ - **๋ฆฌ์†Œ์Šค ๊ฒฝ๊ณ **: CPU/GPU/๋ฉ”๋ชจ๋ฆฌ ์ž„๊ณ„๊ฐ’ ์ดˆ๊ณผ - **์—๋Ÿฌ ์•Œ๋ฆผ**: API ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ์•Œ๋ฆผ - **์„ฑ๋Šฅ ๊ฒฝ๊ณ **: ์‘๋‹ต์‹œ๊ฐ„ ์ž„๊ณ„๊ฐ’ ์ดˆ๊ณผ ### ๋ชจ๋‹ˆํ„ฐ๋ง API ```http # ๊ฐ„๋‹จํ•œ ์ƒํƒœ ์ •๋ณด GET /api/simple { "timestamp": 1234567890.123, "system_type": "Jetson Xavier", "cpu_percent": 15.2, "memory_percent": 45.8, "status": "running" } # ์ „์ฒด ์ƒํƒœ ์ •๋ณด GET /api/status # ์›Œ์ปค ์ƒํƒœ GET /api/worker-status # ์„ธ์…˜ ํ’€ ์ƒํƒœ GET /api/session-status # WebSocket ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ WebSocket /ws ``` ## ๐Ÿงช ํ…Œ์ŠคํŠธ ๋ฐ ๊ฒ€์ฆ ### ์ž๋™ ํ…Œ์ŠคํŠธ ์‹คํ–‰ ```bash # ์ „์ฒด iopaint ํ˜ธํ™˜์„ฑ ํ…Œ์ŠคํŠธ python tests/scripts/test_api.py # ๊ธฐ์กด ํด๋ผ์ด์–ธํŠธ ํ˜ธํ™˜์„ฑ ํ…Œ์ŠคํŠธ python tests/scripts/test_compatibility.py # ํŠน์ • ๊ธฐ๋Šฅ ํ…Œ์ŠคํŠธ python tests/scripts/test_api.py --single inpaint python tests/scripts/test_api.py --single rembg python tests/scripts/test_api.py --single health ``` ### ์„ฑ๋Šฅ ๋ฒค์น˜๋งˆํฌ ```bash # API ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ python tests/scripts/benchmark.py # ๋™์‹œ ์š”์ฒญ ํ…Œ์ŠคํŠธ python tests/scripts/stress_test.py --concurrent 10 ``` ## ๐Ÿ› ๏ธ ์„œ๋ฒ„ ๊ด€๋ฆฌ ### ์„œ๋ฒ„ ์‹œ์ž‘ ```bash # ๊ธฐ๋ณธ ์‹œ์ž‘ (๋ฉ”์ธ + ๋ชจ๋‹ˆํ„ฐ๋ง) ./scripts/start_server.sh # Jetson Xavier ์ตœ์ ํ™” ./scripts/start_server.sh --jetson-optimize # ํ”„๋กœ๋•์…˜ ๋ชจ๋“œ ./scripts/start_server.sh --production # ๋ชจ๋‹ˆํ„ฐ๋ง ์—†์ด ๋ฉ”์ธ๋งŒ ./scripts/start_server.sh --no-monitoring # ์›Œ์ปค ์ˆ˜์™€ GPU ์ง€์ • ./scripts/start_server.sh --workers 4 --gpu 0 ``` ### ์„œ๋ฒ„ ์ƒํƒœ ํ™•์ธ ```bash # ์ƒํƒœ ํ™•์ธ ./scripts/status.sh # ์ƒ์„ธ ์ •๋ณด ./scripts/status.sh --detailed # ์‹ค์‹œ๊ฐ„ ๋ชจ๋‹ˆํ„ฐ๋ง ./scripts/status.sh --watch ``` ### ์„œ๋ฒ„ ์ค‘์ง€ ```bash # ์ •์ƒ ์ข…๋ฃŒ ./scripts/stop_server.sh # ๊ฐ•์ œ ์ข…๋ฃŒ ./scripts/stop_server.sh --force ``` ## ๐Ÿš Jetson Xavier ์ „์šฉ ๊ธฐ๋Šฅ ### ์ž๋™ ์‹œ์Šคํ…œ ๊ฐ์ง€ - ARM64 ์•„ํ‚คํ…์ฒ˜ ์ž๋™ ๊ฐ์ง€ - Tegra ์ปค๋„ ์ž๋™ ์ธ์‹ - Jetson ์ „์šฉ ์„ค์ • ์ž๋™ ์ ์šฉ ### ์„ฑ๋Šฅ ์ตœ์ ํ™” - **์ „๋ ฅ ๋ชจ๋“œ**: MAXN ๋ชจ๋“œ๋กœ ์ตœ๊ณ  ์„ฑ๋Šฅ - **GPU ํด๋Ÿญ**: 1377MHz๋กœ ์ตœ๋Œ€ ์„ฑ๋Šฅ - **๋ฉ”๋ชจ๋ฆฌ ํด๋Ÿญ**: 1600MHz ๊ณ ์† ์„ค์ • - **ํŒฌ ์ œ์–ด**: ์ž๋™ ์˜จ๋„ ๊ด€๋ฆฌ ### ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ - **VRAM ์ž„๊ณ„๊ฐ’**: 70%/30% (x86 ๋Œ€๋น„ ๋ณด์ˆ˜์ ) - **ํŒŒ์ผ ํฌ๊ธฐ ์ œํ•œ**: 25MB (x86: 50MB) - **์›Œ์ปค ์ˆ˜**: ์ตœ๋Œ€ 4๊ฐœ (x86: ์ตœ๋Œ€ 8๊ฐœ) ### ๋ชจ๋‹ˆํ„ฐ๋ง ๋„๊ตฌ - **jtop**: Jetson ์ „์šฉ ์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ๋ง - **nvpmodel**: ์ „๋ ฅ ๋ชจ๋“œ ๊ด€๋ฆฌ - **์˜จ๋„ ์„ผ์„œ**: ์‹ค์‹œ๊ฐ„ ์˜จ๋„ ๋ชจ๋‹ˆํ„ฐ๋ง ```bash # Jetson ์ „์šฉ ๋ชจ๋‹ˆํ„ฐ๋ง ๋ช…๋ น์–ด jtop # ์‹ค์‹œ๊ฐ„ ์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ๋ง nvpmodel -q # ํ˜„์žฌ ์ „๋ ฅ ๋ชจ๋“œ ํ™•์ธ tegrastats # GPU/CPU ํ†ต๊ณ„ ``` ## ๐Ÿ”ง ๊ณ ๊ธ‰ ์„ค์ • ### ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์„ค์ • ```bash # .env ํŒŒ์ผ ํŽธ์ง‘ cp .env.example .env nano .env ``` ```env # ์„œ๋ฒ„ ์„ค์ • MAIN_SERVER_PORT=8000 MONITORING_PORT=8001 WORKERS=1 # GPU ์„ค์ • GPU_DEVICE=0 MAX_VRAM_USAGE=0.7 # ํŒŒ์ผ ์„ค์ • MAX_FILE_SIZE=50 MAX_IMAGE_SIZE=2048 # Jetson ์ตœ์ ํ™” JETSON_OPTIMIZE=true FAN_CONTROL=true ``` ### ๋ชจ๋ธ ์„ค์ • ```python # app/core/config.py์—์„œ ๋ชจ๋ธ ์„ค์ • ๋ณ€๊ฒฝ AVAILABLE_MODELS = { "simple-lama": { "type": "inpainting", "path": "app/models/pt/big-lama.pt", "device": "cuda" }, "migan": { "type": "inpainting", "path": "app/models/onnx/migan_pipeline_v2.onnx", "device": "cuda" }, "rembg": { "type": "background_removal", "models": ["u2net", "u2netp", "silueta"] } } ``` ## ๐Ÿ› ๋ฌธ์ œ ํ•ด๊ฒฐ ### ์ผ๋ฐ˜์ ์ธ ๋ฌธ์ œ #### ์„œ๋ฒ„๊ฐ€ ์‹œ์ž‘๋˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ```bash # ๋กœ๊ทธ ํ™•์ธ tail -f logs/main_server.log tail -f logs/monitoring.log # ํฌํŠธ ์‚ฌ์šฉ ํ™•์ธ netstat -tlnp | grep -E "(8000|8001)" # ์˜์กด์„ฑ ์žฌ์„ค์น˜ pip install -r requirements.txt --force-reinstall ``` #### GPU ๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ ```bash # VRAM ์‚ฌ์šฉ๋Ÿ‰ ํ™•์ธ nvidia-smi # ์›Œ์ปค ์ˆ˜ ์ค„์ด๊ธฐ ./scripts/start_server.sh --workers 1 # ์ด๋ฏธ์ง€ ํฌ๊ธฐ ์ œํ•œ ํ™•์ธ # .env ํŒŒ์ผ์—์„œ MAX_IMAGE_SIZE ์กฐ์ • ``` #### ๋ชจ๋ธ ํŒŒ์ผ ๋ˆ„๋ฝ ```bash # ๋ชจ๋ธ ๋””๋ ‰ํ† ๋ฆฌ ํ™•์ธ ls -la app/models/pt/ ls -la app/models/onnx/ # ๋ชจ๋ธ ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ (์ˆ˜๋™) # README์˜ ๋ชจ๋ธ ๋‹ค์šด๋กœ๋“œ ์„น์…˜ ์ฐธ์กฐ ``` ### Jetson ์ „์šฉ ๋ฌธ์ œ #### ONNX Runtime GPU ์„ค์น˜ (GLIBCXX ํ˜ธํ™˜์„ฑ ๋ฌธ์ œ) Jetson Xavier์—์„œ ONNX Runtime GPU๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ํŠน๋ณ„ํ•œ ์ ˆ์ฐจ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค: ```bash # 1. GCC 11 ์—…๊ทธ๋ ˆ์ด๋“œ (ํ•„์ˆ˜) sudo apt install software-properties-common sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt update sudo apt install gcc-11 g++-11 # 2. Jetson ์ „์šฉ ONNX Runtime GPU ํœ  ๋‹ค์šด๋กœ๋“œ ๋ฐ ์„ค์น˜ wget https://nvidia.box.com/shared/static/zostg6agm00fb6t5uisw51qi6kpcuwzd.whl \ -O onnxruntime_gpu-1.17.0-cp38-cp38-linux_aarch64.whl pip install --force-reinstall onnxruntime_gpu-1.17.0-cp38-cp38-linux_aarch64.whl # 3. ์„ค์น˜ ํ™•์ธ python -c "import onnxruntime as ort; print('ONNX Runtime ๋ฒ„์ „:', ort.__version__); print('Available providers:', ort.get_available_providers())" ``` **์˜ˆ์ƒ ์ถœ๋ ฅ**: ``` ONNX Runtime ๋ฒ„์ „: 1.17.0 Available providers: ['TensorrtExecutionProvider', 'CUDAExecutionProvider', 'CPUExecutionProvider'] ``` > **์ฐธ๊ณ **: ์ž๋™ ์„ค์น˜ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์œ„ ๊ณผ์ •์ด ์ž๋™์œผ๋กœ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. #### ์ „๋ ฅ ๋ชจ๋“œ ์„ค์ • ```bash # MAXN ๋ชจ๋“œ๋กœ ์„ค์ • sudo nvpmodel -m 0 # ํ˜„์žฌ ๋ชจ๋“œ ํ™•์ธ nvpmodel -q ``` #### ์˜จ๋„ ๋ฌธ์ œ ```bash # ์˜จ๋„ ํ™•์ธ cat /sys/devices/virtual/thermal/thermal_zone*/temp # ํŒฌ ์†๋„ ํ™•์ธ cat /sys/devices/pwm-fan/target_pwm ``` ## ๐Ÿ“š ์ถ”๊ฐ€ ๋ฆฌ์†Œ์Šค ### ๋ฌธ์„œ - [API ๋ฌธ์„œ](http://localhost:8000/docs) - Swagger UI - [๋ชจ๋‹ˆํ„ฐ๋ง ๋Œ€์‹œ๋ณด๋“œ](http://localhost:8001) - ์‹ค์‹œ๊ฐ„ ๋ชจ๋‹ˆํ„ฐ๋ง - [๊ฐœ๋ฐœ์ž ๊ฐ€์ด๋“œ](docs/developer_guide.md) - [๋ฐฐํฌ ๊ฐ€์ด๋“œ](docs/deployment_guide.md) ### ์ปค๋ฎค๋‹ˆํ‹ฐ - [GitHub Issues](https://github.com/your-repo/issues) - ๋ฒ„๊ทธ ๋ฆฌํฌํŠธ ๋ฐ ๊ธฐ๋Šฅ ์š”์ฒญ - [Discussions](https://github.com/your-repo/discussions) - ์งˆ๋ฌธ ๋ฐ ํ† ๋ก  ### ๋ผ์ด์„ ์Šค ์ด ํ”„๋กœ์ ํŠธ๋Š” MIT ๋ผ์ด์„ ์Šค ํ•˜์— ๋ฐฐํฌ๋ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ [LICENSE](LICENSE) ํŒŒ์ผ์„ ์ฐธ์กฐํ•˜์„ธ์š”. --- ## ๐ŸŽ‰ ๋น ๋ฅธ ์‹œ์ž‘ ์š”์•ฝ ```bash # 1. ํ”„๋กœ์ ํŠธ ํด๋ก  git clone inpaintServer && cd inpaintServer # 2. ์›ํด๋ฆญ ์„ค์น˜ ๋ฐ ์‹คํ–‰ chmod +x scripts/*.sh && ./scripts/setup_and_run.sh # 3. ์ ‘์† ํ™•์ธ curl http://localhost:8000/health curl http://localhost:8001/api/simple # 4. ๊ธฐ์กด ํด๋ผ์ด์–ธํŠธ ํ˜ธํ™˜์„ฑ ํ…Œ์ŠคํŠธ python tests/scripts/test_compatibility.py ``` **๐ŸŽฏ ๊ฒฐ๊ณผ**: ๊ธฐ์กด ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ ์ˆ˜์ • ์—†์ด 100% ํ˜ธํ™˜! ๐Ÿš€ --- *Made with โค๏ธ for high-performance AI inference*