webrtc에 관련된 자료

http://www.html5rocks.com/ko/tutorials/webrtc/basics/

[번역]절대 지켜져야만 하는 UI 디자인의 7가지 법칙 Mar 10

당신은 웹 디자이너인가요? 만약 그러하다면 당신은 UI 디자이너라는 말이기도 합니다. 그리고 미래에는 오히려 그 UI 디자이너라는 호칭이 웹 디자이너라는 이름보다 더욱 중요해질지도 모릅니다.

오늘날의 웹페이지들이 네비게이션과 메뉴 정도 만을 남긴 간단한 인터페이스라면, 기술의 발전으로 인해 우리가 앞으로 겪게 될 인터페이스는 아마 지금보다 더 유동적이고 개인에 최적화된 것들을 요구하게 될 것입니다.

피할 수 없이 받아들여야만 하는 이 흐름은, 우리가 UI 작업을 더욱더 세밀하게 해야 한다는 것을 의미합니다. 자, 그럼 우리가 정확히 어떤 것들을 기억해야 하는지 살펴보도록 하겠습니다.

1. 명확성의 법칙(Law of clarity)

유저는 확실한 의미전달이 되지 않는다면 그 인터페이스를 사용하려 하지 않습니다.

Image

혹시 지메일(Gmail)을 사용하고 계신가요? 저는 사용 중 입니다. 최근 업데이트 이전까지만 하더라도 페이지 상단에 굉장히 명확한 텍스트 형식의 네비게이션 바를 달았었죠. 구글 캘린더, 드라이브, 시트 등 여러 구글 서비스들을 버튼 클릭 한번으로 사용 할 수 있게 되어 있었습니다.

그런데 구글은 갑자기 애매모호한 아이콘 하나로 모든 것을 ‘단순화’ 하고자 하였습니다. 결과적으로는 대부분의 사람들이 그 아이콘을 알아보지 못했고, 지메일은 결국 소비자들의 원성을 들어야만 했죠.

사람들은 자신들이 이해하지 못하는 것들은 대부분 바로 지나쳐버립니다. 그건 인간의 자연적인 본능이죠. 어떤 기능인지 추측할 수 없는 인터페이스는 피하세요. 다들 그게 무엇인지 굳이 알고 싶어하지 않을 겁니다.

2. 우선순위의 법칙(Law of preferred action)

작업의 우선순위가 무엇인지 알 수 있다면 유저로서는 훨씬 더 수월해집니다.

02-law-of-preffered-action

위의 트위터(Twitter) 화면을 보세요. 새로운 유저가 이 화면을 본다면 무엇부터 해야 하는지 알 수 있을까요?

물론 순서대로라면 트위터에 글부터 써야 하겠죠. 하지만 오른쪽 상단에 ‘새 트위터 작성하기’ 버튼은 상당히 명확하지 않습니다(1번 명확성의 법칙을 보세요). 그리고 왼쪽 사이드바에 있는 ‘새 글 입력창’은 또렷하게 드러나지 않고 배경색에 묻혀 버리기까지 하죠.

온전히 디자인적 시각으로만 바라보았을 때, 트위터에서는 아무래도 유저들이 검색을 하기를 바라거나 왼쪽 상단의 네비게이션 메뉴를 사용하기를 바라는 것 같습니다. 저 요소들이 가장 유명하니까요.

유저들로 하여금 다음에 무엇을 해야 할지 고민하게 만들어서는 안 됩니다. 우선순위가 확실해야 합니다.

3. 문맥의 법칙(Law of context)

유저는 자신이 수정하고 싶은 내용의 설정 인터페이스(버튼)가 문맥상 그 내용 가까이에 있기를 원합니다.

03-law-of-context

여러분은 페이스북(Facebook)에서 이름을 어떻게 수정하시나요? 오른쪽 상단에 설정에 들어간 후, 계정 설정에 들어가서, 이름을 찾아서 클릭하고, 수정 버튼을 누를 겁니다. 링크드인(LinkedIn)에서는 어떻게 이름을 수정할 까요? 이름 옆에 연필 모양 버튼을 클릭하면 끝입니다.

유저들은 항상 인터페이스가 자신들이 수정하고 싶은 내용 옆에 있기를 원합니다. 이것은 실생활에서도 마찬가지로 적용되죠. 옥수수로 팝콘을 해먹고 싶다면, 전자레인지로 가서 전자레인지에 달려있는 버튼을 누르겠죠.

만약 전자레인지가 당신에게 계단을 내려가서, 지하실 문을 열고, 전기통을 열어서, 그 안에 있는 G-35버튼을 클릭하여 팝콘 프로그램을 가동해야 한다고 한다면(페이스북의 이름 바꾸는 작업과 비슷하다고 할 수 있죠) 상당히 편리하지 않을 겁니다.

유저들을 위해 간단하게 배치하세요. 무언가가 수정, 변경, 혹은 설정이 가능한 요소라면 그 설정 버튼을 문맥상 바로 그 옆에다가 둘 수 있도록 하세요.

4. 기본 설정의 법칙(Law of defaults)

유저는 거의 대부분 기본설정을 바꾸지 않을 겁니다.

이 전화 벨소리에 익숙하신가요? 당연히 익숙하실 겁니다. 한때 지구상에서 가장 유명했던 벨소리이니까요. 왜냐구요? 그건 이 벨소리가 핸드폰에 기본으로 설정된 벨소리였고 대부분의 사람들이 바꾸지 않았기 때문이죠.

기본 설정이 얼마나 강력한지는 아래 예시만 보아도 알 수 있습니다.

  • 대부분의 사람들은 기본으로 설정된 배경화면과 벨소리를 그대로 사용한다.
  • 대부분의 사람들은(당신을 포함하여) 집 TV 세트의 기본설정을 수정하여 사용하지 않는다.
  • 대부분의 사람들은 기본 설정된 냉장고 온도를 바꾸지 않는다.

