들어가며

아무리 좋은 도구가 있어도, 그 도구를 소개하는 좋은 문서가 없다면 사람들은 도구의 가치를 알기 어렵습니다. 이 글에서는 “개발자를 위한” 도구를 만들 때, 어떻게 해야 좋은 문서를 작성할 수 있는지 소개합니다.

Note: 이 글은 PyCon US 2021: Writing Good Documentation for Developers의 내용을 정리한 글입니다. 이 글이 마음에 드셨다면 원본 영상도 꼭 보시는 것을 권장드립니다.

“문서는 마케팅 수단이다”

여러분은 방금 정말 복잡한 문제를 해결할 수 있는 멋진 도구(e.g. 라이브러리)를 만들었습니다. 여러분은 이 도구가 너무나 중요하고 유용하다는 것을 알고 있지만, 아직 세상의 많은 개발자(유저)들은 이 도구의 유용성을 알지 못합니다. 사실 그들은 이 도구가 존재한다는 사실조차도 모르고 있습니다.

이 상황에서 이 멋진 도구의 창조자인 여러분이 바라는 것은 다음과 같습니다.

  1. 다른 개발자들이 이 도구의 존재를 찾고
  2. 그들이 이 도구가 유용하다고 판단하고
  3. 그들이 이 도구의 사용법을 배우고
  4. 그들이 이 도구를 사용해 문제를 푸는 것

위와 같은 일련의 과정에서 문서의 역할은 어디까지일까요?

보통은 여기서 3번과 4번을 문서의 역할이라고 생각하는 경우가 많습니다. 개발자들로 하여금 도구를 사용해 그들의 문제를 풀 수 있도록 돕는 것까지가 문서의 역할이라는 생각이지요. 그러나 사실 문서는 문제를 해결하는 것을 돕는 역할뿐만 아니라, 이 도구가 문제를 풀 수 있다는 사실을 “알리는” 역할도 해야 합니다. 즉 1번에서 4번에 이르는 모든 과정이 문서가 해야 하는 역할입니다.

다시 말해서, 문서는 그 자체로 여러분의 도구를 마케팅하는 하나의 수단이 되어야 합니다.

문서가 가장 먼저 알려줘야 하는 것

문서가 도구를 알리는 마케팅 수단이라면, 구체적으로 문서가 알려줘야 하는 내용은 무엇일까요?

개발자들은 어떤 문제를 풀고 싶어합니다. 문제를 푸는 방법을 찾기 위해 그들은 검색을 하거나, 주변 동료들에게 물어보거나, 인터넷 포럼에 질문을 합니다. 이윽고 그들은 다양한 경로를 통해 여러분이 만든 도구의 존재를 알게 됩니다.

아직 그들은 이 도구가 어떤 것인지, 자신의 문제를 해결할 수 있는 적합한 도구인지 알지 못합니다.

이때 그들이 처음 마주하게 되는 것이 바로 도구를 설명하는 문서입니다. 따라서 여러분은 문서를 통해 이러한 개발자들의 물음을 해결해주어야 합니다. 즉, 문서는 먼저 여러분의 도구가 무엇인지를 정의하는 역할을 하여야 합니다.

도구를 정의한다는 것은 다음과 같은 사항들을 의미합니다.

  • 이 도구가 대체 무엇인지
  • 이 도구의 장점은 무엇인지
  • 이 도구에는 어떤 기능들이 있는지
  • 이 도구의 한계점은 무엇인지

이러한 정보를 통해 개발자들은 이 도구가 무엇이며, 그들의 문제를 푸는데 적합한지를 판단할 수 있게 됩니다.

개발자용 문서의 종류

앞선 문단들에서 문서의 역할이 개발자들이 도구를 찾고, 이해하고, 그리고 최종적으로 문제를 풀 수 있도록 돕는 것이라는 점을 살펴보았습니다.

바꾸어 말하면, 문서의 역할은 매우 다양한데요. 단 하나의 문서가 이 모든 역할을 수행할 수는 없습니다. 문서가 수행하는 역할에 따라서 문서의 종류를 나누어야 합니다.

Django의 코어 개발자인 Daniele Procida는 문서의 종류를 다음과 같이 네 가지 카테고리로 나누었습니다.

Image from: PyCon US 2021 - Writing Good Documentation for Developers
  • 튜토리얼(Tutorials): 도구에 대한 Step-by-Step 가이드
  • 설명서(Explanation): 이 도구가 무엇을 하고, 어떻게 동작하고, 그리고 왜 그렇게 동작하는지
  • 안내 책자(How-to Guide): 실제 문제를 풀기 위해서 이 도구를 어떻게 사용해야 하는지
  • 레퍼런스(Reference): 이 도구가 할 수 있는 모든 것에 대한 객관적이고 자세한 설명

