웹 개발 입문자를 위한 Vue.js 프레임워크 소개

누구나 쉽게 시작할 수 있는 Vue.js 프레임워크와 학습 자료 소개

Advertisements

들어가며

요즘 프런트엔드 개발에 관심을 갖는 분들이 점점 많아지고 있습니다. 컴퓨터 공학을 전공한 대학생 뿐만 아니라 비전공자, 퍼블리셔, 디자이너 분들도 점점 멋진 웹 화면을 개발하기 위해 스스로 정보를 찾아가며 웹 개발하는 법을 배우고 있는 것 같아요.

웹 개발을 위한 기초 HTML, CSS, 자바스크립트를 배우고 나면 제일 먼저 찾게 되는게 바로 프런트엔드 프레임워크입니다. React, Angular 처럼 널리 알려진 프레임워크 사이로 요즘 새롭게 떠오르는 쉽고 강력한 프레임워크가 있습니다. 바로 Vue.js 입니다.

이번 글에서는 Vue.js에 대해서 간단히 소개하고, 웹 개발 입문자도 쉽게 프레임워크를 배울 수 있는 자료들을 안내하려고 합니다.

Vue.js 프레임워크란?

먼저 Vue.js 프레임워크가 무엇인지 소개를 하자면 Vue.js는 웹 사이트를 만들 수 있는 웹 개발자들의 도구입니다.

웹 사이트를 만들기 위해서는 HTML, CSS, Javascript와 같은 웹 기술이 필요합니다. 이 3가지 웹 기술로도 요즘 저희가 많이 사용하는 페이스북, 네이버, 구글 등 여러 가지 유형의 사이트를 만들 수 있습니다.

그런데 왜 프레임워크를 사용해서 만들까요? 그 이유는 더 쉽고 빠르게 웹 사이트를 만들 수 있기 때문입니다. 정형화된 방식으로 미리 만들어진 기능들을 편하게 가져다가 다시 사용하기 때문에
백지상태에서 시작하는 것보다는 확실히 더 빠르게 일정 이상의 좋은 품질로 개발할 수 있죠.

화면을 쉽게 개발할 수 있는 프런트엔드 프레임워크는 2000년대 중후반부터 등장했습니다. 그리고 많은 프런트엔드 프레임워크를 거쳐 지금의 Vue.js에 이르기까지 수많은 프레임워크가 등장했죠. 그래서 요즘 웹 사이트를 개발한다고 하면 엄청나게 많은 도구의 선택지가 있습니다.

좋죠. 일단 선택지가 많으니 뭐든 잘 배워서 개발할 때 써먹으면 되니까요. 하지만, 반대로 생각해보면 정말 너무 많습니다. 네 저도 지금 4년 동안 회사에서 웹 개발을 해왔는데 배우는 걸 멈춰본 적이 없습니다. 맨날 새로운 게 튀어나오고 그러면 또 배우고..

그래서 요즘에는 이런 상황에 고통받는 웹 개발자들이 한 둘이 아닙니다. 제 주변만 봐도 그렇거든요. ‘아 또 나왔네……’라면서 한숨을 쉬는 개발자들이 있습니다. 저도 한숨까지는 아닌데 아 공부할게 하나 더 늘었구나라고 생각은 하죠 🙂

Vue.js 프레임워크는 이런 현재 상황에서 가장 쉽게 접근할 수 있는 프레임워크입니다. 요즘 업계에서 많이 사용되는 앵귤러, 리액트와 다르게 HTML, CSS, 자바스크립트 이외에 꼭 알고 있어야 하는 기술도 없으며 프레임워크 자체가 가볍고 쉬운 프레임워크를 지향하기 때문에 배우기가 쉽습니다.

또한 배우기가 쉽다는 점 때문에 더 많은 입문자들에게 관심을 받고 있다고 생각합니다. 그리고 기존에 프런트엔드 개발을 하지 않았던 다른 분야의 개발자들도 Vue.js로 쉽게 웹 개발을 시작하고 있습니다.

서적을 집필하면서..

책을 잠깐 소개하겠습니다.

Do it! Vue.js 입문서는 Vue.js 프레임워크를 처음 배우는 사람들이 쉽게 프레임워크를 배울 수 있도록 집중한 책입니다.

처음 출판사와 도서를 기획하고 목차를 구성하면서 어떻게 하면 이 쉬운 Vue.js 프레임워크를 더 쉽게, 빠르게, 재밌게 알려줄 수 있을까? 라는 고민을 했습니다. 작년에 패스트 캠퍼스인프런에서 강의를 하면서 검증했던 교재와 자료들을 중심으로 수업 중간중간에 수강생들이 이해하지 못하던 부분들, 특히 질문이 많았던 부분들을 어떻게 책에 잘 녹여낼지에 대한 고민을 가장 많이 했습니다. 생각해보면 이 책을 가장 필요로 하는 웹 개발 입문자, 퍼블리셔, 대학생, 실무자를 대상으로 수업을 진행했기에 수업에서 나온 피드백이 정말 소중했었죠.

