본문 바로가기
SeSAC

[새싹X코딩온] 풀스택 4주차 회고록 - 2 | Node.js, javascript 심화

by 리잼 2023. 8. 13.
반응형

Node.js


Node.js의 특징

스택 ( Stack )

  • 한쪽 끝에서만 자료를 넣고 빼는 작업이 이루어지는 자료구조
  • LIFO ( 후입선출 ) 구조
  • top : 스택의 가장 윗 부분
  • pop : 가장 최근에 삽입된 자료 삭제
  • push : top에 새로운 자료 추가
  • stack underflow : 스택이 비어있는데 pop을 시도했을 때 발생
  • stack overflow : 스택이 꽉 차있는데 push를 시도했을 때 발생

콜 스택 ( Call Stack)

function first() {
    second();
    console.log(1);
    return;
}

function second() {
    console.log(2);
    return;
}

first();

위의 코드가 실행되면 어떤 값이 출력될까?

콜스택은 LIFO ( Last Input First Out ) 후입선출 구조이다

 

Non-Blocking I/O

 

백그라운드(background)
뒷 단에서 실행하고 있는 작업! == 특정 작업이 백그라운드로 실행되면 그 동안 다른 일이 가능
포그라운드(foreground)
내 앞에서 실행하고 있는 작업! == 해당 작업이 포그라운드로 실행되면 결과가 나올때까지 기다리는 작업

 

이벤트 기반 ( Event-Driven ) 아키텍쳐

  • 이벤트가 발생할 때 미리 지정해둔 작업을 수행
  • 클릭, 네트워크 요청, 타이머 ..
  • 이벤트 기바나 아키텍처에서는 특정 이벤트가 발생할 때 무엇을 할지 미리 등록해야함
    • 이벤트 리스너 ( Event Listener ) : 이벤트 등록 함수
    • 콜백 함수 ( Callback Function ) : 이벤트가 발생했을 때 실행되는 함수

Event Loop

  • Node.js는 오래 걸리는 작업은 이벤트 루프에 맡김
  • 이벤트 발생시 호출할 콜백함수들을 관리하고, 호출된 콜백함수의 실행 순서를 결정하는 역할을 담당한다
  • 노드가 종료될 때까지 이벤트 처리를 위한 작업을 반복하므로 루프라고 부름

 


모듈

모듈이란 ?

  • 특정한 기능을 하는 함수나 변수들의 집합
  • 재사용 가능한 코드 조각

모듈의 장점

  • 코드 추상화
  • 코드 캡슐화
  • 코드 재사용
  • 의존성 관리

모듈 만들어보기

math.js

const add = (a, b) => a + b;

module.exports = add;

app.js

const add = require('./math');

console.log(add(1, 2));

math2.js

const add = (a, b) => {
    return a + '+' + b + '=' + a + b;
};
const sub = (a, b) => a - b;
const mul = (a, b) => a * b;
const div = (a, b) => {
    if (b !== 0) {
        return a / b;
    } else {
        return '0으로 나눌 수 없습니다.';
    }
};

const E = 2.718;
const PI = 3.141592;

// module.exports = {
//     add: add,
//     E: E,
//     PI: PI,
// };

//case1. 객체로 감싸서 내보내기
module.exports = {
    //obj에서 key와 value가 동일할 때 생략 가능
    add,
    sub,
    mul,
    div,
    E,
    PI,
};

//case2. 하나씩 내보내기
module.exports.add = add;
module.exports.PI = PI;
module.exports.E = E;

//case2. 간단히
exports.add = add;
exports.PI = PI;
exports.E = E;

app2.js

const math = require('./math2');

console.log(math, typeof math);
console.log(math.PI);
console.log(math.E);
console.log(math.add(2, 4));
console.log(math.mul(2, 4));
console.log(math.sub(2, 4));
console.log(math.div(2, 0));
console.log(math.div(4, 2));

모듈 불러올 때 주의할 점

const { } 로 가져올 때는 객체 구조분해해 가져오기에 이름이 동일해야 함

다만 객체가 여러개가아닌 하나만 내보낸 경우엔 이름이 달라도 불러올 수 있다

객체 구조분해란?

  • 보통의 방식으로 객체를 불러올 때 ( 객체명.키 ) 이런식으로 호출 하게되는데
    실무에서는 키값이 훨씬 많기 때문에 객체명을 일일이 다 붙혀주기가 힘든데 이 때 객체 구조분해하여 불러올 수 있다고 함

보통의 방식

const cookie = {
    choco: '초코맛 쿠키',
    vanilla: '바닐라맛 쿠키',
    orange: '오렌지맛 쿠키',
};

console.log(cookie.choco);
console.log(cookie.vanilla);
console.log(cookie.orange);

