앞으로 브라우저와 관련하여 이해한 부분들을 이미지화 하여 진행상태를 스스로 체크해볼 것이다.
- 이해한 부분 : green
- 이해중인 부분 : yellow
- 접근하지 못했지만, 인지하고 있는 부분 : white
- 접근하고 이해하려 노력했지만 모르겠는 부분 : red
지금 까지 이해한 흐름에 대해 나열해보자면,
HTTP를 이용해 서버에게 데이터 요청
-> 서버로부터 HTML을 비롯한 사이트 구성을 위한 데이터 다운로드
-> 렌더링 엔진 시동
-> HTML 파싱
-><Script>를 만나면 서버에 script file 요청
-> script file 패치
-> 자바스크립트 엔진 시동
-> JS파일을 파싱 후 IR로의 간단한 컴파일링
-> IR(바이트 코드)기반으로 인터프리팅 시동
-> JS file 실행
-> 실행 중 hot spot을 AJITC를 이용하여 2차 컴파일링
->(위 과정 중간에) DOM 트리 & CSSOM 구축
-> 랜더 트리 구축
-> 랜더 트리 배치
-> 랜더링
-> 화면 완성!
또한 JS파일을 파싱 후 IR로의 간단한 컴파일링
과정 중 식별자의 스코프가 정의된다는 것 (렉시컬 스코프)
과, 실행 컨텍스트의 outer
와 환경 레코드
에 의해 호이스팅, 클로저와 같은 현상들이 일어난다는 것을 알았다.
정확히는 호이스팅이나 클로저나 모두 렉시컬 환경에 의해 구현되는 현상들이다.
다만 간단한 개념적 접근이었음으로, 궁금증이 완전히 해결되진 못했다.
추가적으로 궁금한 부분들은 아래와 같다.
💡실행 컨텍스트는 어느 단계에서 생성되는 것인지?
1. 렉시컬 환경이 생성되는 시점에서?
2. 실행기가 해당 함수 호출을 맞이했을때?
💡런타임 환경중 메모리 힙과 콜스택은 무엇일까?
왜 두개의 부분으로 나누어져 있는것일까?
💡자바스크립트 엔진의 런타임 환경은 어떻게 이루어져 있는지?
엔진은 메모리 힙과 콜스택으로만 이루어져 있는지? 아니면 다른 무언가가 또 있는지?
💡실행 컨텍스트의 구조는?
렉시컬 환경에 대해서는 이해했는데, 변수 환경은 무엇일까?
실행 컨텍스트 내에도 렉시컬 환경이 존재하던데,
이것은 선언단계에서 생성된 렉시컬 환경을 참조한다는 것인가?
아니면 렉시컬 환경이라는 것이 또 구축되는 것인가?
앞으로 차근차근, JS Engine Run Time 이 어떠한 과정으로 이루어지는지 보다 구체적으로 한번 알아보자.
다만 위 과정을 이해하려면 그동안 애써 무시해왔던 데이터와 메모리에 대한 기초적인 이해가 필요하다.
메모리
는 데이터
를 담는 공간을 뜻하며 기본적으로 Byte(8bit)
단위의 메모리 셀 여러개로 구성된다.
각 메모리는 고유의 주소값을 가지며, Byte
단위로 데이터를 저장한다.
메모리 주소 | 메모리 공간 |
---|---|
0X00000008 | 0001 0101 |
0X00000009 | 1101 0100 |
0X00000010 | 1011 1001 |
0X00000011 | 1101 1010 |
0X00000012 | 0100 0111 |
0X00000013 | 0001 1111 |
간단하게 비유하자면 메모리는 방, 데이터는 방에 있는 아이템들(사람, 가구 등)로 볼 수 있다.
각 방에는 주소가 있으며, 우리는 주소를 통해 방에 접근할 수 있다.
ex) 서울특별시 영등포구 여의도동 국제금융로 10 1402호 라는 주소는
-> 콘래드 호텔 1402호 라는 특정 공간을 가르킨다.
💡 위의 예시에서 서울특별시 영등포구 여의도동 국제금융로 10
은 불변하는 주소라고 볼 수 있다. 즉 건물이 아닌 땅 자체의 주소이므로 이는 대한민국이 망하거나, 대대적인 주소 개편이 있지 않는 한 절대 변할 수 없는 주소이다.
💡 반대로 1402호
는 콘래드 호텔이 철거되거나, 내부 리뉴얼등의 이유로 쉽게 바뀔 수 있는 주소이다.
위의 개념은 프로세스의 VM(가상 메모리)와 물리적 메모리의 개념으로 설명할 수 있으며
이번 시간에는 그냥 간단히
우리는 가상 메모리를 사용하여 보다 최적화된 메모리 할당 방식을 체험할 수 있다.
정도로만 알아두면 될 것같다.
💡궁금한 점이 생겼는데, CPU는 휘발성 메모리인 RAM을 사용하여 데이터를 관리한다.
RAM은 SSD와 같은 비 휘발성 저장장치에서 데이터를 가져와 사용하는데, 그러면 이러한 비 휘발성 메모리에서 휘발성 메모리 영역으로 데이터가 이동하는 과정이 우리가 흔히 아는 로딩시간 이란걸까?
메모리는 할당, 사용, 해제 3단계의 과정을 거쳐 생성되고 사라진다.
프로그램에서 메모리를 사용할 수 있도록 OS는 메모리를 할당해 준다.
저레벨 언어에서는 우리가 메모리의 사이즈를 직접 설정할 수 있지만,
요즘의 고레벨 언어들은 자동으로 메모리의 사이즈를 결정한다.
할당된 메모리는 연산과정 중 사용될 것이다. 가령 우리가 선언한 변수, 혹은 매개변수로 함수의 호출 및 작동이 일어난다면, 프로그램은 할당된 메모리의 주소로 해당 데이터에 접근한다.
더이상 필요없는 데이터를 가지고 있는 메모리 공간은 다시 반납되고, 다른 데이터가 해당 공간을 사용할 수 있게된다. (다른 프로그램에서 해제된 공간에 접근하는 것도 가능하다.)
💡++ 할당과 마찬가지로 해제 또한 저레벨 언어에서는 개발자가 직접 하지만,
요즘의 고레벨 언어는 '가비지 컬렉터' 라는 자동 해제 알고리즘이 탑제되어 있으며 이는 브라우저 엔진마다 다르다고 한다.
컴퓨터 과학에서 메모리 주소(memory address)는 메모리 위치에 대한 식별자로, 컴퓨터 프로그램이나 하드웨어 장치가 데이터를 저장하고 나중에 이를 가져오는 장소이다. 일반적으로 이는 이진 형태의 숫자로 되어 있다.
컴퓨터 프로그램에서 절대 주소는 메모리 위치를 식별하는 메모리 고유 주소이다. 즉, 기억장치 고유의 번지로서, 기억장치 중 기억장소를 직접 숫자로 지정하는 주소역할을 한다. 기계어 정보가 기억되어 있으며, 1,2,3,4…와 같이 16진수로 약속하여 순서대로 결정한다. 반면 상대 주소는 고유 주소가 아니며, 특정 영역에 상대적인 주소를 지정한다.
메모리 주소 by 위키피디아
하드웨어 수준에서, 컴퓨터 메모리는 많은 수의 플립플롭(flip flop)으로 구성되어 있다. 개별 플립플롭은 고유한 식별자(unique identifier)를 통해 위치를 확인할 수 있기 때문에 우리가 그것을 읽거나 쓰는 것이 가능해집니다. 따라서 개념적으로 볼 때 컴퓨터 메모리는 여러 개의 비트로 구성된 커다란 하나의 배열로 볼 수 있으며 우리는 여기에 무언가를 읽고 쓸 수 있습니다.
우리는 인간이기 때문에 사고와 연산을 비트로하는 데에 익숙치 않습니다. 그 보다는 비트를 더 큰 그룹으로 모아 숫자를 표현하도록 합니다. 8비트는 1바이트라고 하고 바이트가 모이면 워드가 됩니다(워드는 16비트일 때도 있고 32비트일 때도 있습니다).
How JavaScript works: memory management + how to handle 4 common memory leaks (translated by Sunki Baek)
💡 현재 조사하려는 부분과 윗 부분과의 연관성은 크지 않다.
다만 저런 개념으로 이루어져 있구나 정도만 알면 될 것 같아,
개인적으로 괜찮은 2개의 글을 참조하였다.
JS에 대해서 배울때 가장 처음 배운 개념은 바로 변수였다.
그만큼 변수 생성은 프로그래밍에서 가장 기본이자 중요한 부분이라 볼 수 있겠다.
개발자에게 변수의 선언은,
어떠한 데이터에 대해, 우리가 해당 데이터 사용이 용이하게끔 정의하는 행위로 볼 수 있다.
반대로 컴퓨터에서 변수의 선언은,
어떠한 데이터를 담는 메모리를 할당하는 행위로 볼 수 있다.
우리가 정수 10 데이터를 가지는 a 변수를 선언할때
let a = 10;
우리는 a
라는 변수에 10
이라는 데이터가 저장될 것으로 생각하지만,
실제 런타임에서는 아래와 같은 일이 벌어진다.
정확히 말해서 컴파일, 혹은 런타임 과정
식별자 | 메모리 주소 | 데이터 값 |
---|---|---|
a | 0001 0111 | 10 |
우리는 단지 a
는10
으로 선언했을 뿐이지만,
프로그램은 a
식별자의 데이터가 담길 '메모리 공간'과 해당 메모리 공간을 가르키는 '메모리 주소'를 할당한다.
즉 우리는 a = 10
으로 받아들이지만, 컴퓨터는a = 0001 0111
로 받아들인다.