Files
AutoCoinTrader/docs/code_review_report_v6.md

27 KiB
Raw Permalink Blame History

AutoCoinTrader Code Review Report (v6)

📋 Executive Summary

분석 일자: 2025-12-10 최종 갱신: 2025-12-10 (검토의견 반영) 리뷰 범위: 전체 코드베이스 (14개 핵심 모듈, 15개 테스트 파일, ~6,000줄) 분석 방법론: 다층 심층 분석 (아키텍처/코드품질/성능/트레이딩로직/리스크관리) 리뷰 관점: Python 전문가 + 전문 암호화폐 트레이더 이중 시각

종합 평가: (4.7/5.0)

항목 평가 변화 (v5 대비)
아키텍처 설계 유지
코드 품질 ⬆️ (구문 오류 수정)
동시성 안전성 유지
예외 처리 ⬆️ (구체화 완료)
테스트 커버리지 ⬆️ (79/79 통과)
트레이딩 로직 유지
리스크 관리 유지

주요 개선점 (v5 대비):

  • CRITICAL 구문 오류 2개 해결
  • Exception 처리 구체화 완료
  • Lock 순서 규약 문서화
  • 매직 넘버 상수화 완료
  • 테스트 100% 통과 달성

v6 갱신 사항 (검토의견 반영):

  • ⬆️ CRITICAL-003: 중복 주문 검증 Timestamp 누락 → Critical 등급 상향 (실거래 영향 크므로 최우선 수정 필요)
  • ⬆️ HIGH-001: 순환 import → High 등급 (장기 유지보수성 확보)
  • ⬆️ HIGH-002: 설정 검증 부족 → High 등급 (운영 사고 예방)
  • ⬆️ MEDIUM-004: ThreadPoolExecutor 종료 → Medium 등급 (운영 안정성)
  • OHLCV 캐시 이미 구현 확인 → LOW-004 항목 삭제, 구현 완료로 업데이트

🎯 분석 방법론

다층 분석 프레임워크

┌─────────────────────────────────────────────────┐
│ Layer 1: 아키텍처 & 디자인 패턴               │
├─────────────────────────────────────────────────┤
│ Layer 2: 코드 품질 & 스타일                   │
├─────────────────────────────────────────────────┤
│ Layer 3: 동시성 & 스레드 안전성               │
├─────────────────────────────────────────────────┤
│ Layer 4: 예외 처리 & 회복력                   │
├─────────────────────────────────────────────────┤
│ Layer 5: 성능 & 최적화                        │
├─────────────────────────────────────────────────┤
│ Layer 6: 트레이딩 로직 & 전략                │
├─────────────────────────────────────────────────┤
│ Layer 7: 리스크 관리 & 안전장치              │
└─────────────────────────────────────────────────┘

1. 아키텍처 & 디자인 패턴 분석

1.1 우수한 설계 (Excellent Design)

모듈 분리 원칙 (SRP) 준수

main.py          → 진입점 및 루프 제어
signals.py       → 매수/매도 신호 생성 및 조건 평가
order.py         → 주문 실행 및 모니터링
holdings.py      → 보유 현황 관리
common.py        → 공통 유틸리티 (Rate Limiter, Budget Manager)
config.py        → 설정 관리 및 검증
state_manager.py → 영구 상태 저장 (bot_state.json)

평가: 각 모듈이 명확한 단일 책임을 가지며, 응집도가 높고 결합도가 낮음.


데이터 흐름 아키텍처

graph TD
    A[main.py] -->|매수 신호 체크| B[signals.py]
    B -->|신호 발생| C[order.py]
    C -->|주문 실행| D[holdings.py]
    D -->|상태 저장| E[state_manager.py]

    A -->|매도 조건 체크| B
    B -->|조건 충족| C

    F[common.py] -.->|Rate Limit| C
    F -.->|Budget Mgmt| C
    G[notifications.py] -.->|알림| B
    G -.->|알림| C

