콘텐츠로 이동

개발 가이드

이 가이드는 Continuum Router 프로젝트의 개발 설정, 아키텍처, 테스트 및 기여 가이드라인을 다룹니다.

목차

사전 요구 사항

필수 도구

  • Rust: 1.75 이상 (Rust 설치)
  • Git: 버전 관리용
  • C 컴파일러: gcc, clang, 또는 MSVC (네이티브 의존성용)

권장 도구

  • cargo-watch: 개발 중 자동 재컴파일
  • cargo-edit: 의존성 관리
  • cargo-audit: 보안 취약점 검사
  • cargo-flamegraph: 성능 프로파일링
  • rust-analyzer: IDE 지원 (VS Code, IntelliJ, vim/neovim)

개발 도구 설치

# 필수 개발 도구 설치
cargo install cargo-watch cargo-edit cargo-audit cargo-flamegraph

# 코드 커버리지 도구 설치
cargo install cargo-tarpaulin

# 벤치마킹 도구 설치
cargo install cargo-criterion

개발 설정

복제 및 설정

# 저장소 복제
git clone https://github.com/lablup/continuum-router.git
cd continuum-router

# 컴파일 확인
cargo check

# 초기 테스트 스위트 실행
cargo test

# 개발 버전 빌드
cargo build

IDE 설정

VS Code

  1. rust-analyzer 확장 설치
  2. 디버깅을 위해 CodeLLDB 확장 설치
  3. 제공된 .vscode/settings.json 사용:
{
  "rust-analyzer.cargo.features": "all",
  "rust-analyzer.checkOnSave.command": "clippy",
  "editor.formatOnSave": true,
  "[rust]": {
    "editor.defaultFormatter": "rust-lang.rust-analyzer"
  }
}

IntelliJ IDEA / CLion

  1. Rust 플러그인 설치
  2. 프로젝트 루트 열기
  3. Preferences → Build → Cargo에서 Cargo 설정 구성

Vim/Neovim

  1. Mason 또는 수동으로 rust-analyzer 설치
  2. LSP 클라이언트 구성 (nvim-lspconfig, coc.nvim 등)
  3. nvim-lspconfig 설정 예제:
require('lspconfig').rust_analyzer.setup({
  settings = {
    ["rust-analyzer"] = {
      cargo = { features = "all" },
      checkOnSave = { command = "clippy" }
    }
  }
})

프로젝트 구조

계층 아키텍처

프로젝트는 깔끔한 4계층 아키텍처를 따릅니다:

┌─────────────────────────────────┐
│         HTTP Layer              │  ← Routes, Middleware, DTOs
├─────────────────────────────────┤
│       Services Layer            │  ← 비즈니스 로직, 오케스트레이션
├─────────────────────────────────┤
│    Infrastructure Layer         │  ← Backends, Cache, HTTP Client
├─────────────────────────────────┤
│         Core Layer              │  ← 도메인 모델, Traits, Errors
└─────────────────────────────────┘

디렉토리 구조

