Javascript 코딩 협약 - noir1986/guide-web-development GitHub Wiki

Coding Convention for Markup Languages (Javascript)

자바스크립트는 다른 언어에 비해 유연한 문법 구조를 가지고 있어 좀 더 엄격한 코딩 스타일 규약이 필요하다. 아무리 작은 프로젝트라 하더라도 이후 유지 보수 및 추가 개발 등의 관리 이슈가 여전히 존재하기 때문에 코딩 스타일 규약은 반드시 필요하다.

목차

1. 용어

1.1 변수 (Variable) ES5 ES6

1.2 상수 (Constant) ES5 ES6

1.3 배열 (Array) ES5 ES6

1.4 객체 (Object) ES5 ES6

1.5 함수 (Function) ES5 ES6

1.5.1 익명 함수

1.5.2 내장 함수

1.5.3 콜백 함수

참고 호이스팅(hoisting) 이란 인터프린터가 자바스크립트 코드를 해석함에 있어서 Global 영역의 선언된 코드블럭을 최상의 Scope로 끌어올리는 것을 호이스팅이라 한다.

목차 돌아가기

2. 네이밍

2.1 일반 규칙

  • 변수, 함수 카멜 케이스(Camel Casing)로 표현한다.
  • 배열은 복수형 이름을 사용한다.
  • 생성자는 파스칼 케이스 (Pascal Casing)로 표현한다.
  • 공백을 허용하지 않는다.
  • 예약어를 사용하지 않는다. (var, if, for)
  • 대문자 약어는 대문자 그대로 사용한다. (HTML, JSON)
  • 상수는 대문자와 언더바(_)를 사용한다.
  • 이벤트 핸들러는 'on'으로 시작하여 사용한다.
  • 반환 값이 불린인 함수는 'is'로 시작하여 사용한다.
  • private은 '_'로 시작하여 사용한다.

참고 변수 선언 시 "var"를 반드시 사용한다. 추가로, 호이스팅되지 않도록 필요한 변수는 함수 상단에서 한번에 선언한다.

2.1.1 변수

  • 잘못된 예
// 숫자, 문자, 불린, 객체, 정규식
var CAT = "rusian blue"; // 대문자 사용
var Age = 6; //파스칼 케이스 사용
var varNeutralization = true; // 예약어 사용
var regex_number = /[0-9]/; // 언더바 사용
var privateObjectName = "cat"; // Private 변수
  • 올바른 예
// 숫자, 문자, 불린, 객체, 정규식
var cat = "rusian blue";
var age = 6;
var neutralization = true;
var regExNumber = /[0-9]/;
var _objectName = "cat";

2.1.2 상수

  • 잘못된 예
const apiKey = "794DBC9F-9743-479A-B5FF-E2A23AA1A8D1"; // 카멜 케이스 사용
  • 올바른 예
const API_KEY = "794DBC9F-9743-479A-B5FF-E2A23AA1A8D1";

2.1.3 배열

  • 잘못된 예
var title = ["Dark Soul", "Monster Hunter"]; // 복수형이 아님
  • 올바른 예
var titles = ["Dark Soul", "Monster Hunter"];

2.1.4 객체

  • 잘못된 예
// html 요소
var header = document.getElementById("header");

// json
var order = {
    "seq": 2018,
    "name": "Gundam Versers",
    "price": 25000
}
  • 올바른 예
// html 요소
var elHeader = document.getElementById("header");

// json
var dataOrder = {
    seq: 2018,
    name: "Gundam Versers",
    price: 25000
}

2.1.5 함수

  • 잘못된 예
// 값을 검증하는 함수
function Available(qty) {
    if ( !qty ) {
        return false;   
    } else {
        return true;
    }
}

// 반환형 함수
function iAm() {
    return "Iron Man";
}

// 실행형 함수
function firstAvenger() {
    document.getElementById("text_hero").value = "Captin America";   
}

// 이벤트 함수
function edit() {
    document.getElementById("form_edit").submit();
}

