컴퓨터 사이언스

컴퓨터는 'a = 10'을 어떻게 이해할까?

하루이2222 2025. 5. 17. 14:47

우리는 코딩을 할 때 너무나도 당연하게 a = 10과 같은 코드를 작성합니다. 개발자에게 'a'는 10이라는 값을 담는 그릇처럼 직관적으로 이해됩니다. 하지만 컴퓨터에게 'a'라는 이름은 아무 의미가 없습니다.

 

컴퓨터는 오직 0과 1, 그리고 메모리 주소로 세상을 이해합니다.

그렇다면 우리가 작성한 이 간단한 한 줄의 코드는 어떻게 컴퓨터가 이해하고 실행할 수 있는 기계어 코드로 변환될까요?

 

변수 'a'와 'b'를 더하는 간단한 과정을 통해, 그 깊고 흥미로운 내부 동작 원리를 단계별로 파헤쳐 봅시다.

1단계: 개발자와의 약속, '변수 선언'

a = 10
b = 20

프로그래밍에서 a = 10과 같은 변수 선언은 특정 데이터를 저장할 공간에 사람이 이해하기 쉬운 이름을 붙여주는 과정입니다.

 

'a'라는 이름은 컴퓨터를 위한 것이 아니라, 코드를 작성하고 읽는 개발자를 위한 기호(Symbol)이자 약속입니다. 컴퓨터는 이 심볼을 보고 "아, 개발자가 무언가를 저장하고 싶어 하는구나"라고 인지하고 다음 단계를 준비합니다.

2단계: 데이터의 집, '메모리 주소'에 저장

컴퓨터는 변수 'a'와 'b'의 데이터를 실제 물리적인 저장 공간인 메모리(RAM)에 저장합니다. 이때 각각의 데이터는 고유한 주소값을 할당받게 됩니다.

  • a의 값 10은 메모리의 특정 주소 (예: 0x1000)에 저장됩니다.
  • b의 값 20은 다른 메모리 주소 (예: 0x2000)에 저장됩니다.

이처럼 모든 변수는 메모리 내의 고유한 주소를 통해 접근되며, 'a'나 'b'라는 이름은 이 주소를 가리키는 별명인 셈입니다.

3단계: CPU의 작업 공간, '레지스터'로 이동

CPU는 연산을 수행할 때 매번 느린 메모리에 접근하는 대신, CPU 내부에 있는 초고속 임시 저장 공간인 레지스터(Register)를 사용합니다. a + b 연산을 수행하기 위해 컴퓨터는 다음과 같이 동작합니다.

  1. 메모리 주소 0x1000에 저장된 값 10을 CPU의 레지스터(예: eax)로 가져옵니다.
  2. 메모리 주소 0x2000에 저장된 값 20을 다른 레지스터(예: ebx)로 가져옵니다.

이제 CPU는 가장 빠른 작업 공간에 연산에 필요한 모든 재료를 준비해두었습니다.

4단계: 컴퓨터의 진짜 언어, '인스트럭션' 생성

개발자가 작성한 a + b라는 코드는 컴파일 과정을 거쳐 CPU가 직접 실행할 수 있는 기계어 명령어, 즉 인스트럭션(Instruction)으로 변환됩니다. 이 과정을 좀 더 이해하기 쉬운 어셈블리 코드로 표현하면 다음과 같습니다.

mov eax, [0x1000]  ; 메모리 주소 0x1000의 값을 eax 레지스터로 이동(move)
mov ebx, [0x2000]  ; 메모리 주소 0x2000의 값을 ebx 레지스터로 이동(move)
add eax, ebx       ; eax 레지스터의 값과 ebx 레지스터의 값을 더해서 결과를 eax에 저장

이제 ab라는 이름은 사라지고, 오직 메모리 주소와 레지스터, 그리고 mov(이동), add(덧셈)와 같은 구체적인 행동 지침만 남았습니다.

5단계 ~ 7단계: 이름과 주소를 연결하고 실행 파일로!

그렇다면 'a'라는 이름이 어떻게 0x1000이라는 주소로 바뀌었을까요? 바로 어셈블러링커 덕분입니다.

  • 심볼 테이블 생성 (어셈블러): 어셈블러는 a0x1000, b0x2000처럼, 코드에 사용된 모든 심볼(변수명, 함수명 등)과 메모리 주소를 연결하는 '심볼 테이블'이라는 목록을 만듭니다.
  • 주소 결정 (링커): 링커는 여러 코드 조각(오브젝트 파일)을 하나로 합치고, 심볼 테이블을 참조하여 mov eax, [a]와 같이 아직 불완전한 주소들을 최종적인 실제 메모리 주소(mov eax, [0x1000])로 확정합니다.
  • 최종 실행 파일 생성: 이 모든 과정을 거치면 마침내 최종 실행 파일이 만들어집니다. 이 파일 안에는 더 이상 'a'나 'b'와 같은 변수 이름이 존재하지 않습니다. 오직 CPU가 따라야 할 인스트럭션과 데이터가 저장될 메모리 주소 정보만 담겨있을 뿐입니다.

운영체제가 이 파일을 실행하면, CPU는 파일에 적힌 인스트럭션을 순서대로 읽어 메모리 주소에 접근하고, 레지스터를 활용해 연산을 수행하며 우리가 의도했던 a + b의 결과를 만들어내는 것입니다.

결론: 변수명은 개발자를 위한 배려

결국 a = 10이라는 코드는 인간의 편의를 위해 고안된 고도의 추상화입니다. 우리가 사용하는 변수명은 컴파일과 링킹 과정에서 자신의 역할을 다하고 사라지는 안내자인 셈입니다.

 

그 이면에서는 변수가 메모리 주소로, 코드가 CPU 인스트럭션으로 변환되는 복잡하지만 정교한 과정이 숨어있습니다. 오늘 당장 사용하는 변수 하나에도 컴퓨터 과학의 깊은 원리가 담겨있다는 사실, 재밌죠?