보통 이렇게, 신입에게 원하는 자격 요건에 '비동기 프로그래밍, 클로저, ES6' 지식이 들어있다. 실제 면접에서도, 화이트보드 코딩 시험으로 클로저 함수를 주고, 바르게 동작하려면 어떻게 코드를 손봐야하는지 시험을 봤다. 특히나 비동기나 클로저는 개념과 실제 코드를 연결짓기 힘든데, 그 점에 유의해서 항상 내가 비동기를 어떻게 제어하고 있는지 돌아보며 코드를 작성하자.
js 인터프리터가 함수의 선언, 할당, 실행을 나누었으나 선언이 코드의 최선두로 끌어올려진 것처럼 동작하는 현상.
코드 상단에서 var 변수를 선언하고 하단에서 a=1;라고 하였다면 상단에서 참조 에러 대신 undefined를 console을 찍게 된다.
let 변수는 선언과 할당을 별도로 실행한다. 따라서 호이스팅 되더라도 할당되지 않아 메모리에 변수가 선언되지 않으며 호출 시 reference 에러가 발생한다.
전역적으로 선언 되어 함수 밖에서 변수가 호이스팅 되도록 허용한다. 즉, 변수가 선언 되기 전에 전역 스코프에서 참조될 수 있다. 재선언도 가능하다.
블록 스코프로 선언되어 변수가 선언 되기 전에나 정의된 블록 외부에서 해당 변수를 참조할 수 없다. 재선언할 수 없다. 값의 변경은 가능하다.
블록 스코프로 선언되어 변수가 선언 되기 전이나 정의된 블록 외부에서 참조할 수 없다. 값을 재할당하거나 재선언할 수 없다.
성장하기 위해 공부하자!
모든 js 객체는 다른 객체에 대한 “참조”인 __proto__
프로퍼티를 가지고 있다. 생성자 함수가 생성할 모든 인스턴스가 공통적으로 사용할 프로퍼티나 메소드를 프로토타입에 미리 구현해 놓음으로써 자산을 공유하여 사용할 수 있다.
비동기 통신이 등장하게 된 배경은, MPA 환경에서 SPA환경으로 프론트엔드와 백엔드가 분리되며 동적인 브라우저 렌더링이 발전했기 때문이다.
가장 처음 등장한 서버와 브라우저가 비동기적으로 데이터를 교환하는 통신
동적 웹 어플리케이션을 만들 수 있어 페이지 일부만 렌더링도 가능하다. 즉, 필요한 부분의 리소스만 로드하여 갱신하므로 빠르고 부드러운 화면 효과로 사용자 경험 증대
프로미스와 콜백 모두 js에서 비동기 처리를 위해 사용하는 패턴이다.
콜백의 경우 함수 처리 순서를 보장하기 위해, 중첩의 중첩이 쌓이는 ‘콜백헬’이 발생하는 단점과 에러 처리가 어려운 단점이 있습니다.
이 문제를 해결하기 위해 ES6부터 Promise를 도입했습니다.
Promise는 생성자 함수를 통해 인스턴스화 하며, 작업 수행 성공 시 resolve 메소드를 호출해 비동기 처리 결과를 후속 처리 메소드로 리턴한다.
비동기 작업 실패시 reject 메소드를 호출해 후속처리 메소드로 전달한다.
여기서 후속처리 메소드는 then
과 catch
가 있으며 두 메소드 모두 Promise 객체를 반환한다. Promise의 then의 메소드 체이닝을 통해 콜백헬 문제를 해결할 수 있다.
async와 await는 Promise를 더욱 쉽게 사용하기 위한 ES2017(ES8) 문법입니다.
async
키워드는 function에 붙여 비동기적인 동작을 하도록 합니다. 이 키워드가 붙은 함수는 항상 Promise 객체를 반환합니다.
await
키워드는 Promise 객체의 앞에 붙여 처리를 기다립니다.
두 키워드를 사용하면 코드가 간결해집니다. 하지만 에러처리를 위해선 try catch를 사용해야합니다. 또한 이 두 키워드를 이용해 동기적 코드 제어가 가능합니다.
async와 await을 사용해 Promise.then을 단축할 수 있습니다. 비동기 제어를 원하는 함수를 async 키워드로 정의하고, 내부에서 await을 사용합니다.
클로저란 내부 함수가 외부로 반환된 이후에도 Life-cycle을 유지하는 것이라고 합니다. 주로, 클로저 안에 정의된 함수는 만들어진 환경을 기억한다고 표현합니다.
클로저를 이용해 class 선언 없이 자바나 다른 언어들에서 쓰이는 private
키워드를 흉내낼 수 있습니다. 그럼, 클로저를 언제, 어떻게 이용하는지 간단히 살펴보겠습니다.
javascript private 프로퍼티는 js class와 함께 실제 스펙에 추가된지 얼마 안 된 문법이라고 합니다. 따라서, 근본적으로 js에선 '_' 키워드를 써서 private으로 취급한다는 컨벤션을 쓰기도 했었습니다. 하지만 이는 필드에 컨벤션을 썼을 뿐 실제로는 public으로 작동하는 문제점이 있었습니다.
따라서 제안된 방법이 클로저를 사용한 캡슐화와 은닉화였습니다. 클로저는 어떤 환경과 그 환경을 조작하는 함수를 연관시켜 주고, 객체지향 프로그래밍과 같은 맥락에서 사용할 수 있습니다.
클로저를 사용하면 그 특성에 따라 스코프 접근을 제안할 수 있습니다.
예시로, count 변수를 숨기며 값을 제어할 수 있도록 만들 수 있습니다.
function counter(){
let count = 0;
return {
add: function() {
count++;
console.log(count);
}
}
}
const countHandler = counter();
countHandler.add(); // 1
countHandler.add(); // 2
함수형 프로그래밍의 목적 중 하나는, "사이드 이펙트를 최대한 일으키지 않는다"
모든 클로저에는 세가지 스코프(체인)이 있다고 합니다.
- 지역 범위 (Local scope)
- 전역 범위 (Global scope)
- 포함하는 범위 (Enclosing scope) : 블록 함수 또는 모듈 범위
참고
Simple js
mdn web docs/closure
은닉을 향한 자바스크립트의 여정
클로저, 그리고 캡슐화와 은닉화