document.getElementById("btn_edit").addEventListener("click", edit); // 이벤트 연결
  • 올바른 예
// 값을 검증하는 함수
function isAvailable(qty) {
    if ( !qty ) {
        return false;   
    } else {
        return true;
    }
}

// 반환형 함수
function getIAm() {
    return "Iron Man";
}

// 실행형 함수
function setFirstAvenger() {
    document.getElementById("text_hero").value = "Captin America";   
}

// 이벤트 함수
function onEdit() {
    document.getElementById("form_edit").submit();
}

document.getElementById("btn_edit").addEventListener("click", onEdit); // 이벤트 연결

목차 돌아가기

3. 기본 규칙

Javascript 코드를 작성할 때 다음과 같은 기본 규칙을 준수한다.

3.1 전역 변수

네임스페이스를 사용하여 전역변수를 최소화하며 암묵적인 전역 변수는 절대로 사용하지 않는다.

  • 잘못된 예
var author = "J. R. R. Tolkien";

// Bad
function title() {
   result = "load of rings";
   return result;
}
  • 올바른 예
var global = {
    author = "J. R. R. Tolkien",
    title = function () {
        var result = "load of rings";
        return result;
    }
}
  • 초기화
// 1차 네임스페이스 사용
var service = window.service || {};

// 그 하위에 서비스명을 2차 네임스페이스 사용
service.notice = service.notice || {};

// 페이지별 또는 기능별 모듈명을 3차 네임스페이스 사용
service.notice.util = {...};
service.notice.component = {...};
service.notice.model = {...};

// 필요에 따라 4차, 5차 네임스페이스로 확장하여 사용
service.notice.view.button = {...};
service.notice.view.pagination = {...};

3.2 선언과 할당

변수

반드시 함수 스코프의 시작 지점에서 변수를 선언해야 한다. 변수는 var 키워드와 함께 선언되어 하며, 이와 동시에 할당(초기화)하는 것을 원칙으로 한다.

  • 잘못된 예
// [Bad] var를 한 번만 사용하여 개행 선언 
var foo,
    bar,
    quux;

// [Bad] var를 한 번만 사용하여 개행 선언 및 할당
var foo = '',
    bar = '',
    quux = '';

// [Bad] 그룹화 없음
var foo;
var bar;
var qux;
var i = 0;
var j = 0;
var len = this._array.length;
var len2 = this._array2.length;
var item;

// [Bad] 그룹화 없음
var i = 0, length = ary.length, j, k;
  • 올바른 예
// [Good] 선언만 하는 변수, 한 줄로 연결하여 선언
var foo, bar, quux;

// [Good] 개별로 개행해서 선언
var foo;
var bar;
var quux;

// [Good] 개별로 개행해서 선언 및 할당
var foo = '';
var bar = '';
var quux = '';

// [Good] 그룹화
var i = 0;
var j = 0;
var len = this._array.length;
var len2 = this._array2.length;
var foo, bar, quux, item;

상수

const API_KEY = "794DBC9F-9743-479A-B5FF-E2A23AA1A8D1";

배열

배열이나 객체를 선언할 때 생성자를 사용할 수도 있지만, 그보다는 리터럴 표기법을 사용하는 것이 가독성과 속도 면에서 좋다. 리터럴 표기법은 간결하고 직관적이며, 실제로 자바스크립트 엔진은 리터럴 표기법에 맞게 최적화되어있다.

  • 잘못된 예
// [Bad]
var emptyArr = new Array();
var arr = new Array(1, 2, 3, 4, 5);
  • 올바른 예
// [Good]
var emptyArr = [];
var arr = [1, 2, 3, 4, 5];

객체

  • 잘못된 예
// [Bad]
var emptyObj = new Object();
var obj = new Object();
  • 올바른 예
// [Good]
var emptyObj = {};
var obj = {1, 2, 3, 4, 5};

함수