이 네 카테고리는 사용 목적과 활용도를 기준으로 다음과 같이 구분할 수 있습니다.

  • 배울 때 / 실용적인 용도로: 튜토리얼
  • 배울 때 / 이론적인 용도로: 설명서
  • 일할 때 / 실용적인 용도로: 안내 책자
  • 일할 때 / 이론적인 용도로: 레퍼런스

레퍼런스 문서와 API 문서

위에서 소개한 네 가지 카테고리의 문서 분류법은 아주 깔끔해서 이해하기 쉬운데요. 그럼에도 한 가지 한계점을 가지고 있습니다. 바로, 레퍼런스 문서의 역할이 다소 모호하다는 점입니다.

위 분류 방법을 소개한 Daniele는 레퍼런스 문서를 다음과 같이 정의합니다.

“레퍼런스는 도구가 동작하는 방식에 대한 기술적인 설명이다”
“Reference guides are technical descriptions of the machinery and how to operate it."

한편으로 그는 동시에 레퍼런스 문서를 다음과 같은 문장으로 표현하기도 합니다.

“레퍼런스는 API, 클래스, 그리고 함수와 같이 소프트웨어를 구성하는 요소들을 사용하는 방법을 설명한다."
“Reference guides describe the software itself - APIs, classes, functions and so on - and how to use them”

위 두 문장은 닮은 것 같지만 사실 서로 다른 얘기를 하고 있습니다. 두 문장에서 설명하는 내용 모두 우리가 문서에서 얻고자 하는 정보임은 분명합니다. 그러나 한 가지 문서가 이 두 가지 내용을 동시에 설명하는 것은 어렵습니다.

왜 그럴까요? 설명에 앞서 이 글에서는 전자는 레퍼런스 문서, 후자는 API 문서라고 구분하겠습니다. 레퍼런스 문서와 API 문서가 어떤 점에서 다른지 예를 들어 살펴보겠습니다.

예시 1) 테스팅 라이브러리

여러분은 테스트를 수행할 수 있는 라이브러리 L를 만들었습니다. 이제부터 L에 대한 문서를 작성하려고 합니다.

L는 테스트 수행 전, 중, 후에 특정 동작을 수행하도록 하는 함수들을 포함하고 있습니다. 예를 들면, 테스트가 수행되기 전에(setup) 테스트용 클래스 인스턴스를 준비하고, 테스트 중에(test) 해당 인스턴스를 사용한 뒤, 마지막으로 테스트가 끝나면(teardown) 해당 인스턴스를 삭제하는 것과 같이 말이죠. 테스트를 작성해본 분들이라면 언어나 프레임워크에 관계없이 많이 겪어보셨을 과정일 것입니다.

1
2
3
4
5
6
7
8
9
@L.setup
def set_it_up():
    # 테스트 전에 수행됩니다.
@L.test
def test_1():
    # 테스트 중에 수행됩니다.
@L.teardown
def tear_it_down():
    # 테스트 후에 수행됩니다.

이 때, 테스트 전, 중, 후에 사용하는 함수는 각각 다르지만, 일련의 과정은 독립적이지 않습니다. 그렇다면 L를 설명하는 문서에는 일련의 과정을 수행하기 위해, 이 동작들이 어떠한 순서로 일어나는 지를 알려주어야 합니다.

즉, 도구를 사용하는 방식에 대한 스토리텔링(Storytelling)을 담은 문서가 필요합니다. 문서가 스토리텔링을 하지 못한다면, 도구를 사용하는 사람은 개발자의 의도대로 도구를 사용하기 어렵습니다. 이러한 역할을 하는 문서가 바로 레퍼런스 문서입니다.

한편, API 문서는 코드 그 자체를 설명합니다. API 문서에 담긴 내용은 함수나 클래스처럼 코드 그 자체와 관련한 것이여야 합니다.

앞선 예에서, 레퍼런스 문서는 setup, test, teardown 함수가 어떻게 연관되어 있고, 어떤 순서로 사용되어야 하는 지를 알려주어야 한다면, API 문서는 각 함수가 어떤 기능을 하는지 상세하게 알려주는 역할을 하여야 합니다.

예시 2) javadoc 문제

앞선 예에서 레퍼런스 문서와 API 문서의 역할 차이에 대해서 살펴보았습니다.

