Do you want to pick up from where you left of?
Take me there

문서화

Elixir 코드 문서화하기.

주석

프로그래머들 사이에서 주석을 얼마나 달아야 하며 어떻게 좋은 문서를 만들어내는 지는 오래된 논쟁거리입니다. 하지만, 동일한 코드 베이스를 가지고 협업할 때 문서화가 얼마나 중요한 지는 모두가 동의합니다.

Elixir에서는 문서화를 일급 시민으로 취급하며 프로젝트에 대한 문서를 생성하기 위한 다양한 함수와 접근법을 제공합니다. Elixir는 코드베이스에 주석을 달기 위한 여러가지 다양한 특성을 코어에서 제공합니다. 다음의 3가지 방식을 보도록 합시다.

인라인 문서화

코드에 주석을 다는 가장 간단한 방법은 인라인 주석일 겁니다. Ruby, Python과 비슷하게 Elixir의 인라인 주석은 #로 나타낼 수 있습니다. 이는 나라에 따라 다르지만 우물 정이나 해시로 알려져 있기도 합니다.

다음의 Elixir 스크립트를 봅시다(greeting.exs).

# 콘솔에 'Hello, chum.' 를 출력합니다.
IO.puts("Hello, " <> "chum.")

이 스크립트를 실행할 때, Elixir는 #로 시작하여 라인이 끝나는 부분을 무시하며 버리는 정보로 취급합니다. 이는 연산에 대해 어떤 값을 부여하지도 않고 스크립트의 성능에 어떠한 영향도 주지 않습니다. 그러나, 어떤 일이 일어날지 확신이 서지 않을 때, 프로그래머가 이 부분에 대해 주석을 읽으면서 알 수 있어야 합니다. 한 줄 주석을 남용하지 않도록 주의하세요! 한 줄 주석으로 코드 베이스를 채우는 것이 누군가에게는 불쾌한 악몽이 될 수도 있습니다. 적절히 사용하시는 것이 좋습니다.

모듈 문서화하기

@moduledoc 주석자는 모듈 수준에서 인라인 주석을 달 수 있게 해줍니다. 일반적으로, 파일의 첫번째 줄에 있는 defmodule 선언부의 바로 아래에 위치합니다. @moduledoc으로 장식된 한 줄 주석을 아래의 예제에서 볼 수 있습니다.

defmodule Greeter do
  @moduledoc """
  사람을 반기는 함수 `hello/1` 를 제공합니다.
  """

  def hello(name) do
    "Hello, " <> name
  end
end

IEx에서 모듈의 문서에 접근하고자 한다면 h 헬퍼 함수를 이용할 수 있습니다. Greeter 모듈을 새 파일 greeter.ex에 넣고 컴파일하면 직접 확인할 수 있습니다.

iex> c("greeter.ex", ".")
[Greeter]

iex> h Greeter

                Greeter

사람을 반기는 함수 hello/1  제공합니다.

주의: Mix 프로젝트 컨텍스트 내에서 작업한다면 파일 컴파일을 위에서 처럼 수동으로 할 필요는 없습니다. Mix 프로젝트에서는 iex -S mix를 사용하여 현재 프로젝트의 IEx 콘솔을 로드할 수 있습니다.

함수 문서화하기

Elixir는 모듈 범위에서 주석을 달 수 있게 해주었듯이, 함수 범위에서도 비슷한 방식으로 주석을 달 수 있게 해줍니다. @doc 주석자는 함수 수준에서의 인라인 주석을 가능하게 해줍니다. @doc 주석자는 주석을 달고자 하는 함수 선언부의 바로 위쪽에 위치합니다.

defmodule Greeter do
  @moduledoc """
  ...
  """

  @doc """
  hello 메시지를 출력합니다.

  ## Parameters

    - name: 사람의 이름을 나타내는 문자열입니다.

  ## Examples

      iex> Greeter.hello("Sean")
      "Hello, Sean"

      iex> Greeter.hello("pete")
      "Hello, pete"

  """
  @spec hello(String.t()) :: String.t()
  def hello(name) do
    "Hello, " <> name
  end
end

다시 IEx로 들어갑시다. 모듈의 이름이 딸린 함수에 대해 헬퍼 명령(h)을 이용하면 다음과 같은 화면을 볼 수 있습니다.

iex> c("greeter.ex", ".")
[Greeter]

iex> h Greeter.hello

                def hello(name)

  @spec hello(String.t()) :: String.t()

hello 메시지를 출력합니다.

Parameters

   name: 사람의 이름을 나타내는 문자열입니다.

Examples

    iex> Greeter.hello("Sean")
    "Hello, Sean"

    iex> Greeter.hello("pete")
    "Hello, pete"

iex>

문서 내에서 마크업을 어떻게 이용하고, 터미널이 이를 어떻게 렌더링하는지 주목하세요. 더욱 세련되어지거나 Elixir 생태계에 멋진 기능들이 추가되는 것들을 떠나서, ExDoc가 HTML 문서를 한번에 생성한다는 것이 엄청 흥미롭게 느껴질 겁니다.

Note: @spec 어노테이션은 코드의 정적 분석에 사용됩니다. 여기에 대해 배우려면, 사양과 타입 강의를 확인하세요.

ExDoc

