JavaScript에서 코드 주석을 추가하는 미묘한 기술

Mar 18 2023
주석이 없는 코드를 디버깅하는 것은 범죄를 해결하려는 형사가 된 것과 같지만 유일한 증인은 외국어로 말하고 어제 사건을 해결하기 위해 목을 조이는 영향력 있는 사람들(클라이언트)이 있습니다. 이미지 출처 — 노트북을 보고 있는 두 남자 · 무료 재고 사진(pexels.

주석이 없는 코드를 디버깅하는 것은 범죄를 해결하려는 형사가 된 것과 같지만 유일한 증인은 외국어로 말하고 어제 사건을 해결하기 위해 목을 조이는 영향력 있는 사람들(클라이언트)이 있습니다.

이미지 출처 — 노트북을 보고 있는 두 남자 · 무료 스톡 사진(pexels.com)

소개

코드 주석을 추가하는 것은 여러 가지 이유로 중요합니다.

1. 코드 가독성. 주석은 코드를 평이한 언어로 설명하여 코드를 쉽게 읽고 수정할 수 있도록 함으로써 개발자가 코드 뒤에 숨겨진 목적을 이해하는 데 도움이 됩니다.

2. 유지보수. 주석은 코드의 목적을 기억하는 데 도움이 되므로 실수로 문제를 일으키지 않고 향후 유지 관리 및 업데이트가 더 쉬워집니다.

3. 협업. 주석은 코드 변경에 대한 컨텍스트를 제공하여 모든 사람이 같은 페이지에 있도록 함으로써 공동 프로젝트에서 오류와 오해를 방지합니다.

4. 문서. 코드 주석은 목적과 기능에 대한 명확성을 제공하여 산업 표준 및 모범 사례를 준수하도록 합니다. 세트를 구축할 때 LEGO 지침 가이드처럼 코드를 더 읽기 쉽고 유지 관리할 수 있으며 작업하기 쉽게 만듭니다.

의미 있고 정확한 주석을 코드에 추가하는 데 시간을 할애함으로써 개발자는 프로젝트의 전반적인 품질과 유지 관리성을 향상시킬 수 있습니다.

코드에 주석을 추가하기 위한 정신 모델

코드 조각에 대한 주석을 작성하기 전에 주석을 작성하려는 의도를 명확히 하는 것이 중요합니다. 코드 주석은 코드의 다음 측면을 전달해야 하는 통신 메커니즘입니다.

1. 목적. 코드의 목적, 코드가 해결하는 문제 및 존재 이유를 설명하십시오.

2. 입력. 유형, 예상 값, 선택적인지 필수인지 여부를 포함하여 코드에 필요한 입력을 지정합니다.

3. 출력. 유형 및 관련 세부 정보를 포함하여 코드에서 생성된 출력을 지정합니다.

4. 사용법. 관련 코드 스니펫을 포함하여 코드 사용 방법의 예를 제공합니다.

5. 연결. 관련 코드 및 외부 리소스에 대한 링크를 추가합니다.

6. 모범 사례. 코드와 관련된 모범 사례 또는 문제를 강조 표시합니다.

올바른 멘탈 모델을 따르면 개발자는 코드가 잘 문서화되고 이해하기 쉽고 시간이 지남에 따라 유지 관리가 가능하도록 할 수 있습니다.

일관성 및 표준화

코드베이스 전체에서 형식과 주석 스타일의 일관성을 유지하는 것이 중요합니다. JavaScript 코드를 문서화하기 위한 문서 표준 및 도구 세트인 JS Doc (JavaScript 문서) 과 같은 도구를 사용하는 것이 좋습니다.

다음은 JS Doc의 기능 중 일부입니다.

  • 태그를 사용하여 코드의 구조, 함수, 매개 변수, 반환 값 및 기타 세부 정보에 대한 정보를 캡처하여 다른 개발자가 읽을 수 있는 참조를 만듭니다.
  • JS Doc 태그는 @기호로 시작하고 태그 이름과 관련 정보가 뒤따릅니다. 예를 들어 param태그는 함수 매개변수를 설명하는 데 사용되는 반면 returns태그는 함수의 반환 값을 설명하는 데 사용됩니다.
  • 소스 코드의 인라인 주석에서 HTML 또는 기타 형식으로 문서를 생성할 수 있습니다.

function factorial(n) {
  if (typeof n !== "number") {
    throw new TypeError("Input must be a number");
  }
  if (n === 0) {
    return 1;
  }
  return n * factorial(n - 1);
}

function factorialWithCallback(n, callback) {
  try {
    const result = {
      input: n,
      output: factorial(n),
    };
    callback(null, result);
  } catch (error) {
    callback(error);
  }
}

일반적으로 사용되는 JS 문서 태그

자주 사용되는 몇 가지 JS Doc 태그를 살펴보겠습니다.

  • @todo

/**
 * @todo Add details about the factorial calculation and edge cases.
 */
function factorial(n) {
  if (typeof n !== "number") {
    throw new TypeError("Input must be a number");
  }
  if (n === 0) {
    return 1;
  }
  return n * factorial(n - 1);
}

/**
 * @todo Add an example usage of the callback function.
 */
function factorialWithCallback(n, callback) {
  try {
    const result = {
      input: n,
      output: factorial(n),
    };
    callback(null, result);
  } catch (error) {
    callback(error);
  }
}

첫 번째 단계는 코드가 수행하는 작업을 설명하는 것입니다. @description태그는 기능, 개체 또는 속성에 대한 자세한 설명을 제공하는 데 사용됩니다. 이 태그를 추가한 후 코드가 어떻게 보이는지 봅시다.

/**
 * @description A function that calculates the factorial of a number using recursion.
 */
function factorial(n) {
  if (typeof n !== "number") {
    throw new TypeError("Input must be a number");
  }
  if (n === 0) {
    return 1;
  }
  return n * factorial(n - 1);
}

/**
 * @description A version of the factorial function that returns the result via a callback.
 */
function factorialWithCallback(n, callback) {
  try {
    const result = {
      input: n,
      output: factorial(n),
    };
    callback(null, result);
  } catch (error) {
    callback(error);
  }
}

코드가 어떤 입력을 받는지 알려주는 부분이 있습니다. @param태그는 함수의 매개변수를 설명하는 데 사용됩니다. 예제에 추가하면 코드가 다음과 같이 됩니다.

/**
 * @description A function that calculates the factorial of a number using recursion.
 * 
 * @param {number} n - The number for which to calculate the factorial.
 */
function factorial(n) {
  if (typeof n !== "number") {
    throw new TypeError("Input must be a number");
  }
  if (n === 0) {
    return 1;
  }
  return n * factorial(n - 1);
}

/**
 * @description A version of the factorial function that returns the result via a callback.
 * 
 * @param {number} n - The number for which to calculate the factorial.
 * @param {function} callback - The function to call with the result of the calculation.
 */
function factorialWithCallback(n, callback) {
  try {
    const result = {
      input: n,
      output: factorial(n),
    };
    callback(null, result);
  } catch (error) {
    callback(error);
  }
}

지금까지 우리는 함수가 무엇을 하는지, 어떤 입력을 받는지 알고 있습니다. 다음은 함수의 반환 값에 대한 설명입니다. @returns예제에 추가하면 코드가 다음과 같이 표시됩니다.

/**
 * @description A function that calculates the factorial of a number using recursion.
 * 
 * @param {number} n - The number for which to calculate the factorial.
 * 
 * @returns {number} The factorial of `n`.
 */
function factorial(n) {
  if (typeof n !== "number") {
    throw new TypeError("Input must be a number");
  }
  if (n === 0) {
    return 1;
  }
  return n * factorial(n - 1);
}

/**
 * @description A version of the factorial function that returns the result via a callback.
 * 
 * @param {number} n - The number for which to calculate the factorial.
 * @param {function} callback - The function to call with the result of the calculation.
 * 
 * @returns {void}
 */
function factorialWithCallback(n, callback) {
  try {
    const result = {
      input: n,
      output: factorial(n),
    };
    callback(null, result);
  } catch (error) {
    callback(error);
  }
}

함수에서 오류가 발생하여 원하는 결과를 생성할 수 없는 경우가 있습니다. @throws이러한 시나리오를 문서화하는 데 도움이 됩니다. @throws예제에 추가하면 코드가 다음과 같이 표시됩니다.

/**
 * @description A function that calculates the factorial of a number using recursion.
 * 
 * @param {number} n - The number for which to calculate the factorial.
 * 
 * @returns {number} The factorial of `n`.
 * 
 * @throws {TypeError} If the input is not a number.
 */
function factorial(n) {
  if (typeof n !== "number") {
    throw new TypeError("Input must be a number");
  }
  if (n === 0) {
    return 1;
  }
  return n * factorial(n - 1);
}

/**
 * @description A version of the factorial function that returns the result via a callback.
 * 
 * @param {number} n - The number for which to calculate the factorial.
 * @param {function} callback - The function to call with the result of the calculation.
 * 
 * @returns {void}
 */
function factorialWithCallback(n, callback) {
  try {
    const result = {
      input: n,
      output: factorial(n),
    };
    callback(null, result);
  } catch (error) {
    callback(error);
  }
}

때때로 코드의 소비자 또는 호출자는 낮은 수준의 구현 세부 정보에 관심이 없으며 호출 및 예상 결과를 얻는 데 관심이 있습니다. @example태그는 기능이나 개체를 사용하는 방법의 예를 제공하는 데 사용됩니다. @example예제에 추가하면 코드가 다음과 같이 표시됩니다.

/**
 * @description A function that calculates the factorial of a number using recursion.
 * 
 * @param {number} n - The number for which to calculate the factorial.
 * 
 * @returns {number} The factorial of `n`.
 * 
 * @throws {TypeError} If the input is not a number.
 * 
 * @example
 * factorial(5);
 * // returns 120
 */
function factorial(n) {
  if (typeof n !== "number") {
    throw new TypeError("Input must be a number");
  }
  if (n === 0) {
    return 1;
  }
  return n * factorial(n - 1);
}

/**
 * @description A version of the factorial function that returns the result via a callback.
 * 
 * @param {number} n - The number for which to calculate the factorial.
 * @param {function} callback - The function to call with the result of the calculation.
 * 
 * @returns {void}
 * 
 * @example
 * factorialWithCallback(5, (error, result) => {
 *   if (error) {
 *     console.error(error);
 *   } else {
 *     console.log(result);
 *   }
 * });
 * // logs { input: 5, output: 120 }
 */
function factorialWithCallback(n, callback) {
  try {
    const result = {
      input: n,
      output: factorial(n),
    };
    callback(null, result);
  } catch (error) {
    callback(error);
  }
}

JSDoc @type태그는 변수, 함수 또는 표현식의 유형을 지정하는 데 사용됩니다. 문서화되는 엔터티 유형에 대한 추가 정보를 제공하고 코드 가독성 및 유지 관리에 도움이 됩니다.

@typedef반면에 JSDoc 태그는 사용자 정의 유형을 정의하는 데 사용됩니다 . 이는 문서화해야 하는 사용자 정의 데이터 구조 또는 유형이 있는 복잡한 프로젝트에서 유용할 수 있습니다. 로 정의된 사용자 정의 유형은 코드의 다른 부분에서 태그 @typedef로 참조될 수 있습니다 .@type

본질적으로 는 @typedef사용자 정의 유형을 정의하는 데 사용되는 반면 @type엔티티 유형을 지정하는 데 사용됩니다.

JSDoc @property태그는 개체 또는 클래스의 속성을 문서화하는 데 사용됩니다. @typedef일반적으로 개체 또는 클래스의 구조를 문서화하기 위해 와 함께 사용됩니다 . 태그 @property는 속성의 이름과 유형은 물론 목적에 대한 설명을 지정합니다.

예제에 , 및 를 추가하면 코드가 다음과 같이 @type표시 @typedef됩니다 .@property

/**
 * @typedef {Object} FactorialResult
 * 
 * @property {number} input - The input to the factorial function.
 * @property {number} output - The output of the factorial function.
 */

/**
 * @description A function that calculates the factorial of a number using recursion.
 * 
 * @param {number} n - The number for which to calculate the factorial.
 * 
 * @returns {number} The factorial of `n`.
 * 
 * @throws {TypeError} If the input is not a number.
 * 
 * @example
 * factorial(5);
 * // returns 120
 */
function factorial(n) {
  if (typeof n !== "number") {
    throw new TypeError("Input must be a number");
  }
  if (n === 0) {
    return 1;
  }
  return n * factorial(n - 1);
}

/**
 * @description A version of the factorial function that returns the result via a callback.
 * 
 * @param {number} n - The number for which to calculate the factorial.
 * @param {function} callback - The function to call with the result of the calculation.
 * 
 * @returns {void}
 * 
 * @example
 * factorialWithCallback(5, (error, result) => {
 *   if (error) {
 *     console.error(error);
 *   } else {
 *     console.log(result);
 *   }
 * });
 * // logs { input: 5, output: 120 }
 */
function factorialWithCallback(n, callback) {
  /**
   * @type {FactorialResult}
   */
  const result = {
    input: n,
    output: factorial(n),
  };
  try {
    callback(null, result);
  } catch (error) {
    callback(error);
  }
}

  • @callback

/**
 * @typedef {Object} FactorialResult
 * 
 * @property {number} input - The input to the factorial function.
 * @property {number} output - The output of the factorial function.
 */

/**
 * @callback FactorialCallback
 * 
 * @param {Error} error - The error that occurred during the calculation, if any.
 * @param {FactorialResult} result - The result of the calculation.
 */

/**
 * @description A function that calculates the factorial of a number using recursion.
 * 
 * @param {number} n - The number for which to calculate the factorial.
 * 
 * @returns {number} The factorial of `n`.
 * 
 * @throws {TypeError} If the input is not a number.
 * 
 * @example
 * factorial(5);
 * // returns 120
 */
function factorial(n) {
  if (typeof n !== "number") {
    throw new TypeError("Input must be a number");
  }
  if (n === 0) {
    return 1;
  }
  return n * factorial(n - 1);
}

/**
 * @description A version of the factorial function that returns the result via a callback.
 * 
 * @param {number} n - The number for which to calculate the factorial.
 * @param {FactorialCallback} callback - The function to call with the result of the calculation.
 * 
 * @returns {void}
 * 
 * @example
 * factorialWithCallback(5, (error, result) => {
 *   if (error) {
 *     console.error(error);
 *   } else {
 *     console.log(result);
 *   }
 * });
 * // logs { input: 5, output: 120 }
 */
function factorialWithCallback(n, callback) {
  /**
   * @type {FactorialResult}
   */
  const result = {
    input: n,
    output: factorial(n),
  };
  try {
    callback(null, result);
  } catch (error) {
    callback(error);
  }
}

그런 다음 이 유형은 함수의 콜백 매개변수에 대한 태그 FactorialCallback에서 참조됩니다 .@paramfactorialWithCallback

예/데모

위 스니펫의 미리보기와 JS Doc을 사용하여 생성되는 문서는 여기에서 확인할 수 있습니다 .

이 예제는 독자에게 이러한 기술을 모두 이해하고 프로젝트에서 구현하면 잠금 해제될 수 있는 잠재력을 보여주기 위한 매우 단순화된 구현이라는 점에 유의하십시오.

요약

복잡하고 난해한 코드베이스로 가득 찬 세상에서 코드 주석은 우리 모두에게 필요한 친구입니다. 향상된 코드 가독성부터 자동 생성된 문서에 이르기까지 다양한 이점을 제공하는 JS Doc 과 같은 도구는 모든 개발 툴킷에 필수적입니다.

노련한 개발자이든 이제 막 시작한 개발자든 표준화된 방식으로 코드를 문서화하는 데 시간을 할애하면 단기적으로 제품에 도움이 될 뿐만 아니라 앞으로 몇 년 동안 코드베이스의 수명과 유지 관리 가능성을 보장할 수 있습니다.

이러한 시스템을 프로젝트에 사용하는 것이 좋습니다. 저를 믿으세요. 당신의 미래는 당신에게 감사할 것입니다!