Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

19. 캡스톤 프로젝트: 타입 안전한 태스크 스케줄러 🟢

이 프로젝트는 본서에서 배운 다양한 패턴들을 하나의 완성된 시스템으로 통합하는 과정입니다. 제네릭, 트레이트, 타입 상태(Type-state), 채널, 에러 처리, 테스트 기법을 모두 동원하여 타입 안전하고 동시성을 지원하는 태스크 스케줄러를 구축해 봅니다.

예상 소요 시간: 4~6시간 | 난이도: ★★★

실무 연습 포인트:

  • 제네릭과 트레이트 경계 (1~2장)
  • 태스크 생명주기를 위한 타입 상태 패턴 (3장)
  • 제로 비용 상태 마커를 위한 PhantomData (4장)
  • 워커 통신을 위한 채널 (5장)
  • 스코프 스레드를 이용한 동시성 (6장)
  • thiserror를 활용한 에러 처리 (10장)
  • 속성 기반 테스트를 포함한 검증 (14장)
  • TryFrom과 유효성 검사 타입 설계 (15장)

프로젝트 개요: 해결해야 할 문제

다음 요구사항을 충족하는 태스크 스케줄러를 만드세요.

  1. **태스크(Task)**는 엄격한 생명주기를 가집니다: 대기(Pending) → 실행 중(Running) → 완료(Completed) 혹은 실패(Failed).
  2. **워커(Worker)**는 채널에서 태스크를 가져와 실행하고 결과를 보고합니다.
  3. **스케줄러(Scheduler)**는 태스크 제출, 워커 관리, 결과 수집을 총괄합니다.
  4. 잘못된 상태 전이는 런타임 패닉이 아닌 컴파일 타임 에러로 차단되어야 합니다.

단계별 가이드

1단계: 태스크 타입 정의

PhantomData와 타입 상태 마커를 사용해 Task 구조체를 설계하세요. Pending 상태의 태스크만 start() 메서드를 가질 수 있으며, 호출 시 Running 상태의 태스크를 반환해야 합니다.

2단계: 작업 함구(Work Function) 정의

태스크가 실제로 수행할 로직을 담을 박스형 클로저(Box<dyn FnOnce(...)>)를 포함하는 WorkItem을 만드세요.

3단계: 에러 처리 시스템 구축

thiserror를 사용하여 스케줄러 폐쇄, 태스크 실패, 채널 통신 에러, 워커 패닉 등을 구분하는 에러 열거형을 정의하세요.

4단계: 스케줄러 구현

채널과 스코프 스레드를 사용하여 여러 워커가 병렬로 작업을 처리하고 결과를 수집하는 전체 로직을 완성하세요.

5단계: 통합 테스트 및 검증

  • 모든 태스크가 정상 처리되는 케이스(Happy path)
  • 특정 태스크가 실패할 때의 에러 핸들링
  • 빈 스케줄러가 정상적으로 소멸되는지 확인하는 테스트를 작성하세요.

평가 기준

항목목표
타입 안전성잘못된 상태 전이(예: 완료된 태스크 재실행)가 컴파일되지 않음
동시성워커들이 병렬로 작동하며 데이터 경합(Data Race)이 없음
에러 처리모든 실패가 TaskResult에 캡처되며, 예기치 않은 패닉이 발생하지 않음
코드 구조API가 impl Into나 유효성 검사 타입을 사용하여 사용하기 편리함
문서화주요 타입과 트레이트에 불변성(Invariant)을 설명하는 주석이 포함됨

확장 아이디어 (심화 학습)

기본 스케줄러가 완성되었다면 다음 기능들을 추가해 보세요:

  1. 우선순위 큐: 특정 우선순위가 높은 태스크를 먼저 처리합니다.
  2. 재시도 전략(Retry Policy): 실패한 태스크를 N번까지 자동으로 재시도합니다.
  3. 취소(Cancellation): 특정 TaskId를 가진 대기 중인 태스크를 취소합니다.
  4. 비동기 버전: tokio와 비동기 채널을 사용하도록 포팅해 보세요.
  5. 메트릭 수집: 각 워커별 처리량, 평균 실행 시간, 실패율을 추적합니다.

본 프로젝트를 성공적으로 마치셨다면, Rust의 핵심 디자인 패턴을 실무에 적용할 준비가 되신 것입니다.