함수는 함수 선언식과 표현식을 사용하여 선언한다. 함수 표현식과 함수 생성자로 선언된 함수는 호이스팅 시 값이 할당되지 않는다. 선언 이전에 사용 시 오류가 발생하므로 함수는 사용 전에 선언해야 한다. 함수 선언문은 변수 선언문 다음에 온다.

  • 잘못된 예
// [Bad] 함수 생성자 사용
var doSomething = new Function('param1', 'param2', 'return param1 + param2;');
  • 올바른 예
// [Good](1)
function doSomething(param1, param2) {
    return param1 + param2;
}

// [Good](2)
var doSomething = function(param1, param2) {
    return param1 + param2;
};

// [Good](3) 이름있는 함수 표현식
var doSomething = function doSomething(param1, param2) {
    return param1 + param2;
};

// [Good](4) - IIEF
(function() {
    ...
})();

3.3 문장의 종료

한 줄에 하나의 문장만 허용하며, 문장의 종료 시에는 반드시 세미콜론(;)을 사용한다.

참고 이를 문법적으로 강제하지 않지만, 예기치 못한 오류가 발생하거나 디버깅을 어렵게 한다.

목차 돌아가기

4. 들여쓰기

절대 space와 tab을 섞어서 사용하지 않는다. 반드시 space와 tab 둘 중 하나를 선택해야 한다. 이는 프로젝트의 성격에 따라 선택이 가능한 부분이며, space를 사용할 경우 2문자 또는 4문자를 사용한다. 들여쓰기에 대한 규칙이 합의되면 편집기의 들여쓰기 설정을 규칙대로 설정 해놓고 사용할 것을 권장한다.

목차 돌아가기

5. 빈 줄

의미 있는 객체를 구분하기 위하여 코드 그룹 간 1줄씩 빈 줄을 만드는 것은 허용한다. 빈 줄의 간격은 1줄을 초과하지 않는다.

목차 돌아가기

6. 인코딩

목차 돌아가기

7. 주석

주석은 코드의 이해를 돕기 위한 보조문이다. 주석에는 한 줄 주석과 여러 줄 주석 두 가지가 있다. 주석은 설명하려는 구문에 맞춰 들여쓰기한다. 문장의 끝에 주석을 작성할 경우, 한 줄 주석을 사용하며 공백을 추가한다. [한 줄 주석]

7.1 일반 주석 (단일 행)

주석 표시 전후 공백

  • 잘못된 예
// [Bad](1) 들여쓰기 없음, 주석 전에 한 줄 띄기 없음
function someFunction() {
// statement에 관한 주석
    statements
}

// [Bad](2) 주석 표시 전후 공백 없음
var someValue += data1 + data2 - length;//데이터 + 데이터 + 길이

// [Bad](2) 여러 줄 주석 사용
var someValue += data1 + data2 - length; /* 데이터 + 데이터 + 길이 */
  • 올바른 예
// [Good](1)
function someFunction() {
    // statement에 관한 주석
    statements
}

// [Good](2)
var someValue += data1 + data2 - length; // 데이터 + 데이터 + 길이

7.2 일반 주석 (복수 행)

여러 줄 주석을 작성할 때는 *의 들여쓰기를 맞춘다. 주석의 첫 줄과 마지막 줄은 비워둔다.

  • 잘못된 예
// [Bad] "*" 표시의 정렬이 맞지 않는다.
/*
* '*' 표시의 정렬이 맞지 않는다.
*/

// [Bad] 주석의 첫줄에 문장이 옴
/* var foo = '';
 * var bar = '';
*var quux;
 */
  • 올바른 예
// [Good](1) "*" 표시의 정렬을 맞춘다.
/*
 * '*' 표시의 정렬을 맞춘다.
 */

7.3 코드 주석

한 줄 주석을 사용한다.

  • 올바른 예
// [Bad] 여러 줄 주석을 사용
...
/*
 * var foo = '';
 * var bar = '';
 * var quux;
 */
  • 올바른 예
