DaleSchool

CLI 도구 만들기: clap으로 인자 파싱

중급15분

학습 목표

  • clap derive 방식으로 CLI 인자를 정의할 수 있다
  • 하위 명령(subcommand)을 구현할 수 있다
  • 자동 도움말/버전 정보를 제공할 수 있다

동작하는 코드

clap 크레이트는 derive 매크로를 제공해 복잡한 CLI도 선언적으로 정의할 수 있게 해줍니다.

use clap::{Parser, Subcommand};

#[derive(Parser, Debug)]
#[command(name = "todo", version, about = "작고 빠른 CLI TODO", long_about = None)]
struct Cli {
    #[command(subcommand)]
    command: Commands,
}

#[derive(Subcommand, Debug)]
enum Commands {
    /// 새 할 일을 추가합니다
    Add {
        #[arg(value_name = "TEXT")]
        text: String,
    },
    /// 할 일을 완료 처리합니다
    Done {
        #[arg(value_name = "ID")]
        id: u32,
    },
    /// 목록을 출력합니다
    List {
        #[arg(long, help = "완료된 항목도 포함")]
        all: bool,
    },
}

fn main() {
    let cli = Cli::parse();
    match cli.command {
        Commands::Add { text } => println!("추가: {text}"),
        Commands::Done { id } => println!("완료 처리: #{id}"),
        Commands::List { all } => println!("목록 출력 (all={all})"),
    }
}
  • Cli::parse()가 자동으로 std::env::args()를 읽고 검증한 뒤 구조체에 채워 넣어요.
  • #[command(version)]을 붙이면 --version 플래그를, about을 채우면 --help에 설명이 자동으로 들어갑니다.

도움말과 에러 메시지

$ todo --help
Usage: todo <COMMAND>

Commands:
  add   새 할 일을 추가합니다
  done  할 일을 완료 처리합니다
  list  목록을 출력합니다
  help  Print this message or the help of the given subcommand(s)

Options:
  -h, --help     Print help (see more with '--help')
  -V, --version  Print version

잘못된 인자를 입력하면 clap이 친절한 메시지와 함께 non-zero exit code로 종료합니다.

$ todo add
? failed to parse argument: TEXT is required but missing

직접 해보기

  1. todo list --all 처럼 --all을 붙였을 때 true, 생략하면 false가 되도록 기본값을 다뤄 보세요.
  2. todo done --id 3처럼 long 옵션/short 옵션을 섞어서 사용하는 subcommand를 하나 더 추가해 보세요.
  3. clap::Parser::command().long_about("...")를 활용해 README 수준의 자세한 도움말을 붙여 보세요.
  1. 환경 변수와 함께 사용#[arg(env = "TODO_PATH")] 속성을 사용해 저장 경로를 환경 변수로도 받을 수 있도록 CLI를 확장해 보세요.
  2. exit 코드 제어 — 비정상적인 상황에서 eprintln!으로 메시지를 출력하고 std::process::exit(1)로 종료하는 패턴을 추가해 보세요.
  3. config 서브커맨드todo config set --key theme --value dark 같은 하위 명령을 설계하고, serde로 설정 파일을 저장하는 로직과 연결해 보세요.