NatSpec 형식

NatSpec 형식 (NatSpec Format)

Solidity 컨트랙트는 특별한 형태의 주석을 사용해 함수, 반환 변수 등에 대한 풍부한 문서를 제공할 수 있어요. 이 특별한 형식을 이더리움 자연어 명세 형식(Ethereum Natural Language Specification Format, NatSpec)이라고 불러요. 컨트랙트를 만들 때 공개 인터페이스 전체(ABI 안의 모든 것)를 NatSpec으로 주석 처리하는 걸 권장해요.

출처: 문서

본문

Solidity 컨트랙트는 특별한 형태의 주석을 사용해 함수, 반환 변수 등에 대한 풍부한 문서를 제공할 수 있어요. 이 특별한 형태를 이더리움 자연어 명세 형식(Ethereum Natural Language Specification Format, NatSpec)이라고 해요.

참고 (Note)

NatSpec은 Doxygen에서 영감을 받았어요. Doxygen 스타일의 주석과 태그를 사용하지만 Doxygen과의 엄격한 호환성을 유지하려는 의도는 없어요. 아래에 나열된 지원 태그를 신중히 살펴봐 주세요.

이 문서는 개발자 중심 메시지와 최종 사용자 대상 메시지로 나뉘어요. 이 메시지들은 최종 사용자(사람)가 컨트랙트와 상호작용할 때(즉 트랜잭션에 서명할 때) 보여질 수 있어요. Solidity 컨트랙트는 모든 공개 인터페이스(ABI 안의 모든 것)에 대해 NatSpec으로 완전히 주석 처리하는 것을 권장해요.

NatSpec은 스마트 컨트랙트 작성자가 사용할 주석 형식을 포함하며, Solidity 컴파일러가 이해하는 형식이에요. 아래에는 컴파일러가 이 주석들을 기계가 읽을 수 있는 형식으로 추출한 출력도 자세히 설명돼 있어요.

NatSpec은 제3자 도구가 사용하는 주석도 포함할 수 있어요. 이는 대부분 @custom:<name> 태그로 이루어지며, 분석·검증 도구가 좋은 사용 사례예요.

문서 예시 (Documentation Example)

