JavaScript 주석 정복하기

서나무·2022년 12월 8일
2

JavaScript

목록 보기
2/3
post-thumbnail

주석 또는 코멘트(comment)는 프로그래밍에 있어 내용을 메모하는 목적으로 쓰인다.
소스 코드를 더 쉽게 이해할 수 있게 만드는 것이 주 목적이며, 협업할 때 유용히 쓰인다. 컴파일러와 인터프리터에 의해 일반적으로 무시되어 프로그램에 영향을 주지 않는다.
출처: [위키백과] 주석 (프로그래밍)

쉽게 말하면 주석은 작성한 코드에 대한 설명을 적고싶을 때 사용한다.

주석의 중요성

어렴풋이,, 주석없이 함수의 이름만 봐도 어떤 일을 수행하는 함수인지 알 수 있도록 코드를 작성하는게 진정한 개발자라는 말을 들은 기억이 있다.

이 말이 틀린건 아니겠지만, 나는 개인적으로 협업을 해야하는 프로젝트에서 주석은 필수라고 생각한다.

소프트웨어는 한번 개발을 하고 뒤돌아서 끝내는게 아니다. 계속해서 수정하고 다듬어가면서 사용자의 요구사항에 맞춰가야 한다.

처음 코드는 내가 작성했어도 수정할 때는 다른 개발자가 코드를 작성할 수 있기 때문에 코드를 이해하는 시간을 줄이기 위해서는 주석을 꼼꼼하게 작성하는 습관이 필요하다. 나는 내가 짠 코드도 일주일만 지나면 까먹는다..

솔직히 나는 그동안 주석을 꼼꼼히 작성하지 않았었는데, 최근 주석의 중요성을 느끼게 되면서 자바스크립트에서 사용 가능한 다양한 주석에 대해서 소개해보려고 한다.

내가 주석의 중요성을 느끼게 된 것에 대해 먼저 작성했는데, 궁금하지 않다면 다양한 주석 알아보기부터 보면 된다.

내가 다 아는 코드야

회사에서 혼자 Vue를 사용해 프론트엔드 개발을 맡아서 진행하던 프로젝트 B가 있다.

정규 프로젝트는 아니었지만 총 22개의 페이지를 만들었으며, 각 페이지에서 필요한 기능들도 많이 개발을 해왔다.

페이지가 22개라고 하니까 정말 많아 보이지만,, 약 15개는 간단한 데이터 CRUD를 하는 단순한 페이지들이다.

처음에는 작게 시작한 프로젝트였는데 규모가 점점 커지면서 코드량이 많아졌지만 "어차피 정규 프로젝트도 아니니까", "내가 다 아는 코드야" 등의 핑계를 대면서 주석을 작성하지 않았다.

그러던 중 프로젝트 B가 중단되고,, 회사에서 기존에 C#으로 진행하던 프로젝트 A에 투입되면서 작은 버그들을 고치거나 기능을 수정하는 일을 맡게 되었다.

천 줄은 기본이지! 변수명은 item1

프로젝트 A는 3년 동안 진행되면서 수 많은 개발자들이 거쳐간 규모가 큰 프로젝트다.

화면 하나당 코드량이 기본 천 줄이었고, 많은건 삼천 줄도 넘어갔다.

그런데 item1, item2 이런 이름을 가진 변수들도 많았고, 주석이 없는 경우도 꽤 있었다. 대충 지은 변수명과 주석 없는 코드들을 보고 막막한 마음부터 들었다.

난이도 높은 버그는 아니였지만 기존 코드들을 분석하면서 원인을 파악하고 수정하다보니 꽤 오랜시간이 걸렸다.

이렇게 몇 개의 버그와 기능들을 수정하면서 주석이 정말 중요하구나.라는 것을 느끼게 되었다.

다양한 주석 알아보기

1. 기본 주석

먼저 기본 주석이다. 보통 자바스크립트 주석이라고 검색하면 나오는 주석이다.

// 한 줄 주석

/**
 * 두 줄 이상
 * 주석
 */

2. JSDoc

JSDoc은 자바스크립트 API 문서 생성기다. 자바스크립트 소스코드에 JSDoc 형식의 주석을 추가하면 API를 설명하는 HTML 문서를 생성할 수 있다.
출처: 15.9 JSDoc을 사용하여 자바스크립트에 타입 힌트 제공하기

JSDoc를 사용하면 함수의 기능, 파라미터, return 값에 대한 설명을 작성할 수 있고 해당 함수를 사용할 때 작성한 정보를 표시해줄 수 있다.

자바스크립트로 코드를 작성하면 모든 타입이 any로 추론된다. 그래서 정확히 어떤 타입의 데이터를 파라미터로 넘겨야 하는지 알려면 함수 선언부에 가서 작성된 주석을 보거나 코드를 직접 해석해야 한다.

