경일게임아카데미 멀티 디바이스 메타버스 플랫폼 개발자 양성과정 20220906 2022/04/04~2022/12/14

Jinho Lee·2022년 9월 6일
0

2022.09.06 경일 메타버스 23주차 2일 수업내용. Node.js - 노드, 자바스크립트 ES2015+

Node.js

  • 자료 : 교과서 “Node.js 교과서” ch. 1 노드 시작하기 p. 23

핵심 개념

  • p. 24 ~ 38

  • Node.js(이하 노드)는 Chrome V8 Javascript 엔진으로 빌드된 Javascript 런타임이다.

    • 노드는 서버만 실행할 수 있는 것이 아니다.
      가장 중요한 것은 Javascript를 실행시킬 수 있는 기반을 제공한다는 것.

서버

  • 서버 :
    네트워크를 통해 클라이언트에 정보나 서비스를 제공하는 컴퓨터 또는 프로그램

    • 클라이언트 : 요청을 보내는 주체

    • 즉, 서버는 클라이언트의 요청에 대해 응답한다.

자바스크립트 런타임

  • 런타임 (Runtime) :
    특정 언어로 만든 프로그램들을 실행할 수 있는 환경

    • 노드는 자바스크립트 런타임 ⇒ 자바스크립트 실행기
  • 노드 - V8 엔진, libuv 라이브러리 사용

    • V8 엔진 : 구글 크롬 출시

    • libuv 라이브러리 : 노드의 특성 구현

    • V8 엔진, libuv 라이브러리 모두 C와 C++로 구현

  • 노드의 특성

    1. 이벤트 기반

    2. 논 블로킹 I/O 모델

이벤트 기반

  • 이벤트 기반 (Event-driven) :
    이벤트가 발생할 때 미리 지정해둔 작업을 수행하는 방식

    • 특정 이벤트가 발생할 때 무엇을 할지 미리 등록할 필요가 있다.
      ⇒ 이를 “이벤트 리스너 (Event Listener)콜백 (Callback) 함수등록한다.”고 한다.
  • 이벤트 루프 (Event Loop) :
    여러 이벤트가 발생했을 때 어떤 순서콜백 함수를 호출할지를 판단

  • 컨텍스트 (Context) :
    함수가 호출되었을 때 생성되는 환경

자바스크립트의 실행 방식 - 이벤트 루프의 개념

  • 노드는 자바스크립트 코드의 맨 위부터 한 줄씩 실행

  • 함수 호출 부분을 발견하면 함수를 호출 스택 (Call Stack)에 입력

  • 스택이므로, 넣은 역순으로 실행 완료 (후입선출)

자바스크립트의 실행 방식 - 이벤트 루프, 태스크 큐, 백그라운드

  • 이벤트 루프 (Event Loop) :
    이벤트 발생 시 호출할 콜백 함수들을 관리, 호출된 콜백 함수의 실행 순서를 결정.
    노드가 종료될 때까지 이벤트 처리 작업을 반복 → 루프

  • 백그라운드 (Background) :
    타이머(ex. setTimeout 등)나 이벤트 리스너들이 대기하는 곳.
    자바스크립트가 아닌 다른 언어로 작성된 프로그램.
    여러 작업이 동시에 실행될 수 있다.

  • 태스크 큐 (Task Queue) :
    이벤트 발생 후, 백그라운드에서 태스크 큐로 타이머나 이벤트 리스너의 콜백 함수를 전송.
    정해진 순서대로 콜백들이 나열되므로 콜백 큐라고도 한다.
    보통 완료된 순서대로 나열.

논 블로킹 I/O

  • I/O 작업은 동시에 처리될 수 있다.

    • I/O 작업 : 입출력 작업

    • 파일 시스템 접근, 네트워크를 통한 요청 등

  • 논 블로킹 :
    이전 작업이 완료될 때까지 대기하지 않고 다음 작업을 수행

    • 블로킹 :
      이전 작업이 끝나야만 다음 작업을 수행

    • 작업들이 동시에 처리될 수 있는 작업이라는 전제 하에, 논 블로킹 방식이 블로킹 방식보다 빠르다.

  • 노드는 I/O 작업백그라운드로 넘겨 동시에 처리한다.
    → 동시에 처리 가능한 작업들은 최대한 묶어야 시간이 절약된다.

  • 의의 :
    논 블로킹을 통해 실행 순서를 바꿔줌으로써 간단한 작업들이 대기하는 상황을 막을 수 있다.

  • 주의 : 논 블로킹동시같은 의미가 아니다.

  • 노드에서, 블로킹과 논 블로킹 / 동기와 비동기는 유사한 개념

    • 동기 (Synchronous) :
      동시에 일어난다. 요청과 그 결과가 동시에 일어난다.
      설계가 간단하고 직관적이지만 결과가 주어질 때까지 대기해야 한다.

    • 비동기 (Asynchronous) :
      동시에 일어나지 않는다. 요청과 결과가 동시에 일어나지 않을 거라는 약속.
      동기보다 복잡하지만 결과가 주어지는 동안 다른 작업을 할 수 있다. 자원 사용이 효율적.

    • 참고 : https://private.tistory.com/24