문서는 각 contract, interface, library, function, enum, enum 값, event 위에 Doxygen 표기 형식으로 삽입돼요. public 상태 변수는 NatSpec 목적상 함수와 동일해요.

  • Solidity의 경우 단일 또는 여러 줄 주석에 ///를 쓰거나 /**로 시작해 */로 끝낼 수 있어요.
  • Vyper의 경우 내부 내용에 들여쓴 """를 같은 주석과 함께 사용해요. Vyper 문서를 참고하세요.

다음 예시는 사용 가능한 모든 태그를 사용한 컨트랙트와 함수를 보여줘요.

참고 (Note)

Solidity 컴파일러는 태그가 external이거나 public일 때만 해석해요. internal이나 private 함수에 같은 주석을 쓰는 건 괜찮지만 그 주석은 파싱되지 않아요. 이는 미래에 바뀔 수 있어요.

open in Remix

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.2 < 0.9.0;

/// @title A simulator for trees
/// @author Larry A. Gardner
/// @notice You can use this contract for only the most basic simulation
/// @dev All function calls are currently implemented without side effects
/// @custom:experimental This is an experimental contract.
contract Tree {
    /// @notice Calculate tree age in years, rounded up, for live trees
    /// @dev The Alexandr N. Tetearing algorithm could increase precision
    /// @param rings The number of rings from dendrochronological sample
    /// @return Age in years, rounded up for partial years
    /// @return Name of the tree
    function age(uint256 rings) external virtual pure returns (uint256, string memory) {
        return (rings + 1, "tree");
    }

    /// @notice Returns the amount of leaves the tree has.
    /// @dev Returns only a fixed number.
    function leaves() external virtual pure returns(uint256) {
        return 2;
    }
}

contract Plant {
    function leaves() external virtual pure returns(uint256) {
        return 3;
    }
}

contract KumquatTree is Tree, Plant {
    function age(uint256 rings) external override pure returns (uint256, string memory) {
        return (rings + 2, "Kumquat");
    }

    /// Return the amount of leaves that this specific kind of tree has
    /// @inheritdoc Tree
    function leaves() external override(Tree, Plant) pure returns(uint256) {
        return 3;
    }
}

태그 (Tags)

모든 태그는 선택적이에요. 다음 표는 각 NatSpec 태그의 목적과 사용 위치를 설명해요. 특별한 경우로, 태그를 전혀 사용하지 않으면 Solidity 컴파일러는 /// 또는 /** 주석을 @notice로 태그된 것처럼 해석해요.

태그 설명 컨텍스트
@title 컨트랙트/인터페이스를 설명하는 제목 contract, library, interface, struct, enum, enum values
@author 작성자 이름 contract, library, interface, struct, enum, enum values
@notice 최종 사용자에게 이것이 무엇을 하는지 설명 contract, library, interface, function, public state variable, event, struct, enum, enum values, error
@dev 개발자에게 추가 세부사항 설명 contract, library, interface, function, state variable, event, struct, enum, enum values, error
@param Doxygen처럼 파라미터를 문서화(반드시 파라미터 이름이 뒤따라야 함) function, event, enum values, error
@return 컨트랙트 함수의 반환 변수를 문서화 function, enum, enum values, public state variable
@inheritdoc 기본 함수에서 빠진 모든 태그를 복사(반드시 컨트랙트 이름이 뒤따라야 함) function, enum, enum values, public state variable
@custom:... 커스텀 태그, 의미는 애플리케이션 정의 everywhere

함수가 (int quotient, int remainder)처럼 여러 값을 반환하면, @param 문과 같은 형식으로 여러 @return 문을 사용해요.

커스텀 태그는 @custom:으로 시작하며 뒤에 하나 이상의 소문자 또는 하이픈이 따라야 해요. 하이픈으로 시작할 수는 없어요. 어디서든 사용할 수 있고 개발자 문서의 일부예요.

동적 표현식 (Dynamic expressions)

Solidity 컴파일러는 Solidity 소스 코드의 NatSpec 문서를 이 안내서에서 설명한 대로 JSON 출력으로 전달해요. 이 JSON 출력을 소비하는 쪽, 예를 들어 최종 사용자 클라이언트 소프트웨어는 이를 최종 사용자에게 직접 보여주거나 일부 전처리를 적용할 수 있어요.

예를 들어 어떤 클라이언트 소프트웨어는 다음을:

open in Remix

/// @notice This function will multiply `a` by 7

호출되는 함수의 입력 a에 값 10이 할당되면 최종 사용자에게 다음과 같이 렌더링해요:

This function will multiply 10 by 7

상속 참고 사항 (Inheritance Notes)

NatSpec이 없는 함수는 자동으로 기본 함수의 문서를 상속받아요. 예외는 다음과 같아요:

  • 파라미터 이름이 다른 경우.
  • 기본 함수가 둘 이상인 경우.
  • 어떤 컨트랙트를 사용해 상속할지 지정하는 명시적인 @inheritdoc 태그가 있는 경우.

문서 출력 (Documentation Output)

컴파일러가 파싱하면 위 예시 같은 문서는 두 개의 다른 JSON 파일을 생성해요. 하나는 함수가 실행될 때 최종 사용자에게 공지 사항으로 소비되기 위한 것이고, 다른 하나는 개발자가 사용하기 위한 것이에요.

위 컨트랙트를 ex1.sol로 저장했다면 다음을 사용해 문서를 생성할 수 있어요:

solc --userdoc --devdoc ex1.sol

출력은 아래와 같아요.

참고 (Note)

Solidity 버전 0.6.11부터 NatSpec 출력에는 version과 kind 필드도 포함돼요. 현재 version은 1로 설정되고 kind는 user 또는 dev 중 하나여야 해요. 미래에 새 버전이 도입되어 옛 버전이 폐기될 가능성이 있어요.

사용자 문서 (User Documentation)

위 문서는 Tree 컨트랙트에 대해 다음 사용자 문서 JSON 파일을 출력으로 생성해요:

{
  "version" : 1,
  "kind" : "user",
  "methods" :
  {
    "age(uint256)" :
    {
      "notice" : "Calculate tree age in years, rounded up, for live trees"
    },
    "leaves()" :
    {
        "notice" : "Returns the amount of leaves the tree has."
    }
  },
  "notice" : "You can use this contract for only the most basic simulation"
}

메서드를 찾는 키는 함수 이름이 아니라 컨트랙트 ABI에 정의된 함수의 표준 시그니처라는 점에 주의해요.

개발자 문서 (Developer Documentation)

사용자 문서 파일과 별도로, 개발자 문서 JSON 파일도 생성되어야 하며 다음과 같이 보여요:

{
  "version" : 1,
  "kind" : "dev",
  "author" : "Larry A. Gardner",
  "details" : "All function calls are currently implemented without side effects",
  "custom:experimental" : "This is an experimental contract.",
  "methods" :
  {
    "age(uint256)" :
    {
      "details" : "The Alexandr N. Tetearing algorithm could increase precision",
      "params" :
      {
        "rings" : "The number of rings from dendrochronological sample"
      },
      "returns" : {
        "_0" : "Age in years, rounded up for partial years",
        "_1" : "Name of the tree"
      }
    },
    "leaves()" :
    {
        "details" : "Returns only a fixed number."
    }
  },
  "title" : "A simulator for trees"
}

더 알아보기 (Learn more)