node.js

[node.js] ES6 문법

vhxpffltm 2019. 7. 29. 23:10

자바 스크립트의 문법에 변화를 가져온 것이 ES2015 혹은 ES6라고 부른다.

 

매년 문법 변경사항과 새로운 문법상세에 대해 늘 새로워진 것이 나온다.

 

언제나 변화에 민감하고 변화하는것을 배워야 한다고 생각한다. 이 중 몇개만 살펴보자.

 

const, let

자바 스크립트에서는 var로 변수를 선언한다. 이제는 const와 let이 대체한다. 

 

var은 함수 스코프를 가지므로 블록 밖의 스코프를 접근할 수 있지만, const와 let은 그럴 수 없다.

 

const와 let의 차이는 const는 한 번 대입하면 다른 값을 대입할 수 없다. 초기화 시 값을 대입하지 않으면 에러가 발생한다. 그래서 변수 선언시 const를 사용하고 다른 값을 대입할 일이 생긴다면 let을 사용하자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <meta http-equiv='X-UA-Compatible' content='IE=edge'>
    <title>Page Title</title>
    <meta name='viewport' content='width=device-width, initial-scale=1'>
    <link rel='stylesheet' type='text/css' media='screen' href='main.css'>
    <script> 
        if(true) {
            var x = 3;
        }
        console.log(x);
        if(true){
            const y=3;
        }
        console.log(y);
        const a=0;
        a = 1;
    </script>
</head>
<body>
</body>
</html>
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by
 

 

어떤 에러가 발생하는지 크롬 개발자 도구로 테스트해보길 바란다.

 

 

 

템플릿 문자열