레퍼런스 문서는 도구를 사용하는 “스토리텔링"을 설명해주는 역할을 하는 반면, API 문서에는 스토리텔링이 등장할 구석이 없습니다. 이는 바꾸어 말하면, 만약 레퍼런스 문서 없이 API 문서만 존재하면 라이브러리를 사용하는 “스토리"를 설명할 수 없다는 문제를 뜻합니다.

이를 잘 설명해주는 예시가 javadoc 문제입니다.

Java 프로젝트의 문서를 자동으로 생성하는 대표적인 도구인 javadoc은 다음과 같이 주석을 이용해 문서를 자동으로 생성합니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
/**
 * Frob the foobar.
 * This method always returns immediately.
 *
 * @param fb A foobar object
 * @param direction The direction in which to frob it.
 *
 * @return true if the object was frobbed successfully.
 */
public boolean frob(FooBar fb, String direction) {
 // ...
}

문서 작성자는 각 함수나 클래스 코드 위에 해당 코드의 설명과 파라미터, 리턴 값 등을 명시하고, 이렇게 표준화된 구조를 바탕으로 javadoc은 자동으로 정형화된 문서를 생성합니다.

이와 같은 javadoc의 방식은 아주 쉽게 표준화된 문서를 생성할 수 있습니다. 각각의 코드 근처에 해당 코드의 설명이 위치함으로써 코드 변화에 맞추어 문서를 관리하는 것도 아주 편리합니다. 그렇기 때문에 javadoc은 크게 성공할 수 있었고, 현재도 많은 Java 라이브러리들이 javadoc을 사용해서 문서화되어 있습니다.

javadoc을 이용해서 문서화된 사이트는 대부분 아래와 같이 생겼는데요.

javadoc으로 만들어진 문서

라이브러리 개발자가 성실하게 주석을 작성했다면, 모든 클래스와 각 클래스를 구성하는 메소드에 대산 정보를 완벽하게 살펴볼 수 있습니다.

그렇지만, 문제는 이 문서에서 수많은 클래스들이 어떻게 상호작용하는 지에 대한 정보는 알 수가 없습니다.

사실 위 사진에 나타난 라이브러리(Apache Commons CLI) 는 굉장히 잘 구조화된 라이브러리입니다. 이 라이브러리를 사용하고자 하는 유저는 단 한 가지 클래스(Option)만 사용하면 이 라이브러리가 제공하는 기능을 대부분 활용할 수 있습니다.

그러나 이 “API 문서"에서는 그 클래스가 무엇인지를 쉽게 알 수가 없습니다.


위의 두 예에서 살펴볼 수 있듯이, 레퍼런스 문서와 API 문서는 서로 구분되어야 하는 문서입니다.

레퍼런스 문서는 시스템을 설명하지만, API 문서는 코드를 설명하고
레퍼런스 문서는 여러 요소를 연결하는 이야기를 설명하지만, API 문서는 각각의 요소들을 단독으로 설명하고
레퍼런스 문서는 논리적 흐름에 따라 배치되어야 한다면, API 문서는 자동화된 규칙에 따라 생성되어야 합니다.

Image from: PyCon US 2021 - Writing Good Documentation for Developers

문서를 연결하는 방법

앞선 내용을 통해 우리는 문서를 5개의 분류로 나눌 수 있음을 살펴보았습니다. 이 문서들은 서로 독립적으로 존재하는 것이 아니라, 각각 용도에 따라 서로를 보완하는 역할을 합니다. 그렇다면 어떻게 이 다양한 분류의 문서들을 함께 사용할 수 있을까요?

가장 먼저 명심해야 할 점은, 유저는 작성자가 의도한 대로 문서를 읽지 않는다는 점입니다. 유저들은 문서를 처음부터 끝까지 읽지 않습니다. 복잡한 API 문서는 물론이고, 짧은 튜토리얼조차도 자신이 필요하다고 생각하는 부분까지만 읽죠. 당연히 문서를 읽을 때의 순서도 작성자가 의도한 순서를 따르지 않습니다.

유저들은 자기만의 “여정"을 하면서 문서를 읽습니다. 따라서 문서를 작성하는 우리가 해야 할 것은 유저의 여정을 상상해보는 것입니다. 유저가 우리의 도구를 찾고 사용하기까지의 여정을 말입니다.