객체 구조분해

const { choco, vanilla, orange } = cookie;
console.log(choco);
console.log(vanilla);
console.log(orange);

객체분해 후 불러올 때 키값이 같은 것을 볼 수 있다.
결과 값


JavaScript에서 모듈을 다루는 방식

  1. CommonJS 모듈
    • 자바 스크립트 표준 모듈 방식은 아님
    • 노드에서 가장 많이 쓰이는 모듈 방식 ( 표준보다 먼저 등장해서 가장 많이 쓰임 )
    • module.exports, require 로 모듈 관리
  2. AMD ( Asynchronous Module Definition )
  3. UMD ( Universal Module Definition )
  4. ES2015 ( ES6 )
    • import, export 키워드로 모듈을 관리

NPM ( Node Package Manager )

  • 노드 패키지를 관리해주는 툴

npm 사용방법

npm init --yes // yes 옵션을 주면 package.json이 기본값으로 생성됨

package.json

  • 패키지들이 서로 의존되어 있어, 문제가 발생할 수 있는데 이를 관리하기 위해 필요한 것
  • 프로젝트에 대한 정보와 사용중인 패키지 이름 및 버전정보가 담겨있는 파일

• name: 패키지 이름

• version: 패키지의 버전

• main: 자바스크립트 실행 파일 진입점 ( 문답식에서의 entry point )

• description: 패키지에 대한 설명

• scripts: npm run 을 이용해 정해놓는 스크립트 명령어

• license: 해당 패키지의 라이센스

 


Express 모듈

 

템플릿 엔진

문법과 설정에 따라 파일을 html 형식으로 변환시키는 모듈

  • ex) ejs, pug, handler
  • 반복되는 코드를 줄일 수 있음
  • 재사용성이 높아짐
  • 유지보수 용이

ejs ( embaded javascript )

  • <% %> : js 코드
  • <%= %> : 변수 값을 출력
  • <%- include(ejs 파일경로, ejs 파일에 전달할 데이터 ) %> : ejs에서 또다른 ejs를 불러오는 구문
  • <%# %> : ejs 태그 주석

 


배열 구조 분해 할당 / 순서가 중요

// 구조분해 할당
// 1. 배열 구조 분해 할당
// 배열 구조 분해 할당시 "순서"가 중요하다

const arr1 = [1, 2, 3, 4, 5];
const arr2 = ['a', 'b', 'c'];

const [one, two, three, four, five] = arr1;
console.log(one, two, three, four, five);

const [에이, 비, 씨, alpha] = arr2;
console.log(에이, 비, 씨, alpha);

let num1 = 1;
let num2 = 2;
console.log('swap 전 >', num1, num2); // 1, 2
[num2, num1] = [num1, num2];
console.log('swap 후 >', num1, num2); // 2, 1

const lists = ['apple', 'grape'];
[f1, f2, f3] = lists;
console.log(f1, f2, f3); // 'apple', 'grape', 'undefined'

const lists2 = ['apple', 'grape'];
[f1, f2, f3 = 'orange'] = lists2;
console.log(f1, f2, f3); // 'apple', 'grape', 'orange'

객체 분해 구조 할당 / key값과 변수명이 같야아 한다

// 2. 객체 분해 구조 할당
// - 변수를 선언하는 순서는 중요하지 않다
// - 키 값과 변수명이 일치해야 함
const obj = {
    title: '오리엔탈',
    content: '재밌어요',
    num: 5,
};
// 객체 구조 분해를 사용하지 않았을 때
console.log(obj.title, obj.content, obj.num);
console.log(obj['title'], obj['content'], obj['num']);

// 객체 구조 분해를 사용하고 싶다면
// key가 존재하지 않을 때를 대비하여 = 연산자를 이용하면 default값을 할당
const { num, title, content, star = 1000 } = obj;
console.log(title, content, num, star); // '오리엔탈', '재밌어요', 5, 1000

const { n1, t1, c1 } = obj;
console.log(n1, t1, c1); // '오리엔탈', '재밌어요', 5

const { num: t2, num: n2, content: c2 } = obj;
console.log(t2, n2, c2); // '오리엔탈', '재밌어요', 5

 

spread, rest

// spread 연산자
// 반복 가능한 객체에 대해서 단일 요소로 압축을 해제하는 역할 (== 객체의 값을 펼침)
// spread in array
const a = [1, 2, 3];
const b = [4, 5];
const spread = [...a, ...b];
console.log(spread);

// spread in string
const c = [...'HEELO'];
const d = 'HEELO'.split('');
console.log(c);
console.log(d);

// spread in object
const chip = {
    base: 'chip',
    company: 'lotte',
};

