Skip to content

Repository files navigation

๐Ÿ“š BookStar AI - ๋„์„œ ์ถ”์ฒœ ์‹œ์Šคํ…œ

AI ๊ธฐ๋ฐ˜ ๊ฐœ์ธํ™” ๋„์„œ ์ถ”์ฒœ ์‹œ์Šคํ…œ์ž…๋‹ˆ๋‹ค. ์ฝ˜ํ…์ธ  ๊ธฐ๋ฐ˜ ํ•„ํ„ฐ๋ง๊ณผ ํ˜‘์—… ํ•„ํ„ฐ๋ง์„ ๊ฒฐํ•ฉํ•œ ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ์ถ”์ฒœ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๐Ÿš€ ๋น ๋ฅธ ์‹œ์ž‘

1. ์˜์กด์„ฑ ์„ค์น˜

๋ฐฉ๋ฒ• 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  # ๊ฐœ๋ฐœ์šฉ ํฌํ•จ

2. ํ™˜๊ฒฝ ์„ค์ •

# ํ™˜๊ฒฝ ์„ค์ • ํŒŒ์ผ ์ƒ์„ฑ
cp .env.toml.template .env.toml

# .env.toml ํŒŒ์ผ์„ ํŽธ์ง‘ํ•˜์—ฌ ์‹ค์ œ ๊ฐ’ ์ž…๋ ฅ

3. ์‹คํ–‰

# ๊ฐœ๋ฐœ ๋ชจ๋“œ
python main.py

# ์„ค์ • ํŒŒ์ผ์˜ ์„œ๋ฒ„ ์ •๋ณด๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค:
# - ๊ธฐ๋ณธ ํ˜ธ์ŠคํŠธ: 0.0.0.0
# - ๊ธฐ๋ณธ ํฌํŠธ: 8000

๐Ÿ—๏ธ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ

bookstar-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 โœ…)

๐Ÿ”„ ์šฐ์„ ์ˆœ์œ„

  1. ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๐Ÿฅ‡ (์ตœ์šฐ์„ )
  2. .env.toml ๐Ÿฅˆ
  3. config.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

๐Ÿ”’ .env.toml ์˜ˆ์‹œ

# โš ๏ธ ์ ˆ๋Œ€ 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_์ด๋ฆ„"

๐Ÿค– AI ์ถ”์ฒœ ์‹œ์Šคํ…œ

๐Ÿ“Š ์ถ”์ฒœ ์•Œ๊ณ ๋ฆฌ์ฆ˜

  • ์ฝ˜ํ…์ธ  ๊ธฐ๋ฐ˜ ํ•„ํ„ฐ๋ง: ์นดํ…Œ๊ณ ๋ฆฌ, ์ €์ž ์„ ํ˜ธ๋„ ๋ถ„์„
  • ํ˜‘์—… ํ•„ํ„ฐ๋ง: ์œ ์‚ฌ ์‚ฌ์šฉ์ž ๊ธฐ๋ฐ˜ ์ถ”์ฒœ
  • ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ๋ฐฉ์‹: ๋‘ ๋ฐฉ๋ฒ•์„ ๊ฒฐํ•ฉํ•˜์—ฌ ์ถ”์ฒœ ํ’ˆ์งˆ ํ–ฅ์ƒ

๐ŸŽฏ ์ถ”์ฒœ ์„ค์ • (config.toml)

์„ค์ • ๊ธฐ๋ณธ๊ฐ’ ์„ค๋ช…
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 ํŒŒ์‹ฑ ์‹œ๊ฐ„ ์ตœ์†Œํ™”

