🚀 오늘의 꼬꼬무
20230727 목요일
오늘의 꼬꼬무 주제 : 변수
나는 항상 ‘꼬리에 꼬리를 무는’ 이라는 말을 굉장히 좋아한다.
앞으로 1일 1 포스팅, 꼬꼬무 프로젝트를 해볼 예정이다.
꼬리에 꼬리를 무는 질문들로 공부해보며, 공부한 것들을 포스팅해 보자는 취지의 프로젝트이다.
💁🏻 변수란 무엇인가?
우리가 10+20을 하면 10과 20, 그리고 + 를 기억하여 그 결과를 계산한다.
→ 이는 컴퓨터도 마찬가지이다.
→ 10은 리터럴 + 는 연산자이다. 이들을 모두 알아서 해석한다.
그럼 10과 20은 어디에 저장하는가? 이들은 모두 메모리에 저장된다.
각 메모리에는 메모리 주소가 있다
→ 이 숫자들은 모두 이진으로 저장된다.
메모리 주소에 저장된 이 친구들을 불러내야 하는데, 직접 메모리 주소를 사용하면 위험도가 있다.
→ 메모리 주소에 직접 접근하다가 시스템의 메모리에 잘못 접근하면 엄청난 문제가 생길 수 있기 때문이다.
⇒ 그래서 자바스크립트는 메모리 주소에 직접적으로 접근하지 못한다.
🤔 그렇다면 우리는 한 개의 값으로 연산을 할 때마다 그 값을 새로 입력해줘야 하는 것인가?
😃 그래서 변수라는 개념이 나온 것이다 !
내가 만약 10이라는 값을 할당 한다고 하자
💡 할당이란 값을 변수에 넣는 것이다
이때 10은 고유한 메모리에 들어갈 것이다
이때 각 메모리 주소를 전부 입력할 수 없으니 (접근이 제한되어 있으니) 우리는 메모리 주소에 이름을 붙인다. 이를 변수라고 한다.
🤔그렇다면 질문이 있는데…
🤷🏻♂️변수와 물리적 주소 가상 주소까지… 공부의 시작이였던 이 질문
👩🏻💼: A라는 변수에 10이라는 값을 할당하는 프로그램을 작성하고 프로그램을 실행 후 완전히 종료하고 다시 실행했다. 그렇다면 10이라 값은 다시 한 번 다른 메모리 자리에 할당되고 이 변수의 이름이 A가 되는 것인가?
그렇다면 이전에 할당된 메모리는 쓰지 않을 텐데, 어떻게 관리하는 것인가?
⏹ : 프로그램을 실행하면 컴퓨터는 해당 프로그램을 메모리에 로드하고 실행하는데, 이 과정에서 변수와 데이터는 메모리에 할당된다.
변수 A에 10이라는 값을 할당하는 경우, 10이라는 데이터가 메모리에 저장되고 해당 메모리 위치에 변수 이름인 A가 매핑된다.
프로그램을 실행하고 완전히 종료한 후 다시 실행하면, 기본적으로 운영체제는 새로운 프로세스로 실행을 시작한다. 이전 실행에서 사용된 메모리는 더이상 사용하지 않는다.
🤷🏻♂️이 메모리는 어떻게 처리하냐라고 묻는다면…?
운영체제는 프로세스의 실행과 종료를 관리하고 각 프로세스가 필요로 하는 메모리를 할당하고 회수하는 작업이 수행된다.
프로그램이 종료되면 해당 프로세스에 사용된 메모리는 운영체제에 의해 회수되어 재사용 가능한 상태가 된다. 이렇게 함으로써 메모리 사용을 좀 더 효율적으로 관리하고 충돌이나 메모리 누수와 같은 문제를 방지한다.
메모리 누수란?
💡 메모리 누수란? : 응용 프로그램에서 데이터를 메모리에 저장했다가, 필요없어졌을때 적절하게 제거되지 않는 것. ‘메모리 릭 (Memory leak)이라고도 한다
- 메모리에 데이터가 남아 있어도 운영 체제가 의도한 것이라면 데이터 누수가 아니다
- windows vista 이후의 운영체제 및 안드로이드에선 옛날만큼 메모리 공간이 빡빡하지 않다는 것을 감안하여 종료시킨 프로그램을 일부러 메모리 상에 남겨두기도 한다
→ 사용자가 다시 실행시켰을때 더 빠르게 응답할 수 있다.
→ 사용자가 다른 작업을 하다가 다시 메모리가 부족해지면 알아서 정리해준다.
??? 엥? 저번에 들었던 가비지 컬렉션의 개념이 생각나. 그 개념은 언어 자체가 메모리를 관리하는 거였는데??
운영 체제의 메모리를 관리 VS 가비지 컬렉션
🌐 운영 체제가 메모리를 관리하는 것
- 운영 체제는 프로세스가 메모리를 요청하면 해당 메모리를 할당하고 , 프로세스가 종료되면 메모리를 회수하여 재사용 가능한 상태로 만든다
- 프로세스들 간의 메모리 공간을 분리하여 충돌이나 오류를 방지하고, 시스템의 안정성을 유지한다
🗑 가비지 컬렉션
- 프로그래밍 언어의 런타임 환경에서 담당하는 기능으로, 메모리를 동적으로 관리하는 상황에서 발생하는 메모리 누수를 방지하고 자동으로 더 이상 사용되지 않는 메모리를 회수하는 역할을 함
- 더이상 필요없는 변수, 객체들을 식별하고 메모리를 자동으로 회수하여 재사용 가능한 상태로 만들어준다.
- JAVA, C#, PYTHON 등의 언어에서 가비지 컬렉션을 지원하며 언어의 런타임 환경이 가비지 컬렉션을 담당한다
운영 체제는 컴퓨터 자원을 관리함
프로세스들의 실행과 메모리 할당/ 회수 담당
가비지 컬렉션은 런타임에서 메모리 관리를 담당
사용하지 않는 것을 식별하고 자동으로 회수
사실 아직도 그 둘의 차이를 잘 이해를 못 했었다.
그래서 예시를 들어서 공부해보기로 했다
💡 이렇게 가정해보자
- VS CODE를 실행한다
- A = 10이라는 값을 할당하는 코드를 쓴다
- 코드를 실행한다
- 종료한다
- VS CODE를 닫는다
- VS CODE를 실행한다
→ 운영 체제는 VScode 프로세스에 필요한 메모리를 할당하고, 사용할 수 있도록 확보한다.
😺 : 이때 좀 더 자세한 과정을 보자면…
→ 가상 주소와 물리 주소에 대한 설명은 이 과정을 모두 적고 공부해보았다.
1. 프로세스 생성
- VSCODE를 실행하면 운영 체제는 새로운 프로세스를 생성한다.
- 프로세스는 실행 중인 프로그램을 나타내며, 자신만의 독립된 메모리 공간을 가지고 실행한다
2. 가상 주소 공간 할당
- 운영 체제는 VS CODE 프로세스에게 가상 주소 공간을 할당한다. 가상 주소 공간은 각 프로세스가 독립적으로 사용하는 가상의 메모리 공간을 의미한다.
- 이 가상 주소 공간은 실제 물리적 메모리와는 분리되어 있으며, 프로세스가 사용하는 주소들은 가상 주소로 매핑되어 실제 메모리에 할당된다.
3. 물리적 메모리 할당
- 가상 주소 공간에 할당된 메모리는 실제 물리적 메모리에 매핑되어야 한다.
- 이때 운영 체제는 VSCODE 프로세스가 필요로 하는 물리적 메모리를 확보한다.
- 즉 , 운영 체제는 VSCODE에 필요한 메모리 공간을 실제 물리적 메모리에 할당하여 사용할 수 있도록 한다.
4. 메모리 보호
- 운영 체제는 각 프로세스들간의 메모리 공간을 보호하기 위해 메모리 보호 기법을 사용한다.
- 각 프로세스는 자신의 주소 공간에서만 접근이 가능하고, 다른 프로세스의 주소 공간에는 접근할 수 없도록 제한된다.
5. 프로세스 실행
- VSCODE 프로세스가 메모리를 할당받고 초기화되면, 운영 체제는 해당 프로세스를 실행시킨다.
- 이제 VSCODE는 자신의 가상 주소 공간 내에서 실행되며, 필요한 데이터와 코드가 메모리에 로드되어 사용된다
7. 변수 쓰기 (가비지 컬렉션)
- 자바스크립트의 경우
// main.js
let A = 10;
console.log(A);
변수 A에 10이 할당되고, 콘솔에 10이 출력된다. 코드 실행이 완료되면 NODE.JS가 사용한 메모리는 운영 체제에 의 해 회수된다.
JS는 가비지 컬렉션을 내장해 이때 가비지 컬렉터에 의해 식별되고 자동으로 회수된다.
- C언어의 경우
#include <stdio.h>
int main() {
int A = 10;
printf("%d\n", A);
return 0;
}
코드 실행이 완료되면 C프로그램이 사용한 메모리는 운영 체제에 의해 회수된다. C 언어는 메모리 할당과 해제를 개발자가 직접 관리해야 하므로, 메모리 누수가 발생하지 않도록 메모리 해제 코드를 작성해야 한다
8. 프로세스 종료:
- VSCODE 실행이 끝나고 VSCODE를 종료하면, 운영 체제는 해당 프로세스가 사용한 메모리를 회수한다.
- 프로세스가 종료되면 할당된 가상 주소 공간과 물리적 메모리는 다른 프로세스가 사용할 수 있도록 해제된다.
- 이렇게 함으로써 VSCODE의 실행에 사용된 메모리가 운영 체제에 의해 회수되고 재사용 가능한 상태가 된다
💁🏻 가상 주소 란 무엇인가?
가상 메모리란? 프로세스는 가상 주소를 사용하고, 데이터를 사용할때 물리 주소로 변환해준다는 것이다.
가상 주소 : 프로세스가 참조하는 주소
물리 주소 : 실제 메모리 주
MMU : CPU에 코드 실행시, 가상 주소 메모리 접근이 필요할때, 해당 주소를 물리 주소 값으로 변환시켜주는 하드웨어 장치.
🤓 그럼 가상 주소 왜 쓰는데?
- 프로세스 독립성 : 각 프로세스는 각각의 가상 주소 공간을가지고 있다. 이로 인해 프로세스는 서로의 주소 공간에 영향을 미치지 않고 독립적으로 실행될 수 있다.
→ 따라서 하나의 프로세스에서 발생한 오류나 메모리 접근 오류가 다른 포르세스에 영향을 미치지 않아 안정성이 향상된다
🤷🏻♂️ 여기서 발생한 의문!
🤔그냥 물리적인 주소를 각각 다르게 주면 되는 거 아니야?
→ 가상 주소는 논리적인 주소이다.
→ 가상 주소를 사용하면 여러 프로세스들이 메모리를 공유할 수 있다. 물리적 메모리의 용량보다 더 많은 가상 주소를 가진 프로세스들이 동시에 실행될 수 있으며, 가상 주소를 물리적 주소로 매핑함으로써 메모리를 효율적으로 사용할 수 있다.
🤬 이게 뭔 소리냐?
아니, 가상 주소는 프로세스가 각각의 가상 주소 공간을 가지며 서로의 공간에 영향을 미치지 않고 독립적으로 사용할 수 있게 한다고 했잖아… 그런데 메모리를 공유한다는 건 무슨 소리야 도대체?
📤 그럼 한번 예시를 들어보자
프로세스 A와 B가 있다. 이들은 물리적 메모리의 용량보다 크다. 이때 가상 주소로 해결하는 방법을 알아보자.
→ 가상 주소를 사용하여 메모리를 효율적으로 관리하기 위해서 운영 체제는 물리적 메모리를 효율적으로 활용해야 한다.
1. 가상 주소 공간 할당:
운영 체제는 각 프로세스 A와 B에게 가상 주소 공간을 할당한다.
각 프로세스는 자신만의 가상 주소 공간을 갖게 된다
2. 물리적 메모리 공간 관리 :
물리적 메모리에는 실제 데이터와 프로그램 코드가 저장되므로 모든 가상 주소를 물리적 주소로 직접 할당할 수는 없다.
3. 페이지 기반 가상 메모리 관리:
대부분의 운영 체제는 페이지 기반의 가상 메모리 관리를 사용하여 가상 주소와 물리적 주소 간의 매핑을 수행한다. 가상 메모리를 작은 크기의 페이지로 나누고, 물리적 메모리도 동일한 크기의 페이지로 나눈다.
4. 페이지 테이블:
각 프로세스마다 페이지 테이블이라는 자료구조를 유지한다.
- 페이지 테이블이란 페이지 테이블은 가상 주소의 각 페이지가 실제 물리적 메모리의 어떤 페이지와 매핑되는지를 기록한다. 프로세스가 가상 주소를 참조하면 페이지 테이블을 사용하여 해당 가상 주소를 물리적 주소로 변환한다
- 페이지 번호(Page Number): 가상 주소에서 페이지 번호를 식별하는 부분
- 페이지 프레임 번호(Page Frame Number): 물리적 메모리에서 페이지가 위치하는 프레임 번호를 기록
- 기타 제어 비트(Control Bits): 페이지에 대한 다양한 제어 정보를 포함한다 예를 들어 해당 페이지가 물리적 메모리에 들어가졌었는지의 여부, 수정 가능한 페이지인지 등을 나타낼 수 있따.

