OptionParser.ParseError — 옵션 파싱 실패

OptionParser.ParseError — 옵션 파싱 실패

OptionParser가 명령줄 옵션을 파싱하다가 잘못된 형태를 만나면 어떻게 될까요? 그때 던져지는 예외가 OptionParser.ParseError예요. 보통 parse!/2 같은 강제(raising) 버전을 쓰면 실패 시점에 이 예외를 만나게 되죠.

출처: OptionParser.ParseError

본문

OptionParser.ParseError옵션 파싱이 실패했을 때 발생하는 예외예요. 예를 들어 OptionParser.parse!/2를 참고하세요. 파싱 실패는 대개 스위치에 기대한 타입과 다른 값이 들어왔을 때 생겨요. strict로 스위치를 :integer로 선언했는데 "abc" 같은 값을 주는 경우가 대표적이죠.

iex> OptionParser.parse!(["--count", "abc"], strict: [count: :integer])
** (OptionParser.ParseError) invalid value for option "--count": expected an integer, got: "abc"

이 예외를 잡아서 사용자에게 "어떤 옵션에 어떤 값이 잘못 들어왔는지"를 친절한 메시지로 보여 줄 수 있어요. CLI 도구를 만들 때, 단순히 예외가 터지는 걸 넘어 사용자가 바로 고칠 수 있게 안내하는 게 좋은 사용자 경험이에요.

parse/2는 실패해도 예외를 던지지 않는 대신 오류 정보를 반환하고, parse!/2는 실패 시 즉시 OptionParser.ParseError를 던져요. "값이 잘못 들어오면 그냥 실패해야 한다"는 상황에는 parse!/2가 더 편리하죠.

이 예외가 알려 주는 정보를 제대로 활용하면 CLI의 오류 메시지를 훨씬 구체적으로 만들 수 있어요. 잘못된 옵션 이름과 그 값, 그리고 기대한 타입이 무엇이었는지가 예외를 통해 드러나거든요. 그래서 이 예외를 rescue로 받은 뒤 "어떤 옵션이 왜 잘못됐는지"를 사용자에게 바로 보여 주는 패턴을 많이 써요.

try do
  OptionParser.parse!(argv, strict: [count: :integer])
rescue
  e in OptionParser.ParseError -> IO.puts("잘못된 옵션: " <> Exception.message(e))
end

짧은 정의만 보면 별것 아닌 예외처럼 보이지만, 실제로는 명령줄 도구의 사용자 경험을 좌우하는 지점에서 자주 만나는 예외예요.

더 알아보기

  • OptionParser — 명령줄 인자 파싱의 주요 모듈
  • OptionParser.parse/2 vs OptionParser.parse!/2 — 예외를 던지지 않는 버전과 던지는 버전
  • try/rescueOptionParser.ParseError를 잡아 사용자에게 안내하는 패턴