src/
├── main.rs                 # 애플리케이션 진입점 및 CLI
├── lib.rs                  # 라이브러리 익스포트 및 모듈 선언
├── core/                   # 핵심 도메인 계층 (외부 의존성 없음)
│   ├── mod.rs             # Core 모듈 익스포트
│   ├── models/            # 도메인 모델
│   │   ├── backend.rs     # 백엔드 설정 및 상태
│   │   ├── model.rs       # LLM 모델 표현
│   │   ├── request.rs     # 요청/응답 모델
│   │   └── health.rs      # 헬스 체크 모델
│   ├── errors.rs          # 오류 타입 및 처리
│   ├── traits.rs          # 도메인 트레이트 및 인터페이스
│   ├── retry/             # 재시도 로직 및 정책
│   │   ├── policy.rs      # 재시도 정책
│   │   └── backoff.rs     # 백오프 전략
│   └── config/            # 설정 모델
│       ├── mod.rs         # Config 모듈 익스포트
│       ├── models.rs      # 설정 구조체
│       └── validation.rs  # 설정 유효성 검사 로직
├── services/              # 비즈니스 로직 계층
│   ├── mod.rs            # 서비스 레지스트리 및 DI 컨테이너
│   ├── backend_service.rs    # 백엔드 관리 및 선택
│   ├── model_service.rs      # 모델 집계 및 캐싱
│   ├── proxy_service.rs      # 요청 라우팅 및 프록시
│   ├── health_service.rs     # 헬스 모니터링
│   └── streaming/        # SSE 스트리밍 지원
│       ├── mod.rs        # Streaming 모듈 익스포트
│       ├── parser.rs     # SSE 이벤트 파싱
│       └── handler.rs    # 스트림 처리 로직
├── infrastructure/        # 외부 통합 계층
│   ├── mod.rs            # Infrastructure 익스포트
│   ├── backends/         # 백엔드 클라이언트 구현
│   │   ├── mod.rs        # 백엔드 트레이트 및 팩토리
│   │   ├── openai.rs     # OpenAI 호환 백엔드
│   │   ├── ollama.rs     # Ollama 백엔드
│   │   └── vllm.rs       # vLLM 백엔드
│   ├── cache/            # 캐싱 구현
│   │   ├── mod.rs        # 캐시 트레이트
│   │   ├── lru.rs        # LRU 캐시
│   │   └── ttl.rs        # TTL 기반 캐시
│   ├── config/           # 설정 로딩
│   │   ├── loader.rs     # 설정 파일 로딩
│   │   └── watcher.rs    # 핫 리로드 지원
│   └── http_client.rs    # 풀링이 있는 HTTP 클라이언트
├── http/                  # HTTP 계층
│   ├── mod.rs            # HTTP 모듈 익스포트
│   ├── routes.rs         # 라우트 정의
│   ├── handlers/         # 요청 핸들러
│   │   ├── chat.rs       # 채팅 완료 엔드포인트
│   │   ├── models.rs     # 모델 목록 엔드포인트
│   │   ├── health.rs     # 헬스 체크 엔드포인트
│   │   └── admin.rs      # 관리자 엔드포인트
│   ├── middleware/       # HTTP 미들웨어
│   │   ├── auth.rs       # 인증
│   │   ├── logging.rs    # 요청 로깅
│   │   ├── metrics.rs    # 메트릭 수집
│   │   └── error.rs      # 오류 처리
│   └── dto/              # Data Transfer Objects
│       ├── request.rs    # 요청 DTO
│       └── response.rs   # 응답 DTO
└── metrics/              # 메트릭 및 모니터링
    ├── mod.rs            # Metrics 모듈 익스포트
    ├── backend.rs        # 백엔드별 메트릭
    ├── routing.rs        # 라우팅 메트릭
    ├── model.rs          # 모델 서비스 메트릭
    └── streaming.rs      # 스트리밍 메트릭

tests/
├── integration/          # 통합 테스트
│   ├── health_test.rs    # 헬스 엔드포인트 테스트
│   ├── chat_test.rs      # 채팅 완료 테스트
│   ├── models_test.rs    # 모델 목록 테스트
│   └── routing_test.rs   # 라우팅 로직 테스트
├── unit/                 # 단위 테스트
│   ├── core/            # Core 계층 테스트
│   ├── services/        # Service 계층 테스트
│   └── infrastructure/  # Infrastructure 테스트
└── common/              # 테스트 유틸리티
    ├── fixtures.rs      # 테스트 픽스처
    ├── mocks.rs         # 모킹 구현
    └── helpers.rs       # 테스트 헬퍼 함수

아키텍처 개요

의존성 흐름

HTTP Layer → Services Layer → Infrastructure Layer → Core Layer
     ↓            ↓                ↓                    ↑
     └────────────┴────────────────┴────────────────────┘
                        Core 타입 사용

주요 디자인 패턴

  1. 의존성 주입: 서비스가 컨테이너를 통해 주입됨
  2. 리포지토리 패턴: 백엔드 구현이 데이터 접근을 추상화
  3. 전략 패턴: 로드 밸런싱 전략이 플러그 가능
  4. 옵저버 패턴: 헬스 모니터링이 이벤트 기반 업데이트 사용
  5. 서킷 브레이커: 연쇄 장애 방지
  6. 백오프와 재시도: 일시적 실패 처리

빌드 및 실행

개발 빌드

# 빠른 개발 빌드
cargo build

# 디버그 출력과 함께 실행
RUST_LOG=debug ./target/debug/continuum-router

# 자동 리로드와 함께 실행
cargo watch -x run

# 특정 설정과 함께 실행
cargo run -- --config dev-config.yaml

릴리스 빌드

