콘텐츠로 이동

개발 가이드

이 가이드는 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계층 아키텍처를 따릅니다:

디렉토리 구조

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       # 테스트 헬퍼 함수

examples/
├── standalone_server.rs  # 설정 파일로 최소 서버 실행
├── axum_integration.rs   # 기존 Axum 앱에 라우터 임베딩
├── programmatic_config.rs  # YAML 없이 코드로 설정
└── hot_reload.rs         # 핫 리로드 및 설정 변경 구독

예제 실행

examples/ 디렉토리에는 라이브러리 API를 시연하는 실행 가능한 Rust 프로그램이 포함되어 있습니다. 다음 명령으로 예제를 실행할 수 있습니다:

cargo run --example <이름> [-- <인수>]

예시:

# 독립 실행 서버 시작
cargo run --example standalone_server -- --config config.yaml

# 커스텀 Axum 앱에 라우터 임베딩
cargo run --example axum_integration -- --config config.yaml

# 프로그래밍 방식으로 설정 (YAML 파일 불필요)
OPENAI_API_KEY=sk-... cargo run --example programmatic_config

# 핫 리로드 시연
cargo run --example hot_reload -- --config config.yaml

자세한 내용은 라이브러리 사용법에서 임베딩 가능한 크레이트 API에 대한 전체 가이드를 참조하세요.

아키텍처 개요

의존성 흐름

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 --lib --no-default-features --features "metrics,hot-reload"

Cargo 기능 플래그

크레이트는 선택적 구성 요소를 활성화하는 기능 플래그를 제공합니다. 바이너리 빌드 시에는 기본적으로 full 기능 세트가 활성화됩니다.

기능 설명 기본값
full 아래 모든 기능 활성화 yes (default 경유)
cli clap을 통한 CLI 바이너리 지원 yes
admin 관리자 API 엔드포인트 yes
metrics Prometheus 메트릭 엔드포인트 yes
files Files API (/v1/files) yes
health-check 백그라운드 헬스 모니터링 yes
hot-reload 라이브 리로드를 위한 설정 파일 감시 yes
webui 임베디드 WebUI 에셋 yes
gcp-auth Gemini 서비스 계정용 Google Cloud 인증 yes

continuum-router를 라이브러리 크레이트로 사용할 때, 필요한 기능만 선택하여 컴파일 시간과 바이너리 크기를 줄일 수 있습니다:

[dependencies]
continuum-router = { git = "...", default-features = false, features = ["metrics", "hot-reload"] }

빌드 예시:

# 최소 코어 라이브러리 (선택적 의존성 없음)
cargo build --lib --no-default-features

# 메트릭 지원 라이브러리
cargo build --lib --no-default-features --features "metrics"

# 관리자 및 핫 리로드 라이브러리
cargo build --lib --no-default-features --features "admin,hot-reload"

# 전체 바이너리 (기본값)
cargo build --release

크로스 컴파일

# 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"

리소스