๐Ÿ“ˆ ์ถ”์ฒœ ๊ณผ์ •

  1. ์‚ฌ์šฉ์ž ๋…์„œ ์ด๋ ฅ ๋ถ„์„: ์ฝ์€ ์ฑ…๊ณผ ์ฝ๊ณ  ์‹ถ์€ ์ฑ… ๋ชฉ๋ก ์กฐํšŒ
  2. ์„ ํ˜ธ๋„ ๊ฐ€์ค‘์น˜ ๊ณ„์‚ฐ: ์ฝ์€ ์ฑ…(0.7) vs ์ฝ๊ณ  ์‹ถ์€ ์ฑ…(1.0) ๊ฐ€์ค‘์น˜ ์ ์šฉ
  3. ์นดํ…Œ๊ณ ๋ฆฌ/์ €์ž ์„ ํ˜ธ๋„ ๊ณ„์‚ฐ: ์นดํ…Œ๊ณ ๋ฆฌ(2.0๋ฐฐ), ์ €์ž(1.5๋ฐฐ) ๊ฐ€์ค‘์น˜๋กœ ์ ์ˆ˜ ์‚ฐ์ถœ
  4. ์œ ์‚ฌ ์‚ฌ์šฉ์ž ํƒ์ƒ‰: KNN ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ ์„ค์ • ๊ฐ€๋Šฅํ•œ ๊ฐœ์ˆ˜๋งŒํผ ์œ ์‚ฌ ์‚ฌ์šฉ์ž ๋ฐœ๊ฒฌ
  5. ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ์ถ”์ฒœ: ์ฝ˜ํ…์ธ  ๊ธฐ๋ฐ˜(70%) + ํ˜‘์—… ํ•„ํ„ฐ๋ง(30%) ๊ฐ€์ค‘์น˜๋กœ ๊ฒฐํ•ฉ
  6. ์ตœ์ข… ์ถ”์ฒœ ๋ชฉ๋ก ์ƒ์„ฑ: ์„ค์ •๋œ ๊ฐœ์ˆ˜๋งŒํผ ๊ฐœ์ธํ™”๋œ ์ถ”์ฒœ ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜

๐Ÿ“ก API ์‚ฌ์šฉ๋ฒ•

๐Ÿ“š ๋„์„œ ์ถ”์ฒœ API

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


๐Ÿ” ๋ณด์•ˆ ๊ฐ€์ด๋“œ

โš ๏ธ ์ ˆ๋Œ€ Git ์ปค๋ฐ‹ ๊ธˆ์ง€

.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

๐Ÿณ Docker ์‹คํ–‰

๋ฐฉ๋ฒ• 1: Docker ๊ด€๋ฆฌ ์Šคํฌ๋ฆฝํŠธ ์‚ฌ์šฉ (๊ถŒ์žฅ)

# ์Šคํฌ๋ฆฝํŠธ์— ์‹คํ–‰ ๊ถŒํ•œ ๋ถ€์—ฌ (์ตœ์ดˆ 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 ๊ฐ’๋งŒ ์ˆ˜์ •ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

๋ฐฉ๋ฒ• 2: Docker Compose ์‚ฌ์šฉ

# ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ๋นŒ๋“œ ๋ฐ ์‹œ์ž‘ (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 ์‹œ์ž‘
  • ๋ณผ๋ฅจ: ๋กœ๊ทธ ๋””๋ ‰ํ† ๋ฆฌ๋งŒ ํ˜ธ์ŠคํŠธ์™€ ๊ณต์œ 
  • ๋„คํŠธ์›Œํฌ: ๊ธฐ๋ณธ ๋„คํŠธ์›Œํฌ ์‚ฌ์šฉ (๊ฐ„์†Œํ™”)

๋ฐฉ๋ฒ• 3: ์ง์ ‘ Docker ๋ช…๋ น์–ด ์‚ฌ์šฉ

# 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

๐ŸŒ ์ ‘์† ์ •๋ณด


๐Ÿ”ง ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ ์„ค์ • ์˜ค๋ฒ„๋ผ์ด๋“œ

# ์„œ๋ฒ„ ์„ค์ • ๋ณ€๊ฒฝ
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 ์ตœ์ ํ™”: ๊ฐ„์†Œํ™”๋œ ์‘๋‹ต ํ˜•ํƒœ๋กœ ๋„คํŠธ์›Œํฌ ํŠธ๋ž˜ํ”ฝ ๋ฐ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„ ์ตœ์ ํ™”

๏ฟฝ๏ฟฝ ์„ค์ • ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ํ•ญ๋ชฉ (์ด 40๊ฐœ)

์นดํ…Œ๊ณ ๋ฆฌ ์„ค์ • ํ•ญ๋ชฉ ์ˆ˜ ์ฃผ์š” ์„ค์ •
์•ฑ ์ •๋ณด 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 ํฌํŠธ ๊ณ ์ •)

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages