var, let, const

JavaScript에는 상수/변수를 선언하는데 사용되는 명령어들이다!

var

제일 기본적으로 사용되었던 변수 선언 명령어

  1. 중복 선언이 가능하여, 중복 선언 시 마지막 값이 할당되게 된다

  2. 참조 유효 범위가 함수 단위 범위로 함수 내에서만 선언되었다면 함수의 어디에서든 사용가능하다!

  3. 호이스팅 된 값이 undefined로 선언되어, 같은 함수 내에서는 선언되기 전에도 참조가 가능하다..

let

ES6 의 등장으로 새로 등장한 변수 선언 명령어

  1. 중복 선언이 불가하다!

  2. 참조 유효 범위는 블록(“{}”)으로 블록 외부에선 참조가 불가하다!
    (따지면 var 보단 범위가 작은거죠!)

  3. 호이스팅 되어도 선언 이전에 참조를 할 수 없다!
    (이러한 구간을 TDZ(일시적 사각 지대/Temporal Dead Zone)라고 한다!)

const

ES6 의 등장으로 새로 등장한 상수 선언 명령어

  1. 중복 선언 및 재할당이 불가능하다!
    (상수자나 한잔해)

  2. 참조 유효 범위는 let과 마찬가지로 블록(“{}”)으로 블록 외부에선 참조가 불가하다!

  3. 호이스팅 되어도 선언 이전에 참조를 할 수 없다!

Promise

비동기 작업의 완료 또는 실패와 그에 따른 결과 값을 나타내는 객체로 비동기 작업을 마치 동기 작업처럼 만들어 주는데 사용한다!

Image

  • 동기: 작업들이 순서에 따라 실행되어 직렬적으로 진행되는 것

  • 비동기: 작업들이 각각 실행되어 순서없이 병렬적으로 진행되는 것

Promise의 상태

Promise는 작업의 완료 여부에 따라 3 가지의 상태를 가질 수 있다!

  1. Pending(대기)

    • 비동기 작업이 실행되지 않은 상태
  2. Fulfilled(성공)

    • 비동기 작업이 성공적으로 완료된 상태
  3. Rejected(거부)

    • 비동기 작업이 실행되었지만, 작업이 실패한 상태

사용 방법

기본적으로 Promise 객체를 생성하고 사용하는 방법이다!

// Promise 객체 선언 인자 값 (성공 , 실패) 를 통해 Promise의 실행 및 성공 여부를 결정함
const promise = new Promise((resolve, reject) => {})
promise
// then()는 Promise의 작업이 끝나고 그에 따라 콜백 함수를 실행시켜주는 메서드
// 첫 번째 인수는 프로미스의 이행된 경우에 대한 콜백 함수이고, 두 번째 인수는 거부된 경우에 대한 콜백 함수
.then(fulfilled,rejected)
// catch()는 then과 기능적으로 같으나, 받는 인수가 거부된 경우에 실행할 콜백 함수 밖에 없는 것이다!
.catch(rejected)
// finally()는 프로미스의 이행과 거부 여부에 상관없이 처리될 경우 항상 호출되어 콜백함수를 실행!
.finally()

추가로 사용할 수 있는 메서드들을 정리 해보았다!

// 주어진 모든 Promise가 이행되거나, 한 Promise가 거부될 때까지 대기하는 Promise 객체를 반환해줌!
// 이를 통해 비동기 작업들을 객체에 집어넣어 한번에 실행시켜줄 수 있음!
Promise.all(iterable(반복가능 객체))

// 위의 메서드에서 모두가 성공될 때에만 끝내도록 하는 놈이다!
Promise.allSettled(iterable(반복가능 객체))

// 주어진 Promise들 중 하나라도 성공하면 끝내는 놈!
Promise.any(iterable(반복가능 객체))

// 주어진 Promise들 중 하나라도 실행되면 끝내는 놈!
// 대신 얘는 끝난 Promise의 성공, 실패에 따라 값을 다르게 준다
Promise.race(iterable(반복가능 객체))

async/await

프로미스를 더욱 간결하고 직관적으로 사용할 수 있게 해주는 ES8의 비동기 처리 방법으로
async 를 함수 앞에 붙여 비동기 함수로 선언할 수 있으며, 이는 이벤트 루프를 통해 비동기적으로 작동한다!

async 함수에는 await식이 포함될 수 있고, 이 식은 async 함수의 실행을 일시 중지하고,
전달 된 Promise의 해결을 기다린 다음 async 함수의 실행을 다시 시작하고 완료후 값을 반환하도록 작동한다!

  • async 함수는 항상 promise를 반환하며, 만약 async 함수의 반환값이 명시적으로 promise가 아니라면 암묵적으로 promise로 감싸지게 된다.
// async / await 사용 
async function foo() {
  await 1;
}