// [Good] 한 줄 주석 사용
...
// var foo = '';
// var bar = '';
// var quux;

7.4 전역, 네임스페이스, 클래스, 함수 주석 (jsDoc)

/**
* @fileoverview 공통 라이브러리
* @author NoiR
* @version 1.0
* @since 2018.01.29
*/

/**
* 암호화 네임스페이스
* @namespace $cryptography 네임스페이스에는 암호화 위한 클래스가 포함되어 있습니다.
* 이 네임스페이스에는 AES, BASE65, UTF-8, MD5등을 암호화, 인코딩 클래스가 포함되어 있습니다.
*/
var $cryptography = $cryptography || {};

/**
* AES(Advanced Encryption Standard) 클래스
* @class 고급 암호화/복호화 클래스
* 양방향 암호화
*/
$cryptography.aes = (function(){
    var _box = [];    
    var _con = [];

    return {
        /**
        * 열쇠
        * @function
        * @author 박지훈
        * @param {String} input 입력 값
        * @param {String} w 최대값
        * @returns {String} 암호화된 문자열
        * @type String
        */
        cipher: function ( input, w ) {
            ...
        },
        /**
        * 키 확장
        * @function
        * @author 박지훈
        * @param {String} key 키 값
        * @returns {Array} 확장된 키 값
        * @type Array
        */
        keyExpansion: function ( key ) {
            ...
        }
    }
})();

목차 돌아가기

8. 블록 구문

if, for, while, try 등 블럭 구문을 사용할 때에는 반드시 개행하여 사용한다. 키워드와 조건문 사이에 빈 칸을 사용하고, 괄호로 블럭의 시작과 끝을 명확히 정의하고, 줄 바꿈하여 사용한다. 한 줄짜리 블럭일 경우 {}를 생략할 수 있지만, 이는 코드 구조를 애매하게 만들며 당장은 라인 두 줄을 줄일 수 있겠지만 이후 오류 발생 확률이 높은 잠재적 위험 요소가 된다.

8.1 if, if-else

  • 잘못된 예
// [Bad] {} 생략, 개행 없음
if(condition) doSomething();

// [Bad] {} 생략, 개행 없음
if (condition) doSomething();
else doAnything();
  • 올바른 예
// [Good]
if (condition) {
    ...
}

// [Good]
if (condition) {
    ...
} else {
    ...
}

8.2 for, for-in

  • 잘못된 예
// [Bad](1) 키워드 사이 띄어쓰기 없음, {} 없음, 개행 안 함
var i = 0;
for(;i<100;i+=1) someIterativeFn();

// [Bad](2) 키워드 사이 띄어쓰기 없음, {} 없음, 개행 안 함
for(var prop in object) someIterativeFn();
  • 올바른 예
// [Good](1) ES5
var length = 100;
var i;

for (i = 0; i < length; i ++) {
    ...
}

// [Good](2) ES5
var i = 0;
var length = 100;

for (; i < length; i ++) {
    ...
}

// Good(3) ES6
const length = 100;

for (let i = 0; i < length; i += 1) {
    ...
}

// [Good](1) for-in ES5
var prop;

for (prop in object) {
    ...
}

// [Good](2) for-in ES6
for (const prop in object) {
    if (object.hasOwnProperty(prop)) {
        ...
    }
}

8.3 while, do-while

  • 잘못된 예
// [Bad] while
while(condition) iterating += 1;

// [Bad] do-while
do statement while(condition)
  • 올바른 예
// [Good] while
while (condition) {
    ...
}

// [Good] do-while
do {
    ...
} while (condition);

8.4 switch-case

// [Good]
switch (value) {
    case 1:
        /* falls through */
    case 2:
        doSomething();
        break;
    case 3:
        return true;
    default:
        throw new Error('This shouldn\'t happen.');
}

8.5 try-catch-finally

// [Good]
try {
    ...
} catch(exception) {
    ...
} finally {
    ...
}

목차 돌아가기