기본 설정은 눈에 크게 띄지는 않지만 이미 우리 세상을 지배하고 있습니다. 그러니 반드시 기본 설정이 최대한 간편하고 효율적일 수 있도록 해주세요. 아마 대부분의 사람들은 그것을 바꾸지 않을 테니까요.

5. 유도의 법칙(Law of guided action)

유저는 당신이 어떠한 행동을 유도한다면 아마 그렇게 할 겁니다.

04-law-of-guided-action

유저가 무언가 하기를 ‘기대’하는 것과 실제로 그것을 ‘요청’하는 것은 다릅니다.

예를 들어 처음 링크드인에서 추천(endorsement) 기능을 만들었을 때, 이 기능이 무엇인지에 대해서 유저들 스스로 알아내기를 바라지는 않았습니다.

대신 그들은 눈에 명확하게 띄는 추천 배너를 오른쪽 상단에 나타나도록 하였죠. 여기에 ‘사람은 기본적으로 서로 추천하는 것을 좋아한다’는 사실이 더해져서 결국 이 기능을 큰 성공으로 이끌었습니다.

여기서 우리가 배울 수 있는 것은, 만약 유저가 무엇인가를 하기를 바란다면 주저하지 않고 ‘물어봐야 한다’는 것입니다.

6. 피드백의 법칙(Law of feedback)

유저는 당신이 명확하고 지속적인 피드백을 줄 때 더욱 확신을 가지게 됩니다.

05-law-of-feedback1

이것은 아주 간단한 규칙입니다. 인터페이스가 유저에게 더 지속적으로 커뮤니케이션 할 수록, 유저는 더욱 확신을 가질 수 있습니다.

지메일은 좋은 피드백 기능을 가진 서비스의 훌륭한 예입니다. 여러분이 하는 모든 행위에서 지속적인 피드백을 받을 수 있습니다. 더 알아보기(Learn more), 되돌리기(undo), 기능을 통해서는 더 깊이 배울 수도 있죠. 이것은 유저 자기 자신이 인터페이스를 통제하고 있다는 느낌을 주고 더불어 제품을 다시 사용하고 싶다는 확신을 줍니다.

7. 간편함의 법칙(Law of easing)

유저는 복잡한 과제라 하더라도 단계별로 나누어 간편하게 주어진다면 그것을 실행 할 확률이 높습니다.

06-law-of-easing

왼쪽과 오른쪽의 양식을 비교해보세요. 둘 다 비슷한 양의 항목이 있지만 오른쪽이 훨씬 더 작성하기가 편하죠.

우리 모두는 길고 복잡한 형태의 양식은 지겹고 번거롭기 때문에 싫어합니다. 하지만 그것을 상단의 메뉴에 둘로 나누어 놓는다면, 훨씬 더 관리하기가 쉬워지죠.

이것이 바로 간편함의 법칙입니다. 사람들은 차라리 하나의 큰 과제보다는 10개의 작은 과제를 해결하려 합니다. 작은 과제들은 우리가 힘들다고 느끼지 않게 해 줄 뿐더러, 과제를 해결 할 때마다 성취감을 주기도 하죠.

과연 이것들은 ‘유의사항’일까요, 아니면 반드시 지켜야 할 ‘법칙’일까요?

제가 위에서 단호하게 ‘법칙’이라는 단어를 사용한 이유가 있습니다. 이 법칙들을 위반 했을 시 단 한번도 좋은 결과가 나오는 것을 보지 못했기 때문이죠.

반 농담이지만, 이 법칙들을 어길 시에는 항상 나쁜 결과가 따릅니다. 그것은 주로 이 불쾌한 인터페이스에 대해 성난 유저들이죠.

UI 디자인은 아주 세밀하고 책임이 막중한 작업입니다. 위의 법칙들은 그 역할을 수행하는데 있어 조금이라도 도움이 될 겁니다.

만약 이 7가지 UI 디자인 법칙들을 어기고자 한다면, 반드시 그에 합당한 이유가 있기를 바랍니다.

원문: 7 unbreakable laws of user interface design by Peter Vukovic

알아둬야 할 JavaScript 프로젝트들

이전 글에서 "2014년에 배우고 싶은 프로그래밍 언어는?"이라는 제목의 설문조사를 실시했었습니다. 예상했었습니다만, JavaScript가 압도적(?) 1위를 차지했는데요. 웹 세상에서 JavaScript라는 언어가 차지하는 비중이 얼마만큼인지를 잘 보여주는 결과였던 것 같습니다. 


http://ayudawordpress.com/insertar-javascript-en-wordpress/



SEE ALSO2014년을 함께할 프로그래밍 언어는?


그래서 이번 글에서는 알아두면 생산성을 높일 수 있는 JavaScript 프로젝트들을 소개하려고 합니다. (jQuery같은 정말 보편적으로 사용되는 프로젝트는 뺐습니다.) 이중에는 라이브러리도 있고, 완전한 프레임워크(framework)도 있습니다. 일별하신 다음에 용도에 맞게 가려 쓰시면 좋을 것 같구요. 제 취향에 따라 고른거라 공신력은 없습니다. 더 공신력 있는 자료를 원하시면 이 페이지 마지막에 있는 링크를 참고하세요. 


사실 "JavaScript를 배워야하는 다섯 가지 이유들"이라는 글을 쓰려고 준비하면서 이런 저런 자료들을 찾아 봤었는데, 인상적인 문구 하나를 발견하고 나서는 포기했습니다. 이런 글이었죠.


"어쨌든 결국에는 배워야 할 언어니까 배워야 한다."


1. Angular.js


