개발자로 근무하면서 기획자나, QA, 운영하시는 분들께 종종 질문들을 받습니다.
위와 같은 다양한 질문들을 받고 설명할 때, 경력과 근무하시는 환경에 따라 CS에 대한 이해가 각각 다르시기 때문에 어떻게 설명을 드려야 하는지 가끔 막막할 때가 있었습니다.
그럴 때마다 CS에 대해 비전공자 분들도 이해하실 수 있는 문서가 있어서 이를 바탕으로 설명할 수 있었으면 좋겠다고 생각했습니다.
이 글은 이처럼, 개발자와 같이 협업하면서 일하시는 분들이 이해하시면 좋을 내용과 원활한 설명을 위한 레퍼런스로써 역할을 수행할 수 있도록 하기 위해 작성되었습니다.
이 포스트는 강민철 님의 [혼자 공부하는 컴퓨터 구조+운영체제] 를 읽고 요약・정리한 글입니다.
일반적으로 윈도우 운영체제라면, 작업 관리자에 들어가면 실행중인 프로세스를 확인할 수 있습니다. 그중에는 사용자가 볼 수 있는 공간에서 실행되는 프로세스도 있지만, 보이지 않는 공간에서 실행되는 프로세스도 있습니다.
전자는 사용자가 보는 앞에서 실행되는 프로세스라는 점에서 포그라운드 프로세스, 후자는 사용자가 보지 못하는 뒤에서 실행되는 프로세스라는 점에서 백그라운드 프로세스라고 합니다.
모든 프로세스는 실행을 위해 CPU를 필요로 하지만, CPU 자원은 한정되어 있습니다. 그렇기에 프로세스들은 차례대로 돌아가며 한정된 시간만큼만 CPU를 이용합니다. 자신의 차례가 되면 정해진 시간만큼 CPU를 이용하고 시간이 끝났음을 날리는 인터럽트가 발생하면 양보하고 다음을 기다립니다.
운영체제는 빠르게 번갈아 수행되는 프로세스의 실행 순서를 관리하고, 프로세스에 CPU를 비롯한 자원을 배분합니다. 이를 위해 운영체제는 프로세스 제어 블록(PCB)을 이용합니다. PCB는 프로세스와 관련된 정보를 저장하는 자료구조입니다. 여기에는 해당 프로세스를 식별하기 위해 꼭 필요한 정보들이 저장됩니다.
메모리는 커널 영역과 사용자 영역으로 나뉘어져 있고, PCB는 커널 영역에 생성됩니다.
하나의 프로세스가 수행을 재개하기 위해 기억해야 할 정보를 문맥(Context)라고 합니다. 하나의 프로세스 문맥은 해당 프로세스의 PCB에 표현되어 있습니다. PCB에 기록되는 정보들을 문맥이라고 봐도 무방합니다.
실행 문맥을 잘 기억해두면 언제든 해당 프로세스의 실행을 재개할 수 있기 때문에 프로세스가 CPU를 사용할 수 있는 시간이 다 되거나 예기치 못한 상황이 발생하여 인터럽트가 발생하면 운영체제는 해당 프로세스의 PCB에 문맥을 백업합니다.
이처럼 기존 프로세스의 문맥을 PCB에 백업하고, 새로운 프로세스를 실행하기 위한 문맥을 PCB로 부터 복구하여 새로운 프로세스를 실행하는 것을 문맥 교환이라고 합니다.
문맥 교환은 여러 프로세스가 끊임업이 빠르게 번갈아가며 실행되는 원리입니다. 문맥 교환이 자주 일어나면 프로세스는 그만큼 빨리 번갈아가며 수행되기 때문에 프로세스들이 동시에 실행되는 것처럼 보입니다.
쓰레드는 실행의 단위입니다. 좀 더 정확히는, 쓰레드란 한 프로세스를 구성하는 실행 흐름 단위입니다. 그리고 하나의 프로세스는 여러 개의 쓰레드를 가질 수 있습니다. 쓰레드를 이용하면 하나의 프로세스에서 여러 부분을 동시에 실행할 수 있습니다.
전통적인 관점에서 보면 하나의 프로세스는 한 번에 하나의 일만을 처리했습니다. '실행의 흐름 단위가 하나' 라는 점에서 이렇게 실행되는 프로세스들은 단일 쓰레드 프로세스라고 볼 수 있습니다.
하지만, 쓰레드라는 개념이 도입되면서 하나의 프로세스가 한 번에 여러 일을 동시에 처리할 수 있게 되었습니다. 즉, 프로세스를 구성하는 여러 명령어를 동시에 실행할 수 있게 되었습니다.
이런 점에서 볼 때 쓰레드는 '프로세스를 구성하는 실행 단위'라고 볼 수 있습니다.
여기서 중요한 점은 쓰레드들은 실행에 필요한 최소한의 정보만을 유지한 채 프로세스 자원을 공유하며 실행한다는 점입니다.
컴퓨터는 실행 과정에서 여러 프로세스가 동시에 실행될 수 있고, 그 프로세스를 이루는 쓰레드는 여러 개 있을 수 있습니다. 이때 프로세스를 동시에 실행하는 것을 멀티 프로세스, 그리고 쓰레드를 동시에 실행하는 것을 멀티 쓰레드라고 합니다.
여기에는 큰 차이가 있습니다. 프로세스끼리는 기본적으로 자원을 공유하지 않지만, 쓰레드끼리는 같은 프로세스 내의 자원을 공유하기 때문입니다.
프로세스의 자원을 공유한다는 특성은 단점이 되기도 하는데, 하나의 프로세스에 문제가 생기면 이와 자원을 공유하는 모든 쓰레드가 영향을 받을 수 있습니다.