9. 데이터형 확인

암묵적 캐스팅으로 인한 혼동을 막기 위해 완전항등연산자인 ===, !== 만을 사용한다.

9.1 문자열 (String)

typeof variable === 'string'

// code-snippet.js 사용 시
tui.util.isString(variable)

9.2 숫자 (Number)

typeof variable === 'number'

// code-snippet.js 사용 시
tui.util.isNumber(variable)

9.3 참거짓 (Boolean)

typeof variable === 'boolean'

// code-snippet.js 사용 시
tui.util.isBoolean(variable)

9.4 객체 (Object)

typeof variable === 'object'

// code-snippet.js 사용 시
tui.util.isObject(variable)

9.5 배열 (Array)

Array.isArray(arrayObject)

// code-snippet.js 사용 시
tui.util.isArray(variable)

9.6 값 없음 (Null)

variable === null

// code-snippet.js 사용 시
tui.util.isNull(variable)

9.6 미할당 (Undefined)

typeof variable === 'undefined'
variable === undefined

// code-snippet.js 사용 시
tui.util.isUndefined(variable)

9.7 요소 (Element)

element.nodeType === 1

// code-snippet.js 사용 시
tui.util.isHTMLNode(element)

목차 돌아가기

10. 조건 확인

10.1 문자열

  • 잘못된 예
// [Bad](1) 값이 있는가?
if (string !== "") ...

// [Bad](2) 값이 비어 있는가?
if (string === '') ...
  • 올바른 예
// [Good](1) 값이 있는가?
if (string) ...

// [Good](2) 값이 비어 있는가?
if (!string) ...

10.2 숫자

  • 잘못된 예
// [Bad](1) 값이 있는가?
if (number !== 0) ...

// [Bad](2) 값이 비어 있는가?
if (number === 0) ...
  • 올바른 예
// [Good](1) 값이 있는가?
if (number ) ...

// [Good](2) 값이 비어 있는가?
if (!number ) ...

10.3 참거짓

  • 잘못된 예
// [Bad](1) 참조변수가 참(true)인가?
if (variable === true) ...

// [Bad](2) 참조변수가 거짓(false)인가?
if (variable === false) ...
  • 올바른 예
// [Good](1) 참조변수가 참(true)인가?
if (variable) ...

// [Good](2) 참조변수가 거짓(false)인가?
if (!variable) ...

10.4 배열

  • 잘못된 예
// [Bad](1) 배열인가?
if (array.length > 0) ...

// [Bad](2) 빈 배열인가?
if (array.length === 0) ...
  • 올바른 예
// [Good](1) 배열인가?
if (array.length) ...

// [Good](2) 빈 배열인가?
if (!array.length) ...

10.5 객체

  • 잘못된 예
  • 올바른 예

목차 돌아가기

11. 반환

특정 값을 반환해야 하는 경우, 함수의 맨 마지막에서 한 번만 return 한다. 단, 예외 처리로 빠져나가기 위해 사용하는 return;은 제외한다. 함수 내에서 if 문이 여러 번 호출되면, 함수로 분리해야 한다. 부득이한 경우에만 이 규칙을 적용한다.

// Good
function getResult() {
    var resultData;
    ...

    if (condition) {
        ...
        resultData = someDataInTrue;
    } else {
        ...
        resultData = someDataInFalse;
    }

    return resultData;
}

// Allow
function foo(isValid) {
    ...
    // 예외처리로 바로 빠져나감
    if (!isValid) {
        return;
    }
    ...
    
    return someDataInTrue;
}

// Allow
function foo(isValid) {
    ...
    // 예외처리로 바로 빠져나감
    if (!isValid) {
        return;
    }
    ...
    
    return someDataInTrue;
}

// Bad
function getResult() {
    ...
    if (condition) {
        ...
        return someDataInTrue;
    }
    ...
    return someDataInFalse;
}

목차 돌아가기

처음으로

https://javascript-minifier.com/ http://dean.edwards.name/packer/