처음에 초고를 쓸 때 그 내용을 책 안에 담는 게 쉬운 작업은 아니었습니다. 기술 서적을 처음 집필하는 입장에서 어떻게 써야지 독자들이 더 쉽게 읽을 수 있을지 감이 잘 안 왔었거든요. 그때 다행히 기술서 편집 경험이 많은 노련한 편집자님을 만나 요약된 정보 위주로 전달하는 블로그 글 형식에서 더 친절하고 쉽고 자세히 설명하는 글 형식으로 탈바꿈할 수 있었습니다.

책 전체를 교정하는 과정에서 특정 부분은 최소 7번 이상 다시 썼던 것 같아요. 편집자님이 쉽고 자세한 설명을 요구했었기 때문이기도 했지만 제 스스로도 다시 읽었을 때 이상하다 싶은 부분들은 그냥 넘어가지 않고 몇 번이고 다시 고쳤습니다. 그렇게 전체 원고를 최소 8번 넘게 정독한 것 같습니다.

또한, 글로 쉽게 설명하기 어려운 부분들은 도형과 그림으로 풀어냈습니다. 그림과 도형 같은 경우에도 제가 한번 쓱 그리고 끝내는 것이 아니라 1차로 제가 작업한 그림을 개발 지식이 있는 전문 디자이너 분께 2차 작업을 맡겼고, 3차로 다시 디자이너 분과 논의하면서 도형을 다듬었습니다. 그리고 4차, 5차 작업을 편집자님, 개발을 모르는 기획자분께 검토 받으며 어느 관점에서 보든지 그 글을 쉽게 이해할 수 있는 그림으로 선정했습니다.

책 작업을 하는 내내 생각했던 1가지는 ‘내 스스로도 납득이 가지 않는 글은 책에 담지 않는다’ 였습니다. 그렇기에 글의 흐름, 단어 설명, 도형과 그림, 예제 코드 등 책의 모든 부분을 하나도 빠짐없이 꼼꼼히 읽고 검토했습니다.

그리고 그 검토 작업에 고맙게도 많은 분들이 도움을 주셨어요. 모든 집필/편집 과정을 함께해준 편집자님, 직관적인 그림과 도형을 그려준 디자이너 겸 개발자님, 전체적인 책의 오탈자와 구성 오류를 검토해준 기획자님, 그리고 베타 리딩과 기술 검수를 맡아준 개발자 두 분까지 합하면 벌써 이 책에는 저 혼자가 아닌 6명의 노력과 시간이 들어갔네요. 그 외에도 조판하는 회사의 직원과 이 책을 함께 검토해주는 출판사 직원까지 생각하면 정말 많은 분들이 좋은 책을 내기 위해 함께해주신 것 같습니다.

그래서인지 이번에 출간된 Do it! Vue.js 입문 책을 자신 있게 추천할 수 있습니다. 혹시 웹 개발을 시작하고 싶다면 Do it! Vue.js 입문 책으로 시작해보시는 건 어떨까요? 🙂

읽어주셔서 감사합니다.
저자 장기효 올림

P.S : 여러 명의 땀과 노력이 들어간 Do it! Vue.js 입문 도서는 아래 링크에서 구매하실 수 있습니다 🙂
Do it! Vue.js 온라인 구매 링크

Vue.js 학습 자료

성능 덕후를 위한 자바스크립트 코딩 패턴 (중급 이상)

이 글은 CodeSchool 의 Javascript Best Practices 를 듣고, 주요 내용을 정리한 글입니다.

Ternary Conditional (삼항 연산자)

  • 다음과 같은 예문이 있다.
var isArthur = true;
var weapon;

if(isArthur) {
  weapon = "Excalibur";
} else {
  weapon = "Longsword";
}
  • 삼항연산자를 이용하면 위의 if else 문을 아래와 같이 바꿀수 있다.
var weapon = isArthur ? "Excalibur" : "Longsword";
  • 또한 삼항 연산자를 다음과 같은 형태로도 사용이 가능하다.
// 두개 이상의 변수를 이용하여 값을 받는 경우
isArthur && isKing ? (weapon = "Ex", helmet = "Goose") : (weapon = "ln", helmet = "Iron")

// 즉시 실행함수로 값을 받는 경우
isArthur && isKing ? function () {
                                   // ...
                     }();
                     :
                     function () {
                       // ...
                     }();

Logical Assignment 1 (OR)

  • OR 연산자 : “falsy” 하지 않은 가장 첫번째 마주친 값을 갖는다.
  • 아래의 삼항 연산자를 OR 연산자를 이용하여 다음과 같이 줄일 수 있다.
// 삼항연산자 사용
function addSword(sword) {
  this.swords = this.swords ? this.swords : [ ];
  this.swords = push.(sword);
}

// OR 연산자 사용
function addSword(sword) {
  this.swords = this.swords || [ ];
  this.swords = push.(sword);
}

// OR 연산자 잘못 사용한 예
function addSword(sword) {
  this.swords = [ ] || this.swords;
  this.swords = push.(sword);
}
// 위의 경우 계속 new array 를 할당함.
  • OR 연산자의 잘못된 사용 예를 더 본다.
// 잘못된 OR 연산자 사용 예
var result1 = 42 || undefined; // undefined 를 절대로 마주치지 않는다.
var result2 = ["Sweet", "array"] || 0; // 0을 절대로 마주치지 않는다.
var result3 = {type: "ring", stone: "diamond"} || ""; // "" 를 절대로 맞추지지 않는다.

// 위를 고쳐보면,
var result1 = undefined || 42;
var result2 = 0 || ["Sweet", "array"]; // 0을 절대로 마주치지 않는다.
var result3 = "" || {type: "ring", stone: "diamond"}; // "" 를 절대로 맞추지지 않는다.

Logical Assignment 2 (And)

  • OR 연산자와는 다르게 두개의 “truthy” 값이 있으면, 마지막으로 확인한 truthy 값이 리턴된다.
  • “falsy” 값의 경우에는 OR 연산자와 동일하게 동작한다.
var result1 = "King" && "Arthur";
console.log(result1); //Arthur
var result2 = "Arthur" && "King";
console.log(result2); // King

Switch Blocks

  • 반복되는 if else 문과 switch 문의 차이점은, 순차적으로 모든 if 문을 도느냐. 아니면 해당하는 case 로 바로 가서 불필요한 연산을 줄이느냐의 차이이다.
var regimnet = 3;

if (regiment == 1) {
  ...
} else if (regiment == 2) {
  ...
} else if (regiment == 3) { // 앞 1,2 를 거쳐 3으로 온다.
  ...
}

switch (regiment) {
  case 1:
    ...
  case 2:
    ...
  case 3: // 3으로 바로 온다.
    ...
}
  • break 문을 사용하지 않고, 공통된 property 를 상위 case 에서 부터 순차적으로 접근하여 추가하는 방법도 있다.

Loop Optimization

  • 컴퓨터 메모리 관점에서 일반적인 for 문의 연산 순서를 보자.
treasureChest = {
  necklaces: ["A", "B", "C", "D"];
};

for (var i = 0; i < treasureChest.necklaces.length; i++) {
  console.log(treasureChest.necklaces[i]); 
} 
  • 위 for 문에서 메모리 연산이 필요한 부분은 다음과 같다.
    1. i 값 탐색
    2. treasureChest 객체 탐색
    3. necklaces 속성 탐색
    4. necklaces 속성의 배열 인덱스 탐색
    5. length 프로퍼티 검색 > 위의 연산을 최적화 해보자 : Cache the necessary values in the local variables
// 1. length property 를 한번만 접근 (기존 for 문은 반복시 마다 접근)
var x = treasureChest.necklaces.length;
for (var i = 0; i < x; i++) {
  console.log(treasureChest.necklaces[i]);
}
  • 위의 리팩토링으로 연산 수가 다음과 같이 줄어들었다.
  • 위 코드는 더 개선할 수 있다.

// 2. for 문의 초기 선언문 쪽에서 x 값을 선언하면, 전역 변수로 var x 를 선언하지 않아도 되어 메모리가 더 효율적이게 된다.
for (var i = 0, x = treasureChest.necklaces.length; i < x; i++) {
  console.log(treasureChest.necklaces[i]);
}
  • 주의할 점 : 자바스크립트는 {} 로 스코핑이 되어 있지 않기 때문에, 위의 for 반복문이 끝나면 x 값은 최종 값으로 할당되어 있다는 사실

  • 또 다른 개선 포인트

// 3. 각 반복 싸이클마다 treasureChest 객체의 속성에 접근을 할 필요가 없다.
var list = treasureChest.necklaces;
for (var i = 0, x = treasureChest.necklaces.length; i < x; i++) {
  console.log(list[i]); } 

모든 인덱스를 접근할 때에는 for loop 문이 좋고, 때로는 for in 보다 성능이 나은 경우가 있다. for in 은 prototype 에 접근하여 기존의 기 정의된 메서드까지 포함하여 출력하므로 비효율적

Performance (Script Loading)

  • Work Intensive javascript 는 body 마지막 태그 맨 위나 async 속성 이용하여 페이지 첫 로딩을 빠르게 한다.

Performance (Inheritance)

  • 자바스크립트에서 상속은 prototype 을 이용
  • 공통으로 쓰는 메서드는 모두 prototype 에 집어 넣는다.
function SignalFire(id, logs) {
  this.id = id;
  this.logs = logs;
  this.functionality1: function() {

  },
  this.functionality2: function() {

  },
  this.functionality3: function() {

  },
}
  • 위 함수의 경우 매번 객체를 생성할 때 마다 사용하지 않는 메서드들을 메모리에서 사용하는 낭비가 발생한다.
  • 따라서, 매번 객체 생성시 필요한 속성이나 메서드만 가져가도록 하고, 공통 메서드는 다음과 같이 prototype 으로 뺀다.
  SignalFire.prototype = {
  functionality1: function() {

  },
  functionality2: function() {

  },
  functionality3: function() {

  },
}