그런데 JSDoc로 주석을 작성해두면 함수를 선언한 곳에 찾아가서 코드를 해석하지 않아도, 함수의 기능과 파라미터 타입에 대해 알 수 있어 매우 유용하다.

함수

/**
 * a와 b를 더한 결과를 반환
 * @param {number} a 첫번째 숫자
 * @param {number} b 두번째 숫자
 * @returns {number} a와 b를 더한 결과
 */
function plus(a, b) {
  return a + b;
}

plus함수에 대한 주석이다. 맨 첫번째 줄은 함수에 대한 설명이고, @param은 파라미터, @returns은 리턴 데이터에 대한 설명을 적을 수 있는 태그다.

파라미터에 대한 주석은 태그유형 {타입} 변수명 설명 순으로 작성하면 된다.

변수

/** @type {number} 이름 */
let name = '';

변수에 대한 주석은 태그유형 {타입} 설명 순으로 작성하면 된다.

JSDoc 참조에서 다양한 종류의 태그들을 더 볼 수 있다.

3. region

region 주석은 코드를 묶어주는 기능을 한다.

//#region 숫자 계산 함수
/**
 * a와 b를 더한 결과를 반환
 * @param {number} a 첫번째 숫자
 * @param {number} b 두번째 숫자
 * @returns {number} a와 b를 더한 결과
 */
 function plus(a, b) {
  return a + b;
}

/**
 * a에서 b를 뺀 결과를 반환
 * @param {number} a 첫번째 숫자
 * @param {number} b 두번째 숫자
 * @returns {number} a에서 b를 뺀 결과
 */
 function minus(a, b) {
  return a - b;
}
//#endregion

코드를 묶을 시작점에서 //#region 설명을 작성해주고, 끝나는 지점에는 //#endregion을 작성하면 된다.

주석을 어떻게 작성하면 잘 작성했다고 소문이 날까?

주석을 작성하는 방법을 설명하기 위해 회원가입을 처리하는 코드를 간단하게 작성해봤다.

// 닉네임
let nickname = '';
// 이메일
let email = '';
// 비밀번호
let password = '';

// 회원가입 클릭 이벤트. 회원가입 결과 콘솔에 출력
async function onClickRegister(nickname, email, password) {
  if (!isValidNickname(nickname)) {
    console.log('Invalid nickname');
    return;
  }
  if (!isValidEmail(email)) {
    console.log('Invalid email');
    return;
  }
  if (!isValidPassword(password)) {
    console.log('Invalid password');
    return;
  }
  const response = await register(nickname, email, password);
  console.log(response);
}

// 회원가입 처리
async function register(nickname, email, password) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Register Successful!');
    }, 2000);
  });
}

// 닉네임 유효성 검사
function isValidNickname(nickname) {
  return /^[-]+$/.test(nickname);
}

// 이메일 유효성 검사
function isValidEmail(email) {
  return /[a-z0-9]+@[a-z]+\.[a-z]{2,3}/.test(email);
}

// 비밀번호 유효성 검사
function isValidPassword(password) {
  return /^[a-z0-9_-]{6,18}$/.test(password);
}

// 코드 실행 결과를 보기 위한 임시 코드
nickname = '서나무';
email = 'seo.namu@example.com';
password = '1234qwer';

onClickRegister(nickname, email, password);

코드를 보면 회원가입 관련된 함수가 두 개나 있다.

  • register : 서버와 통신해서 회원가입을 처리하는 함수
  • onClickRegister : 사용자가 회원가입 버튼을 클릭했을 때 실행시킬 함수
    • 닉네임, 이메일, 비밀번호 유효성 검사
    • register 함수를 호출한 결과를 콘솔에 출력

이렇게 코드를 작성하고 나면 여러 문제들이 발생할 수 있다.

  1. 변수에 다른 자료형의 데이터를 넣는 휴먼에러가 발생할 수 있다.
  2. 회원가입 처리시 onClickRegisterregister 중 어떤 함수를 사용해야 하는지 알기 어렵다.
  3. 각 함수가 어떤 일을 하는지 알기 위해서는 함수 선언부로 가서 주석을 확인해야 한다.
  4. 나중에 혹은 다른 개발자가 파일을 열었을 때 어떤 코드들이 작성되어 있는지 한눈에 파악하기 어렵다.

그러면 주석을 사용해서 위 문제들을 해결해보자!

변수 주석 작성하기

  1. let으로 선언한 변수에 다른 자료형의 데이터를 넣는 휴먼에러가 발생할 수 있다.

사실 문자열로 초기화를 해주면 타입 추론이 string으로 되지만, 변수에 대한 설명을 통해 어떤 데이터를 넣어야할지 알 수 있게 된다.

