웹개발 및 최신 테크 소식을 전하는 블로그, 웹이즈프리

HOME > js

자바스크립트의 메모리 관리와 가비지 컬렉션(Garbage Collection)

Last Modified : 2021-07-04 / Created : 2021-03-22
3,622
View Count

자바스크립트 언어는 C나 비슷한 언어와 달리 추상화가 상대적으로 높은 언어입니다. 그리하여 메모리 관리 및 방법들이 거의 자동으로 이루어진다 할 수 있죠. 그렇다면 자바스크립트는 어떻게 메모리를 사용하고 관리할까요? 또한 자바스크립트를 사용하면서 효과적인 메모리 관리의 방법이 있다면 무엇인지 알아볼려고 합니다.




# 자바스크립트의 메모리 관리


자바스크립트 역시 다른 언어와 비슷한 메모리 관리 프로세스를 가지고 있습니다.  메모리 관리 프로세스는 아래와 같이 크게 세 가지로 구분되어 자바스크립트 엔진에서 수행됩니다.

1. 데이터의 메모리 할당 // Allocation
2. 메모리의 사용 // Read or Write
3. 메모리 비우기 // Release


여기서 메모리의 할당을 위해 자바스크립트 엔진은 데이터에 따라 HeatStack으로 각각 저장되는데 Heat는 크기가 정해지지 않은 값을 저장하고 Stack은 값이 고정된 원시 값(Primitive vales)이 저장됩니다. 여기서 Stack은 0, 1, '문자', null 등등이 여기에 해당하죠. 반면 참조 값은 객체나 함수를 말합니다.


! 가비지 컬렉션(Garbage Collection)의 동작


가비지 컬렉션은 메모리를 비우는 Release에 해당하는 과정으로 가비지 컬렉팅이라고도 합니다. 자바스크립트의 경우 메모리 관리를 자동으로 수행하며 이 부분이 바로 가비지컬렉션(GC)의 역할입니다. 가비지 컬렉션은 메모리를 Release하기 위해서 Heat 메모리 영역의 참조 데이터의 연결이 계속 참조를 유지하는지 확인합니다. 즉 프로세스가 멈추고 더 이상 참조되지 않는 경우 메모리를 비워 성능을 유지하거나 높이는 과정을 수행할 수 있습니다.

여기서 잘 알려진 Reference Count는 초창기(Netscape) 부터 많이 쓰인 방식이나 현재는 잘 사용되지 않습니다. 그 이유 중 하나가 순환참조인데 이 방식을 간략하게 설명하면 사용중인 참조 수를 더하여 계산하는 방식으로 참조가 만약 0이 되었다면 더 이상 사용되지 않을 것이라 판단하여 메모리를 회수할 수 있겠죠. 다만 프로세스가 끝나도 0이 되지 않는  경우가 문제인데 이것이 순환참조... 즉 서로를 참조하는 경우의 문제이고 메모리 누수의 원인이기도 합니다. 이를 해결할 수 있는 방식이 아래의 Mark and Sweep 방식입니다.

[ 참고 ] Mark-and-Sweep 알고리즘
가비지컬렉션의 동작 방식은 최근 대부분의 브라우저의 경우 Mark-and-Sweep 알고리즘을 사용합니다. 말 그대로 모든 참조 값에 대하여 Mark하는 과정을 거치는데 이때 Root라는 시작점을 가지게 됩니다. Root는 우리가 알고 있는 머리객체(window)를 말하며 반드시 Root에서부터의 관계를 사용하는데 이 방식은 순환참조가 발생해도 Root와의 참조가 없는 경우 실제로는 더 이상 사용되지 않을 것이란 판단이 가능하다는 점에서 장점을 가지게 됩니다. 이 후 프로세스가 종료되고 참조 되지 않는 값을 Sweep하는 과정입니다.

최근에는 Mark-and-Sweep 방식이 사용되지만 이 방식의 경우 로직상 Reference Count 방식과 비교시 더 많은 순환과정(전체 코드의 Mark를 확인)이 필요하기 때문에 Garbage Collection을 너무 자주 동작시킬 경우 성능상의 문제점이 발생할 수도 있습니다. 즉 더 나은 방법 ~ 더 효과적인 GC를 구현하기 위해서 계속해서 알고리즘이 개선되고 Mark-and-Sweep 방식 역시 다른 방식으로 변경될 수도 있겠습니다.


@ 메모리 누수(Memory leak)
추가로 메모리 누수(Memory leak)이 발생하지 않도록 해야 하는데 대표적인 예가 순환 참조입니다. 즉 두 값이 서로를 계속해서 참조를 하고 있기 때문에 메모리 누수 발생 여지가 있는 것이지요. 이 외에도 타이머 함수를 중지하지 않고 계속 실행하는 것도 이유가 될 수 있고 또 다른 예로 DOM 엘리먼트를 변수에 저장하고 엘리먼트만 삭제하여 저장된 변수는 계속 남아있는 것이 문제가 될 수 있습니다.

그 외에도 머리객체(전역변수)를 사용한 데이터 사용이나 클로저, 이벤트 등의 사용에서도 메모리 누수의 원인이 생길 수 도 있습니다.


[ 참고 2 ] Heat 메모리 모니터링
NodeJS를 사용하는 자바스크립트 환경의 경우 Heat 영역의 메모리 상황을 시각화하거나 대시보드 형태로 확인할 수 있는 방법들이 존재합니다. 메모리가 환경에서 어떻게 동작하는지 더 자세히 알기 위해서 사용을 고려하는 것도 좋은 방법입니다.

Previous

[자바스크립트] in 연산자 사용하는 방법과 응용

Previous

자바스크립트 문자열을 역순으로 반환하기, reverse string