Performance (Indivdual DOM)

  • list 를 배열로 갖는 DOM 요소에 append 메서드를 이용하여 DOM 을 추가하면 전체 리스트가 reflow 된다. 이는 성능에 악영향을 준다.
  • 성능 향상을 위한 해결법은 Fragment 를 사용한다.
var fragment = document.createDocumentFragment();
fragment.appendChild(element);
list.appendChild(fragment);

Performance (Get rid of var redundancy)

  • var 지정어를 사용할 떄, 다음과 같이 코드량을 줄일 수 있다.
var a = 1;
var b = "hello";
var c = ["a","b","c"];

var a = 1,
b = "hello",
c = ["a","b","c"];

// 코드의 가독성이 높아지고, 간결하다.

Performance (String Concatenation)

  • 문자열의 길이에 따라 += 연산자와 join() 메서드의 성능차이가 발생한다.
  • 문자열이 짧을 떄 : += 연산자가 성능이 더 빠르다.
  • 문자열이 길고, 문자열이 배열안에 리스트 형태로 저장되어 있을 때 : join("\n") 메서드가 성능이 우월하다.
var page = "";
for (var i = 0, x = newPageBuild.length ; i < x ; i++) {
  page += newPageBuild[i];
}

// join() 메서드 활용
page = newPageBuild.join("\n");

Namespacing

  • 팀 프로젝트 시 많은 양의 자바스크립트 코드를 작성할 때, 타 팀원이 작성한 전역변수가 overwrite 되는 경우가 발생한다.
  • 이를 막기 위해 namespacing 을 활용한다.
var a = ["Apple", "Banana", "Coil"];
var c = function () {
  console.log("this is not what I want.");
};

var nameSpace = {
a : "1",
b : 23,
c : function() {
  // ...
}
};

// HTML Element click event
onClick=nameSpace.c();

Javascript Pattern 함수

이 글은 JavaScript Patterns Build Better Applications with Coding and Design Patterns 책을 학습 후 중요 부분을 요약한 것입니다.

Background

  • 자바스크립트의 함수는 일급 객체다.
  • 함수는 유효범위를 갖는다.
  • 함수는 다음과 같은 특징을 갖는 객체다.
    • 프로그램 실행(런타임) 중에 동적으로 생성한다
    • 변수에 할당할 수 있고, 다른 변수에 참조를 복사할 수 있고, 확장가능하고, 삭제할 수 있다.
    • 다른 함수의 인자로 전달할 수 있고, 다른 함수의 반환 값이 될 수 있다.
    • 프로퍼티와 메서드를 가질 수 있다.
  • 자바스크립트에서 함수는 하나의 객체
  • 자바스크립트는 중괄호 {} 의 유효범위가 함수 내부를 제외하곤 없다.

용어

  • 기명 함수 (named function expression)
    var add = function add (a, b) {
    return a + b;
    };
    
  • 무기명 함수 (unnamed function expression) & 함수 표현식 (function expression)
    var add = function (a, b) {
    return a + b;
    };
    
  • 함수 선언문 (function declaration)
    function foo() {
    // body
    }
    

콜백 패턴

  • 함수는 객체이기 때문에 아래처럼 함수를 다른 함수에 콜백 형태로 전달할 수 있다.
    function writeCode (callback) {
    callback();
    }
    
    function introduceBugs () {
    // body...
    }
    writeCode(introduceBugs);
    // ! introduceBugs() 를 넘기게 되면 함수가 호출이 되므로 함수의 참조값만 넘긴다.
    
  • 대부분의 클라이언트 브라우저 프로그래밍은 event-driven 방식 : Don't call us, we'll call you

  • 아래는 타임아웃에 관한 안티패턴이다.

    var thePlotThickens = function () {
    console.log('500ms later...');
    }
    setTimeout(thePlotThickens(), 500); // 안티패턴
    // setTimeout(thePlotThickens, 500) 처럼 함수 포인터만 넘겨줘야 한다.
    

함수 반환하기

  • 함수 반환의 간단한 예
    var setup = function () {
    alert(1);
    return function() {
      alert(2);
    };
    };
    
    var my = setup(); // alert(1)
    my();             // alert(2)
    
  • 함수 반환에서 사용되는 클로저의 예
    var setup = function() {
    var count = 0;
    return function () {
      return (count += 1);
    };
    };
    
    var next = setup();
    next(); // 1
    next(); // 2
    next(); // 3
    

자기 자신을 정의하는 함수

  • 새로운 함수로 자기 자신을 덮어쓰는 경우 : 어플리케이션 성능에 많은 도움이 된다
    // Lazy Function Definition : 사용 시점 전까지 함수를 정의하지 않고 있다가, 호출된 이후에는 더 적게 일한다.
    var scareMe = function () {
    alert(&quot;Boo!&quot;);
    scareMe = function () {
      alert(&quot;Double boo!&quot;);
    };
    };
    
    scareMe();  // Boo!
    scareMe();  // Double Boo!
    
  • scareMe() 함수를 일급객체로 사용하는 예
    scareMe.property = &quot;properly&quot;;
    var prank = scareMe;v
    var spooky = {
    boo: scareMe;
    };
    
    prank();  // Boo!
    prank();  // Boo!
    console.log(prank.property); // &quot;properly&quot;
    
    spooky.boo(); // Boo!
    spooky.boo(); // Boo!
    console.log(spooky.boo.property); // &quot;properly&quot;
    
    scareMe();  // Double Boo!
    scareMe();  // Double Boo!
    console.log(scareMe.property);  // undefined
    

