자바스크립트에서 작성하는 대부분의 코드는 동기(synchronous) 코드이다. 동기 코드는 라인 순서대로(line by line) 실행된다. 아래의 코드를 보자.
const p = document.querySelector('.p'); // 1번
p.textContent = 'My name is Jonas!'; // 2번
alert('Text set!'); // 3번
p.style.colro = 'red'; // 4번
동기(Synchronous) 코드의 문제점
코드가 '1번'라인에 도달하면 '실행 스레드(Thread of execution)'가 동작하며 코드가 실행된다. '실행 스레드'는 실행 컨텍스트의 일부로 컴퓨터 CPU에서 코드를 실질적으로 실행한다. 이 '실행 스레드'에서 '2번', '3번', '4번' 라인이 연속적으로 실행된다. 이때 각각의 코드 라인은 이전 라인의 실행이 끝날때까지 기다린다. (Each line of code waits for previous line to finish) 따라서 코드 한 줄이 실행되는데 작업이 오래 걸리면 문제가 발생할 수 있다. 예를들어, '3번' 라인처럼 alert 경고문이 있다고 가정하자. alert는 '확인' 버튼을 누르기 전까지는 코드의 실행을 차단한다. 즉, 오래 걸리는 동작(Long-running operations)이 코드의 실행을 멈춘(block)다는 사실을 알고 있어야 한다.
대부분의 경우 동기 코드 동작 방식이 문제가 되지 않는다. 하지만, 다음 코드를 실행하기 위해서는 기다려야 한다. '오래걸리는 동작', '5초 동안의 타이머', 'alert' 등의 이유로 코드의 실행을 대기하는 동안 어떠한 코드도 실행되지 않을 것이다. 앞의 코드가 완료되지 않더라고 다음 코드를 실행할 수 있는 방법은 없을까? 이를 위해 비동기(asynchronous) 방식이 탄생했다.
비동기(asynchronous) 코드의 개념
const p = document.querySelector('.p'); // 1번
setTimeout(function () { // 2번
p.textContent = 'My name is Jonas!';
}, 5000)
p.style.color = 'red'; // 3번
상기 코드를 분석해보자. 첫 줄은 여전히 동기 코드로 동작한다. 두번째 코드 동기화 방식으로 동작한다. 하지만, setTimeout 함수는 비동기 방식으로 타이머를 시작한다. 이는 메인 코드가 실행되는 것을 막지 않고, 백그라운드(Background)에서 타이머(Timer)가 실행된다는 것을 의미한다. 이때 setTimeout의 콜백 함수는 바로 실행되지 않고 타이머(Timer)가 Background에서 완료되면 실행된다. 이 경우 콜백 함수는 비동기(asynchronous) 코드이다. 왜냐하면 비동기 코드란 "background" 작업이 완료되었을 때 실행되는 코드이기 때문이다.
Asynchronous code is executed after a task that runs in the "background" finishes
다시 정리하면, 비동기(asynchronous) 코드는 메인 코드의 실행을 차단하지 않는다. (Asynchronous code is non-blocking) 또한, 메인 코드의 실행은 비동기 코드가 완료될 때까지 기다리지 않는다. 결국 setTimeout의 비동기 콜백 함수는 다른 모든 코드가 실행되고 나서 실행된다.
상기 그림의 노란색 박스가 setTimeout으로 비동기 코드가 실행된 부분이다. 다른 코드가 먼저 실행되고 마지막에 실행된 것을 확인할 수 있다. 비동기 단어 그대로의 해석인 동시에 발생하지 않는다는 뜻과 마찬가지로 결국, 비동기(asynchronous)란 일정 시간 동안 프로그램의 행동을 조정하는 것이다. (Coordinating behavior of a program over a period of time)
상기 예시에서 비동기(asynchronous) 코드를 구현하기 위해 콜백 함수가 필요하다는 것을 알 수 있다. 많은 사람들이 오해하는 것이 콜백 함수 혼자서 코드를 비동기로 만들 수 없다는 것이다. (Callback functions alone do not make code asynchronous) 예를 들어, map 메소드도 콜백 함수를 받아들이지만 코드를 비동기로 만들지 않는다. setTimeout 같은 특정 함수만이 비동기로 동작한다.
이미지 로딩과 이벤트의 비동기(asynchronous) 코드
const img = document.querySelector('.dog'); // 1번
img.src = 'dog.jpg'; // 2번
img.addEventListener('load', function () { // 3번
img.classList.add('fadeIn');
});
p.style.width = '300px'; // 4번
'1번', '2번' 코드가 동기(synchronous) 방식으로 동일하게 실행된다. '2번' 라인에서는 '1번' 라인에서 선택한 이미지의 src의 속성(attribute)을 설정하며, 이 작업은 비동기로 동작한다. 즉, 어떠한 이미지 src 속성(attribute) 설정은 Background에서 이미지를 로딩하는 방식으로 동작하는 것이다.
만약, 이미지의 용량이 크다고 가정해보자. 전체 코드가 이미지가 로딩될 때까지 멈추는 것은 비효율적이다. 따라서 JavaScript에서는 이미지 src 속성(attribute) 설정을 Background에 등록하는 비동기 방식으로 구현했다. Background에서 이미지 로딩을 마치면 'load' 이벤트(event)가 Javascript로 인해 자동으로 출력(emit)된다. '3번' 라인은 그러한 'load' 이벤트에 반응하기 위한 코드이며, 이미지 로딩 이벤트가 출력(emit)될 때 실행하기 위한 콜백 함수를 등록한다. 이 콜백 함수는 최종적으로 아래의 노란색 박스와 같이 마지막에 실행된다.
여기서 중요한 사실은 이벤트 리스너(Event Listener)만으로는 코드를 비동기로 만들지 않는다는 것이다. 예를 들어, 버튼을 클릭하는 이벤트 리스너는 Background에서 아무 일도 하지 않는다. 클릭이 일어나길 기다리지만 아무것도 하지 않으며 어떠한 비동기적인 행동은 존재하지 않는다. 상기의 코드 예제를 비동기로 만드는 것은 이미지가 Background에서 비동기로 로딩된다는 것이다. Timer 또는 이미지 로딩과 같은 비동기 작업(Task)이 존재하지 않으면 이벤트 리스너만으로는 비동기 코드가 아니다. 자바스크립트에서 이미지 로딩, 타이머 이외의 비동기 작업은 'Geolocation API'와 'AJAX calls'이 있다.
AJAX CALLS
Asynchronous JavaScript And XML: Allows us to communicate with remote web servers in asynchronous way. With AJAX calls, we can request data from web servers dynamically
AJAX의 가장 큰 장점은 페이지를 다시 로드하지 않고, 웹 서버의 데이터를 동적으로 사용할 수 있다는 것이다. AJAX가 어떻게 동작하는지 알아보기 위해 브라우저에서 클라이언트(Client)라고도 불리는 JavaScript 어플이 실행 중이라고 가정해보자. 클라이언트는 웹 서버에 있는 국가에 대한 데이터를 가져오고 싶어한다. 이때 클라이언트는 AJAX로 서버에 HTTP 요청을 할 수 있다. 그럼 서버는 클라이언트가 요청한 데이터를 포함하는 응답을 해준다.
클라이언트와 서버간의 상호작용은 Background에서 비동기(asynchronous)로 일어난다. GET, POST 등과 같은 다양한 유형의 요청이 있을 수 있다. 서버에 데이터 요청을 했을 때 일반적으로 서버는 Web API를 가지고 있다. 우리가 요청하는 데이터는 이 API에 들어가 있다. 그렇다면 API란 무엇인가?
Application Programming Interface: Piece of software that can be used by another piece of software, in order to allow applications to talk to each other
웹 개발에는 DOM API, Geolocation API, Own Class API, Online API와 같은 정말 많은 종류(types)의 API들이 존재한다. 여기서 Onlinde API는 웹 서버에서 실행되는 응용 프로그램으로 데이터 요청을 받고 데이터베이스에서 데이터를 검색해 클라이언트로 보낸다. (Online API : Application running on a server, that receives requests for data, and sends data back as response) 온라인 API는 많은 사람들이 그냥 API라고 부르는 개념이다. 온라인 API는 백엔드 개발을 통해 만들 수 있다. 또는 3rd-party API를 사용하면 된다.
앞서 AJAX의 개념을 정의할 때 'X'의 뜻이 'XML'의 약자라는 것을 확인했다. 하지만, 최근 웹 개발 환경에서는 XML 데이터를 사용하는 API가 존재하지 않는다. 대부분의 API는 'JSON' 데이터 포맷을 사용한다. JSON은 JavaScript 객체를 String로 변환한 데이터이다.
'Javascript' 카테고리의 다른 글
[JavaScript] 클로저(Closures) - 개념편 (0) | 2024.01.02 |
---|---|
[JavaScript] 비동기 코드의 동작 원리 - 이벤트 루프(The Event Loop) (2) | 2023.12.29 |
[JavaScript] 프로미스(Promise) Consume - rejected 처리 방법 (0) | 2023.11.27 |
[JavaScript] 프로미스(Promise) Consume - fulfilled 처리 방법 (0) | 2023.11.25 |
[JavaScript] 프로미스(Promise)란 - 개념편 (0) | 2023.11.12 |