ExDoc는 HTML(HyperText Markup Language) 문서를 생성하여 Elixir 프로젝트를 위한 온라인 문서를 제공하는 공식 Elixir 프로젝트 입니다. 물론, Github에서 찾을 수 있는 프로젝트입니다. 먼저, 어플리케이션을 만들기 위해 Mix 프로젝트를 생성해 봅시다.

$ mix new greet_everyone

* creating README.md
* creating .formatter.exs
* creating .gitignore
* creating mix.exs
* creating lib
* creating lib/greet_everyone.ex
* creating test
* creating test/test_helper.exs
* creating test/greet_everyone_test.exs

Your Mix project was created successfully.
You can use "mix" to compile it, test it, and more:

    cd greet_everyone
    mix test

Run "mix help" for more commands.

$ cd greet_everyone

이제 @doc 강의에서 보았던 코드들을 lib/greeter.ex라는 파일에 복사/붙여넣기하고, 모든 코드들이 여전히 잘 동작하는지 커맨드 라인으로 확인해보세요. Mix 프로젝트 폴더 내에 있으므로, iex -S mix 명령 시퀀스로 조금 색다르게 IEx를 시작해야 합니다.

iex> h Greeter.hello

                def hello(name)

  @spec hello(String.t()) :: String.t()

hello 메시지를 출력합니다.

Parameters

   name: 사람의 이름을 나타내는 문자열입니다.

Examples

    iex> Greeter.hello("Sean")
    "Hello, Sean"

    iex> Greeter.hello("pete")
    "Hello, pete"

설치하기

위의 출력을 제대로 확인했다면, ExDoc를 설정할 준비가 되었습니다. mix.exs 파일에 :ex_doc 의존성을 추가하세요.

def deps do
  [{:ex_doc, "~> 0.21", only: :dev, runtime: false}]
end

프로덕션 환경에서 ex_doc 의존성을 다운로드 받아서 컴파일되는 것을 원하지 않기 때문에 only: :dev 키-값 쌍을 명시해 두었습니다.

ex_doc는 Earmark라는 라이브러리를 추가합니다.

왜 Earmark를 쓸까요? Earmark는 Elixir 프로그래밍 언어를 위한 마크다운 파서 입니다. ExDoc를 이용하여 @moduledoc, @doc 내부의 문서를 HTML 문서로 아름답게 변환시켜 줍니다.

원한다면 마크 업 도구를 Cmark로 변경할 수 있다는 점에 주목할 가치가 있지만 여기에서 읽을 수 있는 약간 더 많은 설정을 해야합니다. 여기서는, Earmark로 진행 하겠습니다.

문서 생성하기

계속해서, 커맨드 라인에서 다음과 같이 두 개의 명령을 실행해보세요.

$ mix deps.get # ExDoc와 Earmark를 불러옵니다
$ mix docs # 문서를 생성합니다.

Docs successfully generated.
View them at "doc/index.html".

모든 것이 예정대로 되었다면, 위의 예제 출력 메시지와 비슷한 메시지를 볼 수 있을 것입니다. Mix 프로젝트 내부에, doc/라는 디렉터리를 확인할 수 있고, 안에는 자동으로 생성된 문서가 있습니다. 웹 브라우저로 색인 페이지를 열어보면 다음과 같은 화면을 보게 될 것입니다.

ExDoc Screenshot 1

Earmark가 마크다운을 렌더링하고 ExDoc가 이를 쓸만한 포멧으로 표시하는 것을 볼 수 있습니다.

ExDoc Screenshot 2

Github에 배포할 수도 있고, 홈페이지에도 배포할 수 있지만, 보통은 HexDocs에 배포 합니다.

좋은 습관

Elixir의 모범 가이드 라인에 따라 문서화하세요. Elixir는 확실히 역사가 오래되지 않은 언어이기 때문에, 생태계가 커져감에 따라 많은 표준들이 생겨날 것입니다. 커뮤니티에서도 좋은 습관을 정립하기 위해 노력했습니다. 좋은 습관들에 대해서 더 알아보고자 한다면 Elixir 스타일 가이드를 보세요.

defmodule Greeter do
  @moduledoc """
  이 문서는 훌륭한 문서입니다.
  """

end
defmodule Greeter do
  @moduledoc false

end
defmodule Greeter do
  @moduledoc """
  ...

  이 모듈도 `hello/1` 함수를 가지고 있습니다.
  """

  def hello(name) do
    IO.puts("Hello, " <> name)
  end
end
defmodule Greeter do
  @moduledoc """
  ...

  이 모듈도 `hello/1` 함수를 가지고 있습니다.
  """

  alias Goodbye.bye_bye
  # 기타 등등...

  def hello(name) do
    IO.puts("Hello, " <> name)
  end
end
defmodule Greeter do
  @moduledoc """
  ...
  """

  @doc """
  hello 메시지를 출력합니다.

  ## Parameters

    - name: 사람의 이름을 나타내는 문자열 입니다.

  ## Examples

      iex> Greeter.hello("Sean")
      "Hello, Sean"

      iex> Greeter.hello("pete")
      "Hello, pete"

  """
  @spec hello(String.t()) :: String.t()
  def hello(name) do
    "Hello, " <> name
  end
end
강의에 실수가 있거나 기여하고 싶은 부분이 있으신가요? GitHub에서 이 강의를 수정해보세요!