## CLI CLI 자체는 전혀 모던하지 않다. **그러나 다시금 CLI가 중요해진 이유는 모던하다.** 바로 클라우드 때문이다. 대부분의 클라우드 인스턴스는 리눅스 기반에 CLI만 지원한다. 때문에 인스턴스에서 돌아가는 프로그램이 CLI를 지원하지 않으면, 실행과 종료 이외에는 관리자가 할 수 있는 행동이 사실상 없어진다. 배치가 제대로 돌아가지 않은 작업을 직접 실행해야 할 때(1), 오류가 났을 때 로그를 확인하고 조치를 해야 할 때(2), 갑작스럽게 생긴 추가 작업을 지시해야 할 때(3) CLI가 없으면 너무나 불편하다. ## CLI 설정 in Python ### `click` 패키지 ```bash pip install click ``` 파이썬의 내장 패키지인 `argparse`를 통해 CLI 설정할 순 있지만, 그 방법이 매우 투박하고 불편하다. 그에 반해 `click` 패키지는 데코레이터를 통한 CLI 설정을 지원하기 때문에 `click`을 사용하는 것이 좋다. #### `click` 을 이용한 CLI 설정 >**참고 : 폴더 구성** >``` >cli_study.py >pyproject.toml #빌드용 파일, setup.py 대체 >``` ##### `@click.group` 과 `@click.command` CLI는 보통 `[프로그램 이름] [명령어] [인자 또는 옵션]`의 구조를 이룬다. 여기서 `[프로그램 이름]`을 설정하는 것이 `@click.group` 이고, `[명령어]`를 설정하는 것이 `@click.command`이다. 설정한 명령어는 `cli_study.add_command`로 추가할 수 있다. `click` 최근 버전에서는 이전에 다뤘던 [[1. 동적 실행과 네임스페이스를 이용한 인스턴스 관리|동적 실행]] 방식으로 명령어를 추가할 수도 있다.[^1] ```python # cli_study.py import click @click.group() def cli_study(): print("This message is displayed every time 'cli_study' is called") @click.command() def test(): print("test") cli_study.add_command(test) ``` 예를 들어 위와 같이 코드를 작성한 경우, `cli_study test`를 실행할 수 있고 결과는 `cli_study \n test`로 나온다. ##### `@click.argument`와 `@click.option` 다음으로 `[인자 또는 옵션]`을 설정하는 것이 `@click.argument`와 `@click.option`다. 다만, 이 둘은 설정 방법이 조금 다르다. ```python # cli_study.py #... @click.command() @click.argument("num", type=click.INT) def argument(num): for i in range(num): print(i) cli_study.add_command(argument) ``` 먼저 `@click.argument`의 경우 `@click.argument("[인자 이름]", ...)` 방법으로 설정하며, 인자는 CLI에 반드시 포함되어 있어야 한다. 즉, `cli_study argument` 이렇게 실행할 경우, 에러가 발생한다. 타입 지정의 경우, click의 parameters 객체로 지정할 수 있으며 타입 종류는 [공식 문서](https://click.palletsprojects.com/en/8.1.x/parameters/)에서 확인 가능하다. ```python # cli_study.py #... @click.command() @click.option("--num", required=False, type=click.INT) def option(num): if num: for i in range(num): print(i) cli_study.add_command(option) ``` 다음으로 `@click.option`의 경우 `@click.option("--[옵션 이름]", ...)` 방법으로 설정하며, 옵션의 경우 인자와 다르게 CLI에 포함이 되어 있지 않아도 된다. 포함 여부를 강제하는 인자는 `required:boolean`이다. 그 외 타입 지정의 경우 `@click.argument`와 동일한 방법으로 지정한다. ##### CLI 등록 이제 위의 CLI 코드를 실행해보자. `click` 공식 문서에서는 `if __name__ == '__main__'` 방식보다는 `setuptools`를 이용해서 CLI를 등록하는 걸 권장하고 있다.[^2] ###### `pyproject.toml` 작성 ```toml [build-system] requires = ["setuptools"] build-backend = "setuptools.build_meta" [project] name = "cli_study" version = "0.1.0" description = "." dependencies = [     "Click" ] [project.scripts] cli_study = "cli_study:cli_study" ``` `toml`은 `yaml`과 같이 쉽게 쓰고 이해할 수 있는 마크업 언어다. 파이썬의 `setuptools`는 이 `toml`도 지원하는데, `pyproject.toml`로 기존에 쓰이던 `setup.py`를 대체할 수 있다. [^3] `pyproject.toml`에서 CLI 관련 설정은 `[project.scripts]`에서 할 수 있다. 설정하는 방법은 `[CLI 명령어 이름] = "[파이썬 파일 경로]:[@click.group을 단 함수 이름]`이다. 나머지 설정에 대한 내용은 [여기](https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html)에 잘 정리되어 있다. ###### CLI 등록 ```bash pip install -e . ``` pip을 통해 설치한다. `-e`는 코드를 수정하면 자동으로 반영하도록 하는 설정이다. ```bash cli_study --help ``` ``` # 실행 결과 Usage: cli_study [OPTIONS] COMMAND [ARGS]... Options: --help Show this message and exit. Commands: argument option test ``` ```bash cli_study test ``` ``` # 실행 결과 cli_study test ``` ```bash cli_study argument 2 ``` ``` # 실행 결과 cli_study 0 1 ``` ```bash cli_study option ``` ``` # 실행 결과 cli_study ``` ```bash cli_study option --num 2 ``` ``` # 실행 결과 cli_study 0 1 ``` 위 명령어들을 실행하여 결과를 확인해보자. [^1]: [click doc - Custom Multi Commands](https://click.palletsprojects.com/en/8.1.x/commands/#custom-multi-commands) [^2]: [click doc - Switching to Setuptools](https://click.palletsprojects.com/en/8.1.x/quickstart/#switching-to-setuptools) [^3]: [setuptools - Configuring setuptools using pyproject.toml files](https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html)