즉시 실행 함수

  • 즉시 실행함수는 선언됨과 동시에 실행된다. 자기 실행함수 라고도 한다.
  • 즉시 실행함수의 패턴은 다음과 같다.
    1. 함수를 함수 표현식으로 선언한다 (var a = function(){}; 타입으로는 동작하지 않는다.)
    2. 함수 마지막에 괄호쌍을 추가한다.
    3. 전체 함수를 괄호로 감싼다.
  • 즉시 실행함수는 코드 안의 모든 코드를 지역 유효범위로 감싸고, 어떤 변수도 전역 유효범위로 새어나가지 않게 한다.
    (function () {
    var days = [&quot;Sun&quot;, &quot;Mon&quot;];
        today = new Date();
        msg = &quot;Today is&quot; + days[today.getDay()];
    
    alert(msg);
    }());
    
    // days, today, msg 변수들의 범위는 모두 전역이 아니다.
    
  • 즉시 실행함수의 매개변수는 다음과 같이 전달한다.
    (function (who, when) {
    
    console.log(&quot;I met &quot; + who + &quot; on &quot; + when);
    
    }(&quot;Joe Black&quot;, new Date()));
    
  • 일반적으로 즉시 실행함수에는 매개변수를 많이 전달하지 않는게 코드 가독성에 도웅이 된다.

즉시 실행함수의 반환 값

  • 다른 함수와 마찬가지로 즉시 실행함수도 값을 반환할 수 있고, 변수에 할당할 수 있다.

    var result = (function() {
    return 2 + 2;
    }());
    
    var getResult = (function () {
    var res = 2 + 2;
    return function () {
      return res;
    };
    }());
    
  • 장점과 사용방법 : 선언된 모든 변수는 스스로를 호출하는 함수의 지역변수가 되기 때문에, 임시 변수가 전역 공간을 어지럽힐까 걱정하지 않아아도 된다.

즉시 객체 초기화

  • 아래 패턴은 객체가 생성된 즉시 객체를 초기화 한다.

    ({
    maxWidth: 600.
    maxHeight: 400,
    
    gimmeMax : function () {
      return this.maxWidth + &quot;x&quot; + this.maxHeight;
    },
    init : function () {
      console.log(this.gimmeMax());
    }
    }).init();
    
  • 위 패턴의 장점은 초기화 하는 동안, 전역 네임스페이스를 보호할 수 있다.

  • 위 패턴의 단점은 자바스크립트 compression 시에 즉시 실행 함수 패턴에 비해 효과적으로 압축하지 못할 수 있다. 왜냐하면 비공개 프로퍼티와 이름이 더 짧게 변경되지 않는 것이 compression 도구 관점에서는 안전하기 때문.

초기화 시점의 분기

  • 초기화 시점의 분기(로드타임 분기)는 각각 브라우저의 기능을 확인하는 최적화 패턴이다.
  • 아래 코드처럼 각 브라우저의 기능 지원범위를 확인할 수 있다.

    var utils = {
    addListener: function (el, type, fn) {
      if (typeof window.addEventListener === 'function') {
        el.addEventListener(type, fn, false);
      } else if (typeof document.attachEvent === 'function') {
        el.attachEvent('on' + type, fn);
      } else {
        el['on' + type] = fn;
      }
    },
    removeListener: function (el, type, fn) {
      // ...
    }
    };
    
  • 브라우저의 기능은 독립적으로 변하기 때문에, 상기 코드로 초기화 시점 분기를 사용해 기능 지원여부를 판단한다.

설정 객체 패턴

  • 설정 객체 패턴은 좀 더 깨끗한 API 를 제공하는 방법. 라이브러리나 reuse 컴포넌트를 만들 때 유용하다.
  • addPerson() 이라는 함수를 만들 때, 인자수가 많아지면 다음과 같이 addPerson("First Name", "Last Name", ...) 함수 선언이 길어지므로 아래와 같은 패턴을 사용한다.

    addPerson(conf);
    var conf = {
    userName : &quot;batman&quot;,
    first: &quot;Bruce&quot;,
    last: &quot;Wayne&quot;
    };
    
  • 위 패턴의 장점은
    1. 매개변수와 순서를 기억할 필요가 없다.
    2. 선택적인 매개변수를 안전하게 생략이 가능하다.
    3. 매개변수 추가 제거가 편하다.
  • 위 패턴의 단점은
    1. 매개변수의 이름을 기억해야한다.
    2. 프로퍼티의 이름은 압축되지 않는다.

커리 (Curry)

