본문 바로가기

JOURNAL/TIL

210224

반응형

 

Node.js와 브라우저의 차이점

 Node.js는 DOM이 존재하지 않는다는 것이 브라우저와의 가장 큰 차이점 중 하나다. window와 document 객체 역시 존재하지 않는다는 것인데, Node.js에서는 전역 변수를 다룰 때 window 대신 global 키워드를 사용한다. 또한 fetch API도 존재하지 않는데, 서버에 대한 요청 역시 다른 방법을 사용한다. 

 

프론트엔드에서 Node.js가 가지는 의미

 대부분 Node.js가 백엔드 환경이라 생각하는 경우가 많다. 이는 서버를 만들 때 Node.js를 사용할 수 있는 것이 사실이고, 또한 대중적으로 알려진 내용들이 많기 때문이다. 하지만 프론트엔드 개발에서도 다양한 Node.js 모듈들과 npm 생태계를 활용하고 있으며, cli에서 배포 등 자동화를 위한 과정을 처리하는 경우가 많기 때문에 이에 대한 학습은 필수적이다.

 


 package.json

  package.json은 말 그대로, 어떤 프로젝트에 대해서 해당 프로젝트의 package에 대한 설정을 하는 파일이라 생각하면 된다. 프로젝트의 설명, 특정 배포의 프로젝트 버전, 라이센스의 정보, 구성 데이터와 같은 메타 데이터를 포함한다. 보통은 프로젝트의 루트 디렉토리에 파일이 존재한다. 다음은 Vue.js 애플리케이션에서 추출된 package.json의 예이다. 

 

  
  {
    "name": "test-project",
    "version": "1.0.0",
    "description": "A Vue.js project",
    "main": "src/main.js",
    "private": true,
    "scripts": {
      "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
      "start": "npm run dev",
      "unit": "jest --config test/unit/jest.conf.js --coverage",
      "test": "npm run unit",
      "lint": "eslint --ext .js,.vue src test/unit",
      "build": "node build/build.js"
    },
    "dependencies": {
      "vue": "^2.5.2"
    },
    "devDependencies": {
      "autoprefixer": "^7.1.2",
      "babel-core": "^6.22.1",
      "babel-eslint": "^8.2.1",
      "babel-helper-vue-jsx-merge-props": "^2.0.3",
      "babel-jest": "^21.0.2",
      "babel-loader": "^7.1.1",
      "babel-plugin-dynamic-import-node": "^1.2.0",
      "babel-plugin-syntax-jsx": "^6.18.0",
      "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
      "babel-plugin-transform-runtime": "^6.22.0",
      "babel-plugin-transform-vue-jsx": "^3.5.0",
      "babel-preset-env": "^1.3.2",
      "babel-preset-stage-2": "^6.22.0",
      "chalk": "^2.0.1",
      "copy-webpack-plugin": "^4.0.1",
      "css-loader": "^0.28.0",
      "eslint": "^4.15.0",
      "eslint-config-airbnb-base": "^11.3.0",
      "eslint-friendly-formatter": "^3.0.0",
      "eslint-import-resolver-webpack": "^0.8.3",
      "eslint-loader": "^1.7.1",
      "eslint-plugin-import": "^2.7.0",
      "eslint-plugin-vue": "^4.0.0",
      "extract-text-webpack-plugin": "^3.0.0",
      "file-loader": "^1.1.4",
      "friendly-errors-webpack-plugin": "^1.6.1",
      "html-webpack-plugin": "^2.30.1",
      "jest": "^22.0.4",
      "jest-serializer-vue": "^0.3.0",
      "node-notifier": "^5.1.2",
      "optimize-css-assets-webpack-plugin": "^3.2.0",
      "ora": "^1.2.0",
      "portfinder": "^1.0.13",
      "postcss-import": "^11.0.0",
      "postcss-loader": "^2.0.8",
      "postcss-url": "^7.2.1",
      "rimraf": "^2.6.0",
      "semver": "^5.3.0",
      "shelljs": "^0.7.6",
      "uglifyjs-webpack-plugin": "^1.1.1",
      "url-loader": "^0.5.8",
      "vue-jest": "^1.0.2",
      "vue-loader": "^13.3.0",
      "vue-style-loader": "^3.0.1",
      "vue-template-compiler": "^2.5.2",
      "webpack": "^3.6.0",
      "webpack-bundle-analyzer": "^2.9.0",
      "webpack-dev-server": "^2.9.1",
      "webpack-merge": "^4.1.0"
    },
    "engines": {
      "node": ">= 6.0.0",
      "npm": ">= 3.0.0"
    },
    "browserslist": ["> 1%", "last 2 versions", "not ie <= 8"]
  }
  

  위와 같이 프로젝트(패키지)에 대한 전반적인 정보를 가지고 있는데, 이 데이터들 중에는 우리가 프로그램을 실행시키기 위해서 필요한 모듈들에 대해 명시하거나, 실행시키는 방법, 또는 테스트 하는 방법들 역시 명시되어 있다. 

 

  • version: 현재 패키지의 버전을 명시
  • name: 응용 프로그램 / 패키지 이름을 설정
  • description: 응용 프로그램 / 패키지에 대한 간략한 설명
  • main: 응용 프로그램의 진입 점 설정

 

  • scripts: 실행할 수 있는 노드 스크립트 세트를 정의. package.json의 여러 기본 제공 스크립트와 이벤트, 임의의 스크립트 등을 지원한다. npm run-script <stage> 또는 npm run <stage>로 실행이 가능하다. 
  
  npm run-script <command> 
  
  // 예) npm run-script start 
  

 

  • dependencies: 프로그램의 실행과 무관. 오로지 개발을 위해 필요한 의존성 모듈 (설치된 패키지 목록을 종속성으로 설정). 런타임에서 계속 쓰이는 라이브러리 들이라면 dependencies로 들어간다.
  • devDependencies: 프로젝트를 개발하는 환경에서 필요한 모듈들 (개발 종속성으로 설치된 패키지 목록을 설정). 만약 개발 시에 개발자에게 필요한 라이브러리들이라면 devDependencies로 들어간다.

 

 

  참고: nodejs.dev/learn/the-package-json-guide

 