# 최적화된 릴리스 빌드
cargo build --release

# 릴리스 빌드 실행
./target/release/continuum-router

# 특정 기능과 함께 빌드
cargo build --release --features "metrics,tracing"

크로스 컴파일

# cross 설치
cargo install cross

# Linux x86_64용 빌드
cross build --release --target x86_64-unknown-linux-gnu

# macOS ARM64용 빌드
cross build --release --target aarch64-apple-darwin

# Windows용 빌드
cross build --release --target x86_64-pc-windows-gnu

테스트

테스트 실행

# 모든 테스트 실행
cargo test

# 출력과 함께 실행
cargo test -- --nocapture

# 특정 테스트 실행
cargo test test_health_check

# 단일 스레드로 테스트 실행 (디버깅용)
cargo test -- --test-threads=1

# 통합 테스트만 실행
cargo test --test integration

# 단위 테스트만 실행
cargo test --lib

# 문서 테스트 실행
cargo test --doc

테스트 작성

단위 테스트 예제

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_backend_selection() {
        let backends = vec![
            Backend::new("backend1", "http://localhost:8000"),
            Backend::new("backend2", "http://localhost:8001"),
        ];

        let selector = RoundRobinSelector::new(backends);
        let selected = selector.select().unwrap();

        assert_eq!(selected.name(), "backend1");
    }

    #[tokio::test]
    async fn test_async_health_check() {
        let backend = Backend::new("test", "http://localhost:8000");
        let result = backend.health_check().await;

        assert!(result.is_ok());
    }
}

통합 테스트 예제

// tests/integration/chat_test.rs
use continuum_router::test_utils::TestServer;

#[tokio::test]
async fn test_chat_completion() {
    let server = TestServer::new().await;

    let response = server
        .post("/v1/chat/completions")
        .json(&json!({
            "model": "gpt-3.5-turbo",
            "messages": [{"role": "user", "content": "Hello"}]
        }))
        .send()
        .await;

    assert_eq!(response.status(), 200);
}

테스트 커버리지

# 커버리지 리포트 생성
cargo tarpaulin --out Html

# 특정 임계값과 함께 커버리지 생성
cargo tarpaulin --fail-under 80

# Codecov 리포트 생성
cargo tarpaulin --out Xml

코드 품질

포매팅

# 모든 코드 포맷
cargo fmt

# 변경 없이 포매팅 확인
cargo fmt -- --check

# 특정 파일 포맷
cargo fmt -- src/main.rs

린팅

# 경고를 오류로 처리하여 clippy 실행
cargo clippy -- -D warnings

# pedantic 린트와 함께 clippy 실행
cargo clippy -- -W clippy::pedantic

# 자동 수정과 함께 clippy 실행
cargo clippy --fix

보안 감사

# 알려진 취약점 확인
cargo audit

# 취약한 의존성 수정
cargo audit fix

# 보안 리포트 생성
cargo audit --json > audit-report.json

문서화

# 문서 빌드
cargo doc

# 문서 빌드 및 열기
cargo doc --open

# 비공개 항목 포함하여 문서 빌드
cargo doc --document-private-items

# 문서 예제 확인
cargo test --doc

디버깅

디버그 로깅

# 디버그 로깅 활성화
RUST_LOG=debug cargo run

# 특정 모듈에 대해 trace 로깅 활성화
RUST_LOG=continuum_router::services=trace cargo run

# 구조화된 로깅 활성화
RUST_LOG=info RUST_LOG_FORMAT=json cargo run

디버거 사용

VS Code

  1. .vscode/launch.json 생성:
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "lldb",
      "request": "launch",
      "name": "Debug Router",
      "cargo": {
        "args": ["build", "--bin=continuum-router"],
        "filter": {
          "name": "continuum-router",
          "kind": "bin"
        }
      },
      "args": ["--config", "dev-config.yaml"],
      "cwd": "${workspaceFolder}"
    }
  ]
}
  1. 브레이크포인트 설정 후 F5 눌러 디버그

명령줄 (lldb)

# 디버그 심볼과 함께 빌드
cargo build

# lldb로 실행
lldb target/debug/continuum-router

# 브레이크포인트 설정
(lldb) b src/main.rs:50

# 프로그램 실행
(lldb) r --config config.yaml

메모리 디버깅