함수 적용

  • 순수한 함수형 프로그래밍에서 함수는 호출된다고 표현하기 보다 적용된다고 표현한다.
  • 자바스크립트에서도 Function.prototype.apply() 를 이용하여 함수를 적용할 수 있다.
    var sayHi = function (who) {
    return &quot;Hello&quot; + (who ? &quot;, &quot;+ who : &quot;&quot;) + &quot;!&quot;;
    };
    
    sayHi();        // &quot;Hello&quot;
    sayHi(&quot;World&quot;); // &quot;Hello, World&quot;
    sayHi.apply(null, [&quot;hello&quot;]); // &quot;Hello, hello!&quot;
    
  • apply 의 첫 번째 매개변수가 null 이면 this 는 전역 객체를 가리킨다.
    var alien = {
    sayHi: function(who) {
      return &quot;Hello&quot; + (who ? &quot;, &quot; + who : &quot;&quot;) + &quot;!&quot;;
    }
    };
    
    alien.sayHi(&quot;world&quot;); // &quot;Hello, world!&quot;
    sayHi.apply(alien, [&quot;humans&quot;]); // &quot;Hello, humans!&quot;
    
  • 이 코드에서 sayHi() 내부의 this 는 alien 을 가리킨다. 앞선 예제의 this 는 전역 객체를 가리킨다.

  • call() 메서드 역시 apply() 메서드와 비슷하며, 함수의 매개변수가 하나일 때는 굳이 배열을 만들지 않고 아래와 같이 call() 을 이용한다.

    sayHi.apply(alien, [&quot;humans&quot;]); // &quot;Hello, humans!&quot;
    sayHi.call(alien, &quot;humans&quot;);    // &quot;Hello, humans!&quot;
    

Javascript Pattern 리터럴 & 생성자

이 글은 JavaScript Patterns Build Better Applications with Coding and Design Patterns 책을 학습 후 중요 부분을 요약한 것입니다.

객체 리터럴

  • new Object() 보다는 객체 리터럴 var obj = {}; 을 활용한다.
  • 아래와 같이 생성자에 어떤 인자를 받느냐에 따라 다른 객체가 생성된다.
    // 일반 객체
    var o = new Object();
    console.log(o.constructor === Object); // true
    
    // 숫자 객체
    var o = new Object(1);
    console.log(o.constructor === Number); // true
    console.log(o.toFixed(2)); // &amp;quot;1.00&amp;quot;
    
    // 스트링 객체
    var o = new Object(&amp;quot;I am a strong&amp;quot;);
    console.log(o.constructor === String); // true
    console.log(typeof o.substring); // &amp;quot;function&amp;quot;
    
    // boolean 객체
    var o = new Object(true);
    console.log(o.constructor === Boolean); // true
    
  • 위와 같은 이유로, Object() 생성자는 런타임시 결정되는 동적인 값이 생성자에 인자로 전달된 경우 예기치 않은 결과가 반환될 수 있다.

사용자 정의 생성자 함수

  • 내장 생성자가 아니라 직접 사용자가 정의한 생성자 함수 호출은 다음과 같다.

    var Person =  function (name) {
    this.name = name;
    this.say = function () {
      return &amp;quot;I am &amp;quot; + this.name;
    };
    };
    
  • 위의 함수는 사실 아래와 같다.
    var Person =  function (name) {
    // var this = {};
    
    this.name = name;
    this.say = function () {
      return &amp;quot;I am &amp;quot; + this.name;
    };
    
    // return this;
    };
    
  • 따라서, 생성자 함수 내부의 마지막에 다른 객체가 명시적으로 반환되지 않으면, 내부적으로 this 로 참조된 객체가 반환된다.

  • 한가지 더 유의할 점은, 이 Person 함수의 say() 메서드는 객체 생성시에 항상 default로 따라 붙기 때문에 메모리 관점에서 비효율적이다. 그렇기 때문에 아래와 같이

    Person.prototype.say = function() {
    return &amp;quot;I am &amp;quot; + this.name;
    }
    
  • 처럼 필요한 경우에 메서드 멤버는 prototype에 추가하여 사용하는 것이 더 효율적이다.

생성자의 new 강제 패턴

  • 생성자의 첫 글자를 대문자로 쓰는 명명규칙을 사용하여 해당 함수는 늘 생성자로 생성한다.
  • 아래와 같은 that 사용 으로 해당 함수를 생성자로만 사용할 수 있다.

    function Waffle () {
    var that = {};
    that.tastes = &amp;quot;yummy&amp;quot;;
    return that;
    }
    
  • 위처럼 that 을 사용하게 되면 생성자 함수를 new 로 호출하지 않더라도, 항상 생성자 함수로서 역할을 한다.
    var first = new Waffle(),
      second = Waffle();
    console.log(first.tastes); // &amp;quot;yummy&amp;quot;
    console.log(second.tastes); // &amp;quot;yummy&amp;quot;
    
  • 주의 : 위와 같은 that 패턴은 프로토타입에 추가한 멤버를 사용할 수 없게 된다