평가: 단방향 데이터 흐름이 명확하며, 의존성이 잘 관리됨.


⚠️ 1.2 개선 필요 영역

HIGH-001: 순환 import 잠재 위험

위치: signals.pyorder.py

# signals.py
from .order import execute_buy_order_with_confirmation  # 동적 import
from .order import execute_sell_order_with_confirmation

# order.py
from .holdings import get_current_price  # 정적 import
# order.py는 signals.py를 직접 import하지 않지만, 간접 참조 가능

문제점:

  • _handle_buy_signal() 함수 내에서 동적 import 사용 중
  • 모듈 리팩토링 시 순환 의존성 발생 가능
  • 코드 확장 시 유지보수 복잡도 증가

권장 해결 방안:

# 옵션 1: 의존성 역전 (Dependency Inversion)
# order.py에서 콜백 패턴 사용

# order.py
def execute_buy_order_with_confirmation(
    symbol: str,
    amount_krw: float,
    cfg: RuntimeConfig,
    on_success: Optional[Callable] = None  # 콜백 추가
) -> dict:
    # ... 주문 실행 로직
    if on_success:
        on_success(result)
    return result

# signals.py에서는 콜백 제공
from .order import execute_buy_order_with_confirmation
buy_result = execute_buy_order_with_confirmation(
    symbol, amount_krw, cfg,
    on_success=lambda r: record_trade(...)
)

우선순위: 🔴 High (장기 유지보수성 확보)


HIGH-002: 설정 검증 부족

위치: config.pyvalidate_config()

현재 검증 항목:

  • 필수 키 존재 여부
  • 타입 검증 (일부)
  • 범위 검증 (최소값만)

누락된 검증:

# 누락 1: 상호 의존성 검증
# 예: auto_trade.enabled=True인데 API 키 없음

# 누락 2: 논리적 모순 검증
# 예: stop_loss_interval > profit_taking_interval (손절이 익절보다 느림)

# 누락 3: 위험한 설정 경고
# 예: max_threads > 10 (과도한 스레드)

실제 발생 가능한 운영 사고:

시나리오 1: stop_loss_interval=300 (5시간), profit_taking_interval=60 (1시간)
→ 손실은 5시간마다 체크, 익절은 1시간마다 체크
→ 급락 시 손절이 늦어져 큰 손실 발생 가능

시나리오 2: auto_trade.enabled=true, API 키 없음
→ 봇 실행 후 첫 매수 시점에 런타임 에러 발생
→ 사전 검증 부재로 소중한 매수 기회 놓침

권장 추가 검증:

def validate_config(cfg: dict) -> tuple[bool, str]:
    # ... (기존 검증)

    # 추가 1: Auto Trade 설정 일관성
    auto_trade = cfg.get("auto_trade", {})
    if auto_trade.get("enabled") and auto_trade.get("buy_enabled"):
        if not cfg.get("upbit_access_key") or not cfg.get("upbit_secret_key"):
            return False, "auto_trade 활성화 시 Upbit API 키 필수"

    # 추가 2: 간격 논리 검증
    stop_loss_min = cfg.get("stop_loss_check_interval_minutes", 60)
    profit_min = cfg.get("profit_taking_check_interval_minutes", 240)
    if stop_loss_min > profit_min:
        logger.warning(
            "경고: 손절 주기(%d분)가 익절 주기(%d분)보다 김. "
            "손절은 더 자주 체크하는 것이 안전합니다.",
            stop_loss_min, profit_min
        )

    # 추가 3: 스레드 수 검증
    max_threads = cfg.get("max_threads", 3)
    if max_threads > 10:
        logger.warning(
            "경고: max_threads=%d는 과도할 수 있음. "
            "Upbit API Rate Limit(초당 8회, 분당 590회) 고려 필요",
            max_threads
        )

    return True, ""

우선순위: 🔴 High (운영 사고 예방)


