새소식

인기 검색어

Language/Javascript

[Javascript] Node js 기초 2장

  • -
반응형

node js는 공식 홈페이지에서 다운로드가 가능하다.

https://nodejs.org/ko/download

 

다운로드 | Node.js

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

nodejs.org

ES2015+는 자바스크립트 문법이다. 2015년에 자바스크립트 문법에 큰 변화가 있었는데 어떤 식으로 변화되었는지 같이 알아보자.


 보통 javascript는 var로 변수를 선언한다. 하지만 ES2015+부터는 const와 let가 추가되었다.

if(true) { var a = 1; } console.log(a); if(true) { let b = 2; } console.log(b); // ERROR if(true) { const c = 3; } console.log(c); // ERROR

var는 변수를 선언하면 선언한 변수를 나중에 초기값을 설정할 수도 있고 변수의 값을 변경할 수도 있다. 그리고 함수 스코프를 가지므로 블록과 관계없이 접근할 수 있다.

하지만 const와 let는 블록 스코프를 가진다. 그래서 블록 밖에서는 접근할 수가 없다.

또 var로 선언한 변수는 재할당이 가능하고 초기값은 선언안해줘도 된다.

const a = 0; a = 1; // ERROR let b = 0; b = 1; const c; // ERROR

하지만 const는 변수를 선언하는 동시에 초기값을 설정해줘야 하며 재할당도 불가능하다. 그래서 흔히 const는 상수라고도 표현하기도 한다.

let은 초기값을 설정해도 재할당이 가능하다.

ES2015+ 문법에 백틱이 추가되었습니다. 

var x = 1; var y = 2; var result = x + y; var string = x + " + " + y + " = " + result console.log(string); // 1 + 2 = 3

기존 문법 같은 경우는 문자열을 일일히 더해서 string을 만든다.

const x = 1; const y = 2; const result = x + y; const string = `${x} + ${y} = ${result}`; console.log(string); // 1 + 2 = 3

ES2015+ 문법에는 ``으로 문자열을 감싸서 훨씬 깔끔하게 결과를 출력할 수 있다. 그리고 변수를 출력할 때는 ${변수}로 변수 값을 삽입할 수 있다.

객체 리터럴에 편리한 기능들이 추가되었다.

var hack = function() { console.log("I'm hacker"); }; var rh = 'RH'; var oldObject = { hello: function() { console.log("world"); }, hack: hack, } oldObject[rh + 1] = '3nu5'; oldObject.hack(); oldObject.hello(); console.log(oldObject.RH1);
let hack = function() { console.log("I'm hacker"); }; var rh = 'RH'; const newObject = { hello() { console.log("world"); }, hack, [rh + 1]: '3nu5', } newObject.hack(); newObject.hello(); console.log(newObject.RH1);

위와 아래 코드를 비교하면 이제 객체의 메서드에 함수를 연결할 때 콜론과 function을 붙이지 않아도 된다.

그리고 {name: name, age: age} 같이 속성과 변수가 동일한 경우 한 번만 써도 된다.

화살표 함수라는 새로운 개념이 생겼다.

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을 화살표 함수로 간략하게 만들 수 있다. 또한 내부에 return문 밖에 없는 경우는 return 할 값만 작성하면 된다.

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

var candyMachine = { status: { name: 'node', count: 5, }, getCandy: function() { this.status.count--; return this.status.count; }, }; var getCandy = candyMachine.getCandy; var count = candyMachine.status.count;
const candyMachine = { status: { name: 'node', count: 5, }, getCandy() { this.status.count--; return this.status.count; }, }; const { getCandy, status: {count} } = candyMachine;

위 코드를 아래로 변경할 수 있다.

코드의 의미는 candyMachine 객체 안의 속성을 찾아서 변수와 매칭한다.

클래스 문법이 추가되었는데 다른 언어처럼 클래스 기반으로 동작하는 것이 아니라 프로토타입 기반으로 동작한다.