해결방법

  • 위와 같은 생성자 강제 new 패턴 문제점을 해결하려면 아래와 같은 방식을 사용한다.

    function Waffle () {
    
    if (!(this instanceof Waffle)) {
      return new Waffle();
    }
    
    this.tastes = &amp;quot;yummy&amp;quot;;
    }
    Waffle.prototype.wantAnother = true;
    

배열 리터럴

  • 배열 또한 var a = new Array("1", "2"); 와 같은 형식보다는 var a = [1,2]; 배열 리터럴을 이용한다.
  • 해당 객체가 배열인지 판별하려면 .isArray([]);Object.prototpe.toString()를 사용한다.

JSON

  • JSON : JavaScript Object Notation 의 줄임말이다.
    var json = {
    &amp;quot;name&amp;quot; : &amp;quot;value&amp;quot;,
    &amp;quot;some&amp;quot; : [1, 2, 3]
    };
    

정규표현식 리터럴

  • 정규표현식 생성방법은 다음과 같다.
    • var re = /\\/gm;
    • var re = new RegExp("\\\\", "gm");
  • 문법
    • g : 전역 매칭
    • m : 여러줄 매칭
    • i : 대소문자 구분없이 매칭
    • 여러개 패턴 동시 사용 가능 var re = /pattern/gmi;

원시 데이터 타입 래퍼

  • 자바스크립트는 Number, String, Boolean, null, undefiend 5개의 원시 데이터 타입이 존재한다.

요약

  • 객체 리터럴 표기법 : 이름 – 값 쌍을 쉼표로 분리하고, 괄호로 감싸 객체를 생성한다.
  • 생성자 함수 : 내장 생성자 함수와 사용자 정의 생성자, 내장 생성자는 리터럴 표기가 낫다.
  • 생성자 new 강제 패턴 : 생성자 함수가 항상 new 로 호출한 것처럼 보장하는 패턴
  • 배열 리터럴 표기법 : var a = ["1", "2"];
  • 정규표현식 리터럴 : var a = new RegExp() 보다는 var a = /\\gm/gim; 리터럴 방식을 사용한다.

Javascript Pattern 기초

이 글은
JavaScript Patterns Build Better Applications with Coding and Design Patterns 책을 학습 후 주요 부분을 요약한 것입니다.

Basics

  • 전역변수 사용 최소화
  • var 선언 1회
  • 루프내 length 캐쉬 사용
  • 코딩 규칙 준수

전역변수 사용 최소화

  • 네임스페이스 패턴 & 즉시 실행함수 사용
  • 아래와 같은 안티패턴은 피한다.
    function foo () {
    var a = b = 0;
    }
    

    위는 이렇게 바꿔야 한다.

    function foo () {
    var a, b;
    a = b = 0;
    }
    
  • 전역객체 접근방법
    var global = (function() {
    return this; // new 와 생성자를 이용하지 않고 호출하면 this는 항상 전역객체를 가리킨다.
    }());
    
  • 단일 var 패턴
    function func () {
    var a = 1,
        b = 2,
        sum = a + b,
        myobject = {},
        i,
    
        // 변수를 선언할 때는 항상 초기값을 같이 지정하는 습관을 들인다.
    }
    

    위와 같은 코드 기법은 코드 작성량과 전송량이 모두 줄어드는 이점이 있다.

For 루프

  • 아래의 코드는 루프 순회시마다 배열의 length에 접근하는 문제점이 있다 (일반적으로 length 접근은 비용이 크다)

    for (var i = 0; i &lt; array.length; i++) {
    //
    }
    

    위 코드를 아래와 같이 바꾼다.

    for (var i = 0, var max = array.length; i &lt; max; i++) {
    //
    }
    

    또한 이를 단일 var 패턴과 조합하면,

    function looper () {
    var i = 0,
        max,
        array = [];
    
    for (i = 0, max = array.length; i &lt; max; i++) {
    
    }
    }
    

    가 될 수 있다.

For-in 루프

  • 객체를 순회할 때 사용하는 함수

    var man = {
    hands: 2,
    legs: 2,
    heads: 1
    };
    
    if (typeof Object.prototype.clone === &quot;undefined&quot;) {
    Object.prototype.clone = function () {};
    }
    
  • 위 코드의 경우 for-in 루프를 사용할 때 주의할 점은
    // 안티패턴
    for (var variable in object) {
    console.log(i, &quot;:&quot;, man[i]);
    }
    // 콘솔 출력 내용
    // hands : 2
    // legs : 2
    // heads : 1
    // clone function()
    
  • 프로토타입 체인에 따라 상속받은 메서드를 의도치 않게 출력하였다. 따라서 이는 아래와 같이
    // 올바른 패턴
    for (var i in man) {
    if (man.hasOwnProperty(i)) {
      console.log(i, &quot;:&quot;, man[i]);
    }
    }
    // 콘솔 출력 내용
    // hands : 2
    // legs : 2
    // heads : 1
    

