안녕하세요 개발자 베베입니다.
이번 글에서는 프로그램이 만들어지는 과정에 대해서 알아보도록 하겠습니다.
관련 글
프로그램의 정의
우리가 평소에 손쉽게 사용하는 프로그램이란 다음과 같은 뜻을 가지고 있습니다.
- Program : 어떤 문제를 해결하기 위해 컴퓨터에게 주어지는 처리 방법과 순서를 기술한 일련의 명령어 집합
프로그램은 말 그대로 컴퓨터에게 무언가 작업을 시키게 하는 명령어를 모아둔 명령어 모음집입니다. 이 명령어는 컴퓨터가 사용하는 언어인 기계어로 작성되어있으며, 컴퓨터의 부품 중 하나인 CPU는 이 명령어를 해독하고 그에 맞는 명령을 수행합니다.
프로그램을 만든다는 것은 이 명령어를 작성해주는 것과 같습니다. 일단 프로그램을 통해서 얻으려고 하는 목표를 설정한 후, 그 목표를 수행하기 위해 필요한 명령어들을 작성해주는 것이죠.
프로그래밍 언어
위에서 프로그램의 정의에 대해서 알아보았습니다. 결국 프로그램이란 명령어의 모임이라는 것인데요. 그럼 명령어는 어떻게 작성할까요?
명령어를 작성하는 방법은 크게 3가지 방법이 있습니다.
1. 기계어로 명령어를 작성한다.
2. 어셈블리어로 명령어를 작성한다.
3. 고급 언어로 명령어를 작성한다.
이 세가지 방법에 대해서 하나씩 알아보도록 하겠습니다.
기계어
컴퓨터는 기계어를 사용한다고 했었죠. 프로그램을 만드는 가장 단순한 방법은 기계어로 명령어를 작성하는 것입니다. 하지만 말이 그렇다는 것이지 이 방법은 쉽지 않습니다. 그 이유는, 기계어의 형태는 사람이 이해하기에 쉽지 않은 형태를 띄고 있기 때문입니다. 기계어는 아래처럼 숫자로 이루어져 있습니다.
55 89 8B 45 0C 03 45 08 01 05 00 00 00 00 5D C3
컴퓨터는 위 숫자들을 이해할 수 있습니다. 그렇게 설계되었기 때문이죠. 이 세상에 존재하는 모든 프로그램은 이러한 기계어로 쓰여있습니다.
하지만 사람이 위와 같은 기계어로 코드를 작성하는 것은 쉽지 않습니다. 일단 숫자 하나라도 틀리면 실행이 안될꺼고, 딱 봤을 때 무슨 명령어인지 알 수 없으니까요.
어셈블리어
이러한 문제로 인해 2번째 방법인 어셈블리어로 명령어를 작성한다 가 탄생한 것인데요. 어셈블리어는 숫자로 이루어진 기계어의 문제를 해결하기 위해 탄생했습니다. 어셈블리어는 아래처럼 생겼습니다.
ADD SUB MOV
어셈블리어를 딱 보면, 덧셈은 무엇이고 뺄셈은 무엇인지 직관적으로 알 수 있지 않나요? 어셈블리어는 기계어를 영어로 번역해놨기 때문에 사용하기 편했습니다. 하지만 어셈블리어도 큰 단점이 존재하는데, 그것은 코드 작성 시에 컴퓨터의 작동 방식에 대한 깊은 이해가 필요하다는 점입니다. 이러한 단점 때문에 어셈블리어가 탄생한 시기에는 프로그래밍이 인기가 없었습니다. 진입장벽이 높았기 때문이죠.
고급언어
어셈블리어의 단점을 해결하기 위해 좀 더 사람 친화적인 언어인 고급 언어가 탄생하게 됩니다. 우리가 흔히 사용하는 C, Java 같은 프로그래밍 언어는 모두 고급 언어의 범주에 속합니다.
고급언어를 사용한다면 컴퓨터의 구조는 완벽하게 알지 않아도 됩니다. 좀 더 논리적이게 코드를 작성할 수 있게 되며 그로 인해 코드 생산성이 비약적으로 증가하게 됩니다. 예를 들어 어셈블리어로 숫자 1과 1을 더하는 코드를 작성하려면 아래와 같은 코드를 작성해야 합니다.
mov %eax 1
mov %ebx 1
add %eax %ebx
하지만 고급언어를 사용한다면 아래와 같은 논리적이고도 아름다운 코드를 작성할 수 있게 되죠.
1 + 1
시대가 변하면서 프로그램의 크기도 커지고 사용 목적도 다양해졌습니다. 이젠 특별한 이유가 아니라면 어셈블리어를 사용할 이유가 없어졌죠. 왜냐하면 고급 언어로 작성해야만 거대한 프로그램을 관리할 수 있으니까요.
컴파일
프로그램은 기계어로 작성된 명령어의 집합입니다. C언어로 작성된 코드를 실행파일로 변환하기 위해서는 기계어로 번역해주는 과정이 필요한데, 이 과정을 컴파일이라고 부릅니다.
컴파일은 컴파일러라는 특수 프로그램이 수행합니다.
컴파일 전체 과정
C언어로 작성한 코드를 실행파일로 컴파일하는 전체 과정은 다음과 같습니다.
C언어로 작성된 소스파일은 영어 텍스트 파일입니다. 이 파일을 C 컴파일러에게 전달해주면 먼저 전처리 과정을 거칩니다.
그 후에 컴파일러는 기계어로 번역하기 위해 C 코드를 어셈블러에게 전달하여 어셈블리 코드로 변환합니다.
마지막으로 어셈블리 파일을 한 곳에 모아 연결해주는 링크 과정을 거쳐 최종적으로 기계어로 번역하여 실행파일을 생성하게 됩니다.