Documentation - Software Engineering at Google

2022. 6. 29. 22:14Software Engineering

반응형

본 포스팅은 Software Engineering at Google의 Code Review Flow 내용을 정리한 내용입니다.

 

해당 내용은 O'reilly에서 출간하고, 저자에 의해 공개된 Software Engineering at Google을 바탕으로 참고하여 정리한 내용입니다.

내용이 재밌기도 하고 기록하고 싶은 내용이 많아서 몇 가지 정리해볼 예정입니다.

 

이번 주제는 문서화에 대한 내용을 다룹니다.

해당 내용은 아주 중요하다고 하기 보다는, 사내 혹은 팀내에 문서화 문화를 정착시킬 때 참고하면 좋을만한 내용이었습니다. 조금 훑어보면 구글은 문서화에 대한 중요성을 느끼고 마치 코드와 같이 관리한다고 합니다. 버전 정보를 관리하고, 리뷰를 받기도 하죠. 대부분의 내용은 개인적으로도 문서화를 할 때나 주석을 적을 때 참고하면 좋을 내용이었고, 실제 저자도 그렇게 말하고 있습니다.

 


 

Documentation

문서자료 

 

Documentation(이하 Docs)은 엔지니어가 작업을 끝마치기 위해 작성해야 하는 모든 부수적인 텍스트를 의미한다. 

별도로 작성한 문서뿐 아니라 코드 주석까지 포함되는데, 사실 구글에서 엔지니어가 작성하는 문서자료 대부분은 코드 주석이다.

"잘쓴 문서"는 해당 목적에 특화되게 적는 것이다.

 

 

Why Is Docs Needed?

 

문서자료는 단 한 번만 작성하면 되지만 결국 수백 번, 수천 번 읽히게 된다.

문서자료의 혜택은 시간에 비례해 커지고, 해당 코드를 조직의 구석구석까지 퍼뜨리기 위해서는 없어서는 안 되는 요소로 작용한다.

 

예를 들어 아래와 같은 질문들에 답을 제시해 준다.

- 이 설계를 택한 이유가 뭐지? 

- 코드를 왜 이런 식으로 구현했을까?

- (예컨대 2년 후 자신의 코드를 살펴보며) ‘내가’ 왜 이렇게 구현했지?

 

문서자료는 다양한 부류의 사람에게 혜택을 줄 뿐만아니라, 작성자에게도 아래와 같은 도움을 준다.

 


✔️ API를 다듬는 데 도움을 준다.

API 문서화는 API가 가치가 있는지를 알아내는 가장 확실한 방법중 하나이다. 

문서화를 하다 보면 자연스럽게 자신의 설계를 되돌아볼 수도 있고,

API를 깔끔하게 설명 하거나 정의할 수 없다면 설계가 미흡했을 가능성이 크다는 것을 확인할 수 있다.

 


✔️ 유지보수를 위한 로드맵과 과거 이력을 제공한다.

코드를 짜다보면 부득이하게 꼼수를 사용하는 경우가 있는데, 당연히 이런 일은 없어야 하지만 정말 어쩔 수 없다면 주석이라도 잘 작성해둬야 한다. 잘만 작성해두면 2년 전 코드에서 문제점을 찾아야 하는 경우 큰 도움이 되어 줄 수 있다.

 

 

✔️ 코드를 더 전문적이고 매력 있어 보이게 한다.

개발자들은 무의식적으로 문서화가 잘되어 있는 API를더 잘 설계된 API라고 여긴다. 

항상 그런 것은 아니지만 일반적으로 상관성이 높다. 겉치레로 들릴 수도 있을 텐데, 그렇지 않다. 

문서화가 잘되어 있는 제품은 유지관리가 잘되고 있는 제품일 확률이 높기 때문이다. 

 

 

✔️ 이용자들의 질문이 줄어든다. 

다른 사람에게 두 번 이상 같은 설명을 하고 있다면, 그 내용을 문서화하는 게 좋다. 질문이 줄어드는 것은 아마 작성자에게 가장 크게 와닿는 장점이며, 시간이 갈수록 그 혜택을 톡톡히 볼 것이다.

 