const potatoChip = {
    ...chip,
    flavor: 'potato',
};

const sweetPotatoChip = {
    ...chip,
    // base: 'chip',
    // company: 'lotte',
    flavor: 'sweet potato',
};

console.log(chip);
console.log(potatoChip);
console.log(sweetPotatoChip);

const word1 = 'abc';
const word2 = 'xyz';

const word3 = [...word1, ...word2];
console.log(word3);

const values = [10, 20, 30];
function get(a, ...rest) {
    console.log('a >>', a);
    console.log('rest >>', rest);
}

get(...values);

// 객체에서 rest
const iceCream = {
    comapny: 'lotte',
    flavor: 'choco',
    price: 1000,
};

const { flavor, ...rest } = iceCream;
console.log(flavor);
console.log(rest);

// 배열에서 rest
const number = [1, 2, 3, 4, 5, 6, 7, 8];
const [one1, two1, ...rest2] = number;
console.log(one1);
console.log(two1);
console.log(rest2);

클래스

  • 객체 생성 템플릿 => 객체를 만들기 위해 사용
  • ES5 까지 자바스크립트에는 클래스가 없었지만 프로토타입 체이닝을 통해 클래스를 비스무리하게 구현했었다
    하지만 ES6  버전에 들어서 자바의 클래스와 비슷하게 구조 문법을 추가 하였다고 한다.

클래스 생성

ES5 프로토타입 문법

// 생성자
function Person({name, age}) {
   this.name = name;
   this.age = age;
}

Person.prototype.introduce = function() {
   return `안녕하세요, 제 이름은 ${this.name}입니다.`;
};

const person = new Person({name: '이재민', age: 29});
console.log(person.introduce()); // 안녕하세요, 제 이름은 이재민입니다.

ES6 클래스 문법

// 클래스
class Person {
   // 이전에서 사용하던 생성자 함수는 클래스 안에 `constructor`라는 이름으로 정의
   constructor({name, age}) { //생성자
     this.name = name;
     this.age = age;
   }
   // 객체에서 메소드를 정의할 때 사용하던 문법을 그대로 사용하면, 메소드가 자동으로 `Person.prototype`에 저장됩니다.
   introduce() {
     return `안녕하세요, 제 이름은 ${this.name}입니다.`;
   }
}

const person = new Person({name: '이재민', age: 29});
console.log(person.introduce()); // 안녕하세요, 제 이름은 이재민입니다.

두개의 코드에서 확실한 차이가 있다.

 

클래스 예제 ( 사각형의 넓이 구하기 )

class Shape {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }

    getArea() {
        return this.x * this.y;
    }
}
let rec1 = new Shape(3, 4);
console.log(`rec1의 넓이는 : ${rec1.getArea()}`);

클래스 상속

  • extends 라는 키워드를 이용해서 상속을 받을 수 있다.
  • 상속을 이용하면 부모 클래스의 속성과 메서드를 받아와서 ( override ) 자식 클래스에서 사용이 가능하다

클래스 이름 옆에 extends '부모클래스 이름' 을 선언하면 된다

클래스 상속 예제 

class Rectangle extends Shape {
    constructor(x, y) {
        super(x, y);
    }

    getArea() {
        return this.x * this.y;
    }

    getLength() {
        return Math.sqrt(this.getArea());
    }
}

let rec2 = new Rectangle(4, 5);
console.log(
    `rec2의 넓이 : ${rec2.getArea()} / rec2의 대각선 길이 ${rec2.getLength()}`
);

class Triangle extends Shape {
    constructor(x, y) {
        super(x, y);
    }
    getArea() {
        return (this.x * this.y) / 2;
    }
}

let tri1 = new Triangle(10, 5);
console.log(`삼각형 tr1의 넓이는 : ${tri1.getArea()}`);

class Circle extends Shape {
    constructor(x, y, r) {
        super(x, y);
        this.r = r;
    }

    getArea() {
        return Math.PI * this.r * this.r;
    }
}

let cir1 = new Circle(3, 3, 3);
console.log(`원의 넓이는 : ${cir1.getArea()}`);

이처럼 부모 클래스인 Shape 에서 상속받은 생성자와 getArea()를 이용해서 직사각형, 삼각형, 원에서 사용할 수 있는 것을 볼 수 있다

자바의 클래스와 같다고 보면 될 것 같다.


벌써 새싹을 시작한지 한달이 됐다고 한다. 아는 내용들이 많아서 아직 크게 어려운건 없지만 남아 있는 수업들 내용이 많기 때문에

소홀히 했던 복습을 좀 더 할 수 있도록 해야겠는 부분이다

 

오랜만에 자바문법을 사용해서 재밌었던 것 같은 .. 

 

반응형