본문 바로가기
  • soldonii's devlog
Javascript 공부/TIL

200106(월) : 비동기, 고차함수, 일급객체, V8 엔진 등

by soldonii 2020. 1. 7.

이번 주는 비동기 프로그래밍에 대해서 집중적으로 배워보는 한 주이다. 그런데 비동기에 대해서 배우고 실습하기 전에 우선적으로 고차함수, 일차함수와 일급 객체 등의 개념을 가르쳐주셨다. 그래서 이것이 비동기 프로그래밍과 어떤 연관이 있는 것인지 이해한 나름대로 정리해보고자 한다. 우선 이 개념들과 비동기의 연관성을 이해하기 위해서는 저 용어들이 무엇을 의미하는지부터 알아야 한다.

 

1. 일급 객체와 고차 함수

Stack Overflow의 한 글에서 아래와 같이 이야기하고 있다.

In short, it means there are no restrictions on the object's use. It's the same as any other object.
A first class object is an entity that can be dynamically created, destroyed, passed to a function, returned as a value, and have all the rights as other variables in the programming language have.

 

한 마디로, 객체의 사용성에 어떠한 제한이 없다는 의미이다. 세부적인 특징을 몇 개만 살펴보자면,

  • 객체를 자료 구조(Data Structure)에 담을 수 있다.
  • 객체를 함수의 매개변수(parameter)에 전달할 수 있다.
  • 함수에서 객체를 반환(return)할 수 있다.
  • 프로그램의 실행 중간에 생성될 수 있다.(dynamically created and destroyed)

 

비동기를 알기 전에 일급 객체를 배우는 이유는, 바로 자바스크립트에서는 함수도 일급 객체라는 사실 때문이다. 함수가 일급 객체라는 의미는, 위에 기술한 4가지의 특징을 객체 뿐만 아니라 함수도 가진다는 것이다. 특히 두번째, 세번째 특징을 보면 객체를 함수의 매개변수로 전달할 수 있고, 객체를 함수의 반환값으로 줄 수 있다고 되어있다. 따라서 자바스크립트에서는 1) 함수를 함수의 매개변수로 전달하는 것이 가능하고, 마찬가지로 2) 함수를 다른 함수의 반환값으로 줄 수 있다.

 

이처럼 함수를 매개변수로 받거나, 함수를 리턴시키는 함수를 고차 함수라고 부른다.(A higher order function is a function that takes a function as an arugment, or returns a function.)

 

결론적으로, 자바스크립트에서 함수가 일급 객체(First Class Object)이기 때문에 함수를 '고차 함수'로서 활용할 수 있으며, 이 '고차 함수'는 자바스크립트에서 비동기를 처리할 때 전달되는 인자인 콜백 함수로서 활용이 될 수 있다. Promise나 Async Await 등을 사용하지 않을 경우, 비동기를 처리하기 위해서는 콜백 함수를 활용해야 하기 때문에 '자바스크립트에서는 함수도 일급 객체'라는 개념에 대해서 살펴본 것으로 이해했다.

 

2. Asynchronous Programming

비동기 프로그래밍에 들어가기에 앞서, 왜 자바스크립트에서 비동기로 작업을 처리하는 것이 중요한지를 이해해야 한다. 그리고 이를 이해하기 위해서는 자바스크립트의 엔진 구조에 대해서 알아야 하기 때문에 간략하게 정리하고자 한다. 자세한 내용은 기존에 작성된 글을 참고하면 된다.

 

1) 자바스크립트 엔진과 싱글 쓰레드

자바스크립트 엔진은 브라우저마다 그 명칭이 조금씩 다르지만 구글의 크롬 브라우저에서 사용되는 V8 엔진을 기준으로 작성한다. 자바스크립트 엔진의 구조를 크게 두 덩이로 나누면 첫번쨰는 메모리 힙이고 두번째는 콜스택이다.

 

  • 메모리 힙(Memory Heap) : 메모리 할당이 일어나는 공간.
  • 콜 스택(Call Stack) : 함수가 실행되면서 호출되는 실행할 Stack Frame들이 쌓이는 공간.

 