var Family = function(type) { this.type = type || 'family'; }; Family.myfamily = function(family) { return family instanceof Family; } Family.prototype.hello = function() { console.log('world'); }; var Rh = function(type, name, job) { Family.apply(this, arguments); this.name = name; this.job = job; }; Rh.prototype = Object.create(Family.prototype); Rh.prototype.constructor = Rh; Rh.prototype.profile = function() { console.log(this.name + ' ' + this.job); } var person = new Rh('family', 'rhenus', 'hacker'); console.log(Family.myfamily(person));
class Family { constructor(type = 'family') { this.type = type; } static myfamily(family) { return family instanceof Family; } hello() { console.log('world'); } } class Rh extends Family { constructor(type, name, job) { super(type); this.name = name; this.job = job; } profile() { super.hello(); console.log(`${this.name}, ${this.job}`); } } const person = new Rh('family', 'rheus', 'hacker'); console.log(Family.myfamily(person));

자바스크립트와 노드에서는 주로 비동기를 많이 사용한다. 특히 이벤트 리스너를 사용할 때 콜백 함수를 자주 사용한다.

ES2015+에서는 자바스크립트와 노드의 API들이 콜백 대신 프로미스기반으로 재구성되고 있다.

그만큼 프로미스는 반드시 알아두어야 하는 객체이다.

 

프로미스는 다음과 같은 규칙이 있다.

★ 프로미스 객체 생성

const condition = true; const promise = new Promise((resolve, reject) => { // true일 경우 resolve false일 경우 reject if(condition) { resolve("success"); } else { reject("fail"); } }); promise .then((message) => { console.log(message); // resolve일 경우 실행 }) .catch((error) => { console.error(error); // reject일 경우 실행 }) .finally(() => { console.log("default"); // 무조건 실행 });

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

그래서 프로미스 내부에 resolve가 호출되면 then이 reject가 호출되면 catch가 실행된다. finally는 성공/실패 여부 상관없이 실행된다.

 

프로미스를 간단하게 설명하면 실행을 바로 하되 결괏값은 나중에 받는 객체이다.

new Promise는 바로 실행이 되지만 결과값은 then을 붙였을 때 받게 된다.

function findAndSaveUser(Users) { Users.findOne({}, (err, user) => { if(err) { return console.error(err); } user.name = 'rhenus'; user.save((err) => { if(err) { return console.error(err); } Users.findOne({job: 'hacker'}, (err, user) => { // }); }); }); }

코드를 보면 콜백 함수가 3번 중쳡된다. 그럼 콜백 함수가 나올 때마다 에러도 따로 처리해줘야 하고 코드도 복잡해진다.

function findAndSaveUser(Users) { Users.findOne({}) .then((user) => { user.name = 'rhenus'; return user.save(); }) .then((user) => { return Users.findOne({job: 'hacker'}); }) .then((user) => { }) .catch(err => { console.error(err); }); }

그래서 findOne()함수와 save() 함수가 내부적으로 프로미스가 구현돼있다고 가정하에 위 코드처럼 간단하게 만들 수 있다.

async/await 문법으로 인하여 프로미스를 사용한 코드를 한 번 더 깔끔하게 줄일 수 있다.

async function findAndSaveUser(Users) { let user = await Users.findOne({}); user.name = 'rhenus'; user = await user.save(); user = await Users.findOne({ job: 'hacker' }); // }

위의 프로미스 코드를 async/await로 줄였다. async function는 해당 프로미스가 resolve 될 때까지 기다린 뒤 다음 로직으로 넘어간다. 그래서 await Users.findOne({})이 resolve가 되면 user 변수를 초기화한다. 그런데 해당 코드는 에러를 처리하는 부분이 없어서 try/catch문을 추가해야 한다.

 

다음 장에서는 노드 기능을 알아보자.

반응형

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.