난 자바개발자라 그냥 이슈 수정하는 정도만 알면되지 했다가 얼마전 딥한 이슈를 수정하다가
많은 문제들을 마주쳐서 정리 해봤다.
JavaScript 는 싱글스레드다. 한번에 하나씩만 작업을 처리하게 되어있다!
자바스크립트는 내부는 어떻게 동작 할까?
single-thread의 문제에 대한 솔루션으로 자바스크립트는 비동기 처리를 하는데 이 비동기 처리를 위한
자바스크립트의 구조를 알아보자.
WEB (Browser) APIs
**Web(Browser) API**란 브라우저가 우리에게 제공해주는 기능들을 자바스크립트 코드로 사용할 수 있도록 해주는 인터페이스이다.
Callback Queue
Callback Queue 혹은 **Task Queue**는 일종의 자료구조로서 특정 때가 되면 실행 될 콜백 함수들이 자기 차례를 기다리며
서있는 공간이다. js engine 에 해당되고 브라우져 스펙이 아니다.
console.log("Hi!");
setTimeout(function timeout() {
console.log("Click the button!");
}, 5000);
console.log("Welcome to loupe.");
- call stack 에 console.log("Hi!"); 가 들어온다
- call stack 에 setTimeout이 들어온다.
- web apis 에 timeout()이 5초로 돌아간다.
- stack 에 console.log("Welcome to loupe."); 가 들어온다
- timeout이 끝나면 callback queue로 timeout()이 옮겨진다.
- callback queue에서 call stack으로 옮겨가서 console 동작을 수행한다.
setTimeOut은 위와 같은 과정으로 동작하게 된다.
이를 이벤트 루프라고 하는데, 태스크가 들어오길 기다렸다가 태스크가 들어오면 이를 처리하고,
처리할 태스크가 없는 경우엔 잠드는, 끊임없이 돌아가는 위와 같은 상황을 말한다.
처리해야 할 태스크가 없으면 아무런 일도 하지 않고 쉬고 있다가 스크립트나 핸들러, 이벤트가 활성화될 때만 돌아간다.
아주아주 간단하게 썻지만 정의되는 event loop 는 뭐라고 딱 하기 힘들정도로 상세하고 구체적이다.
궁금하면 공식 사이트(?) 같은곳에서 설명하는 걸 보자
js 엔진이 script를 받으면 가장 먼저 하는일은 코드에 있는 데이터에 대한 메모리를 설정한다.
이 시점에서는 실행되는 코드는 없으며, 실행을 위해 준비하는 단계이다.
준비하는 단계에서는 코드는 다음과 같이 저장된다.
function - 전체 함수를 참조하여 저장
let- uninitialized 로 저장
const - uninitialized 되서 호출하면 ReferenceError
var - undefined 로 호출됨
함수와 변수는 코드를 실행하기 전에 실행 컨텍스트를 위해 메모리에 저장됩니다.
이것을 hoisting 라고 한다.
자바스크립트에서는 scope 관련되는 개념이 있다.
이 scope는 프로토 타입을 위해 알아 두어야 하는 개념이다.
밑에서 나오니깐 꼭꼭 기억해두자
위에 그림처럼 scope 가 체인 처럼 연결 되어 있는데,
내부함수는 자신을 포함하고 있는 외부함수의 변수에 접근할 수 있다.
function scope 에서는 global scope에 접근 할 수 있지만
global scope에서는 function scope 에 접근 할 수 없다.
이걸 scope chain 이라고 한다.
scope chain 을 알았으니 __proto__ 를 연관지어서 알아보자.
javascript 를 보다보면 정의 하지 않은 __proto__ 라는것을 확인 할수 있다.
Pool 관련한 객체 Pool 을 보면 위와 같이 관련정보를 알 수 있다.
Pool 에서 따로 정의 하지 않았는데 __proto__가 포함되는것을 알 수 있다.
__proto__ 에서는 Pool 객체를 쓰는 모든 객체에 필요한 기능을 넣어두는곳이다.
Pool 에서 query를 호출하면 Pool 에서는 query 가 없어서
__proto__ 에 있는 query 를 호출한다. (위에 설명한 스코프체인 원리에 의해서)
__proto__를 끝까지 가면 다음과 같은 흐름이다.
Pool→ EventEmitter → Object 의 흐름으로 되어있는것을 알 수 있다.
만약 Pool에서 toString 을 호출한다면
Pool에서 찾아서 없으므로 EventEmitter
EventEmitter 에서 찾아서 없으므로 Object
마지막 Object 에서는 찾아서 Object 에 정의된 toString 이 호출된다.
만약 Pool, EventEmitter , Object 3개에서도 다 없으면
Object 가 가르키는 __proto__ 인 null 이 출력된다.
처음에 노드를 쓸때 그냥 쓰면 되겠지 해서 막 썻는데
Pool 에 대한 정보가 필요해서 디버깅 걸어놓고 이것저것 쳐보다가
어? __proto__ 에 있는건 메소드(함수) 처럼 호출되네?
하고 그냥 썻던건데 이런 원리가 들어있는지 몰랐다.
난 자바가 주언어니깐 라는 생각으로 노드를 제대로 공부 할 생각을 하지 않았다.
우연히 기술블로그를 보다가 배민에서 스프링을 하고 다른곳에 이직해서 노드를 하는 개발자 글을 봤다.
그 글을 보면서 왜 똑같은 시간을 나는 대충해서 보냈을까라는 생각이 들었다.
생각해보면 고등학교에서도 그렇게 시간을 보내서 아쉬운 부분들이 있었는데
글을 쓰면 정리도 좀 되고 얼마나 갈지는 모르겠지만 그래도 좀 꾸준히 글을 써볼 생각이다.
어떤 이슈 때문에 이것을 확인했는지는 다음 포스팅으로~~~~~
'개발' 카테고리의 다른 글
istio(이스티오)와 서비스 메시, 프록시 (1) | 2024.02.12 |
---|---|
mysql aborted clients 문제 해결 (0) | 2023.10.05 |
java 에서 백분위수 빠르게 구하는 방법 (0) | 2023.08.01 |
Spring Reactive 도입기 - R2dbc에서 multiDatabaseSource (0) | 2023.07.20 |
Azure Virtual Machines 설명 (0) | 2023.03.29 |