/** @type {string} 닉네임 */
let nickname = '';
/** @type {string} 이메일 */
let email = '';
/** @type {string} 비밀번호 */
let password = '';

함수 주석 작성하기

  1. 회원가입 처리시 onClickRegisterregister 중 어떤 함수를 사용해야 하는지 알기 어렵다.
  2. 각 함수가 어떤 일을 하는지 알기 위해서는 함수 선언부로 가서 주석을 확인해야 한다.

함수를 사용할 때 함수의 기능에 대해 이해하기 쉽고, 파라미터도 어떤 자료형을 넣어줘야 할지 바로 알 수 있다.

/**
 * 회원가입 클릭 이벤트. 회원가입 결과 콘솔에 출력
 * @param {string} nickname 닉네임
 * @param {string} email 이메일
 * @param {string} password 비밀번호
 */
async function onClickRegister(nickname, email, password) {
  if (!isValidNickname(nickname)) {
    console.log('Invalid nickname');
    return;
  }
  if (!isValidEmail(email)) {
    console.log('Invalid email');
    return;
  }
  if (!isValidPassword(password)) {
    console.log('Invalid password');
    return;
  }
  const response = await register(nickname, email, password);
  console.log(response);
}

/**
 * 회원가입 처리
 * @param {string} nickname 닉네임
 * @param {string} email 이메일
 * @param {string} password 비밀번호
 * @returns {Promise<string>} 회원가입 결과 메시지
 */
async function register(nickname, email, password) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Register Successful!');
    }, 2000);
  });
}

/**
 * 닉네임 유효성 검사
 * @param {string} nickname 닉네임
 * @returns {boolean} 유효성 검사 결과
 */
function isValidNickname(nickname) {
  return /^[-]+$/.test(nickname);
}

/**
 * 이메일 유효성 검사
 * @param {string} email 이메일
 * @returns {boolean} 유효성 검사 결과
 */
function isValidEmail(email) {
  return /[a-z0-9]+@[a-z]+\.[a-z]{2,3}/.test(email);
}

/**
 * 비밀번호 유효성 검사
 * @param {string} password 비밀번호
 * @returns {boolean} 유효성 검사 결과
 */
function isValidPassword(password) {
  return /^[a-z0-9_-]{6,18}$/.test(password);
}

region 주석으로 그룹화하기

  1. 나중에 혹은 다른 개발자가 파일을 열었을 때 어떤 코드들이 작성되어 있는지 한눈에 파악하기 어렵다.

깔끔하게 정리되어 있어서 어떤 코드들이 있을지 파악이 가능하다.


//#region 변수
/** @type {string} 닉네임 */
let nickname = '';
/** @type {string} 이메일 */
let email = '';
/** @type {string} 비밀번호 */
let password = '';
//#endregion

//#region 이벤트
/**
 * 회원가입 클릭 이벤트. 회원가입 결과 콘솔에 출력
 * @param {string} nickname 닉네임
 * @param {string} email 이메일
 * @param {string} password 비밀번호
 */
async function onClickRegister(nickname, email, password) {
  if (!isValidNickname(nickname)) {
    console.log('Invalid nickname');
    return;
  }
  if (!isValidEmail(email)) {
    console.log('Invalid email');
    return;
  }
  if (!isValidPassword(password)) {
    console.log('Invalid password');
    return;
  }
  const response = await register(nickname, email, password);
  console.log(response);
}
//#endregion

//#region 함수
/**
 * 회원가입 처리
 * @param {string} nickname 닉네임
 * @param {string} email 이메일
 * @param {string} password 비밀번호
 * @returns {Promise<string>} 회원가입 결과 메시지
 */
async function register(nickname, email, password) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Register Successful!');
    }, 2000);
  });
}

/**
 * 닉네임 유효성 검사
 * @param {string} nickname 닉네임
 * @returns {boolean} 유효성 검사 결과
 */
function isValidNickname(nickname) {
  return /^[-]+$/.test(nickname);
}

/**
 * 이메일 유효성 검사
 * @param {string} email 이메일
 * @returns {boolean} 유효성 검사 결과
 */
function isValidEmail(email) {
  return /[a-z0-9]+@[a-z]+\.[a-z]{2,3}/.test(email);
}

/**
 * 비밀번호 유효성 검사
 * @param {string} password 비밀번호
 * @returns {boolean} 유효성 검사 결과
 */
function isValidPassword(password) {
  return /^[a-z0-9_-]{6,18}$/.test(password);
}
//#endregion
profile
주니어 프론트엔드 개발자

1개의 댓글

comment-user-thumbnail
2023년 11월 2일

좋은 글 감사합니다^^

답글 달기