※ 이 포스팅은 스터디 강의 자료로 사용되었습니다.
2015년에는 자바스크립트 문법에 매우 큰 변화가 있었습니다. 바로 ES2015(ES6라고도 부릅니다.)가 등장한 것인데요. 이 기점을 기준으로 매년 문법 변경 사항을 발표하고 새로운 문법 상세에 대해서도 활발한 논의가 이루어지고 있습니다. 이전까지 포스팅에서는 ES5 문법을 이용해 예제들을 작성했습니다. 하지만 이제는 ES6를 배워둘 필요가 있다고 알려드리고 싶습니다. ES6에는 다른 언어들의 장점을 본뜬 편리한 기능들이 많이 추가되었기 때문입니다. 하지만 처음부터 ES6 문법으로 포스팅을 작성하지 않은 이유는 이전 포스팅에서는 문법보다는 보다 개념적인 것들을 이해하길 바랐고, 다양한 ES5를 알고 있어야 ES6 문법을 이해하기 쉽고 상황에 맞게 선택할 수 있기 때문입니다.
4-1. const, let
const와 let 같은 경우는 앞선 포스팅에서 잠깐 설명했었던 예약어 입니다. ES5까지는 모든 변수를 var라는 예약어로 선언 했었습니다. 하지만 ES6 문법부터는 더 이상 var를 사용하지 않고 const와 let만을 사용합니다. 먼저 const와 let의 공통점을 알아보도록 하겠습니다.
if (true) {
var x = 'var로 선언한 변수입니다.';
}
console.log(x); // (출력값) var로 선언한 변수입니다.
if (true) {
const y = 'const로 선언한 변수입니다.';
}
console.log(y); // (출력값) ReferenceError: y is not defined
위의 예시를 보면 x는 정상적으로 변수에 할당된 문자열을 출력하는데, y는 에러가 발생하는 것을 알 수 있습니다. 이러한 차이는 바로 블록 스코프에서 오는 차이입니다. var 같은 경우는 함수 스코프를 가지고 있기 때문에 if문의 블록과 관계없이 접근할 수 있습니다. 반면 const와 let은 블록 스코프를 가지기 때문에 블록 박에서는 해당 변수에 접근할 수 없습니다.
블록의 범위는 if, while, for, function 등의 중괄호입니다. 따라서 블록 스코프를 사용함으로써 이전 포스팅에서 발생했던 함수 호이스팅을 예방할 수 있습니다.
그렇다면 const와 let의 차이점은 무엇일까요?
const는 한번 값을 대입하면 다른 값을 다시 대입할 수 없습니다. 만약 다시 다른 값을 대입하려 한다면 에러가 발생하게 됩니다. 또한 초기화 시에 값을 대입하지 않으면 역시 에러가 발생하게 됩니다.
const a = 0;
a = 1; // Error 발생
let b = 0;
b = 1; // 1
const c; // Error 발생
굳이 const와 let을 나눠서 쓸 필요가 있나 싶을 수 있습니다. 모두 let으로 선언하면 실수로 const로 선언한 변수의 값을 바꿔서 에러가 발생할 일은 없을 테니까요. 하지만 의외로 자바스크립트에서는 한번 초기화한 값에 다른 값을 대입하는 경우가 매우 적습니다. 따라서 의미론적으로 기변적으로 변수 선언 시에는 const로 선언하고 다른 값을 대입해야 할 상황이 생겼을 때 let을 사용하는 것이 좋습니다.
4-2. 템플릿 문자열
앞선 포스팅에서는 큰 따옴표와 작은따옴표로 문자열을 나타내는 방법에 대해서 다뤘습니다. 그런데 ES6문법에는 새로운 문자열이 생겼는데 그것이 바로 템플릿 문자열입니다. 템플린 문자열은 기존 문자열과는 다르게 백틱(`)을 사용합니다. 백틱을 사용한 문자열은 특이하게 문자열 안에 변수를 넣을 수 있다는 특징이 있습니다. 아래의 예시를 통해 ES5 문자열에 중간에 변수를 넣는 것과 ES6의 백틱을 사용한 문자열의 차이를 보도록 하겠습니다.
// ES5
var num1 = 1;
var num2 = 2;
var result = 3;
var string1 = num1 + ' 더하기 ' + num2 + "는 \'" + result + "\'입니다.";
console.log(string1);
// ES6
const new1 = 1;
const new2 = 2;
const newResult = 3;
const string2 = `${num1} 더하기 ${num2}는 '${result}'입니다.`;
console.log(string2);
두 예시의 결괏값은 같지만 문법의 간결함은 확연한 차이를 보입니다. ES6 문법은 백틱 문자열 안에 ${변수} 형태로 삽입하기만 하면 되기 때문에 매번 변수와 문자열을 '+'로 이어 줄 필요도 없고 무엇보다 작은따옴표를 사용하기 위해 역 슬래쉬(\)를 사용하는 부분 역시 직관적으로 표현할 수 있게 되었습니다.
4-3. 객체 리터럴
객체 리터럴에도 몇 가지 편리한 기능들이 추가되었습니다. 먼저 ES5 문법으로 객체를 아래와 같이 생성해보도록 하겠습니다.
var hello = function() {
console.log('hello');
};
var mark = 'MARK';
var obj = {
inside: function() {
console.log('객체 안에 바로 함수를 선언');
},
hello: hello,
};
obj[mark + 1] = '아이언맨';
obj.inside(); // (출력값) 객체 안에 바로 함수를 선언
obj.hello(); // (출력값) hello
console.log(obj.MARK1); // (출력값) 아이언맨
obj안의 프로퍼티를 정리하자면 아래와 같습니다.
- inside : 객체 안에서 바로 익명 함수를 선언합니다.
- hello : 미리 생성되어 있는 함수를 프로퍼티로 넣어줍니다.
- MARK1 : 문자열과 숫자를 이용해 프로퍼티를 동적으로 생성해 줍니다.
위의 코드를 ES6로 고쳐보도록 하겠습니다.
const hello = function() {
console.log('hello');
};
const mark = 'MARK';
const obj = {
inside() {
console.log('객체 안에 바로 함수를 선언');
},
hello,
[mark + 1]: '아이언맨',
};
obj.inside(); // (출력값) 객체 안에 바로 함수를 선언
obj.hello(); // (출력값) hello
console.log(obj.MARK1); // (출력값) 아이언맨
여전히 같은 프로퍼티를 가진 객체이지만 훨씬 간결해진 것을 알 수 있습니다. inside 함수는 더 이상 콜론(:)이나 function을 붙이지 않아도 됩니다. 그리고 hello와 같이 함수명이 겹치는 경우에는 한 번만 쓸 수 있게 되었습니다. 또한 객체의 프로퍼티를 동적으로 생성하려면 객체 리터럴 바깥에서 [mark + 1]과 같이 선언했어야 했는데, ES6부터는 객체 안에서 바로 속성으로 사용할 수 있게 되었습니다.
4-4. 화살표 함수
ES6에는 화살표 함수라는 새로운 형태의 함수가 추가되었습니다. 이때까지의 예제는 모두 function() {} 형태로 다루었었는데, 화살표 함수를 사용하면 코드의 양을 확연히 줄일 수 있습니다.
const add1 = function(x, y) {
return x + y;
}
const add2 = (x, y) => {
return x + y;
};
const add3 = (x, y) => x + y;
const square = x => x ** 2;
add1, add2, add3은 모두 같은 로직을 수행하는 함수입니다. 사용하기에 따라서 중괄호를 생략할 수도 있고, 마지막 줄의 square 함수 같은 경우는 인자 역시 하나이기 때문에 소괄호 역시 생략할 수 있습니다. 이와 같이 화살표 함수는 코드 양을 줄이는 데에 많은 도움이 됩니다.
특별히 화살표 함수는 익명 함수로 사용할 때 코드 다이어트 효과를 많이 실감할 수 있습니다. 아래의 예시는 1.5초 후에 실행되는 함수를 function과 화살표 함수 두 가지 형태로 만들어보았습니다. setTimeout함수는 파라미터로 함숫값을 받을 수 있는데, 이때 화살표 함수는 불필요한 function이라는 예약어를 없앰으로써 코드를 훨씬 간결하게 만들었습니다.
const time1 = setTimeout(function() {
console.log('1.5초 후에 실행');
}, 1500);
const time2 = setTimeout(() => {
console.log('1.5초 후에 실행');
}, 1500);
분명 별 차이 없는데? 라고 느끼시는 분이 계실 수 있을 것 같습니다. :)
제가 좋아하는 생활코딩이라는 오픈 튜토리얼 사이트의 관리자이신 이고잉님이 강의에서 자주 하시는 말씀이 있습니다. 프로그래밍을 할 때는 극단적으로 예시를 들어보는 것이 도움이 된다고요.
지금 위에서 언급했던 사소한 차이들의 코드는 아마 이 포스팅의 예시만으로는 별로 와 닿지 않을 수 있습니다. 하지만 만약 위의 예시가 다섯 줄짜리 코드가 아니라 1억 줄짜리 코드라면 어떨까요?
아마 사소한 문법의 개선과 차이로 인해 전보다 훨씬 코드의 양과 가독성이 개선되었을 것입니다. :)
4-5. 비구조화 할당
비구조화 할당은 객체와 배열로부터 프로퍼티를 쉽게 꺼낼 수 있는 문법입니다.
let obj = {
name: '윤자이',
age: 26,
bag: {
item_1: '지갑',
item_2: '전공서적',
},
};
const name = obj.name;
const item1 = obj.bag.item1;
위의 코드는 객체의 프로퍼티를 같은 이름의 변수에 대입하는 코드입니다. 비구조화할당은 위의 코드를 아래와 같이 바꿀 수 있습니다.
let obj = {
name: '윤자이',
age: 26,
bag: {
item_1: '지갑',
item_2: '전공서적',
},
};
const { name, bag: { item_1 } } = obj
조금 헷갈릴 수 있지만 보이는 대로 해석해보면 어렵지 않은 코드입니다.
객체를 나타내는 중괄호를 열고, 그 안에 있는 프로퍼티들을 언급함으로써 간단하게 내용물을 꺼낼 수 있습니다.
이번에는 배열 안의 요소들을 비구조화 할당으로 꺼내보겠습니다.
const arr = ['string', {}, 1, true];
const [str, obj, , bool] = arr;
배열의 요소들은 순서대로 그 값들이 비구조화 할당이 됩니다. 따라서 str은 'string'가 obj에는 {}가 할당됩니다. 하지만 세 번째 요소는 비워둠으로써 할당하지 않았음을 알 수 있습니다.
비구조화 할당 문법 역시 코드 줄 수를 상당히 줄여주므로 유용합니다. 특히 모듈을 주로 사용하는 노드의 경우 이러한 문법을 매우 자주 사용합니다. 아래는 비구조화할당을 이용한 함수 선언 예시입니다.
let obj = {
name: '윤자이',
age: 26,
bag: {
item_1: '지갑',
item_2: '전공서적',
},
};
const test = ({ name, age, bag }) => {
console.log(`name: ${name}, age: ${age}, bag: ${bag}`);
};
test(obj);
코드를 보면 test함수로 obj를 인자로 넘기면 test 함수에서는 obj 함수의 인자를 비구조화 할당으로 받아서 따로 변수에 객체의 요소를 나눠야 하는 코드를 최소화할 수 있습니다.
마치며
지금까지 자바스크립트라는 언어의 특성에 대해 알아보았습니다. 첫 포스팅에서도 말씀드렸다시피 자바스크립트는 자유도가 굉장히 높은 언어입니다. 그래서 오히려 코딩을 할 때 어떤 방법을 사용해야 할지 헷갈리는 경우도 많고, 다른 사람과 협업할 때의 어려움 역시 발생합니다. 이러한 문제점 때문에 자바스크립트는 특히나 해결하기 위해 협업에 유리한 코드 스타일을 갖는 것이 중요하다고 말씀드리고 싶습니다. (JavaScript Standard 컨벤션과 Airbnb 컨벤션을 밑에 링크로 걸어 두었습니다.)
하지만 그럼에도 자바스크립트는 자유도가 강한 언어이기 때문에 최근에는 자바스크립트의 장점과 객체지향 언어의 장점을 결합한 타입스크립트가 상승세를 이루고 있습니다. 이러한 부분도 관심이 있으시면 찾아보시는 것도 도움이 되실 것 같습니다.
Javascript Standard Style Guide: https://standardjs.com/rules.html
Airbnb Javascript Style Guide: https://github.com/airbnb/javascript
한 가지 더 말씀드리고 싶은 점은 ES6 문법은 분명 강력하고 유용한 기능들을 많이 제공하지만 IE를 포함한 구형 브라우저에서는 지원하지 않습니다.
때문에 ES6 문법을 브라우저에서 사용하기 위해서는 트랜스파일러(Transpiler) Babel과 모듈 번들러(Module bundler) Webpack을 이용하여 개발환경을 구축할 필요가 있습니다.
이번 포스팅까지 대부분의 ES6 문법을 다루어 보았습니다. 하지만 아직 한 가지 빼둔 문법이 있습니다. 바로 promise, async/await 문법입니다. 프로미스 같은 경우엔 JavaScript 언어보단 비동기 개념과 Node.js에 대한 이해가 어느 정도 필요하기 때문에 굳이 이 포스팅과 구별하여 포스팅을 하려고 합니다. 다음 포스팅에서 뵙겠습니다. :)
'Language > Javascript (Typescript)' 카테고리의 다른 글
[Typescript] Typescript는 private을 js로 어떻게 구현할까? feat. 클로저 (4) | 2020.04.26 |
---|---|
[Javascript] Tutorial(5): 싱글 스레드 기반 이벤트 루프와 비동기 (0) | 2020.03.16 |
[Javascript] Tutorial(3): 1급 객체 함수 (0) | 2020.03.04 |
[Javascript] Tutorial(2): 자바스크립트 Object(객체) (0) | 2020.03.02 |
[Javascript] Tutorial(1): 자바스크립트 개요 (2) | 2020.03.01 |