var, let, const
JavaScript에는 상수/변수를 선언하는데 사용되는 명령어들이다!
var
제일 기본적으로 사용되었던 변수 선언 명령어
-
중복 선언이 가능하여, 중복 선언 시 마지막 값이 할당되게 된다
-
참조 유효 범위가 함수 단위 범위로 함수 내에서만 선언되었다면 함수의 어디에서든 사용가능하다!
-
호이스팅 된 값이 undefined로 선언되어, 같은 함수 내에서는 선언되기 전에도 참조가 가능하다..
let
ES6 의 등장으로 새로 등장한 변수 선언 명령어
-
중복 선언이 불가하다!
-
참조 유효 범위는 블록(“{}”)으로 블록 외부에선 참조가 불가하다!
(따지면 var 보단 범위가 작은거죠!) -
호이스팅 되어도 선언 이전에 참조를 할 수 없다!
(이러한 구간을 TDZ(일시적 사각 지대/Temporal Dead Zone)라고 한다!)
const
ES6 의 등장으로 새로 등장한 상수 선언 명령어
-
중복 선언 및 재할당이 불가능하다!
(상수자나 한잔해) -
참조 유효 범위는 let과 마찬가지로 블록(“{}”)으로 블록 외부에선 참조가 불가하다!
-
호이스팅 되어도 선언 이전에 참조를 할 수 없다!
Promise
비동기 작업의 완료 또는 실패와 그에 따른 결과 값을 나타내는 객체로 비동기 작업을 마치 동기 작업처럼 만들어 주는데 사용한다!
-
동기: 작업들이 순서에 따라 실행되어 직렬적으로 진행되는 것
-
비동기: 작업들이 각각 실행되어 순서없이 병렬적으로 진행되는 것
Promise의 상태
Promise는 작업의 완료 여부에 따라 3 가지의 상태를 가질 수 있다!
-
Pending(대기)
- 비동기 작업이 실행되지 않은 상태
-
Fulfilled(성공)
- 비동기 작업이 성공적으로 완료된 상태
-
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