[도서] Node.js 디자인패턴 - Chapter 01 - 2

getch_·2021년 6월 3일
0

Node.js 디자인패턴

목록 보기
2/3
post-thumbnail

Node.js 디자인패턴을 읽으며 요약/정리한 내용입니다.

Chapter 01) Node.js 플랫폼에 대하여

개요

  • Node.js의 철학 "Node way"
  • Node.js 버전 6와 ES2015
  • Reactor 패턴 - Node.js 비동기 아키텍처의 핵심 매커니즘

1.2 Node.js 6와 ES2015

  • 책 전체의 예제 코드에서 ES2015(=ES6)를 기반으로 하며, Node.js 6 이상 버전을 기준으로 서술됨
  • Strict 모드: 엄격 모드, 변수 초기화, 중복 선언 등의 코드상 이슈를 엄격하게 체크하여 알려주는 모드
    • "use strict"문을 추가하여 쉽게 적용 가능
    • 함수, 모듈, 파일 단위 등에 대해 적용 가능

1.2.1 let, const 키워드

  • let: 블록 스코프 변수를 선언
// var 사용 예
if (false) {
  var x = "hello";
}
console.log(x); // undefined
//------------------------------------
// let 사용 예
if (false) {
  let x = "hello";
}
console.log(x); // ReferenceError: x is not defined
  • const: 상수 변수 선언
    • 객체 내부의 속성을 변경하면 참조된 속성에 대한 값을 변경하는 것이기 떄문에 에러가 발생하지 않음
    • 즉, Not Error 예제를 보면, X -> {}, {}.name -> "John"이고, 객체가 변경되는 것은 아님
    • 모듈을 사용할 때, 해당 변수가 실수로 재할당되지 않도록 하는 방법이 좋은 예시
// Error
const x = 'This will never change';
x = '...'; // TypeError: Assignment to constant variable
//------------------------------------
// Not Error
const x = {}
x.name = 'John';

1.2.2 화살표 함수

  • 함수 정의를 간결하게 해주는 구문, 다른 언어의 람다식과 같은 형식
  • 파라미터가 1개, 함수의 몸체가 1줄의 코드로 이루어진 경우 (), {}, return을 생략할 수 있음
    • 그 외의 경우 생략 불가
const numbers = [2, 6, 7, 8, 1];
// 생략 가능 예
const even = numbers.filter(x => x%2 === 0);
// 생략 불가능 예
const even = numbers.filter(x => {
  if (x%2 === 0) {
    console.log(x + ' is even!');
    return true;
  }
});
  • 화살표 함수로 정의된 함수는 어휘 범위(lexical scope)로 바인드되어, this의 값이 부모 블록의 값과 같음
    • 기존의 방식으로 함수를 선언하여 사용한 경우 호출 당시의 상황에 따라 this값이 변경되는 문제가 있어, 별도의 방안으로 사용하였음

      어휘 범위는 다른 서적에서는 Lexical Environment라고 표현하기도 하며, 화살표 함수를 사용하여 함수를 호출할 경우 this 값을 부모 블록의 값과 같은 것으로 바인딩하는 것이 아닌 this 자체를 바인딩 하지 않기 때문에 스코프 체인을 통해 부모 블록의 this를 참조하는 것

1.2.3 클래스 구문

  • 개발자에게 익숙하고 가독성을 제공하기 위한 구문상의 편의 기능
  • 실제로는 프로토타입을 통한 상속으로 동작함
class Person {
  constructor (name, surname, age) {
    this.name = name;
    this.surname = surname;
    this.age = age;
  }
  
  getFullname () {
    return this.name + ' ' + this.surname;
  }
  
  static older (person1, person2) {
    return (person1.age >= person2.age) ? person1 : person2;
  }
}
  • 클래스 구문의 중요 특징은 extend 및 super 키워드를 사용하여 프로토타입을 확장 가능
  • 오버라이드도 지원함
class PersonWithMiddlename extends Person {
  constructor (name, middlename, surname, age) {
    super(name, surname, age);
    this.middlename = middlename;
  }
  
  getFullName() {
    return this.name + '' + this.middlename + '' + this.surname;
  }
}

클래스 구문을 통해 생성된 인스턴스는 과거의 방식과 실제 생성된 인스턴스가 다름
클래스 인스턴스는 클래스 객체로 표현되며, prototype 속성과 __proto__ 속성이 null로 표현됨
또한, #field 형식으로 private 필드, 메소드를 설정할 수 있음(ES2020부터 지원)

1.2.4 향상된 객체 리터럴

  • 변수 및 함수를 객체의 멤버로 지정하고, 객체를 생성할 때 동적인 멤버명을 정의할 수 있음
  • setter 및 getter 함수를 제공