// 위의 식은 아래와 같은 의미이다
function foo() {
  return Promise.resolve(1).then(() => undefined);
}
  • await은 최상위 레벨 코드 및 일반 함수에선 사용할 수 없다!

  • await은 thenable(then 사용가능) 객체를 받는다!
    (= 객체가 .then을 지원하면 이 객체를 await과 함께 사용할 수 있음 )

      class Thenable {
          constructor(num) {
              this.num = num;
          }
          then(resolve, reject) {
              console.log(resolve);
              // 1000밀리초 후에 이행됨(result는 this.num*2)
              setTimeout(() => resolve(this.num * 2), 1000); // (*)
          }
      };
    
      async function f() {
          // 1초 후, 변수 result는 2가 됨
          let result = await new Thenable(1);
          console.log(result);
      }
    
      f();
      // => 출력값 [Function (anonymous)] -> 1초 후 2
    

Hoisting

인터프리터(코드를 한 줄씩 읽어 내려가며 즉시 실행하는 프로그램)가 코드를 실행하기 전, 함수, 변수, 클래스 또는 임포트(import)의 선언문을 해당 범위의 맨 위로 끌어올리는 것처럼 보이는 현상을 말한다!

이로인해 함수, 변수, 클래스가 재정의 된 경우 마지막 값을 기준으로 코드가 실행되기에 조심하여야 한다!

function sum(a, b) {
    return a + b;
}

console.log(sum(5, 6))

function sum(a, b) {
    return a - b;
}

이 경우 원했던 값인 11이 아닌, -1 이 나온다!

Arrow Function

ES6 문법 이후부터 생겨난 함수를 만들 수 있는 문법!


// 이게 일반적인 함수 선언
function sum (a,b) {
    return a + b;
}

// 이게 바로 화살표 함수(Arrow Function)
const sum = (a,b) => {return a + b};
  • 화살표 함수는 인자가 1개일 경우에 “()” 를 생략가능하고 함수 로직이 한 문법으로 끝나면 “{}”도 생략이 가능하다!
const square = a => a**2; 
  • 제일 큰 장점으로는 바로 콜백 함수로 불릴 때 this가 부른 객체의 문맥을 계승한다는 것이다!
const clock1 = {
  time: '12:05',
  whatTime: () => console.log(`Current time is ${this.time}`)
};

const clock2 = {
  time: '12:20',
  whatTime: function()  {
    console.log(`Current time is ${this.time}`)
  }
};

// 이 경우 this는 clock.whatTime을 부른 전역객체를 this로 계승하므로 this.time은 undefined가 뜨게된다!
clock1.whatTime(); // Current time is undefined​

// 이 경우에는 this가 clock2 이므로 제대로된 시간이 나온다!
clock2.whatTime(); // Current time is 12:20

Express

Node.js의 프레임워크로 Node.js의 API를 단순화하고, 유용한 기능을 추가해 쉽게 서버를 구축할 수 있게 해준다!

Express 설치

패키지 매니저를 이용해 설치해준다!

# 기본 노드 패키지 매니저 npm
npm install express
# yarn 패키지 매니저
yarn add express

Express 사용

// ./server.js 파일
import Router from './routes/router.js';
import express from 'express';
 
const app = express();
// 포트 번호 지정
const PORT = 3000;
 
// Express에서 req.body에 접근하여, body 데이터를 사용할 수 있도록 설정해주는 미들웨어 2 line
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
 
// 미들웨어인 [Router]를 기본주소 + /api 로 연결 시 실행하도록 연결
app.use('/api'. [Router]);
 
// 기본주소인 localhost:3000 로 서버 오픈
app.listen(PORT)
 
//--------------------------------------------------------------//
 
// ./routes/router.js 파일
import express from 'express';
 
// Express.js의 라우터를 생성
const router = express.Router();
 
router.get('/', (req, res) => {
  return res.json('default url for router.js GET Method');
});
// => localhost:3000/api/ 에 get 요청 시, res(클라이언트에게 응답으로).json(json 형태인)
// 'default url for router.js GET Method' 출력
 
router.get('/about', (req, res) => {
  return res.json('router.js about PATH');
});
// => localhost:3000/api/about 에 get 요청 시, res(클라이언트에게 응답으로).json(json 형태인)
// 'router.js about PATH' 출력
 
router.post('/goods', (req, res) => {
    //입력받은 값(req) 에서 값을 가져와 할당하기
    const name = req.body.name;
    const thumbnailUrl = req.body.thumbnailUrl;
    const category = req.body.category;
    const price = req.body.price;
    // 현재 goodsId의 가장 큰 값 + 1
    const goodsId = goods[goods.length - 1].goodsId + 1; 
    // 할당된 값들로 객체 생성
    const goodsItem = {
    goodsId: goodsId,
    name: name,
    thumbnailUrl: thumbnailUrl,
    category: category,
    price: price,
    };
 
    //goods 라는 배열에 goodsItem 객체 추가 (goods는 맥락상 생략된 객체 배열임)
    goods.push(goodsItem);
 
    return res //클라이언트에게
        .status(201) // 수신양호 200 + 생성완료 1 상태를 보내고
        .json({ goods: goodsItem }); //json 형태로 입력한 값으로 만든 객체를 보낸다 
});
 
// router 보내주기
export default router