싱글 스레드

  • 싱글 스레드 : 스레드가 하나뿐

    • 자바스크립트 코드가 동시에 실행될 수 없는 이유
  • 프로세스 :
    운영체제에서 할당하는 작업의 단위.
    프로세스 간에 메모리 등의 자원을 공유하지 않는다.

  • 스레드 :
    프로세스 내에서 실행되는 흐름의 단위.
    프로세스는 스레드를 여러 개 생성해 여러 작업을 동시에 처리할 수 있다.
    스레드들은 부모 프로세스의 자원을 공유한다.
    같은 주소의 메모리에 접근 가능하므로 데이터를 공유할 수 있다.

  • 엄밀히 말해 노드는 싱글 스레드가 아니다.
    직접 제어 가능한 스레드가 하나

  • I/O 작업을 처리할 때는 멀티 스레딩보다 멀티 프로세싱효율적
    ⇒ 노드는 멀티 프로세싱을 많이 한다.

  • 멀티 스레드 방식은 프로그래밍이 어렵다 → 멀티 프로세싱 방식을 대신 사용

  • 멀티 스레딩과 멀티 프로세싱 비교

    멀티 스레딩멀티 프로세싱
    하나의 프로세스 안에서 여러 개의 스레드 사용여러 개의 프로세스 사용
    CPU 작업이 많을 때 사용I/O 요청이 많을 때 사용
    프로그래밍이 어려움프로그래밍이 비교적 쉬움

스레드 풀과 워커 스레드

  • 노드가 싱글 스레드로 동작하지 않는 두 가지 경우
  1. 스레드 풀 (Thread Pool)

    • 특정 동작을 수행할 때 스스로 멀티 스레드를 사용

    • 암호화, 파일 입출력, 압축

  2. 워커 스레드 (Worker Thread)

    • 노드 12 버전에서 안정화된 기능

    • 사용자가 직접 다수의 스레드를 제어 가능

    • CPU 작업(연산이 많은 작업)이 많은 경우 사용

서버로서의 노드

  • p. 38 ~ 40

  • 노드를 서버로 사용할 때의 장단점은 싱글 스레드, 논 블로킹 모델의 장단점과 크게 다르지 않다.

  • 장점

    • 개수는 많지만 크기는 작은 데이터를 실시간으로 주고받는 데 적합하다.

      • 서버는 기본적으로 I/O 요청이 많이 발생하므로, I/O 처리를 잘하는 노드가 좋다.

      • 논 블로킹 방식으로 I/O 작업을 처리하여 하나의 스레드가 많은 수의 I/O를 감당할 수 있다.

    • 웹 서버가 내장되어 있어 입문자가 쉽게 접근할 수 있다.

    • 자바스크립트를 사용하여 브라우저와 통일된 하나의 언어로 웹사이트를 개발할 수 있고, 이로써 개발 생산성을 획기적으로 높인다.

    • JSON이 자바스크립트 형식이라 쉽게 처리할 수 있다.

    • 안전성, 보안성 측면에서 검증되었다.

  • 단점

    • CPU를 많이 사용하는 작업을 위한 서버로 권장되지 않는다.

      • CPU 부하가 큰 작업에는 적합하지 않다.

      • 다른 언어에 비해 속도가 많이 느리다.

    • 싱글 스레드 방식이라 하나뿐인 스레드가 멈추지 않도록 잘 관리해야 한다.

  • 노드의 장단점

    장점단점
    멀티 스레드 방식에 비해 적은 컴퓨터 자원 사용기본적으로 싱글 스레드라 CPU 코어를 하나만 사용
    I/O 작업이 많은 서버로 적합CPU 작업이 많은 서버로는 부적합
    멀티 스레드 방식보다 쉬움하나뿐인 스레드가 멈추지 않도록 관리가 필요
    웹 서버가 내장되어 있음서버 규모가 커졌을 때 서버 관리가 어려움
    자바스크립트 사용 → 웹 브라우저와 통일어중간한 성능
    JSON 형식과 쉽게 호환됨
    검증된 안정성과 보안성