물론 더 큰 혜택은 문서자료를 읽는 이들에게 돌아갈 것이다.

이 이유로 구글의 C++ 스타일 가이드는 ‘읽는 이에게 최적화하라’라고 이야기한다.





Docs Is Like Code

코드와 마찬가지로 일관되어야 하고, 명확해야 하고, 이해를 방해하는 오류를 피해야한다. 

기술 문서를 작성할 때도 문법은 중요하다.

단지 규칙이 필요해서가 아니다. 설명하는 문체를 표준화하고 혼동 요소를 없애서 독자가 헷갈리지 않게 하기 위함이다.

 

 

✔️ 반드시 따라야 하는 내부 정책과 규칙을 정의
✔️ 버전 관리 시스템에 등록하여 관리
✔️ 관리 책임자 명시
✔️ 변경 후 리뷰 ( + 문서자료가 설명하는 코드와 함께)
✔️ 코드상의 버그를 추적하듯, 문서 내의 문제를 추적
✔️ 주기적으로 평가(혹은 테스트)
✔️ 가능하다면 정확성이나 최신 정보 반영 여부 등을 측정할 수 있는 장치를 마련

 

 

 

 

Know Your Audience

문서 작성의 핵심은 균형을 잘 잡는 것이다. 

구글이 하나 발견한 잘 작성하는 법에 대한 팁은 '짧게' 쓰는 것이다.

주제가 복잡할 때, 그 내용을 처음 접하는 독자를 위해 충분히 설명은 해야겠지만 너무 장황하면 짜증나게 만들 것이다.

 

문서를 짧게 쓰려면 먼저 모든 정보를 담아 쓴 다음, 편집과 중복을 삭제하는 과정을 거친다.

지루한 작업 같겠지만 해당 문서자료의 독자에게 큰 혜택으로 돌아간다는 사실을 잊지마라. 

 

프랑스 과학자이자 철학자인 블레즈 파스칼 Blaise Pascal 은 ‘시간이 더 있었다면 편지가 보다 짧아졌을 거예요’라고 말했다. 문서를 짧고 명확하게 관리한다면 전문가와 초보자 모두를 만족시킬 수 있다.

 

 

Types of Audiences

글을 쓸 때 중요한 요소 중 하나가 독자의 눈높이에 맞는 수준으로 도메인 지식을 다뤄야 한다는 것이다.

기준에 따라 여러 성격의 독자가 있을 수 있는데, 아래와 같은 기준을 생각해볼 수 있다.

 

Experience level 경험 수준

: 전문가 ~ 언어 조차 낯선 초보 엔지니어

 

Domain knowledge 도메인 지식

팀원 ~ API Endpoint만 친숙한 엔지니어

 

Purpose 목적

: 급히 정보만 얻는자 ~ 아무도 맡기 싫어하는 구현까지 하려는 전문가

 

 

 

또는 문서자료를 접하는 방식에 따라서도 구분할 수 있다.

 

 

✔️ Seeker

탐색자 : 자신이 원하는 것을 정확히 알고, 읽고 있는 문서자료가 원하는 정보를 담고 있는지를 알고 싶어 하는 사람

 

이런 독자에게는 일관성이 핵심이다.

코드 주석과 같은 Seeker를 타겟으로한 문서를 작성한다면 일관되게 적는 게 좋다.

빠르게 훑으며 본인이 찾는 내용이 맞는지 판단하기 편할 것이다.

 

 

✔️ Stumbler

배회자 : 무엇을 원하는지를 정확하게 알지 못하는 사람

 

아마도 어떠한 기능을 어떻게 구현해야 할지에 대해 어슴푸레한 아이디어만 가지고 있을 것이다.

이런 독자에게는 명료한 글이 효과적이다.

 

예를들어 파일의 맨 위에 개요나 소개 절을 두어 파일에 담겨 있는 코드의 목적을 설명할 수 있다.

혹은 어떤 독자에게 적합하지 ‘않은’ 문서인지를 알려주는 것도 유용한데,