Switch

  • 아래의 패턴으로 가독성을 향상시킬 수 있다.
    var inspect_me = 0,
      result = '';
    
    switch (inspect_me) {
    case 0:
      result = &quot;zero&quot;;
      break; // 각 case문에 break 반드시 포함
    case 1:
      result = &quot;one&quot;;
      break;
    default: // switch 문 안에 default 는 반드시 포함
      result = &quot;unknown&quot;;
    }
    

들여쓰기

  • 중괄호 { } 의 안에 있으면 들여쓴다.
  • 중괄호 { 시작의 위치는 개발자마다 아래와 같이 2가지로 분류된다.
    // (1)
    if (true) {
    // body
    }
    // (2)
    if (true)
    {
    // body
    }
    
  • 위의 (2) 경우가 아래와 같은 문제를 만들 수 있다.
    function func () {
    return
    {
        name : &quot;Bat&quot;
    };
    } // 결과값 : undefined
    
  • 자바스크립트는 행 종료시 자동으로 세미콜론을 추가하기 때문에 위의 코드는 결국 아래와 같다.
    function func () {
    return undefined;
    {
        name : &quot;Bat&quot;
    };
    } // 결과값 : undefined
    
  • 결론 : 여는 중괄호 { 는 항상 선행하는 명령문과 동일한 라인에 두어야 한다.
    function func () {
    return {
        name : &quot;Bat&quot;
    };
    } // 결과값 : {name : &quot;Bat&quot;}
    

공백

  • 문어체 영어는 쉼표마침표 뒤에 공백을 둔다.
    // (1)
    for (var i = 0, max = 10; i &lt; max; i += 1) {
    
    }
    // (2)
    var a = [1, 2, 3];
    // (3)
    var o = {a: 1, b: 2};
    // (4)
    myFunc (a ,b ,c)
    // (5)
    function myFunc() {}
    // (6)
    var myFunc = function () {};
    
  • 공백을 많이 사용하여 코드의 가독성을 높이면, 코드의 Byte 양이 늘어나는 부작용이 있다.

  • 이는 compression을 이용하여 해결한다. (빌드용 & 배포용 나눌 것)

명명규칙

  • 생성자 함수의 첫 글자는 대문자로
  • 카멜 표기법 (camel case) : 각 단어의 첫 글자만 대문자 firstName
  • 언더스코어 표기법 (underscore) : 단어를 _로 잇는다. first_name

주석작성

  • 코드내 주석으로 API 문서를 자동화 해주는 툴은 jsdocyuidoc 이 있다.

코드압축

  • 압축도구는 아래와 같은 작업으로 코드 Byte 양을 줄인다.
    1. 공백, 줄바꿈, 주석 등을 제거한다.
    • 매개변수 길이 를 줄인다.
    • 전역변수 를 바꾸는 경우 코드를 망가뜨릴 수 있으므로, 보통 지역변수 를 바꾼다.
  • 미리부터 압축된 코드를 작성하려는 것은 잘못된 생각!!

요약

  • 전역변수 사용 최소화
  • 함수 내 var 선언은 1회
  • 내장 생성자의 프로토타입은 확장하지 X
  • 공백, 중괄호 규칙 준수
  • 명명 규칙 준수

Function Expression

Function Expression

First Video

function declaredFunction(str) {
    // since its declared, this is actually loaded right when the program is run. And its loaded into memory and held there until you want to use it
},
var functionExpression = function declaredFunction(str) {
    // this will be only loaded when the program reach the line of this code.
}; // since its assigning to a var, it needs to have semicolon at the end.

어차피 functionExpression("hello"); 를 사용할 것이기 때문에, declaredFunction 는 필요가 없다. 따라서 anonymous function을 사용한다. 다시 정리하면,

var functionExpression = function (str) {
    // what a cushy job
};

확인창을 띄우려면?
return confirm("questions") 를 이용

Second Video (Passing Function Expressions As Parameters)

  • map() method will always take in a funtion as a parameter, and return a new array with the results.
var numbers = [12,4,3];
var results = numbers.map("input a function here");
  • map() works like a loop that applies a function to each array index
    map()을 사용하게 되면 위의 코드가 아래 코드의 효과를 갖게 된다.
var results = [];
for (var i = 0; i < numbers.length ; i++) {
    results[i] = coolFunction(numbers[i]);
}
  • 결론적으로 map() 으로 인해 코딩량을 줄일 수 있다.
    > pass in : deliver or submit sth

Third Video (How to return a function from a function)

shift() array의 가장 앞을 자른다.
‘push()’ array의 가장 맨 뒤에 데이터를 밀어 넣는다.

var puzzlers = [
  function(a) { return 8 * a - 10; },
  function(a) { return (a - 3) * (a - 3) * (a - 3); },
  function(a) { return a * a + 4; },
  function(a) { return a % 5; }
];
var start = 2;

// build applyAndEmpty function expression here
var applyAndEmpty = function(input, queue) {
  var length = queue.length;
  for (var i = 0; i < length ; i ++) {
    input = queue.shift()(input);
  }
  return input;
};

alert(applyAndEmpty(start, puzzlers));