XML 주석으로 코드 문서화하기
XML 주석으로 코드 문서화하기 (Document your code with XML comments)
F#에서는 삼중 슬래시(///)로 시작하는 코드 주석으로 API 문서를 만들어 낼 수 있어요. XML 주석은 코드 파일(.fs)이나 시그니처 파일(.fsi)의 선언보다도 위에 추가되는 특별한 종류의 주석인데요, 이 페이지에서 어떻게 쓰고, 어떤 태그를 쓸 수 있으며, 컴파일러가 어떤 검사를 해 주는지 하나씩 살펴볼게요.
출처: https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/xml-documentation
본문
XML 문서 주석이 뭔가요
F#에서는 삼중 슬래시(///) 코드 주석으로 문서를 만들 수 있어요. XML 주석은 코드 파일(.fs) 또는 시그니처 파일(.fsi)에 정의된, 사용자가 정의한 타입이나 멤버의 정의 위에 추가되는 특별한 종류의 주석이에요.
특별한 이유는, 컴파일러가 이 주석을 처리해서 컴파일 타임에 XML 문서 파일을 생성해 줄 수 있기 때문이에요. 이렇게 생성된 XML 파일을 .NET 어셈블리와 함께 배포하면 IDE가 툴팁으로 타입이나 멤버에 대한 간단한 정보를 보여줄 수 있고요. 또 이 XML 파일을 fsdocs 같은 도구에 넣으면 API 레퍼런스 웹사이트를 만들 수도 있어요.
기본적으로 컴파일러는 XML 문서 주석을 무시해요. 이 동작을 바꾸려면 --warnon:3390을 설정하면 되는데, 그럼 컴파일러가 XML의 문법과 <param>, <paramref> 태그에서 참조하는 매개변수를 검증하게 돼요.
프로젝트 파일에서는 <PropertyGroup> 섹션에 <WarnOn> 요소를 추가해서 이 경고를 켤 수 있어요:
<WarnOn>3390</WarnOn>
XML 파일은 컴파일 타임에 다음과 같은 방법으로 생성할 수 있어요.
-
.fsproj프로젝트 파일의<PropertyGroup>섹션에<GenerateDocumentationFile>요소를 추가하면, 어셈블리와 같은 루트 이름을 가진 XML 파일이 프로젝트 디렉터리에 생성돼요. 예를 들면 이렇게요:<GenerateDocumentationFile>true</GenerateDocumentationFile>자세한 내용은 GenerateDocumentationFile property 문서를 참고하세요.
-
Visual Studio로 애플리케이션을 개발하고 있다면, 프로젝트를 우클릭하고 속성(Properties) 을 선택한 뒤 속성 대화 상자에서 빌드(Build) 탭을 열고 XML documentation file을 체크하면 돼요. 컴파일러가 파일을 쓸 위치도 바꿀 수 있어요.
XML 문서 주석을 쓰는 방법은 두 가지예요. XML 태그를 쓰는 방법과 쓰지 않는 방법인데, 둘 다 삼중 슬래시 주석을 사용해요.
XML 태그 없이 쓰기
/// 주석이 <로 시작하지 않으면, 주석의 전체 텍스트가 바로 뒤에 오는 코드 구문의 요약(summary) 문서로 취급돼요. 각 구문에 짧은 요약만 남기고 싶을 때 이 방법을 쓰면 좋아요.
문서 준비 과정에서 주석이 XML로 인코딩되기 때문에 <, >, & 같은 문자는 이스케이프하지 않아도 돼요. 요약 태그를 명시적으로 지정하지 않는다면 param이나 returns 같은 다른 태그도 지정하지 않는 게 좋아요.
Note — XML 태그 없이 주석을 쓸 때는, 넣은 마크업(HTML 태그나 XML 비슷한 문법)을 컴파일러나 F# 도구가 파싱하거나 검사하지 않아요. GitHub 같은 일부 외부 도구가 그 마크업을 해석하려고 시도할 수는 있는데, 문법에 오류가 있으면 실패할 수 있어요. 문서에 XML 태그를 꼭 써야 한다면
<summary>같은 제대로 된 XML 태그로 주석을 감싸서,--warnon:3390이 켜져 있을 때 컴파일러가 검증할 수 있게 하는 게 좋아요.
다음 예시는 XML 태그 없이 쓰는 방법을 보여줘요. 이 예시에서는 주석의 전체 텍스트가 요약으로 간주돼요.
/// Creates a new string whose characters are the result of applying
/// the function mapping to each of the characters of the input string
/// and concatenating the resulting strings.
val collect : (char -> string) -> string -> string
XML 태그와 함께 쓰기
주석 본문이 <로 시작하면(보통 <summary>), XML 태그를 사용하는 XML 형식의 주석 본문으로 취급돼요. 이 두 번째 방법은 짧은 요약, 추가 설명(remarks), 각 매개변수와 타입 매개변수, 발생하는 예외, 그리고 반환값 설명을 각각 따로 지정할 수 있게 해줘요. 시그니처 파일에서 쓰는 전형적인 XML 문서 주석은 이런 모양이에요:
/// <summary>Builds a new string whose characters are the results of applying the function <c>mapping</c>
/// to each of the characters of the input string and concatenating the resulting
/// strings.</summary>
/// <param name="mapping">The function to produce a string from each character of the input string.</param>
///<param name="str">The input string.</param>
///<returns>The concatenated string.</returns>
///<exception cref="System.ArgumentNullException">Thrown when the input string is null.</exception>
val collect : (char -> string) -> string -> string
권장 태그 (Recommended Tags)
XML 태그를 쓴다면, 다음 표는 F# XML 코드 주석에서 인식하는 바깥쪽(외곽) 태그들을 설명해요.
| 태그 문법 | 설명 |
|---|---|
<summary> text </summary> |
텍스트가 프로그램 요소에 대한 간단한 설명임을 나타내요. 보통 한두 문장으로 써요. |
<remarks> text </remarks> |
텍스트에 프로그램 요소에 대한 보충 정보가 들어 있음을 나타내요. |
<param name=" name "> description </param> |
함수나 메서드 매개변수의 이름과 설명을 지정해요. |
<typeparam name=" name "> description </typeparam> |
타입 매개변수의 이름과 설명을 지정해요. |
<returns> text </returns> |
텍스트가 함수나 메서드의 반환값을 설명함을 나타내요. |
<exception cref=" type "> description </exception> |
발생할 수 있는 예외의 타입과, 어떤 상황에서 던져지는지를 지정해요. |
<seealso cref=" reference "/> |
다른 타입의 문서로 연결되는 See Also 링크를 지정해요. reference는 XML 문서 파일에 나타나는 그 이름이에요. See Also 링크는 보통 문서 페이지 하단에 표시돼요. |
다음 표는 설명 섹션 안에서 쓰는 태그들을 설명해요.
| 태그 문법 | 설명 |
|---|---|
<para> text </para> |
텍스트의 한 문단을 지정해요. remarks 태그 안에서 텍스트를 구분할 때 사용해요. |
<code> text </code> |
텍스트가 여러 줄의 코드임을 나타내요. 문서 생성 도구가 코드에 어울리는 글꼴로 표시할 수 있어요. |
<paramref name=" name "/> |
같은 문서 주석 안에 있는 매개변수를 참조해요. |
<typeparamref name=" name "/> |
같은 문서 주석 안에 있는 타입 매개변수를 참조해요. |
<c> text </c> |
텍스트가 인라인 코드임을 나타내요. 문서 생성 도구가 코드에 어울리는 글꼴로 표시할 수 있어요. |
<see cref=" reference "> text </see> |
다른 프로그램 요소로 연결되는 인라인 링크를 지정해요. reference는 XML 문서 파일에 나타나는 그 이름이고, text는 링크에 표시되는 텍스트예요. |
사용자 정의 태그 (User-defined tags)
앞서 본 태그들은 F# 컴파일러와 일반적인 F# 편집기 도구가 인식하는 태그들이에요. 하지만 사용자가 자신만의 태그를 정의하는 것도 자유로워요. fsdocs 같은 도구는 <namespacedoc> 같은 추가 태그를 지원해 주고요. 자체 제작 문서 생성 도구도 표준 태그를 그대로 쓸 수 있으며, HTML부터 PDF까지 여러 출력 형식을 지원하도록 만들 수 있어요.
컴파일 타임 검사 (Compile-time checking)
--warnon:3390이 켜져 있으면 컴파일러가 XML의 문법과 <param>, <paramref> 태그에서 참조하는 매개변수를 검증해요.
F# 구문 문서화하기 (Documenting F# Constructs)
모듈, 멤버, 유니온 케이스, 레코드 필드 같은 F# 구문은 선언 바로 앞에 오는 /// 주석으로 문서화해요. 필요하다면 클래스의 암시적 생성자는 인자 목록 앞에 /// 주석을 달아 문서화할 수 있어요. 예를 들면 이렇게요:
/// This is the type
type SomeType
/// This is the implicit constructor
(a: int, b: int) =
/// This is the member
member _.Sum() = a + b
제약 사항 (Limitations)
F#에서는 C#이나 다른 .NET 언어의 XML 문서 기능 중 일부가 지원되지 않아요.
- F#에서 상호 참조(cross-reference)는 해당 심볼의 전체 XML 시그니처를 사용해야 해요. 예를 들어
cref="T:System.Console"처럼요.cref="Console"같은 C# 스타일의 간단한 상호 참조는 전체 XML 시그니처로 확장되지 않고, 이런 요소는 F# 컴파일러가 검사하지 않아요. 일부 문서 도구는 후처리 과정에서 이런 상호 참조를 허용할 수는 있지만, 전체 시그니처를 쓰는 게 좋아요. <include>,<inheritdoc>태그는 F# 컴파일러가 지원하지 않아요. 써도 오류가 나지 않지만, 생성되는 문서에 아무 영향도 주지 않은 채 그대로 복사만 돼요.- 상호 참조는
-warnon:3390을 써도 F# 컴파일러가 검사하지 않아요. <typeparam>,<typeparamref>태그에 쓰는 이름도--warnon:3390을 써도 F# 컴파일러가 검사하지 않아요.- 문서가 빠져 있어도 경고가 나오지 않아요.
--warnon:3390을 써도 마찬가지예요.
권장 사항 (Recommendations)
코드 문서화는 여러 이유로 권장돼요. 다음은 F# 코드에서 XML 문서 태그를 쓸 때 알아두면 좋은 모범 사례와 일반적인 사용 시나리오예요.
- 코드에서
--warnon:3390옵션을 켜서 XML 문서가 올바른 XML이 되도록 도와주세요. - 긴 XML 문서 주석을 구현과 분리하려면 시그니처 파일 추가를 고려해 보세요.
- 일관성을 위해, 공개로 보이는 모든 타입과 그 멤버를 문서화하세요. 해야 한다면 전부 해야 해요.
- 최소한 모듈, 타입, 그리고 그 멤버에는 평범한
///주석이나<summary>태그가 있어야 해요. 이래야 F# 편집 도구의 자동 완성 툴팁 창에 표시돼요. - 문서 텍스트는 마침표로 끝나는 완전한 문장으로 작성하세요.