최근 가장 주목받고 있는 MVC 프레임워크죠. angularjs.org 가 웹사이트 주소입니다. 웹 사이트 대문부터가 코드들로 가득한 것이 심상치 않은데요. 일단 이 프레임워크를 사용하면 HTML과 Application 로직을 바인딩하기 위한 코드의 양이 엄청나게 줄어듭니다. View-Model 간 interaction을 처리하기 위해 우리는 그동안 정말 많은 삽질을 해야 했는데요. 그런 수고를 줄여주는 것이죠. 


다만 Angular.js를 사용하려면 HTML 코드에 HTML이 아닌 코드들이 뒤섞이게 되는 문제가 있는데요. Presentation이 Model과 완전히 분리되어야 한다는 원칙이 좀 손해를 보게 되는 것이죠. HTML 문서와 응용 로직 사이의 결합도가 증가하기 때문인데요. 저는 개인적으로 이런 식의 프로그래밍을 싫어합니다만 HTML 디자인을 담당하는 개발자나 도구가 Angular.js를 수용하게 되면 개선될 수도 있겠습니다. 


2. Underscore.js


JavaScript 개발시 생산성을 높여주는 다양한 API를 포괄하는 라이브러리입니다. Python과 유사한 Functional Programming을 할 수 있도록 도와줍니다. 그 이외에도 기능들이 많습니다. 웹사이트는 underscorejs.org 입니다.


3. D3.js


SVG를 활용한 이 엄청난 시각화 도구는 다양한 형태의 인포그래픽을 JSON 형태의 데이터를 사용해 실시간으로 렌더링할 수 있도록 해 줍니다. 그야말로 시각화의 끝판왕. 데이터를 보다 효과적으로 렌더링하는 목적을 달성하기 위해서는 반드시 배워야 하는 도구 중 하나. 웹사이트는 d3js.org


4. Node.js


Node.js는 JavaScript라는 언어의 적용범위를 Front-end에서 Backend 서버 개발로까지 확장시켰습니다. 이 프로젝트 덕분에 JavaScript는 범용적 언어라는 지위를 획득하게 되었다고 봐도 과언이 아닌데요. 이 플랫폼을 사용하면 웹 서버를 비롯한 다양한 형태의 서버를 아주 쉽게 만들 수 있을 뿐 아니라, 과거 독립적인 응용 프로그램에서나 가능했던 일들을 JavaScript로도 할 수 있게 됩니다. 웹사이트는 nodejs.org 


5. two.js


SVG, Canvas, WebGL을 사용해 2차원의 이미지를 그릴 수 있도록 해 줍니다. 현재는 도형만 그릴 수 있습니다만 (텍스트나 이미지는 지원하지 않습니다.) 추후 더 확장될 것으로 예상됩니다만, 어쨌든 현재로는 그렇습니다. 웹 사이트를 가 보면 굉장히 다양한 (그리고 흥미진진한) 예제들을 발견할 수 있는데요. 어떤 것은 D3.js의 영역과 겹치고, 어떤 것은 아닙니다. 용도를 잘 구별해서 사용하는 것이 좋을 듯. 웹사이트 주소는 http://jonobr1.github.io/two.js/ 입니다. 


6. Zebra


데스크탑 응용 프로그램에서 흔히 발견할 수 있는 그리드, 탭, 메뉴, 폼 등등의 요소를 포함하는 응용을 JavaScript로도 작성할 수 있도록 해 줍니다. 웹사이트는 https://github.com/barmalei/zebra 입니다.


7. Formula.js


엑셀이나 구글 스프레드시트에서 사용 가능한 함수들을 JavaScript에서도 사용할 수 있도록 해 주는데요. 이 웹 사이트에 가보면, 이 라이브러리에 포함되어 있는 함수가 여러분의 브라우저에서도 지원되는지 자동으로 테스트 해 주기 때문에 개발에 활용하기가 편합니다. 엑셀 매니아라면 환영할 만한 라이브러리. 웹사이트는 http://stoic.com/formula/ 입니다. 


8. Chart.js


JavaScript로 차트를 그려야 한다면 피해갈 수 없는 라이브러리. 차트를 그리고 싶은 욕구가 샘솟도록 만드는 예쁜 차트들을 제공함. 웹사이트는 http://www.chartjs.org/ 


9. Parallel.js


JavaScript로 멀티코어 프로그래밍을 할 수 있도록 해 주는 라이브러리. 단 여러분의 브라우저가 WebWorker를 지원해야 함. 이 라이브러리를 사용하면 Map-Reduce 같은 프로그래밍 모델을 JavaScript 안에서 사용할 수 있게 됩니다. 단 물리적으로 분리된 시스템이 아니라, 여러 코어 상에서죠. 웹 사이트는 http://adambom.github.io/parallel.js/


10. Meteor


웹-앱을 손쉽게 만들 수 있도록 도와주는 오픈 소스 프레임워크. 웹-앱 개발자라면 반드시 검토해봐야 할 프레임워크 가운데 하나. https://www.meteor.com/


11. jQuery mobile


모바일 기기가 대세인 작금의 상황에 이 라이브러리를 빼먹고 넘어가면 섭섭할 듯. 터치에 최적화된 웹 프레임워크. jQuery == JavaScript 라고 생각하는 사람도 많은 상황이라, 현재 JavaScript 시장의 대세는 역시 jQuery. 모바일에서도 무시할 수 없기 때문에 jQuery 이야기는 안하려고 했으나 어쩔 수 없이 (Orz) 웹사이트는 http://jquerymobile.com/


12. Grunt


JavaScript를 사용한 개발과정을 자동화하고 싶다면? 프로젝트 관리를 자동화 하고 싶다면? JavaScript 프로젝트에도 빌드 도구를 도입하고 싶다면? 그렇다면 현재 대안은 딱 하나 뿐입니다. Grunt 상에서 실행되는 어마어마한 양의 플러그인 수가 Grunt의 인기를 반증합니다. 웹사이트는 http://gruntjs.com/