여기서 자바스크립트는 싱글 쓰레드(Single Threaded)한 언어라는 특징을 알아야 한다. 싱글 쓰레드는 곧 콜 스택이 한 개만 존재한다는 것을 의미하는데, 따라서 자바스크립트는 언어의 특성 상 한 번에 단 하나의 작업만을 수행할 수 있다는 것을 의미한다. 무슨 일이 일어나도 자바스크립트에서는 한 번에 두 개의 일을 동시에 실행하는 것은 불가능하다.

 

그런데 만약 현재 수행해야 하는 작업이 매우 많은 시간이 걸리는 작업일 경우 어떻게 해야할까? 예를 들어 처리해야 하는 작업이 1시간이 걸린다고 했을 때, 자바스크립트에서는 이 작업을 처리하지 못하면 다음 일을 할 수 없고, 따라서 1시간 동안 브라우저는 계속 로딩상태에 머무르게 된다. 당연히 유저 경험은 바닥으로 떨어지게 된다. 따라서 이러한 한계를 극복하기 위해서 자바스크립트에서 비동기가 이렇게 중요하게 다뤄지는 것이다.

 

2) Web APIs, Event Loop, Callback Queue

자바스크립트에서의 비동기 처리에 대해서 이해하려면 자바스크립트가 싱글 쓰레드한 언어라는 점 외에도 자바스크립트 런타임에 대해서 알아야 한다. 이따금씩 코드를 작성하다보면 AJAX 요청을 보내거나, Event(ex. DOM 조작), Timing(ex. setTimeout, setInterval 등)의 코드를 작성할 때가 있는데, 이들은 사실 자바스크립트에 내장된 기능이 아니다. 자바스크립트는 단순한 프로그래밍 언어에 불과하며, 어떤 네트워크 요청 등을 할 능력을 가지고 있지는 않다.

 

# Web APIs

따라서 이러한 작업을 대신 처리해 줄 대상이 필요한데, 이것이 바로 Web API이며 Web API는 브라우저에 내장되어 있다. 작성한 코드 중 위와 같이 자바스크립트 엔진에서 내부적으로 처리가 불가능해 Web API로 요청을 보내면, Web API는 요청한 작업을 받아 순서대로 Callback Queue에게 전달한다.

 

# Callback Queue

콜백 큐(Callback Queue)는 Web API가 전달한 작업을 받아 들어온 순서대로 줄을 세운다. Callback Queue 외에도 Job Queue, Event Queue 등 다양한 종류의 작업에 대해서 각각 줄을 세우게 된다.

 

# Event Loop

이벤트 룹은 콜백 큐와 콜 스택을 주시하고 있는 녀석이다. 전체 프로세스를 관장하는 관리인 같은 느낌이다. 이벤트 룹은 콜 스택을 지켜보다가, 콜 스택이 비어있을 경우 콜백 큐에서 대기하고 있는 작업들을 하나씩 차례대로 콜 스택으로 보내서 실행되도록 하는 역할을 한다.

 

이 같은 방식으로 처리되는 것이 비동기인데, 비동기를 통해서 싱글 쓰레드로 인한 한계를 극복할 수 있게 된다. 예를 들어, 바로 실행되지 못하고 시간이 소요되는 작업의 경우(ex. 서버에 데이터를 요청한 후 받아오는 작업) 이를 Web API를 통해 콜백 큐로 보내버리고, 요청에 대한 응답을 받는 것이 완료됐을 때, 콜 스택이 비어있으면 그 곳으로 보내서 실행되게 하는 것이다. 그리고 네트워크 요청이 수행되는 동안에는 다른 작업이 동기적으로 실행되기 때문에 기존의 문제를 해결할 수 있다.

 

다만 비동기의 경우 a 작업을 요청하고 완료되면 b를, b가 완료되면 c가 수행되도록 연쇄적으로 수행되는 경우가 많은데, 이러할 경우 코드가 점점 안으로 들어가면서 소위 말하는 콜백 지옥(전문 용어로 continuation passing style)에 빠지기 쉽다. 이를 해결하기 위해서 최신 자바스크립트에서는 PromiseAsync Await 같은 개념들이 도입되었고, 이들을 활용하면 비동기적인 작업이지만 시각적으로 코드를 볼 때에는 동기적으로 보이도록 도와준다. 이에 대해서는 추후에 수업을 마친 후 추가로 정리하려고 한다.

댓글