본문 바로가기
부트캠프교육중/CS

가비지 컬렉션과 메모리

by 뭉지야 2023. 3. 28.
728x90

< 가비지 컬렉션 > Garbage collected
-프로그램에서 더 이상 사용하지 않는 메모리를 자동으로 정리하는 것
-이 기능을 가진 언어(혹은 엔진)는 자바, C#, 자바스크립트 등이 있습니다. 
-C 언어 같은 저수준 언어에서는 메모리 관리를 위해 malloc()과 free()를 사용해 개발자가 스스로 메모리를 할당하고 해제해야 합니다.
-JavaScript는 C언어와는 반대로 고수준 언어로서, 객체가 생성되었을 때 자동으로 메모리를 할당하고 필요하지 않다면 자동으로 해제하는 가비지 컬렉션이 내장되어 있습니다.
-가비지 컬렉션의 목적은 메모리 할당을 추적하고, 할당된 메모리 블록이 더이상 필요하지 않게 되었는지를 “스스로” 판단하여 필요하지 않다고 판단이 된다면 해당 메모리를 해제합니다. 

<메모리 생존주기>
-프로그래밍 언어에 관계 없이 비슷합니다.
1. 필요할 때 개발자가 할당합니다.
2. 할당된 메모리를 사용합니다. (Read and Write)
3. 메모리가 더이상 필요하지 않으면 해제합니다.
-2번의 할당된 메모리를 사용하는 것은 모든 언어에서 명시적으로 사용되는 부분입니다. 
- JavaScript로 예시를 들자면 개발자가 변수를 선언해 값을 할당하여 사용하는 부분이 되겠습니다. 그러나 1번과 3번은 C언어와 같은 기계친화적인 저수준 언어에서는 명시적이고, JavaScript와 같은 고수준 언어에서는 암묵적으로 작동합니다. 따라서 여러분들이 직접 이 부분을 제어하지는 않았을 것입니다.

#메모리할당
-JavaScript는 프로그래머 대신, 값을 선언할 때 자동으로 메모리를 할당해줍니다.
-여러분들은 여태껏 변수를 선언하고 배열을 할당하여 안에 요소를 집어넣을 때, 그 배열을 담을 메모리의 크기를 고려하지 않았을 것입니다. 이 부분을 JavaScript가 배열과 배열에 담긴 값들을 위한 메모리 크기 할당을 알아서 진행했기 때문입니다.
-정수, 문자열, 함수, 객체 모든 부분에서 자동적으로 일어납니다.

# 할당된 메모리 사용 (값 사용)
-할당된 메모리를 읽고 쓰는 것을 의미한다.
-변수나 객체 속성의 값을 읽고 쓰거나, 함수 호출 시에 함수에 인수를 전달하여 수행하는 방식으로 일어납니다.

# 메모리 해제
-할당된 메모리가 더이상 필요 없다면 해제를 해야 앱의 성능을 저하시키지 않습니다.



<대표적인 가비지 컬렉션의 방법>
-가비지 컬렉션 알고리즘은 이하 2가지 알고리즘이 가장 유명합니다. 이 2가지 알고리즘이 의존하고 있는 개념은 참조(reference)입니다.
-참조: 명시적이든, 암묵적이든 관계없이 메모리 관리 관점에서 어떤 객체가 다른 객체에 접근할 수 있다면 다른 객체를 참조한다고 말합니다.

#레퍼런스 카운팅(참조 횟수 계산)
-한 객체를 참조하는 변수의 수를 추적하는 방법으로 가장 단순한 형태의 가비지 컬렉션 알고리즘입니다.
-객체를 참조하는 변수는 처음에는 특정 메모리에 대해 레퍼런스가 하나뿐이지만, 변수의 레퍼런스가 복사될 때마다 레퍼런스 카운트가 늘어납니다. 
-객체를 참조하고 있던 변수의 값이 바뀌거나, 변수 스코프를 벗어나면 레퍼런스 카운트는 줄어듭니다. 
-레퍼런스 카운트가 0이 되면, 그 객체와 관련한 메모리는 비울 수 있습니다. 레퍼런스 카운트가 0이 된다는 말은 아무도 그 객체에 대한 레퍼런스를 가지고 있지 않다는 말과 같습니다.

#트레이싱
-한 객체에 flag를 두고, 가비지 컬렉션 사이클마다 flag에 표시 후 삭제하는 mark and sweep 방법입니다.
-현재 대부분의 가비지 컬렉션이 mark and sweep 알고리즘을 이용한 가비지 컬렉터를 장착하고 있습니다.
-객체에 in-use flag를 두고, 사이클마다 메모리 관리자가 모든 객체를 추적해서 사용 중인지 아닌지를 표시(mark)합니다. 그 후 표시되지 않은 객체를 삭제(sweep)하는 단계를 통해 메모리를 해제합니다. 
-이 방법은 앞선 레퍼런스 카운팅 방법보다는 나은데, ‘참조받지 않는 객체’는 ‘닿을 수 없는 객체’기 때문에 가비지 컬렉션을 통해 메모리를 해제할 수 있기 때문입니다.
-mark and sweep 알고리즘은 객체가 필요한지 결정하기 위해 해당 객체에 닿을 수 있는지 (reachable)을 판단합니다. 그리고 3단계를 거칩니다.

1.루트(Roots): 일반적으로 루트는 코드에서 참조되는 전역 변수입니다. 예를 들어 자바스크립트에서 루트로 동작할 수 있는 전역 변수는 window 객체입니다. Node.js에서 이와 동일한 객체는 global입니다. 가비지컬렉터는 모든 루트의 완전한 목록을 만들어냅니다.
2.그런 다음 모든 루트와 그 자식들을 검사해서 활성화 여부를 표시합니다(활성상태이면 가비지가 아닙니다). 루트가 닿을 수 없는 것들은 가비지로 표시됩니다.
3.마지막으로 가비지컬렉터는 활성으로 표시되지 않은 모든 메모리를 OS에 반환합니다.



<메모리 누수>
-메모리 누수의 주요 원인은 예상치 못한 참조입니다.
-예상치 못한 참조는 개발자는 더 이상 사용되지 않을 것이라 생각했지만, 어떠한 이유로 활성화 상태인 루트 트리 안에 존재하는 메모리 조각들입니다. 
-오직 그 코드를 작성한 개발자들만이 해당 메모리 조각을 운영체제로 반환시킬 수 있는지 여부를 명확히 알 수 있기 때문에 해당 부분들을 잘 확인하여 메모리 누수가 일어나는 부분을 막을 줄 알아야 합니다.
-자바스크립트에서 예상치 못한 참조는 더이상 사용되지 않지만 코드 상 어딘가에 유지되어 해제되지 못한 변수들입니다. 어떤 이들은 이를 개발자의 실수라고 말하기도 합니다. 
-메모리 누수는 일반적으로 3가지의 형태가 있습니다.
1.우발적으로 생성된 전역변수
2.DOM 외부에서의 참조
3.클로저의 잘못된 사용

 


출처

코드스테이츠

728x90

'부트캠프교육중 > CS' 카테고리의 다른 글

TDD (소프트웨어 개발 방법론)  (0) 2023.03.29
문자열과 그래픽  (0) 2023.03.28
스레드  (0) 2023.03.28
운영체제, 프로세스  (0) 2023.03.28
Memory  (1) 2023.03.28