유저가 여러분의 도구를 발견하고 사용하게 되는 흔한 절차는 다음과 같습니다.

  1. 어떤 문제를 풀기 위해 구글링을 하다가, 여러분의 도구를 소개한 튜토리얼 블로그 글을 발견합니다.
  2. 튜토리얼을 읽은 유저는 도구에 흥미가 생깁니다. 그래서 이 도구를 자신의 문제에 적용하는 방법을 담은 안내 책자(How-to) 문서를 읽기 시작합니다.
  3. 자신의 문제에 이 도구를 적용하기로 판단한 유저는 문제에 대한 구체적인 해결책, 즉 클래스와 함수 사용법을 알기 위해서 API 문서를 찾아보기 시작합니다.

위 예는 포괄적인 문서(튜토리얼)에서 시작해서, 상세한 문서(API 문서)로 점점 줌인(Zoom-In)하듯이 유저가 문서에 접근하게 되는 경우입니다. 문서를 작성하는 입장에서는 가장 이상적인 여정이라고도 볼 수 있겠네요.

또 다른 여정을 살펴볼까요?

  1. 문제를 풀기 위해 구글링을 하다가, 도구에 대한 안내 책자(How-to) 문서를 발견합니다.
  2. 이게 대체 어떻게 작동하는 거지? 하고 유저는 흥미를 느끼면서 해당 도구의 개념와 사용법을 담은 레퍼런스 문서를 찾아봅니다.
  3. 레퍼런스를 적당히 훑어본 유저는 이 도구가 자신의 문제를 풀기에 적합하다고 판단하고, 다시 처음부터 사용법을 배우기 위해 차근차근 튜토리얼을 살펴봅니다.

이 예시에서 유저는 자신의 필요에 따라 자세한 레퍼런스 문서를 봤다가, 다시 기초적인 튜토리얼로 돌아가는 등 줌인과 줌아웃을 번갈아가면서 수행했습니다.

이외에도 유저가 문서를 통해 도구를 배우게 되는 여정의 종류는 아주 다양합니다. 따라서 문서를 작성하는 사람의 역할은 이러한 다양한 유저의 여정을 인도해주는 것입니다. 그러나 각 유저가 어떤 여정을 할 지는 예측할 수 없습니다. 그렇기 때문에 가장 쉬운 방법은 문서 간 연결고리를 만드는 것입니다.

예를 들어, 튜토리얼에서 특정한 기능을 사용했다면, 해당 기능을 더 알고 싶은 사람을 위해 레퍼런스 문서로 가는 연결고리를 만드세요. 여기서 연결고리는 꼭 직접적인 하이퍼링크가 아니어도 됩니다. 물리적으로 가까운 위치에 관련 문서를 배치시키는 것또한 방법입니다. 순서상으로 튜토리얼 다음에 레퍼런스를 배치한다거나 하는 식으로 말이죠.

피드백 받기

처음부터 좋은 문서를 쓰기란 어렵습니다. 유저는 언제나 여러분이 예상하지 못한 여정을 하고, 여러분이 상상하는 것과 다른 이유와 방식으로 도구를 사용할 것입니다. 그러므로 가장 좋은 방법은 실제로 도구를 사용하는 유저의 의견을 듣는 것입니다.

유저들의 의견을 듣는 방법은 아주 다양합니다. 가장 직접적이고 확실한 방법은 오프라인 행사에서 도구의 튜토리얼 워크샵을 진행하는 방법이 있죠. 도구를 처음 사용하는 유저들이 어떤 부분에서 어려움을 겪는지 알 수 있습니다.

온라인에서는 도구의 Q&A 채널을 만들면 됩니다. 직접 Q&A가 가능한 포럼을 만들어도 좋지만, 번거롭다면 스택 오버플로우나 깃헙 이슈에 올라오는 질문을 모니터링하고 답하는 것으로도 충분합니다.

Question: Q&A를 위한 슬랙이나 디스코드를 운영하는 것은 어떤가요?

많은 오픈소스 도구들이 슬랙을 통한 소통 채널을 운영하지만, 사실 이는 굉장히 안 좋은 방식입니다. 왜냐하면 사람들이 채널을 통해 무엇인가를 물어본다는 것은 일종의 버그리포트고, 개발자들이 그에 답하는 것은 그 자체가 일종의 패치입니다. 이러한 질답-버그리포트와 패치-이 쌓이면 그 자체로 검색 가능한 문서가 됩니다. 그러나 슬랙과 디스코드처럼 비공개 채널에서 발생하는 대화는 검색이 되지 않기에 질답이 누적되는 효과가 적습니다.

결론

문서는 유저가 처음으로 여러분의 도구를 접하게 되는 곳이자, 도구를 홍보하는 마케팅 수단이자, 그 자체로 도구를 정의하는 물건입니다. 이러한 사실을 인지하고 유저의 입장에서 많이 고민해봐야만 좋은 문서가 탄생할 수 있습니다.