2. 코드 품질 & 스타일 분석

2.1 우수한 점

타입 힌팅 (Type Hinting) - 98%+ 커버리지

# 모든 공개 함수에 타입 힌팅 적용
def evaluate_sell_conditions(
    current_price: float,
    buy_price: float,
    max_price: float,
    holding_info: dict,
    config: dict = None
) -> dict:

평가: 산업 표준 수준의 타입 안전성 확보.


Docstring 품질 (Google Style)

def get_upbit_balances(cfg: RuntimeConfig) -> dict | None:
    """
    Upbit API를 통해 현재 잔고를 조회합니다.

    Args:
        cfg: RuntimeConfig 객체 (Upbit API 키 포함)

    Returns:
        심볼별 잔고 딕셔너리 (예: {"BTC": 0.5, "ETH": 10.0})
        - MIN_TRADE_AMOUNT (1e-8) 이하의 자산은 제외됨
        - API 키 미설정 시 빈 딕셔너리 {} 반환
        - 네트워크 오류 시 None 반환

    Raises:
        Exception: Upbit API 호출 중 발생한 예외는 로깅되고 None 반환
    """

평가: 명확한 문서화로 유지보수성 우수.


⚠️ 2.2 개선 필요 영역

LOW-001: 일관성 없는 로그 레벨 사용

문제점: 동일한 유형의 이벤트에 다른 로그 레벨 사용

# signals.py
logger.info("[%s] 매수 신호 발생", symbol)  # INFO
logger.debug("[%s] 재매수 대기 중", symbol)  # DEBUG

# order.py
logger.warning("[매수 건너뜀] %s", reason)  # WARNING
logger.info("[매수 성공] %s", symbol)  # INFO

권장 로그 레벨 가이드라인:

"""
DEBUG   : 개발자용 상세 흐름 추적
INFO    : 정상 작동 중요 이벤트 (매수/매도 성공)
WARNING : 주의 필요 (잔고 부족, 재매수 쿨다운)
ERROR   : 오류 발생 (API 실패, 설정 오류)
CRITICAL: 시스템 중단 위험 (Circuit Breaker Open)
"""

# 권장 수정
logger.warning("[%s] 재매수 대기 중 (%d시간 쿨다운)", symbol, hours)
logger.error("[매수 실패] %s: API 오류", symbol)

우선순위: 🟢 Low


LOW-002: f-string vs % 포매팅 혼재

# 혼재 사용
logger.info(f"[{symbol}] 매수 금액: {amount}원")  # f-string
logger.info("[%s] 매도 금액: %d원", symbol, amount)  # % 포매팅

권장: logging 라이브러리는 % 포매팅을 권장 (lazy evaluation)

# 권장: % 포매팅 (로그가 출력되지 않으면 포매팅 생략)
logger.debug("[%s] 상세 정보: 가격=%f, 수량=%f", symbol, price, volume)

# f-string은 조건부 로그에만 사용
if condition:
    msg = f"복잡한 {계산} 포함된 {메시지}"
    logger.info(msg)

우선순위: 🟢 Low


3. 동시성 & 스레드 안전성 분석

3.1 우수한 점 (Best in Class)

리소스별 Lock 분리

# 완벽한 Lock 분리로 경합 최소화
holdings_lock       # holdings.json 보호
_state_lock         # bot_state.json 보호
_cache_lock         # 가격/잔고 캐시 보호
_pending_order_lock # 대기 주문 보호
krw_balance_lock    # KRW 잔고 조회 직렬화
recent_sells_lock   # recent_sells.json 보호

평가: 산업 표준을 초과하는 설계. 각 리소스가 독립적인 Lock으로 보호됨.


Lock 획득 순서 규약 문서화

# common.py (라인 93-105)
# ============================================================================
# Lock 획득 순서 규약 (데드락 방지)
# ============================================================================
# 1. holdings_lock (최우선)
# 2. _state_lock
# 3. krw_balance_lock
# 4. recent_sells_lock
# 5. _cache_lock, _pending_order_lock (개별 리소스, 독립적)

