[Javascript] 자바스크립트 언어의 특징과 이에 대한 사견

Seong-Am Kim
9 min readFeb 28, 2021
Photo by Danil Shostak on Unsplash

스타트업에서 일하면서 정말 많은 언어들을 접하고 배웠다. 그 중 자바스크립트는 정말 특이하다고 생각되는 언어중 하나였는데 이번에 좋은 영상을 보게 되어서 정리도 할겸 그 특징에 대해 적어보고자 한다.

자바스크립 언어의 특징

자바스크립트는 무엇인가? 자바스크립트를 한 문장으로 표현하면 아래와 같다.

JavaScript is a single-threaded, non-blocking, asynchronous, and concurrent language.

사실 이 문장에 모든 핵심이 다 담겨있다. 쉽게 풀어 이야기 하면 한번에 하나의 작업을 비동기적으로 막힘 없이 동시에 처리하는 언어란 것이다.

그럼 이게 어떻게 이루어지는 것일까? 지금 부터 그 과정을 살펴보자.

자바스크립트는 어떻게 동작하는가?

우선 자바스크립트는 싱글 스레드 언어라는 것이다. 이말은 한번에 하나의 작업밖에 하지 못한다는 말이다.

그런데 우리는 코딩을 할때 콜백을 쓰고 (그럼 이건 대체 어디에서 작업되고 호출이 되는건데?) 실제 웹을 구동 될때 보더라도 마치 멀티 스레드와 같이 동작한다.

지금부터 그 뒤편을 한번 살펴보자.

우선 핵심 키워드 중 하나는 Asnychronous (비동기)라는 것이다. 이것이 Non-blocking을 가능하게 하며 마치 자바스크립트가 여러 개의 작업을 동시에 하는 것처럼 보이도록 만드는 핵심 키워드이다.

(지금은 Async와 Await의 등장으로 좀 나아졌긴 하나 과거 콜백 지옥에 수많은 자바스크립트 개발자들을 빡치게 만드는 요인 중 하나이기도 했다.)

우선 Asynchronus(비동기)를 살펴보기 전에 Synchronous(동기) 적으로 자바스크립트가 동작할때 내부적으로 어떻게 동작하는지 살펴보도록 하자.

Synchronous(동기) 적으로 자바스크립트가 동작할 경우

우선 약간의 기본되는 자료 구조에 대한 선행지식이 필요한데 Stack만 알면 충분하다.

Stack은 Last in, First out으로 가장 나중에 들어온게 먼저 나가는 자료구조이다.

동기적으로 실행된다는 말은 이 Stack 이란 자료구조에 하나 하나씩 쌓여 순차적으로 하나씩 실행된다는 의미이다.

메모리에 다음 그림과 같이 쌓이는 것이다.

위에 그림에서 호출된 순서의 역순이 실행되어 Stack에서 빠져나가는 순서이다. 즉 가장 나중에 호출된게 먼저 실행되어 Stack에서 빠져나간다.

우리가 브라우져에서 오류 메세지를 볼때도 이 Stack을 기반으로 실행된 순서를 보여준다.

제일 아래가 먼저 호출된 순서로 마지막 multiply에서 에러가 발생했음을 보여준다.

이렇게 동기적으로 실행될때에는 한번에 한가지의 일을 하나씩 실행되면서 프로그램이 동작한다.

실제 자바스크립트는 싱글스레드로 한번의 하나의 일밖에 처리하지 못한다.

브라우저가 위와 같이 하나의 스레드로만 동기적으로 작동할 경우 다른 작업을 처리하기 위하여 화면을 랜더링 하는 과정에 멈춰 버리거나 특정 동작을 하는데 있어서 사용자는 엄청난 시간을 기다려야 할 것이다.

하지만 우리는 실제 위와 같은 현상을 겪지 않는다. 그러면 어떻게 그게 가능한 것일까?

Asynchronus(비동기) 적으로 자바스크립트가 동작할 경우

그 비밀은 비동기에 있다. 실제 시간이 오래 걸리는 작업에 대해 자바스크립트는 다른 곳에 본인이 할 일을 위임하고 위임 된 곳에 작업이 모두 끝나면 메인 스레드에 결과를 표시한다.

웹의 경우 이를 브라우져가 도와주는데 WebAPIs, Callback Queue, Event loop가 이를 가능하게 한다.

원래 싱글스레드로 동작한다면 이 지연 시간동안 프로그램은 아무것도 하지 못하는게 맞다. 하지만 브라우저에선 그렇게 작동하지 않으며 앞서 이야기 했듯이 위임을 하게 되는데 이 과정이 비동기적으로 작동을 한다.

우리는 비동기적으로 작동하는 대표적 함수인 setTimeout을 가지고 예를 살펴볼 것이다.

setTimeout뿐만 아니라 대체로 프로세스 처리에 오래 걸리는 작업들은 모두 비동기적으로 작동을 한다. (API 호출 처리, 파일 읽고 쓰기 등)

setTimeout 이란 함수는 알고 있듯이 첫번째 인자에 함수(콜백)를 넣어주게 되면 두번째 인자에 지정한 시간 만큼 뒤에 인자로 넣어준 함수가 실행이 된다.아래의 GIF는 이를 도식화 한것으로 과정을 설명 하면 아래와 같다.

대체로 프로세스 처리에 오래 걸리는 작업들은 모두 비동기적으로 작동을 한다. (API호출 처리, 파일 읽고 쓰기 등)

아래의 GIF는 이를 도식화 한것으로 과정을 설명 하면 아래와 같다.

