개발과 문서가 따로노니 신경쓸 것이 두 배로 생긴다.
이에 소스코드로부터 개발문서를 만들어보기로 했다.
Sphinx란 Python을 위한 문서화 라이브러리로 소스코드로부터 문서(html, LaTeX 등)를 정적으로 생성하는 도구이다.
이 말고도 다른 라이브러리들이 많이 있지만 대부분 Sphinx를 선호하는 듯 하다. [참고]
Sphinx로 만들어진 문서를 서빙할 때 단연코 가장 많이 쓰이는 방식은 Read-the-Docs (이하 RTD)를 통한 호스팅이다.
RTD는 Sphinx로 만들어진 html 문서를 호스팅하는 곳으로 파이썬 개발자들은 반드시 한 번 정도는 봤을 사이트이다.
RTD 테마가 생각보다 잘 만들어져있어서 일부러 웹 호스팅을 하지 않더라도 Sphinx에 RTD 테마를 입혀 private docs로 사용하는 경우도 많다.
워낙 유명하다보니 어떻게 하는지는 이곳 저곳에 잘 나와있다. [공식-영어] [공식-한글]
방법도 단순하다.
1. Sphinx를 깔고
2. Sphinx 문법으로 파일을 구성한 후
3. 빌드하기만 하면 된다.
이제 하나하나 확인해보자.
1. Sphinx 설치
설치는 간단하다.
Anaconda나 pip으로 다음과 같이 Sphinx 패키지를 설치한다.
(참고로 Anaconda 사용자가 pip을 혼용해도 conda처럼 해당 가상환경에서만 설치된다)
$ conda install Sphinx # Anaconda 사용 시 $ pip3 install Sphinx # Anaconda 미사용 시
2. Sphinx 세팅
프로젝트의 최상위 디렉터리에서 docs 디렉터리를 만들어 진행하면 된다.
$ mkdir docs $ cd docs $ sphinx-quickstart
3. Sphinx 빌드
정말 뭐 없다.
위의 세팅 과정에서 생긴 Makefile을 이용해 빌드하면 된다.
$ make html
그러면 build 디렉터리에 html/index.html이 생겼을 것이다.
열어서 확인해보면 다음과 같은 웹페이지를 볼 수 있다.
여기까지가 Private Docs의 제작 과정이다.
이 Docs를 RTD를 이용해 웹 호스팅을 하고싶다면 RTD에 가입을 해서 Project를 Import하면 된다.
다만 RTD에서의 호스팅은 Public Repository만 가능하므로 Private 호스팅을 하고 싶다면 Private 네트워크에서만 볼 수 있는 웹서버에 올려두면 될 것이다.
cf. RTD 테마 적용
RTD 웹사이트에 등록하지 않고 Local의 Sphinx 문서에 RTD 테마를 적용하고싶다면 테마를 설치하고 docs/source 디렉터리의 conf.py 파일에 별도의 세팅을 해주면 된다.
테마는 보통 Sphinx를 설치하며 같이 설치되긴 한다.
$ conda install sphinx_rtd_theme # Anaconda 사용 시 $ pip3 install sphinx_rtd_theme # Anaconda 미사용 시
html_theme = 'sphinx_rtd_theme' # in conf.py file
경우에 따라 conf.py 최상단의 os.path를 수정해줄 수도 있다.
이건 환경마다 다르니 편한대로 사용하면 된다.
테마를 적용하면 아까의 볼품없는 테마가 이렇게 변한다.
e.g. Sphinx 마크다운 사용 예제
Sphinx 템플릿과 가이드는 이곳에 정리되어있다.
그리고 구체적인 Sphinx의 문법(reStructureTree, RST)은 이곳에 정리되어있다.
간단하게 카테고리와 마크다운 파일을 만들어보자.
Sphinx에서 마크다운을 사용하기 위해서는 myst_parser 패키지를 설치한 후 conf.py에 myst_parser extension을 등록해야 한다.
$ pip3 install myst_parser
그 이후, source_suffix 속성을 통해 Sphinx가 읽을 수 있는 파일의 종류를 지정해주어야 한다. (디폴트는 rst만 인식하도록 되어있다) [index.rst 설정 참고]
extensions = ['myst_parser'] source_suffix = { '.rst': 'restructuredtext', '.txt': 'markdown', '.md': 'markdown', }
위 과정을 거치지 않으면 마크다운 파일을 인식할 수 없어 다음과 같은 에러가 발생하게 된다.
> WARNING: toctree contains reference to nonexisting document
이제 패키지에 마크다운 파일을 만들어보자.
source 디렉터리에서 A라는 디렉터리를 만들고 그 안에 a1.md와 a2.md를 넣을 것이다.
$ mkdir docs/source/A $ cat "Hi" > docs/source/A/a1.md $ cat "Bye" > docs/source/A/a2.md
그 후 index.rst의 toctree 부분에 위에서 생성한 디렉터리와 파일을 등록해주면 된다.
.. toctree:: :maxdepth: 2 :caption: A: A/a1.md A/a2.md
주의할 점은 Sphinx는 들여쓰기로 스페이스 3개를 사용한다는 점이다.
스페이스 4개로 들여쓰기를 하게되면 Sphinx가 제대로 인식하지 못한다.
이제 다시 docs 디렉터리에서 빌드를 하면 다음과 같은 웹페이지를 볼 수 있게된다.
e.g. Sphinx autodoc 사용 예제
이번에는 Python 파일로부터 rst 파일을 생성해본다.
우선 rst 파일을 다루기 위해 conf.py의 extension에 sphinx.ext.autodoc를 추가한다.
또한, 빌드 과정 중 모듈을 찾을 수 있도록 conf.py의 상단에 주석처리된 path 관련 내용을 수정한다.
path 수정은 사용자의 빌드 환경에 따라 다른데, 필자는 build와 source 디렉터리를 분리해서 사용하기 때문에 source 디렉터리 기준으로 부모(docs)의 부모(최상위) 디렉터리를 지정하여 사용한다.
만약 이후의 빌드 과정에서 모듈을 찾지 못한다는 에러가 발생하면 path 지정이 제대로 되지 않아서이다.
import os import sys # sys.path.insert(0, os.path.abspath('.')) # Default path sys.path.insert(0, os.path.abspath('../..')) # 필자의 path
이제 테스트를 위해 프로젝트 최상위 디렉터리에 다음과 같은 테스트 패키지를 만든다.
test 패키지 내부에 A, B라는 서브 패키지를 두고 각각 a와 b 모듈을 작성하였다.
project ├── test │ ├── A │ │ ├── __init__.py │ │ └── a.py │ ├── B │ │ ├── __init__.py │ │ └── b.py │ └── __init__.py └── doc ├── Makefile ├── build └── source ├── _static ├── _templates ├── conf.py └── index.rst
a.py와 b.py에는 테스트를 위해 만든 클래스가 들어있으며 내용은 다음과 같다.
""" ==================================== :mod:`a` 모듈 a ==================================== .. moduleauthor:: hooni <hooni@hoo.ni> .. note:: LGPLv3 설명 ===== 이 모듈은 문서화 테스트를 위한 모듈입니다. Revision History ------------------- * [2021/04/23] - 모듈 작성 """ class A: """문서화 테스트를 위한 임시 클래스 """ def __init__(self, a: int): """ 클래스 생성자 :param a: 생성자 파라미터 >>> a = A(10) """ self.a = a def print_value(self): """ 멤버변수 a를 출력하는 메소드 >>> A(10).print_value() 10 """ print(self.a)
이제 Python 파일로부터 rst 파일을 생성할 차례이다.
sphinx-apidoc 명령어를 이용하면 된다.
이 명령어는 반드시 프로젝트의 최상위 디렉터리에서 실행해야 한다.
test 패키지로부터 rst 파일을 생성해 docs/source에 저장하는 명령어는 다음과 같다.
$ sphinx-apidoc -f -o docs/source test > Creating file docs/source\test.rst. > Creating file docs/source\test.A.rst. > Creating file docs/source\test.B.rst. > Creating file docs/source\modules.rst.
그 결과 각 패키지 별 rst 파일과 modules.rst 파일이 생성되었다.
modules.rst 파일은 모든 모듈의 내용이 기술돼있는 최상위 문서이다.
이제 modules.rst를 기존의 index.rst에 연결하여 링크해주면 된다.
.. toctree:: :maxdepth: 2 :caption: Contents: modules
그리고 빌드를 한 후 웹페이지를 확인하면 다음과 같이 세련된 창을 볼 수 있다.