프로그래밍/Node.js

Node.js 2장. 알아두어야 할 자바스크립트

p-a-r-k 2019. 1. 2. 15:18
반응형

* 해당 글은 (주)길벗 `Node.js교과서` 내용을 바탕으로 복습 차 정리중입니다.


2.1 ES2015+

2015년에는 자바스크립트 문법에 큰 변화가 있었습니다. 바로 ES2015(ES6)가 등장한 것이었습니다.

2018년 현재 ES2018까지 나왔고, 보통 자바스크립트를 배울 때는 ES5의 문법을 배웁니다. (var 변수선언..등)

노드는 ES2015+(ES2015 이상 문법을 의미)문법 기반으로 재편되고 있으므로 이 문법에 익숙해져야 합니다.


2.1.1 const, let

보통 자바스크립트를 배울 때 var로 변수를 선언하는 방법부터 배웁니다.

하지만 var은 이제 const와 let이 대체합니다. 

const와 let이 가지는 공통적인 특징인 블록스코프에 대해 알아봅시다.

1
2
3
4
5
6
7
8
9
if (true) {
  var x = 3;
}
console.log(x);
 
if (true) {
  const y = 3;
}
console.log(y);

크롬 개발자도구[F12]나 jsfiddle등에서 실행 시키면 결과를 볼 수 있습니다.

x는 정상적으로 출력되는데 y는 에러가 발생합니다. var을 const로만 바꿨을 뿐인데 차이가 발생하는 것 입니다.

var은 함수 스코프를 가지므로 if문의 '블록'과는 관계없이 접근할 수 있습니다.

하지만 const와 let은 블록 스코프를 가지므로 '블록 밖'에서는 변수에 접근할 수 없습니다.

블록 범위는 if..while..for..function등의 중괄호 입니다.

함수 스코프 대신 블록 스코프를 사용함으로서 호이스팅같은 문제도 해결되고 코드관리가 좀 더 수월해졌습니다.

const와 let의 차이는 const는 한번 대입하면 다른 값을 대입할 수 없습니다. 

또한 초기화시 값을 대입하지않으면 에러가 발생합니다.


2.1.2 템플릿 문자열