아래 첨부 영상에도 해당 이미지와 같은 것들이 나오니 끊어 보고 싶으신 분들은 참고 바란다.
  1. setTimeout이 호출되면 이 처리과정을 WebAPIs 에게 위임한다.

2. WebAPIs 에선 이를 처리하고 시간이 모두 종료되면 callback Queue에 콜백함수를 밀어 넣는다.

3. Event Loop에선 Call Stack을 주시하다가 처리 할 수 있을때 Callback Queue에 대기중인 콜백 함수를 Call Stack으로 밀어 넣는다.

4. CallStack은 전달받은 콜백 함수를 실행한다.

Console 에서 볼 수 있듯이 Call Stack 에선 ‘Start’를 먼저 실행해서 출력하고 다음 setTimeout을 실행하지만 이는 비동기적으로 동작하기에 바로 WebAPIs 로 전달된다. 그리고 다음 ‘End’가 출력되고 이 후 다시 Callback Queue로 부터 전달 받은 ‘Hello world’를 출력하는 것이다.

글쓴이의 표현력이 미숙해 이 내용은 글로써 설명하는 것보다 영상으로 전달하는게 훨씬 더 효과적이라고 생각한다. 이해가 잘 안가시는 분은 글 가장 아래 영상을 참고하시면 좋을것 같다.

Callback Queue, Event loop의 필요성

그럼 이제 여기서 의문이 생긴다.

시간이 오래 걸리는 작업에 대해 WebAPIs가 처리하는건 알겠는데 그럼 그 이후 바로 Call Stack으로 넘겨주면 되지 않나? 왜 번거롭게 Callback Queue로 보냈다가 이를 Event loop를 통해 다시 Stack으로 밀어 넣는 작업을 하는걸까?

그 답변은 다음과 같다.

만약 지금은 단지 setTimeout함수 하나이지만 그 개수가 수십, 수백개라면? 그리고 Stack에서 지금 중요한 처리를 하고 있는 중이라면?

이를 처리하는데 있어 위와 같이 Callback Queue와 Event loop가 없으면 메인스레드는 중요하지 않은 문제들로 인해 지연과 병목이 발생할 가능성이 있다.

때문에 이를 해결하기 위해 Callback Queue와 Event loop가 절대적으로 필요한 것이다.

(Queue는 Stack 과는 다른 FIFO(First in, First out)인 자료구조이다.)

정리

결론적으로 자바스크립트만 본다면 싱글스레드 언어가 맞다.

하지만 언어가 가지고 있는 한계점을 브라우저나 Node는 다른 API를 통해 해결하고 있으며 이는 비동기적으로 처리되어 싱글 스레드임에도 불구하고 우리는 구현하는데 있어 불편함이 없이 사용자에게 제공할 수 있는 것이다.

다시 한번 처음 정의 했던 자바스크립트 언어에 대한 요약을 살펴보자.

JavaScript is a single-threaded, non-blocking, asynchronous, and concurrent language.

이제 이 문장이 이해가 가는가? 혹 이해 가지 않는 다면 이는 전적으로 글쓴이의 실력이 미숙해서 그러니 가장 아래 첨부된 영상을 보시길 추천한다.

왜 이렇게 자바스크립트는 인기가 많을까?

이 주제에 대해선 사견으로 참고 정도로만 봐주셨으면 한다.

자바스크립트는 웹뿐만 아니라 모바일 앱, 데스크톱 앱에서도 쓰일 만큼 다양한 분야에서 사용된다.

내가 가지던 의문 중 하나는 분명 자바스크립트보다 좋은 언어가 많은데 다른 언어보다 어떤 장점이 있길래 이렇게 인기가 많을까? 였다.

그 중 하나는 Node를 기반으로 형성된 커다란 생태계가 큰 몫을 차지한다고 생각한다. 개발자는 혼자 개발하지 않으며 개발하는 그 분야에서의 확장성과 편의성을 생각할 수 밖에 없다.

그 두번째의 요인이 오늘 알아본 특징과 맞물린 동시성에 대한 문제이다.

예측 가능한 프로그램이란 개발자의 의도에 맞게 동작하는 프로그램을 이야기 하며 우리는 이를 벗어났을때 버그가 발생했다고 이야기 한다.

많은 프로그램을 복잡하게 예상 불가능 하도록 만드는 중요한 요인 중 하나가 이 동시성에서 기반한다.

하지만 자바스크립트는 싱글스레드 언어로 한번에 하나의 일을 처리함으로써 이에 대한 복잡도를 확 낮추었다.

한번에 하나의 일을 처리함으로써 좀 더 예측 가능하고 버그가 발생했을때 이를 추적하기에도 용이하다.

즉, 위의 특징들이 자바스크립트란 언어의 제한점이자 동시에 장점이 될 수도 있다는 부분이다.

이 밖에도 자바스크립트가 인기를 얻은 이유야 많겠지만 위의 요소들이 그 중 하나가 되지 않았을까 하는게 개인적인 생각이다.

(아마 난 타입스크립트가 없었다면 자바스크립트와 관련된 개발하지 않았을것 같다. 타입이 달라도 오류가 나지 않는다니! 너무 너그럽다…. )

그동안의 언어의 발전과 더불어 생태계가 더 확대 되었기 때문에 이제는 안쓸 수가 없는 언어가 되어 버렸지만 자바스크립트란 언어가 가지는 특징으로 인해 여전히 잘 쓰기엔 어려운 언어인 듯 하다.

--

--