서버 외의 노드

  • p. 41

  • 노드는 웹, 모바일, 데스크톱 애플리케이션 개발에도 사용된다.

  • 노드 기반 웹 프레임 워크

    • 앵귤러 (Angular) :
      구글 진영 프론트엔드 앱 개발

    • 리액트 (React) :
      페이스북 진영 프론트엔드 앱 개발

    • 뷰 (Vue)

  • 모바일 개발 도구

    • 리액트 네이티브 (React Native) :
      페이스북, 인스타그램, 핀터레스트, 월마트, 테슬라 등이 사용 중
  • 데스크톱 개발 도구

    • 일렉트론 (Electron) :
      Atom, Slack, Discord, Visual Studio Code 등 개발

자바스크립트

  • 자료 : 교과서 “Node.js 교과서” ch. 2 알아두어야 할 자바스크립트 p. 65

ES2015+

  • ES2015+ : ES2015 이상의 자바스크립트

const, let

  • p. 67 ~ 68

  • var는 호이스팅 등의 문제로 코드 관리가 어려워 const와 let이 대체

  • var :
    함수 스코프

  • const :
    블록 스코프
    상수, 초기화해야 하며 한 번만 값을 할당

  • let :
    블록 스코프
    변수

  • 호이스팅 :
    실제 선언된 위치와 상관없이 메모리 접근이 가능한 문제.
    더 정확히는, 변수의 정의가 그 범위에 따라 선언과 할당으로 분리되어
    변수의 선언을 항상 컨텍스트 내의 최상위로 끌어올리는 것을 의미한다.

  • 예시 코드

    x = 10;
    console.log(x); // 10
    if (true) {
        var x = 3;
    }
    console.log(x); // 3
    
    if (true) {
        const y = 3;
    }
    //console.log(y); // Error