실제 구글 문서 중 상당수는 아래와 같이 ‘TL;DR문’으로 시작한다.

 

"TL;DR : 구글의 C++ 컴파일러가 궁금한 게 아니라면 더 읽을 필요 없습니다"

 

 

 

Docs Types

문서 타입은 Reference Documentation, Design Docs, Tutorials, Conceptual Documentation, Landing Pages으로 5가지를 설명하는데 해당 포스팅에서는 Reference Documentation, Tutorials 만을 정리한다.

 

Reference Documentation

매일 작성하거나, 코드베이스에 속한 코드의 사용법을 설명하는 문서 모두를 말한다.

 

 

✔️ File comments

파일 주석

 

구글에서는 거의 모든 코드 파일에 파일 주석이 적혀있어야 한다.

아래 코드와 같이 일반적으로 파일 주석에서는 파일에 담겨 있는 내용을 요약해줘야 한다.

해당 코드의 주요 쓰임새어떤 독자를 의도하고 만든 코드인지를 명시하는 것이다.

 

// -----------------------------------------------------------------------------
// str_cat.h
// -----------------------------------------------------------------------------
//
// This header file contains functions for efficiently concatenating and appending
// strings: StrCat() and StrAppend(). Most of the work within these routines is
// actually handled through use of a special AlphaNum type, which was designed
// to be used as a parameter type that efficiently manages conversion to
// strings and avoids copies in the above operations.
…

 

한두 문단으로 간결하게 설명할 수 없는 API라면 충분히 사려 깊게 설계되지 않은 API일 수 있다는 신호이기 때문에, API를 분리하는 방안을 고려해보는 게 좋다.

 

 

 

✔️ Class comments

클래스 주석

 

현대적 언어들은 대부분 객체지향을 지원하며,

클래스 주석은 코드베이스에서 사용되는 API 객체들을 정의하는 중요한 주석이다.

구글에서는 모든 public class(and structs)는 해당 목적과 주요 메서드들을 설명하는 클래스 주석을 담고 있어야 한다.

 

// -----------------------------------------------------------------------------
// AlphaNum
// -----------------------------------------------------------------------------
//
// The AlphaNum class acts as the main parameter type for StrCat() and
// StrAppend(), providing efficient conversion of numeric, boolean, and
// hexadecimal values (through the Hex type) into strings.

 

클래스 주석은 보통 "objects"임을 부각하기 위해 클래스 자체를 문장의 주어로 두고 어떻게 동작하는지를 설명하는 형태로 작성한다. 예를 들어 아래와 같이 작성한다.

 

"The Foo class contains x, y, z, allows you to do Bar, and has the following Baz aspects"
- Foo 클래스는 x, y, z 속성을 가지며, Bar라는 기능을 제공하고, 다음과 같이 Baz라는 측면을 지니고 있다

 

 

 

✔️ Function comments

함수 주석

 

구글에서는 반드시 function(method)이 "무슨 일을 하는지"를 설명하는 함수 주석이 있어야 한다. 함수 주석은 함수가 무슨 동작을 하고 무엇을 반환하는지를 설명하며, "능동성does"을 부각하기 위해 동사로 시작해야 한다.

 

// StrCat()
//
// Merges the given strings or numbers, using no delimiter(s),
// returning the merged result as a string.
…

 

이처럼 함수 주석을 선언적인 동사로 시작하면 헤더 파일 전체에 일관성이 생긴다.

탐색자는 API 설명의 첫 동사만으로 원하는 기능이 맞는지를 빠르게 파악할 수 있다.

e.g. Merges, Deletes, Creates ...

 

함수 주석에서 ‘Returns’, ‘Throws’ 같은 다양한 보일러플레이트(상용구)를 사용하는 경우도 있지만, 인위적으로 섹션을 구분하지 않고 하나의 문장으로 표현하는 게 더 명확한 경우가 많았다.

 

// Creates a new record for a customer with the given name and address,
// and returns the record ID, or throws `DuplicateEntryError` if a
// record with that name already exists.
int AddCustomer(string name, string address);

 