const namespace = '-webkit-';
const style = {
  [namespace + 'box-sizing'] : 'border-box',
  [namespace + 'box-shadow'] : '10px10px5px #888888'
};

const person = {
  name: 'George',
  surname: 'Boole',
  
  get fullname () {
    return this.name + '' + this.surname;
  }
  
  set fullname (fullname) {
    let parts = fullname.split('');
    this.name = parts[0];
    this.surname = parts[1];
  }
};

console.log(person.fullname); // George Boole
console.log(person.fullname = 'Alan Turing');
console.log(person.name); // Alan

1.2.5 Map과 Set Collection

  • Map: ES2015부터 제공하는 안전하고 유연하며 직관적인 방식으로 HashMap 컬렉션을 제공하는 새로운 프로토타입
    • set, get, has, delete 등의 메소드 지원
    • 루프 내 모든 entry는 첫 번째 요소로 키를, 두 번째 요소로 값을 가지는 배열
    • 함수도 Map의 키로 사용이 가능, 일반 객체({})는 키가 문자열로 변환되기 때문에 불가능
    • 루프 실행시 삽입 순서를 보장, 일반 객체({})는 항상 보장되지 않음
    • 테스트 프레임워크 제작에 응용 가능
  • Set: Map과 동일하지만, 모든 요소들이 유일한 값을 가지는 목록을 생성
    • add, has, delete, size 등의 메소드 지원
    • Set안의 데이터는 중복이 불가능, 데이터를 직접 꺼내올 수 있는 방법 없음
    • 루프 내 모든 entry는 값을 가짐
    • 요소로 객체와 함수도 포함 가능
// Map
const profiles = new Map();
profiles.set('twitter', '@adalovelace');
profiles.set('facebook', 'adalovelace');
profiles.set('googleplus', 'ada');

profiles.size; // 3
profiles.has('twitter'); // true
profiles.get('twitter'); // "@adalovelace"
profiles.has('youtube'); // false
profiles.delete('facebook');
profiles.has('facebook'); // false
profiles.get('facebook'); // undefined
for (const entry of profiles) {
  console.log(entry);
}

// Set
const s = new Set([0, 1, 2, 3]);
s.add(3);
s.size; // 4
s.delete(0);
s.has(0); //false

for (const entry of s) {
  console.log(entry);
}

1.2.6 WeakMap 및 WeakSet Collection

  • Map, Set 프로토타입에 대한 "weak" 버젼
  • Map, Set과의 차이점
    • WeakMap: 루프로 요소 전체를 탐색할 방법이 없고, 객체 만을 키로 가질 수 있음
    • WeakSet: 객체 만을 요소로 가질 수 있음
    • 가장 큰 차이점은 요소의 키 또는 요소로 가진 객체가 다른 곳에서 참조하지 않고, WeakMap, WeakSet에만 있을 경우 해당 객체를 가비지 컬렉트 할 수 있음
  • 객체와 관련된 메타 데이터를 저장할 경우 매우 유용
// WeakMap
let obj = {};
const map = new WeakMap();
map.set(obj, {key: "some_value"});
console.log(map.get(obj)); // {key: "som_value"}
obj = undefined; // 다음 가비지 컬렉트 사이클에서 맴에 관련된 객체와 데이터가 정리됨

// WeakSet
let obj1 = {key: "val1"};
let obj2 = {key: "val2"};
const set = new WeakSet([obj1, obj2]);
console.log(set.has(obj1)); // true
obj1 = undefined; // obj1이 set에서 제거됨
console.log(set.has(obj1)); // false

1.2.7 Template 표기법

  • 문자열을 지정하는 대안으로 제공
  • 역 따옴표(`)를 구분 기호로 사용
  • 템플릿 표기 구문을 문자열 내에서 ${expression}의 형식으로 사용하여 변수 또는 표현식을 삽입할 수 있음
const name = "Leonardo";
const interests = ["arts", "architecture", "science", "music", "mathematics"];
const birth = { year: 1452, place: "Florence" };
const text = `${name} was an Italian polymath interested in many topics such as ${interests.join(', ')}. He was born in ${birth.year} in ${birth.place}`
console.log(text);

1.2.8 ES2015의 기타 기능들

  • 기본 매개 변수(Default function parameters)
  • 나머지 매개 변수(Rest parameters)
  • 전개 연산자(Spread operator)
  • 비구조화(Destructuring)
  • new.target('2장. Node.js 필수 패턴'에서 다룸)
  • Proxy('6장. 디자인 패턴'에서 다룸)
  • Relect
  • Symbols
profile
한꺼번에 몰아치지 아니하고 오래도록.

0개의 댓글

관련 채용 정보