[ 개발 잡소리 ] 메모리 구조

2024. 7. 26. 22:43개발잡소리

메모리 구조는 무엇일까?

딱딱한 정의부터 말하자면 메모리의 구조란

프로그램이 실행될 때 운영체제가 프로그램에게 제공해 주는 공간의 구조이다.

 

개발에 있어서 이 메모리 구조라 함은 코드를 이해함에 있어서 굉장히 중요한 내용이자

어쩌면 상식 중에서도 상식이라고 할 수 있다.

 

우리가 아무 생각 없이 사용하는 변수들이나 코드들까지 모두 메모리의 어딘가에 0과 1로써

저장된다는 사실을 알고는 있을 것이다. 하지만 이들이 정확히 어디에 저장되는지는

별로 알 필요가 없다고 생각할 수 있다.

당연히 메모리 커널의 몇 번 줄에 몇 번 칸부터 몇 번까지 딱딱 들어있는지 알필요는 없으나

어느 영역에 들어가 있는지는 알 필요가 있다.

 

왜 알아야 하는지에 대한 얘기는 이쯤 하고 설명하겠다.

 


 

우선 이 메모리 구조란 놈은 앞서 언급했듯이

프로그램이 실행될 때 운영체제가 프로그램에게 제공해 주는 공간의 구조이다. 

 

이 구조는 크게 4가지 영역으로 나뉘는데,

항상 이런 그림을 그리면서 설명한다.

어쨌든 이렇게 4개의 영역이 있다.

각각 위와 같이 분류되고 각각의 역할이 모두 다르다.

 

자주 쓰이고 중요한 아래쪽부터 순서대로 설명하겠다.

 


우선 STACK 영역이다

이 영역은 생명주기가 가장 짧은 영역으로 금방 할당되었다가 사라진다.

따라서 지역변수매개변수들이 이 영역에 할당되고.

할당구조는 선입 호출인 STACK과 동일하게 작동하기 때문에 이름도 STACK이다.

 

왜 그럴까? 로직의 흐름을 읽어보면 이해하기 쉽다.

뭐 대충 이런 함수가 있다 치자. JS로 작성되었고 id와 name을 받아서 출력해 주는 함수이다.

성별은 id분류체계가 누가 만들었는지는 몰라도 40번 위로는 다 여성이라고 한다.

 

일단 이 코드의 흐름에서 isMan이라는 변수는 언제 메모리에 할당이 될까?

바로 이 Func() 함수가 실행되면 할당된다.

또한 매개변수도 같이 Func()가 실행되면서 STACK영역에 할당되고 순서는 다음과 같다.

어 근데 왜 name이 먼저 할당되었지?라는 의문이 발생할 수 있는데

이는 나중에 다른 글에서 알아볼 것이다.

 

어쨌든 Func()이 실행되면 위와 같은 순서로 할당되고 메모리에서 삭제될 때도 isMan부터 삭제된다.

 

함수가 끝났다, 한 영역이 끝났다는 것은

이 중괄호로 결정이 된다.

한 중괄호 안에 있는 것들을 같은 지역변수로 묶는 것처럼, 이 지역변수들은 차례대로 STACK영역에

할당되고 들어온 역순으로 삭제된다.

 

따라서 이 중괄호 영역은 순식간에 CPU에서 처리되어 지나가기 때문에 STACK영역에

들어가는 변수들의 생명주기가 짧은 것이다.

 


 

다음은 HEAP 영역이다

Heap메모리의 장점은 사용자가 직접 관리할 수 있다는 점이고 단점 또한 그렇다.

이런 Heap영역에 들어가는 변수들은 평범한 초기화로는 할당되지 않는데,

C++과 같은 메모리를 직접적으로 다루기 편한 강력한 언어를 사용해 보았다면

어느 정도 알고 있을 수도 있을 동적 할당이라는 것이 있다.

 

동적할당이란 돈을 빌리는 것과 비슷하다. 동적 할당을 하게 되면

HEAP메모리에서 일정량의 메모리를 빌려서 딱 어느 실행시간 동안 사용할 메모리를 빌려 쓴다.

그리고 이 빌린 돈은 나중에 갚아야 하는데 그렇지 않으면 메모리 누수가 발생하게 된다.

메모리를 빌려 할당해 놓고 그냥 튄 것이다.

 

원래라면 딱 필요한 프로세스에서 쓰고 나서 본인의 생명주기가 다하기 전에,

메모리를 반환해야 하는데 그러지 않고 먼저 사라진 것이다.

(빚이 쌓여있는데 안 갚고 먼저 죽어버린 것이다.)

 

하지만 몇 가지 언어들은 이런 복잡한 채무관계를 자동으로 해결해 주는데

그걸 해주는 게 가비지 컬렉터(Garbage Collector)라는 놈이다.

이 고마운 친구는 우리가 생각 없이 생성하여 할당된 여러 가비지(쓰레기)들의 생명주기를

하나하나 파악하여 메모리 할당을 해제하고 소멸시켜 준다.

 

 

 

정말 좋은 기능이지만 그만큼 오버헤드가 심하다.

C#언어가 느린 이유가 이 가비지 컬렉터라는 놈 때문이다.

 

 

 

 

 


 

다음은 Data 영역이다

Data영역부터는 크게 할 말은 없다.

Data영역에는 전역 변수와 클래스의 정적 변수들이 저장된다.

얘네들은 프로그램이 딱 메모리를 할당받고 실행되었을 때부터

프로그램이 종료될 때 함께 소멸한다.  따라서 생명주기가 가장 길다고 할 수 있다.

 

따라서 메모리의 수명이 긴 만큼 많이 사용하는 것을 별로 권장하지 않는다.

그 외는 별다른 특이사항은 없다.

 


마지막으로 Code 영역이다

말 그래도 Code, 실행할 프로그램의 코드가 저장되는 영역이다.

CPU는 프로세스를 처리할 때 여기에서 필요한 부분을 가져가서 실행시킨다.

 

..끝이다

 


 

대충 메모리 영역이란 것은 이런 것이다.

 

앞으로 개발하면서 변수를 만들고 인스턴스를 생성함에 있어서 얘가 어디에 할당되었다가

소멸되는지, 데이터의 흐름을 이해한다면 프로그램이 동작하는 과정을 더 잘 이해할 수 있을 것이다.

또한 가비지 컬렉터가 있는 언어로 개발을 하고 있다면 약간의 감사를 표하며 개발해 보도록 하자.