사후조건, 매개변수, 반환값, 예외 상황이 하나의 문장에 자연스럽게 녹아 있는 모습이 보기 좋았다. 실제로 서로 독립적이지 않기 때문이다. 각각을 상용구 섹션에서 구분해 적는다면 장황하고 반복적이게 되어 명확성이 오히려 떨어질 것이다. (모두가 동의하진 않겠지만,)

 

 

 

Tutorials

튜토리얼에서 중요한 것은 당신이 수행해야 했던 모든 일을 적는 것이다.

어떠한 사전 설정, 권한, 도메인 지식도 가정하지 말아야하며,

설정 사항들은 튜토리얼 앞부분의 사전 요구사항 절에 명시하는 것이 좋다.

 

대부분의 튜토리얼은 전체 과정을 여러 단계로 나눠 안내한다. 이 때, 각 단계에 명확한 번호를 붙여야 한다.

 

 

📌 A bad Tutorial

 

1. http://example.com 서버에서 패키지를 다운로드한다. 
2. 셸 스크립트를 홈 디렉터리에 복사한다.
3. 셸 스크립트를 실행한다. 
4. 이제 foobar 시스템이 인증 시스템과 통신할 것이다. 
5. 인증이 완료되면 foobar가 ‘baz’라는 새 데이터베이스를 실행시킬 것이다.
6. 명령줄에서 SQL 명령으로 ‘baz’가 실행되는지 확인할 수 있다. 
7. CREATE DATABASE my_foobar_db;를 입력한다.

 

 

이 절차에서 4단계와 5단계는 서버에서 이루어진다.

해당 튜토리얼은 독자가 무언가를 해야 하는지가 불분명한데, 흐름상 3단계에 추가하는게 좋아 보인다.

또한 6단계와 7단계가 서로 다른 일을 하는 건지도 불분명하다.

실제로는 같은 일이기 때문이다.

 

독자가 한 번에 수행하는 작업은 하나의 단계에서 설명하여 각 단계에서 할 일을 헷갈리지 않도록 해야 한다. 또한 독자가 눈으로 확인할 수 있는 입력이나 출력이 있다면 별도의 줄에 명시해주는 게 좋다.

보통 고정폭의 굵은 글꼴로 표기한다. 하단의 개선된 튜토리얼 참고

 



📌 A bad Tutorial made Batter

개선된 튜토리얼

 

1. http://example.com 서버에서 패키지를 다운로드합니다.

$ curl -I http://example.com

 

2. 셸 스크립트를 홈 디렉터리에 복사합니다. 

$ cp foobar.sh ~

 

3. 홈 디렉터리에서 셸 스크립트를 실행합니다. 

$ cd ~; foobar.sh

 

이제 foobar 시스템이 인증 시스템과 통신할 것입니다. 인증이 완료되면 foobar가 ‘baz’ 라는 새 데이터베이스를 구동한 다음 사용자가 명령을 입력할 수 있는 셸을 띄울 것입니다. 

 

4. 명령줄에서 다음 SQL 명령을 실행하여 ‘baz’가 제대로 동작하는지 확인합니다. 

baz:$ CREATE DATABASE my_foobar_db;

 

 

여기서 모든 단계에서 독자가 특정한 일을 수행해야 한다는 것을 확인할 수 있다.

 

 

 

Docs Reviews

기술 문서 리뷰에 효과적인 방식은 크게 세 가지입니다. 각각은 다음과 같이 서로 다른 측면을 중점적으로 살핍니다. 

 

A technical review, for accuracy

기술 리뷰 - 정확성

주로 해당 주제 전문가가 수행하며, 팀 동료인 경우가 많다. 코드 리뷰 과정에서 함께 다루곤 한다.

 

An audience review, for clarity.

독자 리뷰 - 명확성

주로 도메인을 잘 모르는 사람이 수행한다. 팀에 새로 합류한 동료나 해당 API의 고객일 것이다. 

 

  A writing review, for consistency.

작문 리뷰 - 일관성

주로 테크니컬 라이터나 자원자가 수행한다.

 

 

 

Docs Philosophy