템플릿 문자열

  • p. 68

  • 백틱 (Tab키 위, ` )으로 감싸는 문자열

  • 문자열 안에 변수를 넣을 수 있다.

    • ${변수} 형식
  • 다른 따옴표와 함께 사용 가능

  • 예시 코드

    const num1 = 1;
    const num2 = 2;
    const result = 3;
    const string = `${num1} 더하기 ${num2}는 '${result}'`;
    console.log(string); // 1 더하기 2는 '3'

객체 리터럴

  • p. 68 ~ 70

  • 코딩의 편의를 위한 문법, 생략 위주

  • 객체 리터럴 :
    컨텐츠를 그대로 대입하는 방법으로 객체를 생성하는 방식

  1. 객체의 메소드에 함수를 연결할 때 콜론(:)과 function을 붙이지 않아도 된다.

  2. sayNode: sayNode처럼 속성명과 변수명이 동일한 경우에는 한 번만 써도 된다.

  3. 객체의 속성명은 동적으로 생성할 수 있다.

  • 예시 코드

    // Old
    var sayNode = function() {
        console.log('Node');
    };
    var es = 'ES';
    var oldObject = {
        sayJS: function() {
            console.log('JS');
        },
        sayNode: sayNode,
    };
    oldObject[es + 6] = 'Fantastic';
    oldObject.sayNode(); // Node
    oldObject.sayJS(); // JS
    console.log(oldObject.ES6); // Fantastic
    
    // New
    const newObject = {
        sayJS() {
            console.log('JS');
        },
        sayNode,
        [es + 6]: 'Fantastic',
    };
    newObject.sayNode(); // Node
    newObject.sayJS(); // JS
    console.log(newObject.ES6); // Fantastic

화살표 함수

  • p. 70 ~ 71

  • 람다식과 비슷하게 이해 가능할 것 같다.

  • => 로 함수를 선언

  • 함수 내부에 return문 이외에 없는 경우 축약 가능

    • (매개 변수) => (반환 값);
  • 매개 변수가 한 개면 소괄호로 묶어주지 않아도 된다.

  • 예시 코드 1

    function add1(x, y) {
        return x + y;
    }
    
    const add2 = (x, y) => {
        return x + y;
    }
    
    const add3 = (x, y) => x + y;
    
    const add4 = (x, y) => (x + y);
    
    function not1(x) {
        return !x;
    }
    
    const not2 = x => !x;
  • 기존 function과 다른 this 바인드 방식
    상위 스코프의 this를 그대로 물려받는다.

  • 예시 코드 2

    // function
    var relationship1 = {
        name: 'zero',
        friends: ['nero', 'hero', 'xero'],
        logFreinds: function () {
            var that = this; // relationship1을 가리키는 this를 that에 저장
            this.friends.forEach(function (friend) {
                console.log(that.name, friend);
            });
        },
    };
    relationship1.logFreinds();
    
    // =>
    const relationship2 = {
        name: 'zero',
        friends: ['nero', 'hero', 'xero'],
        logFriends() {
            this.friends.forEach(friend => {
                console.log(this.name, friend);
            });
        },
    };
    relationship2.logFriends();

구조분해 할당

  • p. 71 ~ 73

  • 구조분해 할당을 사용하면 객체와 배열로부터 속성이나 요소를 쉽게 꺼낼 수 있다.

  • 예시 코드 1

    // 객체의 속성을 같은 이름의 변수에 대입
    
    // Old
    var candyMachine = {
        status: {
            name: 'node',
            count: 5,
        },
        getCandy: function () {
            this.status.count--;
            return this.statucs.count;
        },
    };
    var getCandy = candyMachine.getCandy;
    var count = candyMachine.status.count;
    
    // New
    const candyMachine = {
        status: {
            name: 'node',
            count: 5,
        },
        getCandy() {
            this.status.count--;
            return this.status.count;
        },
    };
    const { getCandy, status: { count } } = candyMachine;
    • candyMachine 객체 안의 속성을 찾아서 변수와 매칭

    • 다만 구조분해 할당을 사용하면 함수의 this가 달라질 수 있다.

      • 달라진 this를 원래대로 바꾸려면 bind 함수를 따로 사용해야 한다.
  • 예시 코드 2

    // 배열에 대한 구조분해 할당
    // 배열 array의 첫 번째, 두 번째 요소와 네 번째 요소를 변수에 대입
    
    // Old
    var array = ['nodejs', {}, 10, true];
    var node = array[0];
    var obj = array[1];
    var bool = array[3];
    
    // New
    const array = ['nodejs', {}, 10, true];
    const [node, obj, , bool] = array;
    • New에서 변수명을 지어주지 않은 10은 무시
  • 구조분해 할당 문법은 코드 줄 수를 상당히 줄이고 모듈 시스템에 유용

클래스

  • p. 73 ~ 75

  • 자바스크립트는 프로토타입 기반으로 동작

  • 프로토타입 :
    디자인 패턴으로, 객체를 생성할 때 원본이 되는 객체를 복사해서 생성하는 패턴이다.
    자바스크립트의 경우, 함수(생성자)를 이용해 원본을 복사하는 형식으로 객체를 생성한다.

  • 예시 코드

    // 프로토타입 상속 예제 코드
    var Human = function(type) {
        this.type = type || 'human';
    };
    
    Human.isHuman = function(human) {
        return human instanceof Human;
    }
    
    Human.prototype.breathe = function() {
        alert('h-a-a-a-m');
    };
    
    var Zero = function(type, firstName, lastName) {
        Human.apply(this, arguments);
        this.firstName = firstName;
        this.lastName = lastName;
    };
    
    Zero.prototype = Object.create(Human.prototype);
    Zero.prototype.constructor = Zero; // 상속하는 부분
    Zero.prototype.sayName = function() {
        alert(this.firstName + ' ' + this.lastName);
    };
    var oldZero = new Zero('human', 'Zero', 'Cho');
    Human.isHuman(oldZero); // true
    
    // Human 생성자 함수를 Zero 생성자 함수가 상속한다.
    // Human.apply와 Object.create 부분이 상속받는 부분
    
    // 클래스 기반 상속 예제 코드
    class Human {
        constructor(type = 'human'){
            this.type = type;
        }
    
        static isHuman(human) {
            return human instanceof Human;
        }
    
        breathe() {
            alert('h-a-a-a-m');
        }
    }
    
    class Zero extends Human {
        constructor(type, firstName, lastName) {
            super(type);
            this.firstName = firstName;
            this.lastName = lastName;
        }
    
        sayName() {
            super.breathe();
            alert(`${this.firstName} ${this.lastName}`);
        }
    }
    
    const newZero = new Zero('human', 'Zero', 'Cho');
    Human.isHuman(newZero); // true
    
    // 전반적으로 class 안으로 그룹화되었다.
    // extends 키워드로 쉽게 상속 가능

0개의 댓글