Run JavaScript Everywhere.

Welcome to Node.js!

nodejs.dev


 # 화살표 함수

  이전에 기본적으로 사용하던 함수 표현식의 형태는 다음과 같다.

 
   const sub = function(x,y){
     return x-y;
   }
   

 같은 함수를 화살표 함수로 표현하면 다음과 같이 나타낼 수 있다.

 
  const sub = (x,y) => {
     return x-y;
  }
  

  화살표 함수는 function 키워드를 화살표로 축약시켜 나타낸 것이다. 본문에 return문만 존재한다면, return도 생략 가능하다. 단 return문을 생략하는 경우에는 중괄호를 사용하면 안된다. 화살표함수에서 리턴이 생략된 케이스의 표현에 대해서는 다음과 같이 정리가 가능하다.

  // 정상적으로 작동하는 케이스
  const sub = (x,y) => x-y;
  const sub = (x,y) => (x+y);

  // 정상적으로 작동하지 않고 undefined를 리턴
  const sub = (x,y) => {x+y}

    화살표 함수는 클로저를 표현할 때 더욱 강력하다. 일반적인 함수로 표현된 클로저의 예는 다음과 같다. 

  const sub = function(x){
    return function(y){
      return x-y;
    }
  }

  sub(7)(5) // 2

  위와 같은 클로저 함수를 다시 화살표 함수로 표현하면 다음과 같이 작성할 수 있다.

  // (1) function 키워드를 없앤다.
   const sub = (x) => {
     return (y) => {
       return x-y;
     }
   }
   
   
  // (2) return을 생략하고, return만 존재했으므로 중괄호도 없앤다.
   const sub = (x) => {
      return y => x-y;
   }
   
   
  // (3) 마지막 return도 생략해준다.
   const sub = x => y => x-y;
 
 

 


# Spread/Rest

  • Spread: 배열을 풀어 인자로 전달 또는 각각의 요소로 넣는 경우 사용.
  
  function sum(x, y, z) {
    return x + y + z;
  }

  const numbers = [1, 2, 3];

  console.log(sum(...numbers));
  // expected output: 6

 

  • Rest: 정해지지 않은 인수를 배열로 형태로 나타나게 한다. 파라미터의 수가 가변적인 경우 유용하게 사용될 수 있다.
  
  function sum(...theArgs) {
    return theArgs.reduce((previous, current) => {
      return previous + current;
    });
  }

  console.log(sum(1, 2, 3));
  // expected output: 6

  console.log(sum(1, 2, 3, 4));
  // expected output: 10

 

 참고: developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/Spread_syntax.

 

전개 구문 - JavaScript | MDN

전개 구문을 사용하면 배열이나 문자열과 같이 반복 가능한 문자를 0개 이상의 인수 (함수로 호출할 경우) 또는 요소 (배열 리터럴의 경우)로 확장하여, 0개 이상의 키-값의 쌍으로 객체로 확장시

developer.mozilla.org

          developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Functions/rest_parameters

 

Rest 파라미터 - JavaScript | MDN