평가: 데드락 방지를 위한 명확한 규약 문서화. 엔터프라이즈급 품질.


KRWBudgetManager - 토큰 기반 예산 관리

class KRWBudgetManager:
    """
    - 고유 토큰으로 각 주문 구분
    - 동일 심볼 다중 주문 안전 지원
    - Race Condition 완벽 차단
    """
    def allocate(self, symbol, amount_krw, upbit=None, ...) -> tuple[bool, float, str]:
        token = secrets.token_hex(8)  # 고유 토큰 생성
        # ...

평가: 복잡한 동시성 문제를 우아하게 해결. Google/Meta 수준의 설계.


⚠️ 3.2 개선 여지

MEDIUM-004: ThreadPoolExecutor 종료 처리

위치: threading_utils.py

현재 코드:

def run_with_threads(symbols, cfg, aggregate_enabled=False):
    with ThreadPoolExecutor(max_workers=workers) as executor:
        # ... 작업 실행
    # with 블록 종료 시 자동 shutdown(wait=True)

잠재적 문제:

  • SIGTERM 수신 시 진행 중인 스레드가 완료될 때까지 대기
  • 최악의 경우 5분 이상 종료 지연 가능 (fetch_ohlcv 타임아웃 × 스레드 수)
  • Docker 컨테이너 재시작 시 종료 지연으로 인한 불편함

실제 시나리오:

1. 사용자가 docker stop 실행 (SIGTERM 전송)
2. 8개 스레드가 각각 API 호출 중 (최대 300초 타임아웃)
3. 모든 스레드 완료까지 최대 5분 대기
4. Docker가 10초 후 SIGKILL 전송 → 강제 종료
5. 진행 중인 주문 데이터 손실 가능성

권장 개선:

# 전역 종료 플래그 활용
_shutdown_requested = False

def run_with_threads(symbols, cfg, aggregate_enabled=False):
    with ThreadPoolExecutor(max_workers=workers) as executor:
        futures = []
        for symbol in symbols:
            if _shutdown_requested:  # 조기 종료
                break
            future = executor.submit(process_symbol, symbol, cfg=cfg)
            futures.append(future)

        # 타임아웃 기반 종료
        for future in as_completed(futures, timeout=60):
            if _shutdown_requested:
                break
            try:
                future.result(timeout=10)
            except TimeoutError:
                logger.warning("스레드 타임아웃, 강제 종료")

우선순위: 🟡 Medium (운영 환경 안정성)


4. 예외 처리 & 회복력 분석

4.1 우수한 점

구체적 예외 처리 (v5 개선 완료)

# holdings.py (v5 개선)
except json.JSONDecodeError as e:
    logger.error("[ERROR] JSON 디코드 실패: %s", e)
except OSError as e:
    logger.exception("[ERROR] 입출력 예외: %s", e)
    raise

# order.py (v5 개선)
except (requests.exceptions.RequestException, ValueError, TypeError, OSError) as e:
    logger.error("[매도 실패] 예외 발생: %s", e)

평가: 구체적 예외 처리로 버그 은폐 방지. 엔터프라이즈급 품질.


Circuit Breaker 패턴

class CircuitBreaker:
    STATES = ["closed", "open", "half_open"]
    # 연속 3회 실패 → 5분 차단 → 점진적 복구

평가: 마이크로서비스 아키텍처 수준의 회복력 메커니즘.


ReadTimeout 복구 로직

# order.py
except requests.exceptions.ReadTimeout:
    # 1단계: 중복 주문 확인
    is_dup, dup_order = _has_duplicate_pending_order(...)
    if is_dup:
        return dup_order

    # 2단계: 최근 주문 조회
    found = _find_recent_order(...)
    if found:
        return found

평가: 네트워크 불안정 환경에서도 안정적 작동. 실전 경험 기반 설계.


