
순서대로 하나씩 진행. 위에서 아래로


이번엔 작업 2의 도출을 함수로 진행.

같은 결과 도출.
브라우저는 자바스크립트 코드를 실행시키기 전에 함수나 변수 같은 선언문들을 코드 최상단으로 올려버림. -> 호이스팅

호이스팅되면 이렇게 바뀜. 그리고 브라우저는 코드를 위에서부터 아래로 차례대로 읽기 시작.
자바스크립트는 기본적으로는 동기적으로 실행됨!
내가 작성한 자바스크립트 코드는 브라우저 안에 있는 자바스크립트 엔진에 의해 실행된다. 크롬 브라우저의 경우 'V8'이라는 자바스크립트 엔진이 내장되어 있다. 자바스크립트가 기본적으로 동기적인 이유는, 코드를 실행시켜주는 자바스크립트 엔진이 한 번에 한 가지 일만 할 수 있기 때문에 동기적으로 수행되는 것이다.
자바스크립트는 싱글스레드 언어이다.
싱글스레드는 한 번에 한 가지 일만 할 수 있다! 자바스크립트 엔진은 한 번에 한 가지 일만 할 수 있는 싱글스레드이기 때문에, 내가 작성한 코드는 한 번에 한 줄씩 동기적으로 작동함. 그렇기에 직관적인 동기 프로그래밍이지만 오래 걸리는 작업을 할 때는 '똥기 프로그래밍'이 되기도 함. 오래 걸리는 작업을 동기로 처리하게 되면, 'blocking'이라는 현상이 발생한다. 동기적으로 수행하니까 하나의 작업이 끝날 때까지는 다음 작업을 절대 시작할 수 없다. 그렇기에 오래 걸리는 작업을 하게 되면 블로킹 현상이 발생한다.
작업 1은 네트워크 상으로 서버로부터 데이터를 받아오는 일을 한다고 가정해보자. 이런 네트워크 통신은 시간이 좀 걸리기 때문에 이 작업이 진행되는 동안 나머지 작업은 블로킹 상태에 있게 됨. 작업 1이 다 끝나면 작업 2가 시작. 그래서 동기 프로그래밍은 이러한 문제점이 존재한다. 이것을 해결하기 위한 '비동기 프로그래밍.'
비동기 프로그래밍은 코드를 비동기적으로 수행하는 방식이다. 이는 해당 작업이 끝날 때까지 기다리지 않고, 바로 다음 작업으로 넘어가게 된다. 오래 걸리는 작업 1을 동기가 아니라 비동기로 수행하면, 작업 1을 일단 시작한다. 그리고 바로 다음 작업 2로 넘어감. 작업 1이 수행되는 동안 작업 2도 진행된다. 나머지 작업들이 블로킹 현상 없이 차례대로 처리된다! 오래 걸리는 작업 1이 끝나면 콜백 함수를 호출한다든지 필요한 처리를 해주면 됨.

setTimeout은 브라우저가 제공하는 비동기 함수임. 비동기 함수란 비동기적으로 동작하는 함수겠죠. setTimeout은 두 개의 인자를 받을 수 있다! 첫 번째 인자는 '콜백 함수', 두 번째 인자는 지연 시간을 나타내는 밀리세컨 단위의 숫자를 전달 받음. 위 코드와 같이 setTimeout 함수를 호출하면, 첫 번째 인자로 전달해준 콜백 함수가 3초 뒤에 실행된다. 
1이 먼저 출력되고 3초 뒤에 2가 출력됨.


앞서 봤던 코드와 동일한 결과! 분명 코드상으로는 2가 먼저 출력될 것 같음. setTimeout이 비동기적으로 수행되는 비동기 함수이기 때문. setTimeout은 다음 작업인 console.log('1')이 실행되는 것을 블로킹하지 않았다는 뜻. setTimeout이 3초 동안 돌아갈 때, console.log('1')이 수행되었기 때문.
근데 여기서 의문이 듦.
근데 어떻게 비동기 작업을 하는 것일까.
여러 가지 일을 동시에 할 수 있었던 것은 'Web API' 덕분. 브라우저는 생각보다 많은 기능을 제공해줌. 브라우저 내부를 살펴보면, 브라우저 엔진만 존재하는 것이 아니라 'web API'도 있음. 'API'는 자바스크립트 언어 자체와는 별개로 다양한 API(setTimeout, fetch, DOM...)를 제공해준다. 웹 API는 자바스크립트 엔진이 아닌 별도의 브라우저 환경에서 실행된다. 이 환경은 여러 가지 일을 동시에 할 수 있는 멀티스레드환경임. setTimeout은 웹 API이므로 멀티스레드인 웹 API 환경에서 동작한다. 그래서 내가 setTimeout의 타이머를 돌리는 동시에 다른 작업을 수행할 수 있었던 것임. 

시작, 1이 출력되고 3초 후 2가 출력됨.
자바스크립트 엔진은 위에서부터 코드를 동기적으로 실행시킴. 첫 줄이 실행되면서 출력, setTimeout을 만나게 됨. 이는 웹 API라서 setTimeout이 호출되면 웹 API 환경에서 타이머가 돌아가기 시작. 인자로 전달해준 콜백 함수도 웹 API에게 던져짐. setTimeout 호출 자체는 끝났으니까 자바스크립트 엔진은 console.log('1')을 실행시킴. 시간이 지나고 웹 API 환경의 타이머가 완료되면, 자바스크립트 엔진이 전달해준 콜백 함수를 전달 받아 실행시킨다. 그래서 2 출력.