AI ๊ธฐ๋ฐ ๊ฐ์ธํ ๋์ ์ถ์ฒ ์์คํ ์ ๋๋ค. ์ฝํ ์ธ ๊ธฐ๋ฐ ํํฐ๋ง๊ณผ ํ์ ํํฐ๋ง์ ๊ฒฐํฉํ ํ์ด๋ธ๋ฆฌ๋ ์ถ์ฒ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํฉ๋๋ค.
๋ฐฉ๋ฒ 1: uv ์ฌ์ฉ (๊ถ์ฅ)
# uv ์ค์น (์๋ ๊ฒฝ์ฐ)
pip install uv
# ๋ฐฉ์ A
uv lock
uv sync
uv sync --dev # ๊ฐ๋ฐ์ฉ ํฌํจ
# ๋ฐฉ์ B
uv venv
uv pip sync requirements.txt
uv pip sync requirements-dev.txt # ๊ฐ๋ฐ์ฉ ํฌํจ๋ฐฉ๋ฒ 2: requirements.txt ์ฌ์ฉ
pip install -r requirements.txt
pip install -r requirements-dev.txt # ๊ฐ๋ฐ์ฉ ํฌํจ# ํ๊ฒฝ ์ค์ ํ์ผ ์์ฑ
cp .env.toml.template .env.toml
# .env.toml ํ์ผ์ ํธ์งํ์ฌ ์ค์ ๊ฐ ์
๋ ฅ# ๊ฐ๋ฐ ๋ชจ๋
python main.py
# ์ค์ ํ์ผ์ ์๋ฒ ์ ๋ณด๋ก ์คํ๋ฉ๋๋ค:
# - ๊ธฐ๋ณธ ํธ์คํธ: 0.0.0.0
# - ๊ธฐ๋ณธ ํฌํธ: 8000bookstar-ai/
โโโ ๐ main.py # ๋ฉ์ธ ์คํ ํ์ผ
โโโ ๐ config.toml # ์ฑ ์ค์ (๊ณต๊ฐ)
โโโ ๐ .env.toml.template # ํ๊ฒฝ์ค์ ํ
ํ๋ฆฟ
โโโ ๐ .env.toml # ์ค์ ํ๊ฒฝ์ค์ (Git ์ ์ธ)
โโโ ๐ฆ pyproject.toml # ํ๋ก์ ํธ ์ค์ ๋ฐ ์์กด์ฑ
โโโ ๐ณ Dockerfile # Docker ์ค์
โโโ ๐ bookstar/ # ๋ฉ์ธ ํจํค์ง
โ โโโ ๐ฏ main.py # FastAPI ์ ํ๋ฆฌ์ผ์ด์
โ โโโ โ๏ธ config/ # ์ค์ ๊ด๋ฆฌ
โ โ โโโ __init__.py
โ โ โโโ config.py
โ โ โโโ logging_config.py # ๋ก๊น
์์คํ
์ค์
โ โโโ ๐๏ธ models/ # ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ชจ๋ธ
โ โ โโโ __init__.py
โ โ โโโ models.py
โ โโโ ๐ schemas/ # API ์คํค๋ง
โ โ โโโ __init__.py
โ โ โโโ schemas.py
โ โโโ ๐ database/ # ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ
โ โ โโโ __init__.py
โ โ โโโ connection.py
โ โโโ ๐ค services/ # AI ์ถ์ฒ ๋ก์ง
โ โ โโโ __init__.py
โ โ โโโ recommendation.py
โ โโโ ๐ ๏ธ utils/ # ์ ํธ๋ฆฌํฐ (๋ฐ์ฝ๋ ์ดํฐ ๋ฑ)
โ โโโ __init__.py
โ โโโ decorators.py
โโโ ๐ examples/ # ์ฌ์ฉ ์์
โ โโโ logging_example.py # ๋ก๊น
์์คํ
์์
โ โโโ logs/ # ์์ ์คํ ๋ก๊ทธ
โโโ ๐ logs/ # ๋ก๊ทธ ํ์ผ๋ค (5์ข
๋ฅ)
โ โโโ bookstar.log # ์ ์ฒด ๋ก๊ทธ (14์ผ ๋ณด๊ด)
โ โโโ bookstar_error.log # ์๋ฌ ๋ก๊ทธ (30์ผ ๋ณด๊ด)
โ โโโ bookstar_access.log # ์ก์ธ์ค ๋ก๊ทธ (7์ผ ๋ณด๊ด)
โ โโโ bookstar_performance.log # ์ฑ๋ฅ ๋ก๊ทธ (10์ผ ๋ณด๊ด)
โ โโโ bookstar_traceback.log # Traceback ๋ก๊ทธ (60์ผ ๋ณด๊ด)
โโโ ๐งช tests/ # ํ
์คํธ ์ฝ๋ (64๊ฐ ํ
์คํธ, 88% ์ปค๋ฒ๋ฆฌ์ง)
โโโ __init__.py
โโโ conftest.py # ํ
์คํธ ์ค์ ๋ฐ ํฝ์ค์ฒ
โโโ test_main.py # FastAPI ํ
์คํธ (2๊ฐ)
โโโ test_config.py # ์ค์ ์์คํ
ํ
์คํธ (15๊ฐ)
โโโ test_logging.py # ๋ก๊น
์์คํ
ํ
์คํธ (12๊ฐ)
โโโ test_decorators.py # ๋ฐ์ฝ๋ ์ดํฐ ํ
์คํธ (17๊ฐ)
โโโ test_recommendation.py # ์ถ์ฒ ์์คํ
ํ
์คํธ (18๊ฐ)
config.toml: ๊ณต๊ฐ ์ค์ (Git โ ).env.toml: ๋ฏผ๊ฐํ ์ ๋ณด (Git โ).env.toml.template: ์ค์ ๊ฐ์ด๋ (Git โ )
- ํ๊ฒฝ๋ณ์ ๐ฅ (์ต์ฐ์ )
- .env.toml ๐ฅ
- config.toml ๐ฅ
# ๐ ์ ํ๋ฆฌ์ผ์ด์
๊ธฐ๋ณธ ์ ๋ณด
[app]
title = "BookStar AI"
description = "AI ๊ธฐ๋ฐ ๋์ ์ถ์ฒ ์์คํ
"
version = "1.0.0"
cors_origins = ["http://127.0.0.1:9101"]
# ๐ ์๋ฒ ์ค์
[server]
host = "0.0.0.0"
port = 8000
# ๐ค AI ์ถ์ฒ ์์คํ
์ค์
[recommendation]
default_recommendations_count = 10 # ๊ธฐ๋ณธ ์ถ์ฒ ๋์ ๊ฐ์
similar_users_count = 3 # ํ์
ํํฐ๋ง ์ ์ฌ ์ฌ์ฉ์ ์
content_weight = 0.7 # ์ฝํ
์ธ ๊ธฐ๋ฐ ๊ฐ์ค์น
collaborative_weight = 0.3 # ํ์
ํํฐ๋ง ๊ฐ์ค์น
# ์ฌ์ฉ์ ์ ํธ๋ ๊ณ์ฐ ๊ฐ์ค์น
read_book_weight = 0.7 # ์ฝ์ ์ฑ
์ ๊ฐ์ค์น (vs ์ฝ๊ณ ์ถ์ ์ฑ
)
unread_book_weight = 1.0 # ์ฝ์ง ์์ ์ฑ
์ ๊ฐ์ค์น
category_preference_weight = 2.0 # ์นดํ
๊ณ ๋ฆฌ ์ ํธ๋ ๊ฐ์ค์น
author_preference_weight = 1.5 # ์ ์ ์ ํธ๋ ๊ฐ์ค์น
# PyTorch ๋ชจ๋ธ ํ๋ จ ์ค์ (deprecated ํจ์์ฉ)
num_epochs = 300 # ํ๋ จ ์ํฌํฌ ์
learning_rate = 0.122 # ํ์ต๋ฅ
# ๐ ๋ก๊น
์์คํ
์ค์
[logging]
level = "INFO"
use_json = false
enable_console = true
log_dir = "logs"
# ์ฑ๋ฅ ์๊ณ๊ฐ ์ค์ (ms)
performance_threshold_ms = 100
db_query_threshold_ms = 50
api_processing_threshold_ms = 200
heavy_computation_threshold_ms = 500
# ๋ก๊ทธ ๋ณด๊ด ์ ์ฑ
(์ผ ๋จ์)
main_log_retention_days = 14
error_log_retention_days = 30
access_log_retention_days = 7
performance_log_retention_days = 10
traceback_log_retention_days = 60# โ ๏ธ ์ ๋ Git์ ์ฌ๋ฆฌ์ง ๋ง์ธ์!
[aws]
region = "ap-northeast-2"
bucket_name = "your-bucket-name"
access_key_id = "์ค์ _AWS_ํค"
secret_access_key = "์ค์ _AWS_์ํฌ๋ฆฟ"
[database]
user = "์ค์ _DB_์ฌ์ฉ์"
password = "์ค์ _DB_๋น๋ฐ๋ฒํธ"
host = "์ค์ _DB_ํธ์คํธ"
port = 3306
name = "์ค์ _DB_์ด๋ฆ"- ์ฝํ ์ธ ๊ธฐ๋ฐ ํํฐ๋ง: ์นดํ ๊ณ ๋ฆฌ, ์ ์ ์ ํธ๋ ๋ถ์
- ํ์ ํํฐ๋ง: ์ ์ฌ ์ฌ์ฉ์ ๊ธฐ๋ฐ ์ถ์ฒ
- ํ์ด๋ธ๋ฆฌ๋ ๋ฐฉ์: ๋ ๋ฐฉ๋ฒ์ ๊ฒฐํฉํ์ฌ ์ถ์ฒ ํ์ง ํฅ์
| ์ค์ | ๊ธฐ๋ณธ๊ฐ | ์ค๋ช |
|---|---|---|
default_recommendations_count |
10 | ๊ธฐ๋ณธ ์ถ์ฒ ๋์ ๊ฐ์ |
similar_users_count |
3 | ํ์ ํํฐ๋ง์์ ์ฐธ๊ณ ํ ์ ์ฌ ์ฌ์ฉ์ ์ |
content_weight |
0.7 | ์ฝํ ์ธ ๊ธฐ๋ฐ ํํฐ๋ง ๊ฐ์ค์น |
collaborative_weight |
0.3 | ํ์ ํํฐ๋ง ๊ฐ์ค์น |
read_book_weight |
0.7 | ์ฝ์ ์ฑ ์ ์ ํธ๋ ๊ฐ์ค์น |
unread_book_weight |
1.0 | ์ฝ์ง ์์ ์ฑ ์ ์ ํธ๋ ๊ฐ์ค์น |
category_preference_weight |
2.0 | ์นดํ ๊ณ ๋ฆฌ ์ ํธ๋ ๊ณ์ฐ ๊ฐ์ค์น |
author_preference_weight |
1.5 | ์ ์ ์ ํธ๋ ๊ณ์ฐ ๊ฐ์ค์น |
num_epochs |
300 | PyTorch ๋ชจ๋ธ ํ๋ จ ์ํฌํฌ ์ |
learning_rate |
0.122 | PyTorch ๋ชจ๋ธ ํ์ต๋ฅ |
- ์บ์ฑ ์์คํ : ์ฌ์ฉ์ ๋ฐ์ดํฐ ๋ฐ ์ ํธ๋ ์บ์ฑ
- ์ฟผ๋ฆฌ ์ต์ ํ: ๋จ์ผ JOIN ์ฟผ๋ฆฌ๋ก ๋ฐ์ดํฐ ์กฐํ
- ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ฑ: ํ์ํ ์ปฌ๋ผ๋ง ์ ํ์ ๋ก๋
- ์์ ํ ์ค์ ๊ธฐ๋ฐ: config.toml์์ ๋ชจ๋ ์ถ์ฒ ํ๋ผ๋ฏธํฐ ์กฐ์ ๊ฐ๋ฅ (ํ๋์ฝ๋ฉ ์์ ์ ๊ฑฐ)
- ๋์ Docker ์ค์ : docker-run.sh๊ฐ config.toml์์ ํฌํธ๋ฅผ ์๋์ผ๋ก ์ฝ์ด์ด
- API ์๋ต ์ต์ ํ: book_id๋ง ๋ฐํํ์ฌ ๋คํธ์ํฌ ํธ๋ํฝ ๋ฐ JSON ํ์ฑ ์๊ฐ ์ต์ํ
- ์ฌ์ฉ์ ๋ ์ ์ด๋ ฅ ๋ถ์: ์ฝ์ ์ฑ ๊ณผ ์ฝ๊ณ ์ถ์ ์ฑ ๋ชฉ๋ก ์กฐํ
- ์ ํธ๋ ๊ฐ์ค์น ๊ณ์ฐ: ์ฝ์ ์ฑ (0.7) vs ์ฝ๊ณ ์ถ์ ์ฑ (1.0) ๊ฐ์ค์น ์ ์ฉ
- ์นดํ ๊ณ ๋ฆฌ/์ ์ ์ ํธ๋ ๊ณ์ฐ: ์นดํ ๊ณ ๋ฆฌ(2.0๋ฐฐ), ์ ์(1.5๋ฐฐ) ๊ฐ์ค์น๋ก ์ ์ ์ฐ์ถ
- ์ ์ฌ ์ฌ์ฉ์ ํ์: KNN ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ์ค์ ๊ฐ๋ฅํ ๊ฐ์๋งํผ ์ ์ฌ ์ฌ์ฉ์ ๋ฐ๊ฒฌ
- ํ์ด๋ธ๋ฆฌ๋ ์ถ์ฒ: ์ฝํ ์ธ ๊ธฐ๋ฐ(70%) + ํ์ ํํฐ๋ง(30%) ๊ฐ์ค์น๋ก ๊ฒฐํฉ
- ์ต์ข ์ถ์ฒ ๋ชฉ๋ก ์์ฑ: ์ค์ ๋ ๊ฐ์๋งํผ ๊ฐ์ธํ๋ ์ถ์ฒ ๊ฒฐ๊ณผ ๋ฐํ
POST /recommend_books
Content-Type: application/json
{
"user_id": 123
}์๋ต ์์:
{
"recommendations": [
{
"book_id": 10650
},
{
"book_id": 54381
},
{
"book_id": 49817
}
]
}๐ ์๋ต ํํ ๋ณ๊ฒฝ์ฌํญ:
- ๊ฐ์ํ๋ ์๋ต: ์ด์
book_id๋ง ๋ฐํ (์์ธ ์ ๋ณด ์ ๊ฑฐ) - ๋ด๋ถ ID ์ฌ์ฉ: ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ด๋ถ
idํ๋ ์ฌ์ฉ (๊ธฐ์กดaladin_book_id๋์ ) - ์ฑ๋ฅ ์ต์ ํ: ํ์ํ ์ต์ํ์ ์ ๋ณด๋ง ์ ์กํ์ฌ ์๋ต ์๋ ํฅ์
logs/
โโโ bookstar.log # ์ ์ฒด ๋ก๊ทธ (14์ผ ๋ณด๊ด)
โโโ bookstar_error.log # ์๋ฌ ์ ์ฉ (30์ผ ๋ณด๊ด)
โโโ bookstar_access.log # HTTP ์์ฒญ ๋ก๊ทธ (7์ผ ๋ณด๊ด)
โโโ bookstar_performance.log # ์ฑ๋ฅ ์ธก์ ๋ก๊ทธ (10์ผ ๋ณด๊ด)
โโโ bookstar_traceback.log # ์์ธ ์์ธ ์ ๋ณด (60์ผ ๋ณด๊ด)
| ์๊ณ๊ฐ | ๊ธฐ๋ณธ๊ฐ | ์ค๋ช |
|---|---|---|
performance_threshold_ms |
100ms | ๊ธฐ๋ณธ ์ฑ๋ฅ ๋ก๊ทธ ์๊ณ๊ฐ |
db_query_threshold_ms |
50ms | ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฟผ๋ฆฌ ์๊ณ๊ฐ |
api_processing_threshold_ms |
200ms | API ์ฒ๋ฆฌ ์๊ณ๊ฐ |
heavy_computation_threshold_ms |
500ms | ๋ฌด๊ฑฐ์ด ์ฐ์ฐ ์๊ณ๊ฐ |
- ์๊ฐ ๊ธฐ๋ฐ ๋กํ ์ด์ : ๋ชจ๋ ๋ก๊ทธ๊ฐ ๋งค์ผ ์์ ์ ๋กํ ์ด์
- ์๋ ์ญ์ : ์ค์ ๋ ๋ณด๊ด ์ผ์ ํ ์๋ ์ญ์
- ์์ถ ์ ์ฅ: ์ค๋๋ ๋ก๊ทธ๋ ์๋์ผ๋ก ์์ถ
๐ ์์ธํ ๋ก๊น ๊ฐ์ด๋: LOGGING_GUIDE.md
.env.toml # ๐ซ ๋ฏผ๊ฐํ ์ ๋ณด ํฌํจ| ํ๊ฒฝ | ๋ฐฉ๋ฒ | ์์ |
|---|---|---|
| ๋ก์ปฌ ๊ฐ๋ฐ | .env.toml |
ํ์ผ์ ์ค์ ๊ฐ ์ ์ฅ |
| CI/CD | ํ๊ฒฝ๋ณ์ | GitHub Secrets, GitLab Variables |
| ํ๋ก๋์ | ์ธ๋ถ ์๋น์ค | AWS Secrets Manager, Vault |
- โ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋น๋ฐ๋ฒํธ
- โ AWS ์ก์ธ์ค ํค
- โ API ํ ํฐ
- โ ์๋ฒ IP ์ฃผ์
- โ ์ํธํ ํค
# ์ ์ฒด ํ
์คํธ ์คํ
pytest
# ์ปค๋ฒ๋ฆฌ์ง ํฌํจ ํ
์คํธ
pytest --cov=bookstar --cov-report=term-missing
# ํน์ ํ
์คํธ ์คํ
pytest tests/test_config.py # ์ค์ ์์คํ
ํ
์คํธ (15๊ฐ)
pytest tests/test_main.py # FastAPI ์๋ํฌ์ธํธ ํ
์คํธ (2๊ฐ)
pytest tests/test_logging.py # ๋ก๊น
์์คํ
ํ
์คํธ (12๊ฐ)
pytest tests/test_decorators.py # ๋ฐ์ฝ๋ ์ดํฐ ํ
์คํธ (17๊ฐ)
pytest tests/test_recommendation.py # ์ถ์ฒ ์์คํ
ํ
์คํธ (18๊ฐ)
# ์ค์ ์์คํ
๋น ๋ฅธ ๊ฒ์ฆ (๊ธฐ๋ณธ)
python -c "from bookstar.config import settings; settings.app; settings.server; settings.recommendation; settings.logging; settings.aws; settings.database; settings.database_url; print('โ
๋ชจ๋ ์ค์ ๋ก๋ ์ฑ๊ณต')"
# ์ค์ ์์คํ
์์ ๊ฒ์ฆ (pytest์ ๋์ผํ ๋ก์ง)
python -c "
from bookstar.config.config import settings
try:
# ๋ชจ๋ ์ค์ ์น์
์ ๊ทผ ๋ฐ ๊ฒ์ฆ
app = settings.app
server = settings.server
rec = settings.recommendation
log = settings.logging
aws = settings.aws
db = settings.database
db_url = settings.database_url
# ํ์ ํค ์กด์ฌ ํ์ธ
assert 'title' in app and 'host' in server and 'level' in log
assert 'default_recommendations_count' in rec
assert 'region' in aws and 'user' in db
# ๋ฐ์ดํฐ ํ์
๊ฒ์ฆ
assert isinstance(server['port'], int)
assert isinstance(log['performance_threshold_ms'], int)
assert isinstance(rec['content_weight'], (int, float))
# ๊ฐ ๋ฒ์ ๊ฒ์ฆ
assert 1 <= server['port'] <= 65535
assert abs(rec['content_weight'] + rec['collaborative_weight'] - 1.0) < 0.001
print('โ
๋ชจ๋ ์ค์ ๊ฒ์ฆ ์๋ฃ (pytest ์์ค)')
except Exception as e:
print(f'โ ์ค์ ๊ฒ์ฆ ์คํจ: {e}')
exit(1)
"# ์ฝ๋ ํ์ง ๊ฒ์ฌ
ruff check .
# ์ฝ๋ ์๋ ์์
ruff check . --fix
# ํ์
์ฒดํฌ
mypy bookstar/
# ์ ์ฒด ํ์ง ๊ฒ์ฌ
pytest && pytest --cov=bookstar && mypy bookstar/ && ruff check .
# ๋ก๊น
์์คํ
์์ ์คํ
python examples/logging_example.py# ์คํฌ๋ฆฝํธ์ ์คํ ๊ถํ ๋ถ์ฌ (์ต์ด 1ํ)
chmod +x docker-run.sh
# Docker ์ด๋ฏธ์ง ๋น๋
./docker-run.sh build
# ์ปจํ
์ด๋ ์์ (config.toml์์ ํฌํธ ์๋ ์ฝ๊ธฐ)
./docker-run.sh start
# ์ํ ํ์ธ
./docker-run.sh status
# ์ค์๊ฐ ๋ก๊ทธ ํ์ธ
./docker-run.sh logs
# ์ปจํ
์ด๋ ์ค์ง
./docker-run.sh stop
# ์ปจํ
์ด๋ ์ฌ์์
./docker-run.sh restart๐ง ๋์ ํฌํธ ์ค์ : docker-run.sh๋ config.toml์์ ํฌํธ๋ฅผ ์๋์ผ๋ก ์ฝ์ด์ ์ฌ์ฉํฉ๋๋ค. ํฌํธ๋ฅผ ๋ณ๊ฒฝํ๋ ค๋ฉด config.toml์ server.port ๊ฐ๋ง ์์ ํ๋ฉด ๋ฉ๋๋ค.
# ๋ฐฑ๊ทธ๋ผ์ด๋์์ ๋น๋ ๋ฐ ์์ (mysql ์๋น์ค ํ์)
docker-compose up -d --build
# ์ํ ํ์ธ
docker-compose ps
# ๋ก๊ทธ ํ์ธ
docker-compose logs -f ai-server
# ์ค์ง ๋ฐ ์ ๊ฑฐ
docker-compose down๐ Docker Compose ๊ตฌ์กฐ:
- ํฌํธ: 8000 ๊ณ ์ (ํธ์คํธ:์ปจํ ์ด๋ ๋ชจ๋ 8000)
- ์์กด์ฑ: mysql ์๋น์ค๊ฐ ๋จผ์ ์์๋ ํ ai-server ์์
- ๋ณผ๋ฅจ: ๋ก๊ทธ ๋๋ ํ ๋ฆฌ๋ง ํธ์คํธ์ ๊ณต์
- ๋คํธ์ํฌ: ๊ธฐ๋ณธ ๋คํธ์ํฌ ์ฌ์ฉ (๊ฐ์ํ)
# Docker ์ด๋ฏธ์ง ๋น๋
docker build -t docker-ai-server .
# Docker ์ปจํ
์ด๋ ์คํ
docker run -d \
--name ai-server \
-p 8000:8000 \
--restart unless-stopped \
-v $(pwd)/logs:/app/logs \
docker-ai-server
# ์ปจํ
์ด๋ ์ํ ํ์ธ
docker ps์ฑ๊ณต์ ์ผ๋ก ์คํ๋๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ปจํ ์ด๋ ์ํ๋ฅผ ํ์ธํ ์ ์์ต๋๋ค:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
07417843388d docker-ai-server "python main.py" 17 hours ago Up 17 hours (healthy) 0.0.0.0:8000->8000/tcp ai-server
- API ์๋ฒ: http://localhost:8000
- API ๋ฌธ์: http://localhost:8000/docs
- ํฌ์ค์ฒดํฌ: 30์ด๋ง๋ค ์๋ ํ์ธ
# ์๋ฒ ์ค์ ๋ณ๊ฒฝ
export SERVER_HOST=127.0.0.1
export SERVER_PORT=9000
# ๋ก๊ทธ ๋ ๋ฒจ ๋ณ๊ฒฝ
export LOG_LEVEL=DEBUG
# ์ถ์ฒ ๊ฐ์ ๋ณ๊ฒฝ (ํ์ฌ๋ config.toml์์๋ง ์ง์)# ์ค์๊ฐ ๋ก๊ทธ ๋ชจ๋ํฐ๋ง
tail -f logs/bookstar.log
# ์๋ฌ ๋ก๊ทธ๋ง ํ์ธ
tail -f logs/bookstar_error.log
# ์ฑ๋ฅ ๋ก๊ทธ ํ์ธ
tail -f logs/bookstar_performance.log# ๋๋ฆฐ ์ฟผ๋ฆฌ ํ์ธ
grep "๋๋ฆฐ ์ฟผ๋ฆฌ" logs/bookstar.log
# ์ฑ๋ฅ ์๊ณ๊ฐ ์ด๊ณผ ํจ์ ํ์ธ
grep "์คํ ์๋ฃ" logs/bookstar_performance.log- โ
์์ ํ ํ๋์ฝ๋ฉ ์ ๊ฑฐ: ๋ชจ๋ ์ค์ ๊ฐ์ด
config.toml์์ ๊ด๋ฆฌ๋จ - โ ๋์ ์ค์ ์์คํ : Docker ์คํฌ๋ฆฝํธ๊น์ง ์ค์ ํ์ผ ๊ธฐ๋ฐ์ผ๋ก ์๋
- โ ํฌ๊ด์ ํ ์คํธ: 64๊ฐ ํ ์คํธ, 88% ์ฝ๋ ์ปค๋ฒ๋ฆฌ์ง ๋ฌ์ฑ
- โ ์ฝ๋ ํ์ง: MyPy, Ruff ๋ชจ๋ ๊ฒ์ฌ ํต๊ณผ
- โ ๋ก๊น ์์คํ : 5์ข ๋ฅ ๋ก๊ทธ ํ์ผ, ์๋ ๋กํ ์ด์ ๋ฐ ๋ณด๊ด ์ ์ฑ
- โ AI ์ถ์ฒ ์์คํ : ํ์ด๋ธ๋ฆฌ๋ ์๊ณ ๋ฆฌ์ฆ, ์์ ํ ์ค์ ๊ธฐ๋ฐ
- โ Docker ์ต์ ํ: ์ค๋ณต ์ค์ ์ ๊ฑฐ, mysql ์์กด์ฑ ์ถ๊ฐ, ๊ฐ์ํ๋ ๊ตฌ์กฐ
- โ API ์ต์ ํ: ๊ฐ์ํ๋ ์๋ต ํํ๋ก ๋คํธ์ํฌ ํธ๋ํฝ ๋ฐ ์ฒ๋ฆฌ ์๊ฐ ์ต์ ํ
| ์นดํ ๊ณ ๋ฆฌ | ์ค์ ํญ๋ชฉ ์ | ์ฃผ์ ์ค์ |
|---|---|---|
| ์ฑ ์ ๋ณด | 4๊ฐ | ์ ๋ชฉ, ์ค๋ช , ๋ฒ์ , CORS |
| ์๋ฒ | 2๊ฐ | ํธ์คํธ, ํฌํธ |
| ์ถ์ฒ ์์คํ | 10๊ฐ | ์ถ์ฒ ๊ฐ์, ๊ฐ์ค์น, ์๊ณ๊ฐ ๋ฑ |
| ๋ก๊น | 15๊ฐ | ๋ก๊ทธ ๋ ๋ฒจ, ์๊ณ๊ฐ, ๋ณด๊ด ์ ์ฑ ๋ฑ |
| ๋ฐ์ดํฐ๋ฒ ์ด์ค | 5๊ฐ | ์ฐ๊ฒฐ ์ ๋ณด |
| AWS | 4๊ฐ | ์ธ์ฆ ์ ๋ณด |
# ๋ชจ๋ ํ์ง ๊ฒ์ฌ ํต๊ณผ
โ
pytest: 64๊ฐ ํ
์คํธ ๋ชจ๋ ํต๊ณผ
โ
์ปค๋ฒ๋ฆฌ์ง: 88% (782๊ฐ ๊ตฌ๋ฌธ ์ค 92๊ฐ ๋๋ฝ)
โ
mypy: 15๊ฐ ์์ค ํ์ผ์์ ํ์
์ฒดํฌ ๋ฌธ์ ์์
โ
ruff: ๋ชจ๋ ์ฝ๋ ์คํ์ผ ๋ฐ ํ์ง ๊ฒ์ฌ ํต๊ณผ
โ
์ค์ ๊ฒ์ฆ: ๋ชจ๋ ์ค์ ์น์
๋ก๋ ์ฑ๊ณต
โ
Docker: ์ค๋ณต ์ ๊ฑฐ, ์์กด์ฑ ๊ด๋ฆฌ, 8000 ํฌํธ ๊ณ ์
โ
API ์๋ต ์ต์ ํ: book_id๋ง ๋ฐํํ๋ ๊ฐ์ํ๋ ํํ๋ก ๋ณ๊ฒฝ์ด์ config.toml ํ์ผ ํ๋๋ง ์์ ํ๋ฉด ์ ์ฒด ์์คํ
์ ๋์์ ์์ ํ ์ ์ดํ ์ ์์ต๋๋ค. ํ๋์ฝ๋ฉ๋ ๊ฐ์ ๋ ์ด์ ์กด์ฌํ์ง ์์ผ๋ฉฐ, ๋ชจ๋ ์ค์ ์ด ์ค์ํ๋์ด ๊ด๋ฆฌ๋ฉ๋๋ค.
Docker ๋ฐฐํฌ ๋ฐฉ์:
- ๊ฐ๋ฐ/ํ
์คํธ:
docker-run.sh์ฌ์ฉ (๋์ ํฌํธ) - ํ๋ก๋์
:
docker-compose์ฌ์ฉ (mysql ์์กด์ฑ, 8000 ํฌํธ ๊ณ ์ )