새로운 문자열 문법이 생겼습니다. ""나 ''로 감싸는 기존 문자열과는 다르게 백틱(`)으로 감쌉니다.

특이한 점은 ``안에 변수를 넣을 수 있다는 것입니다.

ES5 문법 사용 시

문자열 string1은 띄어쓰기와 변수, 더하기 기호 때문에 가독성이 좋지 않습니다.

또한, 작은 따옴표를 이스케이프 하느라 지저분합니다.

1
2
3
4
5
var num1 = 1;
var num2 = 2;
var result = 3;
var string1 = num1 +' 더하기 '+ num2 +'는 \''+ result +'\'';
console.log(string1);


ES6 문법 사용 시

${변수} 형식으로 더하기 없이 문자열에 넣을 수 있습니다.

백틱 사용으로 작/큰따옴표를 함께 사용할 수 있습니다.

1
2
3
4
5
const num3 = 1;
const num4 = 2;
const result2 = 3;
const string2 = `${num3} 더하기 ${num4}는 '${result2}'`;
console.log(string2);


2.1.3 객체 리터럴

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
 * ES5 문법
 */
var sayNode = function () {
    console.log('Node');
}
var es = 'ES';
var oldObject = {
    sayJS: function() {
        console.log('JS');
    },
    sayNode: sayNode,
};
oldObject[es + 6] = 'Fantastic';
 
oldObject.sayNode();
oldObject.sayJS();
console.log(oldObject.ES6);
 
/**
 * ES6 문법
 */
const newObject = {
    sayJS() {
        console.log('JS');
    },
    sayNode,
    [es + 6]: 'Fantastic'
}
newObject.sayNode();
newObject.sayJS();
console.log(newObject.ES6);

이제 sayJS같이 '객체에 함수를 연결'할 때 :과 function을 붙이지 않아도 됩니다.

sayNode: sayNode처럼 속성, 변수명이 겹치는 경우에는 한 번만 쓸 수 있게 되었습니다.

또한, 객체의 속성명을 동적으로 생성 할 수 있습니다.

예전문법에서는 ES6라는 속성명을 만드려면 객체 밖에서 [es+6]을 해야했지만 이제 객체 안에서 선언해도 됩니다.


2.1.4 화살표함수

기존의 function () {} 외에도 추가로 화살표함수라는 새로운 함수문법이 추가되었습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
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;

add1~4는 모드 같은 기능을 하는 함수입니다. not1, 2도 같은 기능을 합니다.

화살표함수에서는 fuction선언 대신 => 기호로 함수를 선언합니다.

화살표함수에서는 한줄로 선언시 return문을 생략할 수 있습니다. 또한 소괄호로 감쌀 수도 있습니다.

+ 화살표함수는 상위스코프의 this를 그대로 물려받을 수 있습니다.


2.1.5 비구조화 할당

이름은 어색하지만 유용합니다. 객체와 배열 로부터 속성이나 요소를 쉽게 꺼낼 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
// 객체 비구조화
const candyMachine = {
    status: {
        name: 'node',
        count: 5
    },
    getCandy() {
        this.status.count--;
    return this.status.count;
    }
};
const { getCandy, status: {count} } = candyMachine;

candyMachine 객체 안의 속성을 찾아서 변수와 매칭해줍니다. count처럼 여러 단계 안의 속성도 찾을 수 있습니다.

1
2
3
// 배열 비구조화
const arry = ['nodejs', {}, 10, true];
const [node, obj, , bool] = array;

배열의 경우 위치에 따른 요소들을 초기화해 줍니다.


2.1.6 프로미스

자바스크립트와 노드에서는 주로 비동기 프로그래밍을 합니다. 특히 이벤트 주도 방식 때문에 콜백 함수를 자주 사용합니다. 

ES 2015부터는 자바스크립트와 노드의 API들이 콜백대신 프로미스기반으로 재구성됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const condition = true;
const promise = new Promise((resolve, reject) => {
    if (condition) {
    resolve('성공')
  else {
    reject('실패')
  }
})
 
promise.then((msg) => {
    console.log(msg); // 성공(resolve)한 경우 실행
}).catch((err) => {
    console.log(err); // .실패(reject)한 경우 실행
})

new Promise로 프로미스를 생성할 수 있으며, 안에 resolve와 reject를 매개변수로 갖는 콜백 함수를 넣어줍니다.

이렇게 만든 promise변수에 then과 catch메서드를 붙일 수 있습니다.

내부에서 resolve가 호출되면 then이 실행되고, reject가 호출되면 catch가 실행됩니다.


1
2
3
4
5
6
7
8
9
10
const promise1 = Promise.resolve('성공1')
const promise2 = Promise.resolve('성공2')
 
Promise.all([promise1, promise2])
             .then((res) => {
            console.log(res) // ['성공1', '성공2']
       })
       .catch((err) => {
            console.error(err)
       })

Promise.resolve는 즉시 resolve하는 프로미스를 만드는 방법입니다. reject도 마찬가지 입니다.

프로미스가 여러개일 때 Promise.all에 넣으면 모두 resolve될 때까지 기다렸다가 then으로 넘어갑니다.

다만, Promise중 하나라도 reject가 되면 catch로 넘어갑니다.


2.1.7. async / await

노드 7.6버전 부터 지원되는 기능입니다. 자바스크립트에서의 스펙은 ES2017입니다.

async/await문법은 프로미스를 사용한 코드를 한 번 더 깔끔하게 줄여줍니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// promise..
function findAndSaveUser(Users) {
    Users.findOne({})
         .then((user) => {
            user.name = 'park'
          return user.save()
       })
       .then((user) => {
            return Users.findOne({gender: 'm'})
       })
       .then((user) => {
            // 생략
       })
       .catch((err) => {
            console.error(err)
       })
}
 
// async await..
const findAndSaveUser2 = async (Users) => {
    try {
    let user = await Users.findOne({})
    user.name = 'park'
    user = await user.save()
    user = await Users.findOne({gender: 'm'})
    // 생략
  catch(e) {
    console.error(e)
  }
}

함수 선언부를 일반 함수 대신 async function으로 교체한 후, 프로미스 앞에 await를 붙였습니다.

이제 함수는 해당 프로미스가 resolve될 때까지 기다린 뒤 다음로직으로 넘어갑니다.



2.2 프런트엔드 자바스크립트

2.2.1 AJAX

AJAX(asynchronous Javascript And XML)는 비동기적 웹 서비스를 개발하기 위한 기법입니다.

이름에 XML이 들어있지만 꼭 XML을 사용해야하는 것은 아니며, 요즘은 JSON을 많이 사용합니다.

쉽게말해서 페이지이동없이 서버에 요청을 보내고 응답을 받는 기술입니다.

보통 AJAX요청은 jQuery나 axios같은 라이브러리를 이용해서 보냅니다.

하지만 라이브러리 사용없이 자바스크립트가 기본으로 제공하는 방식으로 요청을 보내봅니다.

프런트엔드에서는 IE가 ES6지원이 느리므로 ES5문법을 사용해봅니다.

1
2
3
4
5
6
7
8
9
10
11
12
var xhr = new XMLHttpRequest()
xhr.onreadystatechange = function() {
    if (xhr.readyState === xhr.DONE) {
    if (xhr.status === 200 || xhr.status === 201) {
        console.log(xhr.responseText)
    else {
        console.error(xhr.responseText)
    }
  }
}
xhr.open('GET''http://요청 주소')
xhr.send()


2.2.2 FormData

HTML Form태그의 데이터를 동적으로 제어할 수 있는 기능입니다. 주로 ajax와 함께 사용합니다.

1
2
3
4
5
6
7
8
9
10
var formData = new FormData()
formData.append('name''park')
formData.append('item''orange')
 
formData.has('item')  // true
formData.has('money'// false
formData.get('item')  // orange
formData.delete('item')
formData.set('name''update park')
formData.getAll('name'// ['update park']

FormData생성자로 formData객체를 만들면, append메서드로 키-값 형식의 데이터를 저장할 수 있습니다.

append를 여러번 사용하여 키하나에 여러개의 값을 추가해도 됩니다.

has는 해당 키에 대한 값이 있는지 여부를 체크하고, get은 주어진 키에 해당하는 값을 가져옵니다.

getAll메서드는 배열형식으로 모든 값을 가져오고, delete는 제거 set은 수정입니다.


2.2.3 encodeURLComponet, decodeURLComponent

서버가 한글주소를 이해하지 못하는 경우가 있으므로, AJAX요청 시 encodeURIComponent메서드를 사용합니다.

1
2
3
// example
xhr.open('GET''https://nodejs.org/api/'+ encodeURIComponent('노드'));
xhr.send();


2.2.4 data attribute와 dataset

프런트엔드에서 AJAX로 데이터를 주고 받을때 주로 변수 혹은 FORM input value값을 가지고 통신합니다.

혹은 jQuery의 data() 메서드도 사용해본적이 있을 겁니다.


HTML5에도 HTML과 관련된 데이터를 저장하는 공식적인 방법이 있습니다.

바로 html5 data attribute입니다. (jquery data()메서드 도 동일합니다.)

1
2
3
4
5
6
7
8
9
10
<ul>
  <li data-id="1" data-my-color="red">Park</li>
  <li data-id="1" data-my-color="yellow">June</li>
  <li data-id="1" data-my-color="green">Kim</li>
  <li data-id="1" data-my-color="blue">Jung</li>
</ul>
<script>
    console.log(document.querySelector('li').dataset)
  // { id: 1, myColor: 'red' }
</script>

HTML태그 속성으로 data-@로 시작하는 것들을 넣어줍니다. 이들이 data attribute입니다.

data-id와 data-my-color속성을 준것을 확인할 수 있습니다.

기본적으로 스네이크표기법인 data-@-@로 표시하지만, 위 스크립트 태크에서 볼 수 있듯이 javascript로 가져오게되면,

카멜케이스로 data-는 사라지고 각 '-'의 첫 글자가 대문자로 변형되어 표시됩니다.

또한 스크립트로 dataset에 데이터를 추가할 수 있습니다.

dataset.myAge = 25; 라고 넣으면 data-my-age="25"인 속성이 추가됩니다.

반응형