⚠️ 4.2 개선 필요 영역

CRITICAL-003: 중복 주문 검증의 Timestamp 누락 (매우 중요)

위치: order.py_has_duplicate_pending_order()

현재 로직:

# 수량/가격만으로 중복 판단
if abs(order_vol - volume) < 1e-8:
    if price is None or abs(order_price - price) < 1e-4:
        return True, order

문제점:

  1. 동일 수량/가격의 서로 다른 주문 구분 불가
    • 예: 10초 간격으로 동일 금액 매수 시 두 번째 주문이 중복으로 오판
  2. Timestamp 기반 검증 없음
    • 과거 완료된 주문(done)을 현재 진행 중인 주문으로 오판
    • 1분 전 주문과 방금 주문을 구분 못함

심각도 평가:

  • 🔴 실거래 영향: 정상적인 재매수 기회를 차단하여 수익 기회 손실
  • 🔴 발생 빈도: 동일 금액 매수 설정 시 높은 확률로 발생
  • 🔴 디버깅 난이도: 로그에서 "중복 주문 감지"로만 표시되어 원인 파악 어려움

실제 발생 가능 시나리오:

1. 14:00:00 - BTC 50,000원 매수 주문 (타임아웃)
2. 14:00:05 - 재시도 로직으로 동일 주문 발견 → 중복 판단 (✅ 정상)
3. 14:00:10 - 주문 체결 완료 (state="done")
4. 14:05:00 - 매수 신호 재발생, 동일 금액 매수 시도
5. 14:05:01 - 5분 전 "완료된 주문"을 중복으로 오판 → 매수 차단 (❌ 치명적 버그)

권장 해결 방안:

def _has_duplicate_pending_order(
    upbit, market, side, volume, price=None,
    lookback_sec=120  # 2분 이내만 검사
):
    """중복 주문 확인 (시간 제한 추가)"""
    now = time.time()

    try:
        orders = upbit.get_orders(ticker=market, state="wait")
        if orders:
            for order in orders:
                # 시간 필터 추가
                order_time = order.get("created_at")  # ISO 8601 형식
                if order_time:
                    order_ts = datetime.fromisoformat(order_time.replace('Z', '+00:00')).timestamp()
                    if (now - order_ts) > lookback_sec:
                        continue  # 오래된 주문은 건너뜀

                # 기존 수량/가격 검증
                if order.get("side") != side:
                    continue
                if abs(float(order.get("volume")) - volume) < 1e-8:
                    if price is None or abs(float(order.get("price")) - price) < 1e-4:
                        logger.info(
                            "[중복 감지] %.1f초 전 주문: %s",
                            now - order_ts, order.get("uuid")
                        )
                        return True, order

        # Done orders도 시간 제한 적용
        dones = upbit.get_orders(ticker=market, state="done", limit=5)
        # ... (동일한 시간 필터 적용)
    except Exception as e:
        logger.warning("[중복 검사] 오류: %s", e)

    return False, None

우선순위: 🔴 Critical (즉시 수정 필요, 실거래 수익 손실 직결)


5. 성능 & 최적화 분석

5.1 우수한 점

캐시 전략

# 2초 TTL 캐시로 API 호출 최소화
_price_cache: dict[str, tuple[float, float]] = {}
_balance_cache: tuple[dict | None, float] = ({}, 0.0)

PRICE_CACHE_TTL = 2.0
BALANCE_CACHE_TTL = 2.0

효과:

  • API 호출 80% 감소 (추정)
  • Rate Limit 여유 확보

Rate Limiter (Token Bucket)

api_rate_limiter = RateLimiter(
    max_calls=8,          # 초당 8회
    period=1.0,
    additional_limits=[(590, 60.0)]  # 분당 590회
)

평가: Upbit API 제한(초당 10회, 분당 600회)을 완벽하게 준수.


⚠️ 5.2 개선 여지

