1. 메모리 구조
모든 컴퓨터에는 RAM(메인 메모리)이 있어. 그게 뭔지, 어떤 특징이 있는지, 그리고 제일 중요한 건 우리한테 무슨 쓸모가 있는지 알아보자!
모든 프로그램(심지어 C#으로 짠 프로그램도) 실행 전에 RAM에 올라가. RAM에는 프로그램 코드(프로세서가 실행하는 코드)랑 프로그램 데이터(프로그램이 직접 메모리에 넣는 데이터)가 들어있어.
RAM이 뭔지, 뭐랑 비슷한지 궁금하지?
엑셀을 떠올려봐 😎 엑셀 시트는 셀로 이루어져 있고, 각 셀마다 고유 번호가 있어(A1, A2, ... B1, B2). 셀 번호만 알면 언제든 값을 넣거나 꺼낼 수 있지. 컴퓨터 메모리도 거의 똑같이 생겼어.

프로그램이랑 그 데이터는 실행 중에 메모리에 저장돼. 컴퓨터 메모리는 전부 작은 셀, 즉 바이트 단위로 나눠져 있어. 각 셀마다 고유 번호가 있는데, 이걸 0, 1, 2, 3, ... 이런 식으로 매겨. (번호는 0부터 시작해.) 셀 번호만 알면 거기에 데이터를 저장하거나 꺼낼 수 있어. 어떤 셀에는 프로그램 코드(프로세서 명령어)가, 어떤 셀에는 프로그램 데이터가 들어가. 셀 번호를 셀 주소라고도 해.
프로세서는 메모리에 올라간 프로그램의 명령어를 실행할 수 있어. 거의 모든 프로세서 명령어는 이런 식이야: 몇몇 셀에서 데이터 가져오기 → 뭔가 작업하기 → 결과를 다른 셀에 저장하기.
수백 개의 간단한 명령어를 조합하면 복잡하고 유용한 명령어가 만들어져.
코드에서 변수를 선언하면, 아직 안 쓰인 메모리의 일부가 할당돼. 보통 몇 바이트 정도야. 변수를 선언할 때는 반드시 어떤 타입의 정보를 저장할 건지 지정해야 해: 숫자인지, 텍스트인지, 아니면 다른 데이터인지. 타입을 모르면 변수에 얼마만큼 메모리를 할당해야 할지 알 수 없으니까.
컴퓨터 초창기에는 프로그램이 그냥 메모리 셀 번호로만 작업했는데, 나중에 프로그래머 편의를 위해 셀에 이름을 붙이기 시작했어. 변수의 고유 이름은 사실 프로그래머를 위한 거야. 프로그램은 실행 중에 번호만으로도 충분히 잘 돌아가.
2. 메모리 속 변수
C#에는 정수 저장용 기본 타입이 4개 있어. byte, short, int, long이야.
| 타입 | 크기(바이트) | 이름의 유래 |
|---|---|---|
| byte | 1 | Byte, 한 바이트 메모리를 차지해서 그래 |
| short | 2 | Short Integer의 줄임말이야 |
| int | 4 | Integer의 줄임말이야 |
| long | 8 | Long Integer의 줄임말이야 |
그리고 C#에는 실수 타입도 2개 있어 — float랑 double:
| 타입 | 크기(바이트) | 이름의 유래 |
|---|---|---|
| float | 4 | Floating Point Number의 줄임말이야 |
| double | 8 | Double Float의 줄임말이야 |
프로그램이 변수 생성 명령어를 만나면, 변수 타입에 따라 작은 메모리 공간이 할당돼.
int a = 10;
변수의 주소는 그 변수에 할당된 메모리 블록의 첫 번째 셀 주소야.
C# 프로그램은 메모리에 직접 접근하는 게 금지돼 있어. 메모리 작업은 전부 C#이랑 .NET이 엄격하게 관리해.
3. 메모리 속 string 타입
string 타입은 데이터를 많이 담을 수 있어서, 그냥 데이터 타입이 아니라 완전한 객체야.
string 타입 데이터(텍스트)는 별도의 객체에 저장되고, 그 객체에 메모리가 할당돼. 그리고 그 객체의 주소가 변수에 저장돼. 변수에도 메모리가 할당되지.

- a라는 int 타입 변수는 4 바이트를 차지하고, 값 1을 저장해.
- b라는 int 타입 변수는 4 바이트를 차지하고, 값 10,555를 저장해. 여기서 쉼표는 소수점이 아니라 자리수 구분이야. 소수점은 점(.)으로 구분해.
- d라는 double 타입 변수는 8 바이트를 차지하고, 값 13.001을 저장해.
- str라는 string 타입 변수는 4 바이트를 차지하고, 값 D12을 저장해. 이건 텍스트가 들어있는 객체의 첫 번째 셀 주소야.
string 타입 객체(텍스트 포함)는 별도의 메모리 블록에 저장돼. 그 첫 번째 셀 주소가 str 변수에 저장돼.
4. 우리가 대입할 때 무슨 일이 일어날까
또 하나 중요한 건 대입이 어떻게 동작하는지야. 예를 들어:
int a = 10;
int b = a;
b = 20;
Console.WriteLine(a); // 10
이 예제에서는 메모리에 두 개의 셀이 만들어져: 하나는 a용, 하나는 b용. b = a;라고 쓰면 값이 복사돼(10), "상자" 자체가 복사되는 게 아니야. b를 바꿔도 a에는 아무 영향 없어.
이번엔 문자열로 똑같이 해보자:
string s1 = "Hello";
string s2 = s1;
s2 = s2 + " World";
Console.WriteLine(s1); // "Hello"
Console.WriteLine(s2); // "Hello World"
여기서 s1이랑 s2 두 변수는 같은 문자열 "Hello"를 가리키고 있어. 근데 s2 = s2 + " World"를 하면, s2에 새 문자열 "Hello World"가 만들어지고, s1은 여전히 예전 문자열 "Hello"를 가리켜.
5. 왜 프로그래밍에서는 다 0부터 셀까?
사람들은 왜 프로그래밍에서 거의 항상 0부터 세는지 궁금해하지. 사실 0부터 세는 게 더 편한 경우가 엄청 많아(물론 1부터 세는 게 편한 경우도 있긴 해).
가장 쉬운 예가 바로 메모리 주소 지정이야. 만약 변수에 4 바이트 메모리를 할당받았고, X가 첫 번째 바이트의 주소라면, 각 바이트의 주소는 뭐가 될까? X+0, X+1, X+2, X+3 이렇게 돼. 그래서 인덱스가 0, 1, 2, 3인 바이트 그룹이 생기는 거지.
데이터 블록 안에서 상대 주소를 생각하면 항상 0부터 번호가 매겨져. 이게 바로 0부터 세는 제일 흔한 이유야.
GO TO FULL VERSION