# valgrind 사용 (Linux)
valgrind --leak-check=full ./target/debug/continuum-router

# Address Sanitizer 사용
RUSTFLAGS="-Z sanitizer=address" cargo build -Z build-std --target x86_64-unknown-linux-gnu
./target/x86_64-unknown-linux-gnu/debug/continuum-router

성능 프로파일링

CPU 프로파일링

# 플레임 그래프 생성
cargo flamegraph -- --config config.yaml

# 특정 시나리오 프로파일
cargo flamegraph --bin continuum-router -- --benchmark

# perf 사용 (Linux)
perf record -g ./target/release/continuum-router
perf report

벤치마킹

# 벤치마크 실행
cargo bench

# 특정 벤치마크 실행
cargo bench routing

# 벤치마크 결과 비교
cargo bench -- --save-baseline main
git checkout feature-branch
cargo bench -- --baseline main

벤치마크 작성

// benches/routing_bench.rs
use criterion::{black_box, criterion_group, criterion_main, Criterion};

fn benchmark_routing(c: &mut Criterion) {
    c.bench_function("round_robin_selection", |b| {
        let selector = RoundRobinSelector::new(backends);
        b.iter(|| {
            selector.select(black_box(&request))
        });
    });
}

criterion_group!(benches, benchmark_routing);
criterion_main!(benches);

메모리 프로파일링

# heaptrack 사용 (Linux)
heaptrack ./target/release/continuum-router
heaptrack_gui heaptrack.continuum-router.*.gz

# Instruments 사용 (macOS)
cargo instruments -t Allocations

기여하기

개발 워크플로우

  1. Fork 및 Clone

    git clone https://github.com/YOUR_USERNAME/continuum-router.git
    cd continuum-router
    

  2. Feature 브랜치 생성

    git checkout -b feature/amazing-feature
    

  3. 변경 사항 작성

  4. Rust 규칙을 따르는 코드 작성
  5. 새 기능에 대한 테스트 추가
  6. 문서 업데이트

  7. 변경 사항 테스트

    cargo test
    cargo fmt
    cargo clippy -- -D warnings
    

  8. 변경 사항 커밋

    git add .
    git commit -m "feat: Add amazing feature"
    

  9. Push 및 PR 생성

    git push origin feature/amazing-feature
    

코드 표준

  • Rust 명명 규칙 준수 (함수는 snake_case, 타입은 CamelCase)
  • 포괄적인 테스트 작성 (커버리지 >90% 목표)
  • 공개 API에 doc 주석으로 문서화
  • 일관된 포매팅을 위해 cargo fmt 사용
  • 모든 cargo clippy 경고 해결
  • 함수를 작고 집중되게 유지
  • 상속보다 합성 선호
  • 적절한 오류 처리 사용 (Result/Option)

커밋 메시지 형식

Conventional Commits 사양 준수:

<type>(<scope>): <subject>

<body>

<footer>

타입:

  • feat: 새 기능
  • fix: 버그 수정
  • docs: 문서만
  • style: 코드 스타일 변경
  • refactor: 코드 리팩토링
  • perf: 성능 개선
  • test: 테스트 추가
  • chore: 유지보수 작업

Pull Request 가이드라인

  1. 제목: 명확하고 설명적
  2. 설명: 무엇을, 왜, 어떻게 설명
  3. 테스트: 새 기능에 대한 테스트 포함
  4. 문서: 관련 문서 업데이트
  5. Breaking Changes: 명확히 표시
  6. Issues: 관련 이슈 참조

리뷰 프로세스

  1. 자동화된 검사 통과 필수
  2. 최소 한 명의 메인테이너 승인
  3. 해결되지 않은 대화 없음
  4. main 브랜치와 최신 상태

문제 해결

일반적인 문제

컴파일 오류

# 빌드 캐시 정리
cargo clean

# 의존성 업데이트
cargo update

# 충돌하는 기능 확인
cargo tree --duplicates

테스트 실패

# 상세하게 테스트 실행
cargo test -- --nocapture --test-threads=1

# 경쟁 조건 확인
cargo test -- --test-threads=1

# 테스트 환경 확인
cargo test -- --ignored

성능 문제

# 릴리스 빌드 프로파일
cargo build --release
perf record ./target/release/continuum-router
perf report

# 블로킹 연산 확인
RUST_LOG=trace cargo run 2>&1 | grep "blocking"

리소스