캐시 전략 검증 결과

위치: indicators.pyfetch_ohlcv()

검증 결과: OHLCV 캐싱 이미 구현됨

# src/indicators.py 라인 21-66
_ohlcv_cache = {}  # 이미 존재
CACHE_TTL = 240.0  # 4분 TTL

def fetch_ohlcv(ticker, interval, count, use_cache=True):
    cache_key = f"{ticker}_{interval}_{count}"

    # 캐시 확인
    if use_cache and cache_key in _ohlcv_cache:
        cached_df, cached_time = _ohlcv_cache[cache_key]
        if time.time() - cached_time < CACHE_TTL:
            return cached_df.copy()

    # API 호출 및 캐시 저장
    # ...

평가:

  • 캐시 키 설계 우수 (ticker + interval + count)
  • TTL 설정 적절 (4분)
  • 복사본 반환으로 원본 보호
  • 만료된 캐시 자동 정리 (_cleanup_ohlcv_cache())

결론: 이 항목은 이미 적용되어 있으므로 추가 작업 불필요


8. 테스트 분석

8.1 우수한 점

테스트 커버리지: 79/79 통과 (100%)

테스트 종류 파일 수 커버리지
단위 테스트 15개 핵심 기능
통합 테스트 3개 동시성, 상태 동기화
경계값 테스트 1개 손익 경계
스트레스 테스트 2개 10 스레드

평가: 산업 표준을 초과하는 테스트 품질.


⚠️ 8.2 개선 여지

MEDIUM-006: End-to-End 테스트 부재

누락된 시나리오:

# 전체 플로우 테스트 (매수 → 보유 → 매도)
def test_full_trading_cycle():
    """
    1. 매수 신호 발생
    2. 매수 주문 실행
    3. holdings.json 업데이트
    4. max_price 추적
    5. 익절 조건 발생
    6. 부분 매도 (50%)
    7. 트레일링 스탑 발동
    8. 전량 매도
    9. recent_sells 기록
    10. 재매수 방지 확인
    """
    # Mock을 최소화하고 실제 플로우 검증

우선순위: 🟡 Medium


9. 보안 분석

9.1 우수한 점

# 1. API 키 환경변수 관리
upbit_access_key = os.getenv("UPBIT_ACCESS_KEY")

# 2. 파일 권한 설정 (rw-------)
os.chmod(holdings_file, stat.S_IRUSR | stat.S_IWUSR)

# 3. 민감 정보 로그 제외
logger.info("API 키 유효성 확인 완료")  # 키 값 노출 안 함

# 4. 토큰 기반 주문 확인
token = secrets.token_hex(16)  # 추측 불가능한 토큰

평가: 기본적인 보안 수준 충족.


⚠️ 9.2 개선 필요 영역

LOW-005: API 키 검증 강화

현재:

# 단순 잔고 조회로 검증
balances = upbit.get_balances()

권장:

def validate_upbit_api_keys_enhanced(access_key, secret_key):
    """강화된 API 키 검증"""
    try:
        upbit = pyupbit.Upbit(access_key, secret_key)

        # 1. 잔고 조회 (읽기 권한)
        balances = upbit.get_balances()

        # 2. 주문 가능 여부 확인 (쓰기 권한)
        # Dry run 주문 시도 (실제 주문 안 됨)
        try:
            # 최소 금액으로 테스트 주문 (실패해도 OK)
            upbit.buy_limit_order("KRW-BTC", 1000000, 0.00000001)
        except Exception as e:
            error_msg = str(e)
            if "insufficient" in error_msg.lower():
                # 잔고 부족 = 주문 권한 있음
                pass
            elif "invalid" in error_msg.lower():
                return False, "주문 권한 없는 API 키"

        # 3. IP 화이트리스트 확인 (선택)
        # ...

        return True, "OK"
    except Exception as e:
        return False, str(e)

우선순위: 🟢 Low


10. 문서화 분석

