메모리 심화

김동현·2023년 9월 18일
0

CS 상식

목록 보기
1/2
post-thumbnail

메모리 주소

변수를 선언할 때 자바스크립트 내부에선 어떤 일이 발생할까? 이 코드가 실행될 때 자바스크립트는 변수의 고유 식별자를 생성하고 메모리에 주소를 할당한다. 최종적으로 생성한 주소에 값을 넣게 된다.

이 과정을 시각화하면 아래의 그림과 같다. 우리가 선언한 변수나 상수는 값을 바라보고 있는 것이 아닌 메모리 주소를 바라보고 있다.

만약 여기서 새로운 변수에 기존 변수를 대입하면 어떻게 될까? 답은 간단하다. 기존 변수의 메모리 주소를 참조하게 된다.

여기서 한가지만 더해보자. 만약 기존 변수를 조작하면 어떻게 될까? 두번째 생성한 변수의 값도 변하게 될까? 이번에는 그렇지 않다. 새로운 메모리 주소를 할당 받고 그것에 값을 넣게 된다. 그 이유는 자바스크립트에서 원시 타입은 변경이 불가능하기 때문이다. 따라서 원시 타입의 값이 변경 될 때는 항상 메모리가 할당된다.

자바스크립트 엔진

자바스크립트 엔진은 가상 머신(Virtual Machine)으로 구성 되어 있다. 이 가상 머신에는 메모리 모델을 구현해놓았는데 각각 Heap 영역과 Call Stack 영역으로 구성 되어 있다. Heap 은 참조 타입이 들어가고 Call Stack 은 원시 타입이 들어가게 된다.
방금 전에 위의 과정을 Call Stack 으로 표현하면 스택처럼 하나씩 쌓이게 된다.

아래의 그림에서 만약 좌측에 있는 코드를 실행 시키게 되면 어떻게 될까?

먼저 순차적으로 Call Stack 에 변수들이 쌓이게 된다. 배열 같은 경우 오브젝트 타입이기 때문에 참조 타입으로 분류 된다. 배열을 선언하면 Heap 에 배열 영역이 생성 되는데 Call Stack 에 생성된 배열 변수는 Heap 에서 생성된 배열의 메모리 주소를 참조하게 된다. 여기서 Heap 영역 메모리는 동적으로 크기가 변할 수 있다. 따라서 배열의 값을 추가하면 Heap 메모리 영역에 그대로 할당이 된다. 배열을 상수로 선언 했는데 동작하는 이유이기도 하다. 상수여도 push 함수가 동작하는 이유는 Call Stack 에 할당된 메모리를 변경 하는 것이 아닌 Heap 메모리를 변경 하는 것이기 때문이다. 위의 그림처럼 이제 모든 로직이 종료 되었다. 그런데 여기서 사용을 마친 메모리는 어떻게 정리가 될까?

가비지 컬렉터

자바스크립트 엔진은 가비지 컬렉터(Garbage Collector)라는 것을 통해 메모리를 정리한다. 가비지 컬렉터는 사용하지 않는 메모리를 해제하는 역할을 맡고 있다. 앞서 사용된 메모리 주소도 가비지 컬렉터에 의해 정리 될 수가 있다.

이때, 현대적인 브라우저의 가비지 컬렉터는 Mark and Sweep Algorithm 을 통해 메모리를 정리 하고 있다. 브라우저의 최상위 객체인 window 에서부터 시작하여 닿을 수 없는 곳은 필요 없는 주소라 생각하여 지우는 알고리즘이다. 아래의 그림을 보면 window 로부터 아래로 뻗어 나가는데 가장 왼쪽 string 은 닿지가 않는다. 이런 경우는 메모리에서 삭제가 된다.

메모리 정리

다시 처음 상황으로 되돌아가보자. 만약 또 다시 값을 할당하여 첫번째 메모리 값을 아무도 참조하지 않는다면 어떻게 될까? 가비지 컬렉터에 의해 조용히 사리지게 된다. 이처럼 메모리가 지워지게 되는 것은 참조가 중요하다. 참고로 클로저가 가능한 이유도 참조 덕분이라고 할 수 있다.

profile
가치를 전달하는 개발자

0개의 댓글

관련 채용 정보