새로운 문자열이다. 'tab'키의 위에 있는 `이다. 문자열안에 변수를 넣을 수 있다.

 

1
2
3
4
5
6
7
<script> 
        const num3 = 1;
        const num = 2;
        const result = 3;
        const string = `${num} 더하기 ${num3}는 '${result}'`;
        console.log(string);
    </script>
 
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

이 같은 결과를 얻을 수 있다. ${변수}로 이제 '더하기' 기호를 사용하지 않아도 된다.

 

 

 

객체 리터럴

{} 으로 표현하는 것이며, {}안에 함수, 객체, 속성값을 담을 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<script> 
        var sayNode = function(){
            console.log('NODE');
        }
        var es = 'ES';
        var oldObjecrt = {
            sayJs: function(){
                console.log('JS');
            },//객체의 메서드에 함수를 연결할 떄 
            sayNode: sayNode, // 2번 사용한다.
        };
 
        oldObjecrt[es+6]='fantastic';
        //객체의 속성명
        oldObjecrt.sayNode();
        oldObjecrt.sayJs();
        console.log(oldObjecrt.ES6);
    </script>
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
<script> 
        const newObject = {
            sayJs(){
                console.log('JS');
            },
            sayNode,
            [es+6]:'Fantastic',
        };
        newObject.sayNode();
        newObject.sayJs();
        console.log(newObject.ES6);
    </script>
 

 

위의 두 코드는 모두 같다. 요약하면 객체의 메서드 연결에 : 과 function을 붙이지 안하도 되고, 속성명과 변수명의 중복을 피해 하나로 표현한다. 그리고 동적으로 객체의 속성명을 설정할 수 있다.

 

 

 

화살표 함수

기존의 funtion() {} 을 화살표로 대체한다. 

1
2
3
4
5
6
<script> 
        function add1(x,y){
            return x+y;
        }
        const add2 = (x,y) => x+y;
    </script>
 

 

위 두 함수는 같은 기능을 한다. function 키워드와 return 키워드를 생략하여 나타낼 수 있다.

 

화살표 함수에서 this함수의 바인딩 방식이 다르다. 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script> 
        var relation1 = {
            name : 'zero',
            friends : ['nero''hero''xero'],
            logfriend: function(){
                var that = this; // relation1을 가리키는 this를 that에 저장
                this.friends.forEach(function(friend){
                    console.log(that.name,friend);
                })
            }
        }
        relation1.logfriend();
 
        const relation2 = {
            name : 'zero',
            friends : ['nero''hero''xero'],
            logfriend(){
                this.friends.forEach(friend =>{
                    console.log(this.name,friend);
                });
            }
        }
        relation2.logfriend();
    </script>
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

 

위 코드에서 relation1.logfriend()안의 foreach문에서는 function을 사용하여 각자 다른 함수 스코프의 this를 가지므로 that이라는 변수를 사용해 relation1에 간접적으로 접근한다.

 

relation2.logfriend()안의 foreach문에서는 화살표 함수로 바깥 스코프인 logfriend()의 this를 그대로 사용할 수 있다. 즉 상위 스코프의 this를 그대로 사용할 수 있다.  물론 결과는 두 객체 모두 같다.

 

 

 

 

비구조화 할당

객체와 배열로부터 속성이나 요소를 쉽게 꺼낼 수 있다. 코드 줄 수를 상당히 줄일 수 있다.

 

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
<script> 
       var candy = {
           status: {
               name'node',
               count: 5,
           },
           get2:function(){
               this.status.count--;
                return this.status.count;
            }
       };
       var gett = candy.get2;
       var count = candy.status.count;
       //객체의 속성을 같은 이름의 변수에 대입하는 코드
       const candy2 = {
           status2:{
               name2:'node',
               count2: 5,
           },
           get3(){
               this.status2.count2--;
               return this.status2.count2;
           }
       }
       const {get3,status2:{count2}} = candy2;
       //이같이 candt2 객체 안의 속성을 찾아서 변수와 매칭시킬 수 있다.
    </script>
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

 

프로미스(promise)

자바 스크립트와 Node는 비동기 프로그래밍을 진행한다. 이벤트 주도 방식을 통한 콜백 함수를 자주 사용한다. 이 프로미스를 통해 콜백 헬(callback hell)을 극복한다.

 

  - 객체생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<script> 
      const condition = true;
      const promise = new Promise((resolv, reject) =>{
          if(condition){
              resolv('성공');
          }
          else {
              reject('실패');
          }
      });
 
      promise.then((message)=>{
          console.log(message); // 성공한 경우 실행
      })
      .catch((error)=>{
          console.error(error); // 실패한 경우 실행
      })
    </script>
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

 

new Promise로 프로미스 생성, 두 매개변수를 갖는 콜백함수 지정, 

promise변수에 then과 catch메서드 사용 가능, resolv가 실행되면 then이 실행, reject면 catch실행

 

두 매개변수에 넣은 인자는 then과 catch의 매개변수에서 받을 수 있다. 예로 resolv('성공') 호툴되면 then의 message가 '성공'이 된다. condition변수를 false로 바꾸면 반대로 바뀜...

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
          console.log(message); // 
      })
      .then((message2)=>{
          console.log(message2);
          return new Promise((resolv,reject)=>{
              resolv(message2);
          })
      });
      .then((message3)=>{
          console.log(message3);
      })
      .catch((error)=>{
          console.error(error); // 
      })
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

 

처음 then에서 message를 resolv하면 다음 then에서 받을 수 있다. 여기서 다시 message2를 resolv했으므로 다음 then에서 message3을 받는다. 이것을 활용해 콜백을 프로미스로 바꿀 수 있다. 예를 보자

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function findAndSave(users){
          users.findOne({},(err,user)=>//첫번째 콜백
              if(err){
                  return console.log(err);
              }
              user.name = 'zere';
              user.save((err)=>{// 2번쨰 콜백
                  if(err){
                      return console.error(err);
                  }
                  user.findOne({gender: 'm'}, (err,user)=>//3번째 콜백
                      //
                  });
              });
          });
      }
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function findAndSave(users){
        users.findOne({}).then((user) =>{
            user.name2 = 'zero2';
            return user.save();
        })
        .then((user)=>{
            return users.findOne({gender2:'m2'});
        })
        .then((user)=>{
            //
        })
        .catch(err =>{
            console.error(err);
        });
    } 
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 


아래코드의 then메서드는 순차적으로 실행된다. 콜백에서 매번 따로 처리해야 하던 에러도 마지막 catch에서 한번에 처리할 수 있다. 메서드가 프로미스 방식을 지원하면 위 코드와 같이 사용할 수 있다.

findOne과 save메서드가 내부적으로 프로미스 객체를 가지고 있어 가능하다.

 

이외에도 Promise.all 과 Promise.resolve, Promise.reject도 있다.

 

async/await

노드 7.6 버전부터 지원하는 기능이다. 이것은 프로미스를 사용한 코드를 한번 더 깔끔하게 한다.

 

위의 promise 코드를 한번 더 바꿀 수 있다.

 

1
2
3
4
5
6
7
8
async function findAndSaveUser(Users){
            let user = await Users.findOnd({});
            user.name = 'zero';
            user = await user.save();
            user = await User.findOnd({gender : 'm'});
            //
        }
    } 
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

 

함수 선언부에 async function으로 바꾸고 프로미스 앞에 await를 추가하면, 함수는 프로미스가 resolve될 때까지 기다린 다음 로직으로 넘어간다. 예를들어 await Users.findOne({})이 resolve될 때까지 기다린 뒤, user변수를 초기화한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
const findAndSaveUser = async (Users) => {
            try{
                let user = await Users.findOne({});
                user.name = 'zero';
                user = await user.save();
                user = await User.findOne({gender:'m'});
                //
            }
            catch(error){
                console.error(error);
            }
        }
    } 
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

 

위와 같이 try/catch문으로 에러를 처리하는 부분을 만들어준다. 위의 코드는 화살표 함수를 통해 작성하였다.

이제 중첩되는 콜백 함수는 프로미스를 거쳐 async/await 문법으로 사용하는 연습을 한다면 코드가 간결해질 수 있다. 

이와 함께 Promise.all 대신 for await of 문을 사용해서 프로미스를 반복 할 수있다.

 

출처 : 책 - Node.js 교과서 

https://www.zerocho.com/

'node.js' 카테고리의 다른 글

[node.js] Express_ Router객체  (0) 2019.08.24
[node.js] Express_구조 와 미들웨어  (0) 2019.08.24
[Node.js] NPM 시작하기  (0) 2019.08.21
[Node.js] Node 내장 객체 및 모듈  (0) 2019.08.21
[node.js] 콜백 함수, 프로토타입  (0) 2019.08.17