이 이외에도 많사오니 아래의 링크를 참고하세요. 지금 GitHub에서 가장 인기있는 JavaScript 프로젝트 100개의 리스트를 확인할 수 있습니다. (2013년 말 기준) 1위는 Grunt. 


http://www.takipiblog.com/wp-content/uploads/2013/11/Javascript.jpg


http://www.takipiblog.com/2013/11/20/we-analyzed-30000-github-projects-here-are-the-top-100-libraries-in-java-js-and-ruby/


출처 : http://www.buggymind.com/533

Airbnb JavaScript 스타일 가이드

원문:https://github.com/airbnb/javascript

Airbnb JavaScript 스타일 가이드() {

목차

  1. Types
  2. Objects
  3. Arrays
  4. Strings
  5. Functions
  6. Properties
  7. Variables
  8. Hoisting
  9. Conditional Expressions & Equality
  10. Blocks
  11. Comments
  12. Whitespace
  13. Commas
  14. Semicolons
  15. Type Casting & Coercion
  16. Naming Conventions
  17. Accessors
  18. Constructors
  19. Events
  20. Modules
  21. jQuery
  22. ES5 Compatibility
  23. Testing
  24. Performance
  25. Resources
  26. In the Wild
  27. Translation
  28. The JavaScript Style Guide Guide
  29. Contributors
  30. License

Types 원문

  • Primitives: primitive type은 그 값을 직접 조작합니다.

    • string
    • number
    • boolean
    • null
    • undefined
    var foo = 1,
        bar = foo;
    
    bar = 9;
    
    console.log(foo, bar); // => 1, 9
  • Complex: 참조형(Complex)은 참조를 통해 값을 조작합니다.

    • object
    • array
    • function
    var foo = [1, 2],
        bar = foo;
    
    bar[0] = 9;
    
    console.log(foo[0], bar[0]); // => 9, 9

    [↑]

Objects 원문

  • Object를 만들 때는 리터럴 구문을 사용하십시오.

    // bad
    var item = new Object();
    
    // good
    var item = {};
  • 예약어(reserved words)를 키로 사용하지 마십시오. 이것은 IE8에서 동작하지 않습니다. More info

    // bad
    var superman = {
      default: { clark: 'kent' },
      private: true
    };
    
    // good
    var superman = {
      defaults: { clark: 'kent' },
      hidden: true
    };
  • 예약어 대신 알기 쉬운 동의어(readable synonyms)를 사용하십시오.

    // bad
    var superman = {
      class: 'alien'
    };
    
    // bad
    var superman = {
      klass: 'alien'
    };
    
    // good
    var superman = {
      type: 'alien'
    };
    

    [↑]

Arrays 원문

  • 배열을 만들 때 리터럴 구문을 사용하십시오.

    // bad
    var items = new Array();
    
    // good
    var items = [];
  • 길이를 알 수없는 경우는 Array#push를 사용하십시오.

    var someStack = [];
    
    
    // bad
    someStack[someStack.length] = 'abracadabra';
    
    // good
    someStack.push('abracadabra');
  • 배열을 복사 할 필요가있는 경우 Array#slice를 사용하십시오. jsPerf

    var len = items.length,
        itemsCopy = [],
        i;
    
    // bad
    for (i = 0; i < len; i++) {
      itemsCopy[i] = items[i];
    }
    
    // good
    itemsCopy = items.slice();
  • Array와 비슷한(Array-Like)한 Object를 Array에 변환하는 경우는 Array#slice를 사용하십시오.

    function trigger() {
      var args = Array.prototype.slice.call(arguments);
      ...
    }

[↑]

Strings 원문

  • 문자열은 작은 따옴표''를 사용하십시오.

    // bad
    var name = "Bob Parr";
    
    // good
    var name = 'Bob Parr';
    
    // bad
    var fullName = "Bob " + this.lastName;
    
    // good
    var fullName = 'Bob ' + this.lastName;
  • 80 문자 이상의 문자열은 문자열 연결을 사용하여 여러 줄에 걸쳐 기술 할 필요가 있습니다.

  • Note : 문자열 연결을 많이하면 성능에 영향을 줄 수 있습니다. jsPerf & Discussion

    // bad
    var errorMessage = 'This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.';
    
    // bad
    var errorMessage = 'This is a super long error that \
    was thrown because of Batman. \
    When you stop to think about \
    how Batman had anything to do \
    with this, you would get nowhere \
    fast.';
    
    
    // good
    var errorMessage = 'This is a super long error that ' +
      'was thrown because of Batman.' +
      'When you stop to think about ' +
      'how Batman had anything to do ' +
      'with this, you would get nowhere ' +
      'fast.';
  • 프로그램에서 문자열을 생성 할 필요가 있는 경우 (특히 IE는) 문자열 연결 대신 Array#join을 사용하십시오. jsPerf.

    var items,
        messages,
        length,
        i;
    
    messages = [{
        state: 'success',
        message: 'This one worked.'
    },{
        state: 'success',
        message: 'This one worked as well.'
    },{
        state: 'error',
        message: 'This one did not work.'
    }];
    
    length = messages.length;
    
    // bad
    function inbox(messages) {
      items = '<ul>';
    
      for (i = 0; i < length; i++) {
        items += '<li>' + messages[i].message + '</li>';
      }
    
      return items + '</ul>';
    }
    
    // good
    function inbox(messages) {
      items = [];
    
      for (i = 0; i < length; i++) {
        items[i] = messages[i].message;
      }
    
      return '<ul><li>' + items.join('</li><li>') + '</li></ul>';
    }

    [↑]

Functions 원문

  • 함수식(Function expressions)

    // 익명함수식(anonymous function expression)
    var anonymous = function() {
      return true;
    };
    
    // 명명된 함수식(named function expression)
    var named = function named() {
      return true;
    };
    
    // 즉시실행 함수식(immediately-invoked function expression (IIFE))
    (function() {
      console.log('Welcome to the Internet. Please follow me.');
    })();
  • (if 및 while 등) 블록 내에서 변수에 함수를 할당하는 대신 함수를 선언하지 마십시오. 브라우저는 허용하지만 (마치 'bad news bears'처럼) 모두 다른 방식으로 해석됩니다.

  • Note: ECMA-262에서는block은 statements의 목록에 정의되어 있습니다 만, 함수 선언은 statements가 없습니다.이 문제는 ECMA-262의 설명을 참조하십시오. .

    // bad
    if (currentUser) {
      function test() {
        console.log('Nope.');
      }
    }
    
    // good
    var test;
    if (currentUser) {
      test = function test() {
        console.log('Yup.');
      };
    }
  • 매개 변수(parameter)에 arguments를 절대 지정하지 마십시오. 이것은 함수 범위로 전달 될arguments객체의 참조를 덮어 쓸 것입니다.

    // bad
    function nope(name, options, arguments) {
      // ...stuff...
    }
    
    // good
    function yup(name, options, args) {
      // ...stuff...
    }

    [↑]

Properties 원문

  • 속성에 액세스하려면 도트.를 사용하십시오.

    var luke = {
      jedi: true,
      age: 28
    };
    
    // bad
    var isJedi = luke['jedi'];
    
    // good
    var isJedi = luke.jedi;
  • 변수를 사용하여 속성에 접근하려면 대괄호[]을 사용하십시오.

    var luke = {
      jedi: true,
      age: 28
    };
    
    function getProp(prop) {
      return luke[prop];
    }
    
    var isJedi = getProp('jedi');

    [↑]

Variables 원문

  • 변수를 선언 할 때는 항상 var를 사용하십시오. 그렇지 않으면 전역 변수로 선언됩니다. 전역 네임 스페이스를 오염시키지 않도록 Captain Planet도 경고하고 있습니다.

    // bad
    superPower = new SuperPower();
    
    // good
    var superPower = new SuperPower();
  • 여러 변수를 선언하려면 하나의 var를 사용하여 변수마다 줄바꿈하여 선언하십시오.

    // bad
    var items = getItems();
    var goSportsTeam = true;
    var dragonball = 'z';
    
    // good
    var items = getItems(),
        goSportsTeam = true,
        dragonball = 'z';
  • 정의되지 않은 변수를 마지막으로 선언하십시오. 이것은 나중에 이미 할당된 변수 중 하나를 지정해야하는 경우에 유용합니다.

    // bad
    var i, len, dragonball,
        items = getItems(),
        goSportsTeam = true;
    
    // bad
    var i, items = getItems(),
        dragonball,
        goSportsTeam = true,
        len;
    
    // good
    var items = getItems(),
        goSportsTeam = true,
        dragonball,
        length,
        i;
  • 변수의 할당은 스코프의 시작 부분에서 해주십시오. 이것은 변수 선언과 Hoisting 관련 문제를 해결합니다.

    // bad
    function() {
      test();
      console.log('doing stuff..');
    
      //..other stuff..
    
      var name = getName();
    
      if (name === 'test') {
        return false;
      }
    
      return name;
    }
    
    // good
    function() {
      var name = getName();
    
      test();
      console.log('doing stuff..');
    
      //..other stuff..
    
      if (name === 'test') {
        return false;
      }
    
      return name;
    }
    
    // bad
    function() {
      var name = getName();
    
      if (!arguments.length) {
        return false;
      }
    
      return true;
    }
    
    // good
    function() {
      if (!arguments.length) {
        return false;
      }
    
      var name = getName();
    
      return true;
    }

    [↑]

Hoisting 원문

  • 해당 스코프의 시작 부분에 Hoist된 변수선언은 할당되지 않습니다.

    // (notDefined가 전역 변수에 존재하지 않는다고 가정했을 경우)
    // 이것은 동작하지 않습니다.
    function example() {
      console.log(notDefined); // => throws a ReferenceError
    }
    
    // 그 변수를 참조하는 코드 후에 그 변수를 선언 한 경우
    // 변수가 Hoist된 상태에서 작동합니다.
    // Note : `true`라는 값 자체는 Hoist되지 않습니다.
    function example() {
      console.log(declaredButNotAssigned); // => undefined
      var declaredButNotAssigned = true;
    }
    
    // 인터 프린터는 변수 선언을 스코프의 시작 부분에 Hoist합니다.
    // 위의 예는 다음과 같이 다시 작성할 수 있습니다.
    function example() {
      var declaredButNotAssigned;
      console.log(declaredButNotAssigned); // => undefined
      declaredButNotAssigned = true;
    }
  • 익명 함수의 경우 함수가 할당되기 전에 변수가 Hoist될 수 있습니다.

    function example() {
      console.log(anonymous); // => undefined
    
      anonymous(); // => TypeError anonymous is not a function
    
      var anonymous = function() {
        console.log('anonymous function expression');
      };
    }
  • 명명 된 함수의 경우도 마찬가지로 변수가 Hoist될 수 있습니다. 함수 이름과 함수 본체는 Hoist되지 않습니다.

    function example() {
      console.log(named); // => undefined
    
      named(); // => TypeError named is not a function
    
      superPower(); // => ReferenceError superPower is not defined
    
      var named = function superPower() {
        console.log('Flying');
      };
    }
    
    // 함수이름과 변수이름이 같은 경우에도 같은 일이 일어납니다.
    function example() {
      console.log(named); // => undefined
    
      named(); // => TypeError named is not a function
    
      var named = function named() {
        console.log('named');
      }
    }
  • 함수 선언은 함수이름과 함수본문이 Hoist됩니다.

    function example() {
      superPower(); // => Flying
    
      function superPower() {
        console.log('Flying');
      }
    }
  • 더 자세한 정보는 Ben Cherry의 JavaScript Scoping & Hoisting를 참조하십시오.

    [↑]

Conditional Expressions & Equality(조건식과 등가식) 원문

  • == 나 != 보다는 === 와 !== 를 사용해 주십시오
  • 조건식은ToBoolean 메소드에 의해 엄밀하게 비교됩니다. 항상 이 간단한 규칙에 따라 주십시오.

    • Objects 는 true 로 평가됩니다.
    • undefined 는 false 로 평가됩니다.
    • null 는 false 로 평가됩니다.
    • Booleans 는 boolean형의 값 으로 평가됩니다.
    • Numbers 는 true 로 평가됩니다. 하지만 +0, -0, or NaN 의 경우는 false 입니다.
    • Strings 는 true 로 평가됩니다. 하지만 빈문자 '' 의 경우는 false 입니다.
    if ([0]) {
      // true
      // Array는 Object 이므로 true 로 평가됩니다.
    }
  • 짧은형식을 사용하십시오.

    // bad
    if (name !== '') {
      // ...stuff...
    }
    
    // good
    if (name) {
      // ...stuff...
    }
    
    // bad
    if (collection.length > 0) {
      // ...stuff...
    }
    
    // good
    if (collection.length) {
      // ...stuff...
    }
  • 더 자세한 정보는 Angus Croll 의 Truth Equality and JavaScript를 참고해 주십시오.

    [↑]

Blocks 원문

  • 복수행 블록은 중괄호 ({})를 사용하십시오.

    // bad
    if (test)
      return false;
    
    // good
    if (test) return false;
    
    // good
    if (test) {
      return false;
    }
    
    // bad
    function() { return false; }
    
    // good
    function() {
      return false;
    }

    [↑]

Comments 원문

  • 복수행의 코멘트는 /** ... */ 를 사용해 주십시오. 그 안에는 설명과 모든 매개 변수와 반환 값에 대한 형식과 값을 설명합니다.

    // bad
    // make() returns a new element
    // based on the passed in tag name
    //
    // @param <String> tag
    // @return <Element> element
    function make(tag) {
    
      // ...stuff...
    
      return element;
    }
    
    // good
    /**
     * make() returns a new element
     * based on the passed in tag name
     *
     * @param <String> tag
     * @return <Element> element
     */
    function make(tag) {
    
      // ...stuff...
    
      return element;
    }
  • 한 줄 주석에는//를 사용하십시오. 코멘트를 추가하고 싶은 코드의 상단에 작성하십시오. 또한 주석 앞에 빈 줄을 넣어주십시오.

    // bad
    var active = true;  // is current tab
    
    // good
    // is current tab
    var active = true;
    
    // bad
    function getType() {
      console.log('fetching type...');
      // set the default type to 'no type'
      var type = this._type || 'no type';
    
      return type;
    }
    
    // good
    function getType() {
      console.log('fetching type...');
    
      // set the default type to 'no type'
      var type = this._type || 'no type';
    
      return type;
    }
  • 문제를 지적하고 재고를 촉구하거나 문제에 대한 해결책을 제시하는 등 의견의 앞에 FIXME 나 TODO를 붙이는 것으로 다른 개발자의 빠른 이해를 도울 수 있습니다. 이러한 어떤 액션을 동반한다는 의미에서 일반 코멘트와는 다릅니다. 액션은 FIXME - 해결책이 필요 또는 TODO - 구현이 필요 입니다.

  • 문제에 대한 코멘트로 // FIXME :를 사용하십시오.

    function Calculator() {
    
      // FIXME: 전역 변수를 사용해서는 안됩니다.
      total = 0;
    
      return this;
    }
  • 문제 해결책에 대한 코멘트로 // TODO :를 사용하십시오.

    function Calculator() {
    
      // TODO: total은 옵션 매개 변수로 설정되어야 함.
      this.total = 0;
      return this;
    }

    [↑]

Whitespace 원문

  • 탭에는 공백 2개를 설정하십시오.

    // bad
    function() {
    ∙∙∙∙var name;
    }
    
    // bad
    function() {
    ∙var name;
    }
    
    // good
    function() {
    ∙∙var name;
    }
  • 중괄호({})의 앞에 공백을 하나 넣어주십시오.

    // bad
    function test(){
      console.log('test');
    }
    
    // good
    function test() {
      console.log('test');
    }
    
    // bad
    dog.set('attr',{
      age: '1 year',
      breed: 'Bernese Mountain Dog'
    });
    
    // good
    dog.set('attr', {
      age: '1 year',
      breed: 'Bernese Mountain Dog'
    });
  • 파일의 마지막에는 빈 줄을 하나 넣어주십시오.

    // bad
    (function(global) {
      // ...stuff...
    })(this);
    // good
    (function(global) {
      // ...stuff...
    })(this);
    
  • 메소드 체인이 길어지는 경우 적절히 들여쓰기(indentation) 하십시오.

    // bad
    $('#items').find('.selected').highlight().end().find('.open').updateCount();
    
    // good
    $('#items')
      .find('.selected')
        .highlight()
        .end()
      .find('.open')
        .updateCount();
    
    // bad
    var leds = stage.selectAll('.led').data(data).enter().append('svg:svg').class('led', true)
        .attr('width',  (radius + margin) * 2).append('svg:g')
        .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
        .call(tron.led);
    
    // good
    var leds = stage.selectAll('.led')
        .data(data)
      .enter().append('svg:svg')
        .class('led', true)
        .attr('width',  (radius + margin) * 2)
      .append('svg:g')
        .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
        .call(tron.led);

    [↑]

Commas 원문

  • 선두의 comma는 하지마십시오.

    // bad
    var once
      , upon
      , aTime;
    
    // good
    var once,
        upon,
        aTime;
    
    // bad
    var hero = {
        firstName: 'Bob'
      , lastName: 'Parr'
      , heroName: 'Mr. Incredible'
      , superPower: 'strength'
    };
    
    // good
    var hero = {
      firstName: 'Bob',
      lastName: 'Parr',
      heroName: 'Mr. Incredible',
      superPower: 'strength'
    };

 - 말미의 불필요한 쉼표도 하지 마십시오. 이것은 IE6/7과 quirksmode의 IE9에서 문제를 일으킬 수 있습니다. 또한 ES3의 일부 구현에서 불필요한 쉼표가 있는 경우, 배열 길이를 추가합니다. 이것은 ES5에서 분명해졌습니다.(source):

제 5 판에서는 말미의 불필요한 쉼표가 있는 ArrayInitialiser (배열 초기화 연산자)라도 배열에 길이를 추가하지 않는다는 사실을 명확히하고 있습니다. 이것은 제 3 판에서 의미적인 변경은 아닙니다만, 일부의 구현은 이전부터 이것을 오해하고 있었을지도 모릅니다.

```javascript
// bad
var hero = {
  firstName: 'Kevin',
  lastName: 'Flynn',
};

var heroes = [
  'Batman',
  'Superman',
];

// good
var hero = {
  firstName: 'Kevin',
  lastName: 'Flynn'
};

var heroes = [
  'Batman',
  'Superman'
];
```

**[[↑]](#TOC)**

Semicolons 원문

  • 네!(Yup.)

    // bad
    (function() {
      var name = 'Skywalker'
      return name
    })()
    
    // good
    (function() {
      var name = 'Skywalker';
      return name;
    })();
    
    // good
    ;(function() {
      var name = 'Skywalker';
      return name;
    })();

    [↑]

Type Casting & Coercion(강제) 원문

  • 문의 시작 부분에서 형을 강제합니다.
  • Strings:

    //  => this.reviewScore = 9;
    
    // bad
    var totalScore = this.reviewScore + '';
    
    // good
    var totalScore = '' + this.reviewScore;
    
    // bad
    var totalScore = '' + this.reviewScore + ' total score';
    
    // good
    var totalScore = this.reviewScore + ' total score';
  • 숫자는parseInt를 사용하십시오. 항상 형변환을 위한 기수(radix)를 인수로 전달하십시오.

    var inputValue = '4';
    
    // bad
    var val = new Number(inputValue);
    
    // bad
    var val = +inputValue;
    
    // bad
    var val = inputValue >> 0;
    
    // bad
    var val = parseInt(inputValue);
    
    // good
    var val = Number(inputValue);
    
    // good
    var val = parseInt(inputValue, 10);
  • 어떤 이유에 의해 parseInt 가 병목이 되고, 성능적인 이유로 Bitshift를 사용할 필요가 있을 경우, 하려고 하는것에 대해, why(왜)와 what(무엇)의 설명을 코멘트로 남겨주십시오.

      // good
      /**
       * parseInt가 병목을 일으키므로
       * Bitshift로 문자열을 수치로 강제적으로 변환하는 방법으로
       * 성능을 개선시킵니다.
       */
      var val = inputValue >> 0;
  • Booleans:

    var age = 0;
    
    // bad
    var hasAge = new Boolean(age);
    
    // good
    var hasAge = Boolean(age);
    
    // good
    var hasAge = !!age;

    [↑]

Naming Conventions 원문

  • 한문자 이름은 피하십시오. 이름에서 의도를 읽을 수 있도록 하십시오.

    // bad
    function q() {
      // ...stuff...
    }
    
    // good
    function query() {
      // ..stuff..
    }
  • Object, 함수, 그리고 인스턴스로는 camelCase를 사용하십시오.

    // bad
    var OBJEcttsssss = {};
    var this_is_my_object = {};
    var this-is-my-object = {};
    function c() {};
    var u = new user({
      name: 'Bob Parr'
    });
    
    // good
    var thisIsMyObject = {};
    function thisIsMyFunction() {};
    var user = new User({
      name: 'Bob Parr'
    });
  • Class와 생성자에는 PascalCase를 사용하십시오.

    // bad
    function user(options) {
      this.name = options.name;
    }
    
    var bad = new user({
      name: 'nope'
    });
    
    // good
    function User(options) {
      this.name = options.name;
    }
    
    var good = new User({
      name: 'yup'
    });
  • private 속성 이름은 밑줄 _ 을 사용하십시오.

    // bad
    this.__firstName__ = 'Panda';
    this.firstName_ = 'Panda';
    
    // good
    this._firstName = 'Panda';
  • this의 참조를 저장할 때 _this 를 사용하십시오.

    // bad
    function() {
      var self = this;
      return function() {
        console.log(self);
      };
    }
    
    // bad
    function() {
      var that = this;
      return function() {
        console.log(that);
      };
    }
    
    // good
    function() {
      var _this = this;
      return function() {
        console.log(_this);
      };
    }
  • 함수에 이름을 붙여주십시오. 이것은 stack traces를 추적하기 쉽게하기 때문입니다.

    // bad
    var log = function(msg) {
      console.log(msg);
    };
    
    // good
    var log = function log(msg) {
      console.log(msg);
    };

    [↑]

Accessors 원문

  • 속성을 위한 접근자(Accessor) 함수는 필요 없습니다.
  • 접근자 함수가 필요한 경우 getVal() 이나 setVal('hello') 라고 사용합니다.

    // bad
    dragon.age();
    
    // good
    dragon.getAge();
    
    // bad
    dragon.age(25);
    
    // good
    dragon.setAge(25);
  • 속성이 boolean의 경우 isVal() 이나 hasVal() 라고 사용합니다.

    // bad
    if (!dragon.age()) {
      return false;
    }
    
    // good
    if (!dragon.hasAge()) {
      return false;
    }
  • 일관된다면 get() 이나 set() 이라는 함수를 작성해도 좋습니다.

    function Jedi(options) {
      options || (options = {});
      var lightsaber = options.lightsaber || 'blue';
      this.set('lightsaber', lightsaber);
    }
    
    Jedi.prototype.set = function(key, val) {
      this[key] = val;
    };
    
    Jedi.prototype.get = function(key) {
      return this[key];
    };

    [↑]

Constructors 원문

  • 새 Object에서 프로토타입을 재정의하는 것이 아니라, 프로토타입 객체에 메서드를 추가해 주십시오. 프로토타입을 재정의하면 상속이 불가능합니다. 프로토타입을 리셋하는것으로 베이스 클래스를 재정의 할 수 있습니다.

    function Jedi() {
      console.log('new jedi');
    }
    
    // bad
    Jedi.prototype = {
      fight: function fight() {
        console.log('fighting');
      },
    
      block: function block() {
        console.log('blocking');
      }
    };
    
    // good
    Jedi.prototype.fight = function fight() {
      console.log('fighting');
    };
    
    Jedi.prototype.block = function block() {
      console.log('blocking');
    };
  • 메소드의 반환 값으로 this를 반환함으로써 메소드 체인을 할 수 있습니다.

    // bad
    Jedi.prototype.jump = function() {
      this.jumping = true;
      return true;
    };
    
    Jedi.prototype.setHeight = function(height) {
      this.height = height;
    };
    
    var luke = new Jedi();
    luke.jump(); // => true
    luke.setHeight(20) // => undefined
    
    // good
    Jedi.prototype.jump = function() {
      this.jumping = true;
      return this;
    };
    
    Jedi.prototype.setHeight = function(height) {
      this.height = height;
      return this;
    };
    
    var luke = new Jedi();
    
    luke.jump()
      .setHeight(20);
  • 독자적인 toString()을 만들 수도 있지만 올바르게 작동하는지, 부작용이 없는 것만은 확인해 주십시오.

    function Jedi(options) {
      options || (options = {});
      this.name = options.name || 'no name';
    }
    
    Jedi.prototype.getName = function getName() {
      return this.name;
    };
    
    Jedi.prototype.toString = function toString() {
      return 'Jedi - ' + this.getName();
    };

    [↑]

Events

  • (DOM 이벤트나 Backbone events와 같은 고유의) 이벤트 탑재체(payloads)의 값을 전달하는 경우 원시 값(raw value) 대신 해시 인수(hash)를 전달합니다. 이렇게하는 것으로 나중에 개발자가 이벤트와 관련된 모든 핸들러를 찾아 업데이트 하지 않고 이벤트 탑재체(payloads)에 값을 추가 할 수 있습니다. 예를 들어, 이것 대신 :

    // bad
    $(this).trigger('listingUpdated', listing.id);
    
    ...
    
    $(this).on('listingUpdated', function(e, listingId) {
      // do something with listingId
    });

    이쪽을 선호합니다.:

    // good
    $(this).trigger('listingUpdated', { listingId : listing.id });
    
    ...
    
    $(this).on('listingUpdated', function(e, data) {
      // do something with data.listingId
    });

    [↑]

Modules 원문

  • 모듈의 시작은 ! 로 시작하십시오. 이것은 문말에 세미콜론을 넣는것을 잊은 모듈을 연결할때 런타임 오류가 발생하지 않기 때문입니다.
  • 파일 이름은 camelCase를 사용하여 같은 이름의 폴더에 저장해주십시오. 또한 단독으로 공개할 경우 이름을 일치시켜주십시오.
  • noConflict() 라는 명칭으로 (이름이 겹쳐 덮어 써지기 전의) 모듈을 반환하는 메서드를 추가해주십시오.
  • 항상 모듈의 시작 부분에서'use strict';를 선언해주십시오.

    // fancyInput/fancyInput.js
    
    !function(global) {
      'use strict';
    
      var previousFancyInput = global.FancyInput;
    
      function FancyInput(options) {
        this.options = options || {};
      }
    
      FancyInput.noConflict = function noConflict() {
        global.FancyInput = previousFancyInput;
        return FancyInput;
      };
    
      global.FancyInput = FancyInput;
    }(this);

    [↑]

jQuery 원문

  • jQuery Object의 변수 앞에는 $을 부여해 주십시오.

    // bad
    var sidebar = $('.sidebar');
    
    // good
    var $sidebar = $('.sidebar');
  • jQuery 쿼리결과를 캐시해주십시오.

    // bad
    function setSidebar() {
      $('.sidebar').hide();
    
      // ...stuff...
    
      $('.sidebar').css({
        'background-color': 'pink'
      });
    }
    
    // good
    function setSidebar() {
      var $sidebar = $('.sidebar');
      $sidebar.hide();
    
      // ...stuff...
    
      $sidebar.css({
        'background-color': 'pink'
      });
    }
  • DOM 검색은 Cascading $('.sidebar ul') 이나 parent > child $('.sidebar > ul') 를 사용해주십시오. jsPerf

  • jQuery Object 검색은 스코프가 붙은 find를 사용해주십시오.

    // bad
    $('ul', '.sidebar').hide();
    
    // bad
    $('.sidebar').find('ul').hide();
    
    // good
    $('.sidebar ul').hide();
    
    // good
    $('.sidebar > ul').hide();
    
    // good
    $sidebar.find('ul');

    [↑]

ECMAScript 5 Compatibility 원문

Testing 원문

  • 네!(Yup.)

    function() {
      return true;
    }

    [↑]

Performance 원문

Resources 원문

Read This

Other Styleguides

Other Styles

Further Reading

Books

Blogs

In the Wild

This is a list of organizations that are using this style guide. Send us a pull request or open an issue and we'll add you to the list.

Translation

This style guide is also available in other languages:

The JavaScript Style Guide Guide

Contributors

License

(The MIT License)

Copyright (c) 2012 Airbnb

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

[↑]

};

영작할때 유의어를 찾아주는 사이트

https://www.wordinglab.com/