Rest 파라미터 구문은 정해지지 않은 수(an indefinite number, 부정수) 인수를 배열로 나타낼 수 있게 합니다. function f(a, b, ...theArgs) { } 함수의 마지막 파라미터의 앞에 ... 를 붙여 (사용자가 제공한

developer.mozilla.org


# 구조 분해 할당

  • 배열을 분해
   const array = [ 'never','really','over' ];
   const [first,second] = array;

   console.log(first); // 'never'
   console.log(second); // 'really'
 
   const arr = [];
   function newArr([first,second]){
      arr.push(second);
      arr.push(first);
   }
   
   console.log(arr); // ['really','never']
   

 

  • spread 또는 rest를 배열 / 객체의 분해에 적용
 
    // 배열
  
    const array = ['la', 'la', 'la', 'how', 'it', 'goes'];
    const [first,second,third, ...rest] = array;
    
    console.log(first); // 'la'
    console.log(rest); // ['how', 'it', 'goes'];
    
    
    // 객체
    
    const user = { name: 'JJY', major: 'EE', gender: 'female' };
    
    function userInfo({name, major, gender}){
       return `user ${name} majored in ${major}.`; 
    }
    
    console.log(userInfo(user)); 
    // `JJY majored in EE.`
    

   

  => 구조 분해는 예시나 문제를 많이 보고 풀어봐야 익숙해질 듯 하다.

 

 

참고: developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

 

구조 분해 할당 - JavaScript | MDN

구조 분해 할당 구문은 배열이나 객체의 속성을 해체하여 그 값을 개별 변수에 담을 수 있게 하는 JavaScript 표현식입니다. The source for this interactive example is stored in a GitHub repository. If you'd like to cont

developer.mozilla.org


 # CommonJS의 도입배경과 Module, exports, require

   자바스크립트를 브라우저만이 아니라 범용적으로 사용하기 위해 도입하게 된 것이 바로 모듈화 작업이다. 이런 모듈화를 이끄는 여러 가지 중의 하나가 바로 CommonJS이다. 기존 브라우저용으로만 취급되던 자바스크립트의 문제는 호환되는 표준 라이브러리가 없고, 데이터베이스에 연결할 표준 인터페이스가 없으며 의존성 문제를 해결하는 공통 패키지의 모듈 저장소가 필요하다는 점 등 핵심적인 문제들이 다수 존재했다. 이러한 문제점들은 모듈화를 통해 해결되었는데, 이 '모듈화'는 관련된 코드들을 하나의 코드 단위로 캡슐화 하는 과정을 말한다.

 

 

  •  스코프: 모든 모듈은 자신만의 독립적인 실행 영역이 존재해야함. => 전역변수와 지역변수를 분리하는 것이 중요하다.
  •  정의: 모듈 정의는 exports 객체를 이용. => 각각의 모듈끼리 정보 교환이 필요할 때, 해당 js 파일의 함수를 외부로 공개한다.
  •  사용: 모듈 사용은 require 함수를 이용. => exports를 통해 공개된 함수를 다른 모듈에서 이용하려면 require() 함수가 이용된다.

 

  그런데 모든 파일이 로컬 디스크에 있어 바로 불러올 수 있는 경우에는 크게 문제가 없지만, 브라우저에서는 필요한 모듈에 대해 모두 내려받기 전까지 다른 일을 할 수 없다는 단점이 있다. 이를 해결하기 위해서 동적으로 script 태그를 삽입하는 방식을 사용한다. 

 

 

# module.exports vs exports

{ } << module.exports << exports

 

  module.exports, exports는 모두 같은 object를 바라보지만, 최종적으로 리턴되는 값은 module.exports이다. exports는 call by reference로 module.exports를 바라보고 있다. 위와 같이 서로 같은 객체를 바라보고 있는 경우에는 exports에 우리가 추가한 내용이 module.exports에도 추가된다. 하지만 만약 exports에 다른 객체를 할당하게 된다면, module.exports의 객체와 달라지므로 영향을 줄 수 없게 되므로 주의해야한다.

 

 

참고: d2.naver.com/helloworld/12864

 


공부해야 할 내용들

 클래스와 인스턴스

  •  new 키워드의 사용법
  •  class 키워드의 사용법
  •  현실 모델을 바탕으로 클래스와 메소드의 속성 디자인

 

 this, call, apply, bind와 같은 함수 메소드의 이해

 


 

반응형

'JOURNAL > TIL' 카테고리의 다른 글

210317  (2) 2021.03.17
210225  (0) 2021.02.25
210223  (0) 2021.02.23
210222  (0) 2021.02.22