가상 주소에 의해 주소가 지정된 페이지와 물리 메모리의 페이지 간의 관계 (단순한 주소 공간 스킴에서) 물리 메모리는 수많은 프로세스에 속하는 페이지를 포함할 수 있다. 거의 사용하지 않을 경우 페이지는 디스크에 보관할 수 있으며, 물리 메모리가 꽉차 있으면 위의 그림처럼 일부 페이지는 물리 메모리에 위치하지 않는다.
(이미지 출처: 위키백과)
5. 페이지 폴트
프로세스가 처음으로 해당 페이지를 접근할 때 물리적 메모리에 해당 페이지가 없는 경우 페이지 폴트가 발생
- 페이지 폴트란? → 즉, 프로세스가 요청한 페이지가 현재 물리적 메모리에 올라와 있지 않을 때 발생 → 이 경우 운영체제는 해당 페이지를 물리적 메모리로 가져와야 함
- 프로세스가 페이지 폴트를 발생시키면, 운영 체제는 먼저 해당 페이지가 디스크에 저장되어 있는지 확인한다
- 만약 해당 페이지가 디스크에 저장되어 있다면, 디스크에서 가져온다
- 가져온 페이지를 물리적 메모리에 적재하고, 페이지 테이블을 업데이트하여 해당 가상 주소가 새로운 물리적 주소와 매핑되도록 한다
- 이후에 다시 참조해보면 데이터나 코드에 접근할 수 있다
6. 페이지 교체
물리적 메모리 공간이 가득 찬 경우, 운영 체제는 페이지 교체 알고리즘을 사용하여 더 이상 사용되지 않는 페이지를 디스크로 옮기고 새로운 페이지를 메모리에 로드한다.
→ 이렇게 함으로써 물리적 메모리에 가상 주소 공간을 연결할 수 있다
7. 다중 프로그래밍과 스와핑
다중 프로그래밍 환경에서는 여러 개의 프로세스가 동시에 실행된다. 만약 모든 프로세스가 동시에 물리적 메모리에 올라갈 수 없는 경우, 운영 체제는 스와핑 기법을 사용하여 현재 실행 중인 프로세스의 일부를 디스크로 내보내고, 새로운 프로세스를 메모리에 로드함으로써 다른 프로세스로 전환한다.
후기
변수가 어디에 할당되는지 찾다가 많은 것을 알게 된 공부였다.
실제 메모리보다 더 쓰는 방식으로 저러한 방식을 채택한 개발자들이 정말 대단해 보였고 나 또한 저렇게 시대를 이끌어가는 개발자가 되고 싶었다.
'2023 공부한것들' 카테고리의 다른 글
2. OSINT의 기초 개념을 알아보자 (1) | 2023.08.07 |
---|---|
1. OSINT를 공부해보자 (로드맵) (0) | 2023.08.07 |
데이터 타입의 필요성은 모르겠고, 오류를 안 띄우려면? (0) | 2023.08.06 |
포렌식) 디스크 이미징 (0) | 2023.08.06 |
[5-6] 표현식인 문과 표현식이 아닌 문 (0) | 2023.06.30 |