10.1 우수한 점

docs/
├── project_requirements.md    # 기획서
├── implementation_plan.md     # 구현 체크리스트
├── user_guide.md             # 사용자 가이드
├── project_state.md          # 현재 상태
└── code_review_report_v*.md  # 리뷰 기록 (v1~v6)

평가: 포괄적인 문서화로 유지보수성 우수.


⚠️ 10.2 개선 필요 영역

LOW-006: API 문서 부재

권장 추가:

# docs/api_reference.md

## 핵심 함수 레퍼런스

### order.py

#### place_buy_order_upbit()
**목적**: 매수 주문 실행
**파라미터**:
- market (str): 마켓 코드 (예: "KRW-BTC")
- amount_krw (float): 매수 금액 (KRW)
- cfg (RuntimeConfig): 설정 객체

**반환값**: dict
- status: "filled" | "partial" | "failed" | ...
- uuid: 주문 ID
- ...

**예외**:
- ValueError: 금액이 최소 주문 금액 미만
- ...

**예제**:
```python
result = place_buy_order_upbit("KRW-BTC", 50000, cfg)
if result["status"] == "filled":
    print("매수 성공")

**우선순위**: 🟢 Low

---
# code_review_report_v6 최종 ?<3F><20>??<3F>선?<3F>위 로드<EBA19C>?

## ?<3F><> 개선 권고?<3F>항 ?<3F>선?<3F>위

### ?<3F><> CRITICAL (즉시 ?<3F>정 ?<3F>요)
| ID | ??<3F><> | ?<3F>향??| ?<3F>상 ?<3F>업 ?<3F>간 |
|----|------|--------|---------------|
| **CRITICAL-003** | 중복 주문 검<>?Timestamp ?<3F>락 | ?<3F>거???<3F>익 ?<3F>실 | 2?<3F>간 |

**권장 ?<3F>업 ?<3F>서**:
1. `order.py`??`_has_duplicate_pending_order()` ?<3F>수??`lookback_sec=120` ?<3F>라미터 추<>?
2. Timestamp 비교 로직 구현 (created_at ?<3F>드 ?<3F>싱)
3. ?<3F>스??케?<3F>스 추<>? (?<3F>간 경계 케?<3F>스)
4. ?<3F>제 거래 ??Dry-run 검<>?

---

### ?<3F><> HIGH (?<3F>기 ??개선 권장)
| ID | ??<3F><> | ?<3F>향??| ?<3F>상 ?<3F>업 ?<3F>간 |
|----|------|--------|---------------|
| **HIGH-001** | ?<3F>환 import ?<3F>재 ?<3F>험 | ?<3F>기 ?<3F><>?보수??| 4?<3F>간 |
| **HIGH-002** | ?<3F>정 검<>?부<>?| ?<3F>영 ?<3F>고 ?<3F>방 | 2?<3F>간 |

**권장 ?<3F>근**:
- HIGH-001: ?<3F>존????<3F><> ?<3F>턴 ?<3F>용, 콜백 기반 ?<3F><EFBFBD>?리팩?<3F>링
- HIGH-002: `validate_config()` 강화, ?<3F>호 ?<3F>존???<3F>리??모순 검<>?추<>?

---

### ?<3F><> MEDIUM (중기 개선 ??<3F><>)
| ID | ??<3F><> | ?<3F>향??| ?<3F>상 ?<3F>업 ?<3F>간 |
|----|------|--------|---------------|
| **MEDIUM-004** | ThreadPoolExecutor 종료 처리 | ?<3F>영 ?<3F>정??| 3?<3F>간 |
| **MEDIUM-006** | End-to-End ?<3F>스??부??| ?<3F><>? ?<3F>스??| 6?<3F>간 |

**권장 ?<3F>근**:
- MEDIUM-004: Signal handler 추<>?, graceful shutdown 구현
- MEDIUM-006: ?<3F>체 거래 ?<3F>로???<3F>합 ?<3F>스???<3F>성

---

### ?<3F><> LOW (?<3F>기 개선 ??<3F><>)
| ID | ??<3F><> | ?<3F>향??| ?<3F>상 ?<3F>업 ?<3F>간 |
|----|------|--------|---------------|
| **LOW-001** | 로그 ?<3F>벨 ?<3F><>???| ?<3F><EFBFBD>??<3F>율 | 1?<3F>간 |
| **LOW-002** | f-string vs % ?<3F>매???<3F>일 | 코드 ?<3F><>???| 1?<3F>간 |
| **LOW-005** | API ??검<>?강화 | 보안 | 2?<3F>간 |
| **LOW-006** | API 문서 ?<3F>성 | 개발 ?<3F>산??| 4?<3F>간 |

---

## ?<3F><><>??<3F>료 ??<3F><>

| ??<3F><> | ?<3F>태 | 비고 |
|------|------|------|
| **OHLCV 캐시** | ??구현 ?<3F>료 | `indicators.py`???<3F><>? ?<3F>용??(TTL 240<34>? |
| **v5 개선?<3F>항** | ??모두 ?<3F>용 | CRITICAL-001, CRITICAL-002, HIGH-001, MEDIUM-001, MEDIUM-002 |

---

## ?? 3?<3F>계 ?<3F>행 계획

### Phase 1: 긴급 (1주일)
  1. CRITICAL-003 ?<3F>정 (2h)
  2. HIGH-002 구현 (2h)
  3. ?<3F><>? ?<3F>스??(1h) <0A>??<3F>요: 5?<3F>

### Phase 2: ?<3F>기 (2주일)
  1. HIGH-001 리팩?<3F>링 (4h)
  2. MEDIUM-004 개선 (3h)
  3. ?<3F>합 ?<3F>스??(2h) <0A>??<3F>요: 9?<3F>

### Phase 3: 중장<ECA491>?(1개월)
  1. MEDIUM-006 E2E ?<3F>스??(6h)
  2. LOW ??<3F><> ?<3F>괄 처리 (8h)
  3. 문서??(4h) <0A>??<3F>요: 18?<3F>

---

## ?<3F><> ?<3F>심 ?<3F>찰

1. **?<3F>키?<3F>처 ?<3F>수??*: 모듈 분리, ?<3F>시???<3F>계??Google/Meta ?<3F><>?
2. **?<3F>전 검<>??<3F>요**: CRITICAL-003?<3F> ?<3F>거??직전 반드???<3F>정
3. **기술 부<>?관<>?*: HIGH/MEDIUM ??<3F><>?<3F> 코드 ?<3F>장 ???<3F>결 권장
4. **지?<3F>적 개선**: ??? ?<3F>선?<3F>위 ??<3F><>???<3F>진??개선?<3F>로 ?<3F>질 ?<3F>상

---

## 변<>??<3F>력

**v6.1 (2025-12-10)**:
- 검?<3F><EFBFBD>?반영: CRITICAL-003 ?<3F>급 ?<3F>향 (Medium ??Critical)
- HIGH-001, HIGH-002 ?<3F>급 ?<3F>향 (Medium ??High)
- MEDIUM-004 ?<3F>급 ?<3F>향 (Low ??Medium)
- OHLCV 캐시 구현 ?<3F>인 ?<3F>료, LOW-004 ??<3F><>
- ?<3F>선?<3F>위 로드<EBA19C>?<3F>?3?<3F>계 ?<3F>행 계획 추<>?

**v6.0 (2025-12-10)**:
- 최초 ?<3F>성: 7계층 ?<3F>층 분석 ?<3F>레?<3F>워???<3F>용
- 11<31>?개선 ??<3F><> ?<3F>출 (CRITICAL 1, HIGH 2, MEDIUM 2, LOW 6)
- v5 개선?<3F>항 검<>??<3F>료 (5/5 ??<3F><>)