기술 문서자료들의 틀을 제대로 구성해놓지 않으면 혼란스러운 문서가 되곤 한다. 

그러니 어떤 문서든 처음 두 문단이 끝나기 전에 다음 키워드를 생각해보며 틀을 잡아가자.


WHO ?

독자다.

혹은 대상 독자가 누구인지를 문서 안에서 명확하게 밝혀줘야 할 때도 있다.

가령, ‘Secret Wizard 프로젝트에 새로 합류한 엔지니어를 위한 문서입니다’처럼 말이다. 

 

WHAT ?

문서의 목적을 알려준다.

 

‘이 문서는 Frobber 서버를 테스트 환경에서 구동하기 위해 설계된 튜토리얼입니다’ 처럼 말이다.

때로는 ‘무엇’을 작성하는 것만으로 문서를 적절하게 구성하는 데 도움이 된다.

예를 들어 ‘무엇’과 연관이 없는 정보가 적혀 있다면 해당 내용을 별도 문서로 옮기라는 신호이다. 

 

WHEN ?

문서가 생성되고, 리뷰되고, 갱신된 날짜를 말한다.

소스 코드에 임베드된 문서자료는 날짜 정보가 묵시적으로 들어간다.

다른 형태의 문서자료들도 게시publishisng될 때 이 정보가 자동으로 추가되기도 한다.

만약 자동화된 시스템이 없다면 문서 자체에 작성일(혹은 최종 갱신일)을 기입하길 바란다. 

 

WHERE ?

문서가 존재해야 할 장소를 말해주며, 역시 묵시적으로 결정되는 경우가 많다.

보통 설정과 관련된 정보는 버전 관리 시스템으로,

보통 해당 문서자료가 설명하는 소스 코드와 함께 관리한다.

그 외 목적의 정보는 다른 포맷의 문서를 이용한다.

 

예를 들어 구글에서는 특히 설계와 관련한 문제는 구글 문서 Google Docs 를 애용하는데, 협업하기 편하기 때문이다. 하지만 어느 시점부터 공유 문서의 주 용도가 ‘논의’보다는 ‘안정된 버전 기록’ 쪽으로 치우치기 시작한다. 그 시점이 되면 더 안정적이고, 소유권도 명확하고, 버전 관리도 잘 되는 다른 시스템으로 옮기는 게 좋다.

 

 

WHY ?

문서의 목적을 설정한다.

문서를 읽은 독자가 무엇을 얻어가기를 바라는지를 요약한다. 경험상 ‘WHY’는 문서의 소개 부분에 명시하는 게 좋다. 그러면 마지막에 요약을 작성할 때 ‘WHY’를 기초로 원래 기대한 바를 달성했는지를 확인하고 달성하도록 보강할 수 있다.

 

 

 

 

Deprecating Docs

문서 폐기

 

오래된 코드와 마찬가지로 오래된 문서도 문제를 일으키곤 한다.

문서를 버리는 일은 되도록 생기지 않도록 노력해야 하지만, 

문서가 본래의 목적을 더 이상 수행할 수 없다면 폐기하거나 폐기 대상으로 표시해 줘야 한다

그리고 할 수 있다면 최신 정보의 위치를 명시해라.

 
내 소유가 아니더라도 ‘이 문서는 더 이상 유효하지 않다’ 같은 댓글을 남길 수 있다.

아무런 표식 없이 마치 여전히 유효한 문서처럼 돌아다니는 것보다 훨씬 낫다.

 

구글에서는 아래와 같이 문서자료에 ‘신선도 보증 기간 freshness date ’을 붙여두곤 한다.

문서에 마지막으로 리뷰한 날짜를 기록해두면 이를 활용하여 가령 3개월 동안 갱신되지 않을 시 알림 메일을 보내는 식이다.  신선도 보증 기간은 (그리고 문서의 오류도 버그처럼 추적하면) 이 문서를 관리하는 골칫거리를 해결하는 데 효과적이다. 

 

<!--*
# Document freshness: For more information, see go/fresh-source.
freshness: { owner: `username` reviewed: '2019-02-27' }
*-->

 

 

반응형