프로세스 VS 스레드
들어가며
컴퓨터 프로그램을 사용할 때 전공 지식이 꼭 필요하진 않습니다.
하지만 소프트웨어를 직접 개발하는 사람이라면,
언젠가는 컴퓨터 실행 내부 요소를 하나씩 따져보게 되는 순간이 찾아옵니다.
아마 운영체제(OS)에 대해 처음 입문하면 가장 먼저 듣게 되는 개념이
바로 프로세스와 스레드일 것입니다.
결론부터 말하자면 이 둘을 한마디로 정의하면 다음과 같습니다.
- 프로세스(Process): 운영체제로부터 자원을 할당받은 작업의 단위
- 스레드(Thread): 프로세스가 할당받은 자원을 이용하는 실행 흐름의 단위
여기서 중요한 단어는 바로 “작업의 단위(프로세스)”와 “실행 흐름의 단위(스레드)”입니다.
프로그램과 프로세스
정적 프로그램(Static Program)
‘프로세스’라는 용어는 다소 낯설 수 있지만, ‘프로그램’이라는 단어는 누구나 익숙합니다.
예를 들어 윈도우의 *.exe 파일이나 맥OS의 *.dmg 파일처럼,
실행 가능한 파일을 우리는 프로그램이라고 부릅니다.

하지만 이 시점의 프로그램은 아직 실행되지 않은 상태입니다.
단순히 저장 장치에 올라가 있는 정적인 코드 덩어리일 뿐이죠
그래서 이를 정적 프로그램(Static Program), 줄여서 그냥 프로그램(Program)이라고 부릅니다.
즉, 프로그램은 자바·C 같은 언어로 작성된 코드가 파일로 완성된 결과물,
말 그대로 코드 묶음입니다.
프로세스(Process)
그렇다면 프로세스는 무엇일까요?
프로그램이 단순한 코드 덩어리에 불과하다면,
프로세스는 그 코드가 실제로 실행되어 살아 움직이는 상태입니다.
- 프로그램을 더블 클릭 → 메모리에 적재 → CPU 자원 할당 → 실행 시작
이 일련의 과정을 거친 순간,
프로그램은 정적 상태를 벗어나 동적(動的)인 실행 단위,
즉, 프로세스로 변합니다.

사실 이 개념은 전혀 낯설지 않습니다.
우리가 Ctrl + Alt + Del을 눌러 열어보는 작업 관리자(Task Manager) 속 목록이 바로 실행 중인 프로세스들입니다.
프로그램 vs 프로세스 정리
결국 두 개념은 실행 여부에서 갈립니다.
같은 앱이라도 실행 전에는 “프로그램”, 실행 후에는 “프로세스”인 것이죠.
그래서 흔히 혼용되기도 하지만, 엄밀히는 다른 개념입니다.
| 구분 | 프로그램 | 프로세스 |
| 정의 | 실행 가능한 파일 | 실행되어 동작 중인 프로그램 |
| 상태 | 정적 (저장 장치에만 존재) | 동적 (메모리에 적재, CPU 자원 할당) |
| 비유 | 코드 덩어리 | 그 코드가 실행되어 돌아가는 상태 |
| 예시 | chrome.exe 파일 | 실행 중인 크롬 브라우저 창 |
스레드(Thread)
프로세스의 한계
과거에는 프로그램을 실행하면 보통 프로세스 하나만을 사용했습니다.
하지만 시간이 흐르며 프로그램은 점점 복잡해지고,
동시에 여러 가지 일을 처리해야 하는 경우가 많아졌습니다.
예를 들어 예전에는 파일을 다운로드하면,
그 프로세스가 실행을 끝낼 때까지 다른 일을 할 수 없었습니다.
다운로드가 끝날 때까지 하루 종일 기다려야 했던 셈이죠.
그렇다고 동일한 프로그램을 여러 개의 프로세스로 띄우면 어떻게 될까요?
각각의 프로세스가 메모리를 따로 차지하고,
CPU 자원을 중복해서 할당받게 됩니다.
자원 낭비가 심해지고 효율도 떨어지겠죠.
→ 바로 이 한계를 극복하기 위해 등장한 개념이 스레드(Thread)입니다.
스레드의 개념
스레드란 하나의 프로세스 내에서 동시에 진행되는 작업 갈래, 실행 흐름의 단위를 말합니다.

비유를 들어보죠.
크롬 브라우저를 실행하면 프로세스 하나가 만들어집니다.
그런데 우리는 그 안에서 파일을 다운로드하면서,
동시에 온라인 쇼핑을 하고, 또 게임까지 하기도 합니다.
이게 가능한 이유는, 하나의 프로세스 안에서 여러 작업 흐름이 동시에 돌아가기 때문입니다.
이 각각의 흐름이 바로 스레드입니다.
여러 개의 스레드가 있으면 이를 멀티스레드(Multi-thread)라고 부릅니다.
즉, 하나의 프로세스 안에 여러 개의 스레드가 들어 있고,
이들이 동시에 다양한 작업을 처리해주면서 프로그램이 훨씬 더 유연하고 빠르게 동작할 수 있는 것입니다.
스레드와 프로그래밍
일반적으로 하나의 프로그램은 하나 이상의 프로세스를 가지고 있고,
하나의 프로세스는 반드시 하나 이상의 스레드를 갖습니다.
즉, 프로세스가 생성되면 자동으로 메인(Main) 스레드가 하나 만들어집니다.
여기에 추가 스레드를 2개, 3개 ... 넣고 싶다면?
→ 이는 개발자가 직접 프로그래밍을 통해 구현해야 합니다.
그래서 별도로 스레드 프로그래밍이라는 주제가 존재하는 것이죠.
프로세스의 메모리 구조
프로그램이 실행되어 프로세스가 되면, 운영체제(OS)는 해당 프로세스에 독립된 주소 공간을 만들어 줍니다.

이 공간은 크게 4가지 영역으로 나뉘며, 각 영역은 다른 성격과 수명을 가집니다.
1. 코드 영역 (Code / Text Segment)
- 역할: 실행할 기계어 코드(함수, 명령어 등)를 저장.
- 특징:
- 읽기 전용(Read-only) → 코드 자체가 실행 중에 변경되지 않도록 보호.
- 여러 프로세스가 같은 프로그램을 실행할 경우, 코드 영역은 공유될 수 있음.
2. 데이터 영역 (Data Segment)
- 역할: 전역 변수, static 변수 등 프로그램 전체에서 공유되는 데이터를 저장.
- 세부 영역:
- .data: 초기값이 있는 전역/정적 변수.
- .bss: 초기값이 없는 전역/정적 변수 (실행 시 0으로 초기화).
- .rodata: 상수(const), 리터럴 문자열 등 변경 불가 데이터.
- 특징:
- 프로그램 시작 시 크기가 결정됨.
- 프로세스가 끝날 때까지 유지됨.
3. 스택 영역 (Stack)
- 역할: 함수 호출 시 생성되는 지역 변수, 매개변수, 리턴 주소 등을 저장.
- 특징:
- 함수 호출 시 할당되고, 함수 종료 시 해제됨 (LIFO 구조).
- 자동으로 관리됨 (malloc/free 같은 명시적 해제가 필요 없음).
- 메모리 초과 시 Stack Overflow 발생.
- 스레드마다 독립적인 스택을 가짐.
4. 힙 영역 (Heap)
- 역할: 런타임에 동적으로 생성되는 객체/메모리 블록을 저장.
- 특징:
- malloc, new 같은 시스템 호출을 통해 개발자가 직접 관리.
- 사용 후 반드시 free, delete로 해제 필요.
- 크기가 자유롭게 늘어나거나 줄어들 수 있음.
- 잘못된 관리 시 메모리 누수(Memory Leak) 발생 가능.
- 프로세스 내에서 스레드들이 공유.
스레드의 자원 공유
스레드는 프로세스가 할당받은 자원을 활용하는 실행 단위입니다.
스레드끼리는 프로세스의 자원을 공유하며 실행 흐름의 일부가 되기 때문에, 여러 동시 작업이 가능한 것이죠.
그래서 흔히 “하나의 프로세스 안에 여러 개의 스레드가 들어있다”라고 표현합니다.
프로세스 메모리 구조와 스레드
- 프로세스:
- 독립적인 코드, 데이터, 힙, 스택 공간을 가짐.
- 다른 프로세스와는 메모리 공간을 공유하지 않음.
- 스레드:
- 같은 프로세스 내의 코드, 데이터, 힙을 공유.
- 스택은 독립적 → 각 스레드마다 독립적인 함수 호출과 실행 흐름이 가능
- Heap 메모리는 공유되므로 → 서로 다른 스레드가 같은 데이터를 읽고 쓸 수 있다.
👉 바로 이 점 덕분에 스레드는 효율적인 동시 실행이 가능해집니다.

프로세스의 자원 공유
반면, 프로세스는 기본적으로 서로의 메모리에 직접 접근할 수 없습니다.
각 프로세스는 메모리에서 독립적인 주소 공간을 가지고 실행되기 때문입니다.
그렇다면 프로세스끼리는 정보를 절대 공유할 수 없을까요?
사실 특별한 방법을 사용하면 가능합니다.
이를 IPC(Inter-Process Communication, 프로세스 간 통신)라고 부릅니다.
대표적인 방식은 다음과 같습니다.
- IPC (Inter-Process Communication)
- LPC (Local Inter-Process Communication)
- 공유 메모리(Shared Memory) 설정
- 파이프
- 메시지 큐
하지만 이러한 방식은 단순히 CPU 레지스터만 교체하는 수준이 아니라,
RAM과 CPU 사이의 캐시 메모리까지 초기화해야 합니다.
즉, 자원 부담이 크고 효율이 떨어집니다.
스레드 vs 프로세스 자원 공유
바로 이 차이 때문에, 현대 운영체제는 다중 프로세싱도 지원하지만
기본적으로는 멀티스레딩을 중심으로 동작합니다.
- 프로세스는 독립성이 강하지만, 자원 공유와 협력이 무겁다.
- 스레드는 자원을 공유하면서도 독립적인 실행 흐름을 가지므로, 다중 작업에 더 효율적이다.
프로세스 & 스레드의 동시 실행 원리
1. 멀티태스킹 (Multi-tasking)
- 우리가 음악을 들으면서 웹서핑도 하고, 메신저도 쓰는 것은
운영체제(OS)가 프로세스와 스레드를 동시에 실행하는 것처럼 관리하기 때문입니다. - 실제로는 CPU 코어 개수보다 훨씬 많은 프로세스/스레드가 실행되지만,
OS의 스케줄링과 컨텍스트 스위칭(Context Switching) 덕분에 동시 실행처럼 보이게 됩니다.
2. 병렬성 (Parallelism)
물리적으로 동시에 실행되는 것
- 정의: 여러 개의 코어에서 여러 작업을 물리적으로 동시에 실행하는 것.
- 예) 쿼드코어 CPU에서 4개의 작업이 동시에 진행됨.
- CPU가 많을수록 실제 처리 속도가 줄어듦.
3. 동시성 (Concurrency)
동시에 실행되는 것처럼 보이는 것
- 정의: 단일 코어에서도 여러 작업이 동시에 실행되는 것처럼 보이게 하는 방식.
- 실제로는 CPU가 A → B → C → D 작업을 아주 짧은 시간 단위로 번갈아 처리.
- 컨텍스트 스위칭(Context Switching)을 통해 작업 전환이 이루어짐.
- 사용자는 프로그램들이 "동시에 실행되는 것처럼" 느끼게 됨.
4. 병렬성과 동시성의 결합
- 실제 컴퓨터에서는 병렬성과 동시성이 섞여서 작동합니다.
- 코어 수(병렬성)만큼 여러 프로세스/스레드가 동시에 실행.
- 나머지는 스케줄링 + 동시성 처리로 번갈아 실행.
- 이렇게 해서 "4코어 8스레드 CPU"에서도 수십 개, 수백 개의 프로세스를 동시에 다루는 것이 가능.
5. 동시성이 필요한 이유
- 하드웨어 한계
- CPU 클럭 속도를 무작정 높이기 어렵기 때문에, 다수의 프로세스를 동시에 처리하려면 동시성이 필요.
- 효율성
- 무거운 작업이 먼저 실행되어 가벼운 작업이 대기하지 않도록, 작은 단위로 쪼개 번갈아 실행
→ 빠른 반응성 제공.
- 무거운 작업이 먼저 실행되어 가벼운 작업이 대기하지 않도록, 작은 단위로 쪼개 번갈아 실행
프로세스 & 스레드의 생명 주기
프로세스와 스레드는 단순히 “생겼다 → 사라졌다”가 아니라,
하나의 생명 주기(Life Cycle)를 가집니다.
운영체제는 이 생명 주기를 관리하면서,
CPU와 메모리 같은 시스템 자원을 효율적으로 분배합니다.
그래서 멀티태스킹 환경이 가능해지고,
우리가 동시에 여러 작업을 하는 것처럼 보이는 것입니다.
프로세스 스케줄링(Process Scheduling)
운영체제는 동시에 실행을 원하는 여러 프로세스 중에서,
누구에게 CPU를 먼저 줄지를 계속 결정해야 합니다.
이 과정을 프로세스 스케줄링이라고 합니다.
- 고려 요소: 우선순위, 실행 시간, 작업량
- 목적: CPU 활용률 극대화, 시스템 전체 성능 향상
- 결과: 사용자는 여러 작업을 동시에 처리하는 것처럼 느낄 수 있음 (멀티태스킹)
대표적인 스케줄링 알고리즘은 다음과 같습니다.
- FCFS (First-Come, First-Served) : 먼저 도착한 프로세스 순서대로 실행
- SJF (Shortest Job First) : 실행 시간이 가장 짧은 프로세스 우선
- Priority : 우선순위가 높은 프로세스 우선
- Round-Robin (RR) : 일정 시간 단위로 프로세스를 번갈아 실행
- Multilevel Queue : 여러 개의 대기열을 두고 상황에 따라 다른 방식으로 스케줄링
👉 한마디로 말해, 프로세스 스케줄링은 운영체제가 심판이 되어
프로세스들에게 공평하고 효율적으로 CPU를 배분하는 과정입니다.
프로세스 상태(Process States)
프로세스는 실행되는 동안 여러 상태를 오가며 변화합니다.
운영체제는 이 상태를 관리하면서, 언제 실행할지·언제 대기시킬지를 조정합니다.
일반적으로 프로세스는 다음 5가지 상태를 가집니다.
| 상태 | 설명 |
| 생성(New) | 프로세스가 막 생성된 상태. 아직 실행 준비가 되지 않음 |
| 준비(Ready) | CPU를 할당받기 위해 대기 중인 상태. 언제든 실행될 수 있음 |
| 실행(Running) | CPU를 할당받아 실제로 실행 중인 상태 |
| 대기(Waiting) | I/O 요청 등 이벤트로 인해 잠시 멈춰 있는 상태. 이벤트가 끝나면 다시 Ready로 전환 |
| 종료(Terminated) | 실행이 완료되어 메모리에서 제거된 상태 |

운영체제는 상황에 따라 이 상태들을 전환합니다. 예를 들어:
- Dispatch : Ready → Running
- Interrupt : Running → Ready
- I/O Wait : Running → Waiting
- Completion : Waiting → Ready
👉 이처럼 프로세스는 상황에 따라 New → Ready → Running → Waiting → Terminated 사이를 오가며,
운영체제는 이 흐름을 관리해 전체 시스템이 원활하게 동작하도록 합니다.
결론: 프로세스와 스레드의 핵심 정리
프로세스와 스레드는 운영체제를 이해하는 데 있어 가장 기본적이면서도 중요한 개념입니다.
- 프로세스(Process)는 운영체제로부터 자원을 할당받아 독립적으로 실행되는 작업의 단위입니다.
프로그램이 단순한 파일 상태에서 벗어나 실제로 실행될 때 프로세스가 되며, 각자 독립적인 주소 공간을 가집니다. - 스레드(Thread)는 프로세스 내부에서 실행되는 흐름의 단위입니다.
같은 프로세스 안에서는 코드, 데이터, 힙 영역을 공유하고, 스택만 독립적으로 갖습니다.
이 구조 덕분에 여러 스레드가 효율적으로 협력하면서 동시에 다양한 일을 처리할 수 있습니다.
프로세스는 안정성과 독립성이 뛰어나지만,
서로 자원을 공유하려면 무거운 IPC 방식을 써야 한다는 한계가 있습니다.
반대로 스레드는 자원을 공유하기 때문에 가볍고 빠르게 협력할 수 있지만,
동기화 문제나 충돌 위험을 관리해야 한다는 숙제를 안고 있습니다.
현대의 운영체제와 프로그램은 이 두 개념을 적절히 활용합니다.
- 여러 애플리케이션을 동시에 실행하기 위해 멀티프로세스를 사용하고,
- 하나의 애플리케이션 안에서 다양한 작업을 병렬적으로 처리하기 위해 멀티스레드를 사용합니다.
결국, 프로세스와 스레드는 “독립성과 효율성의 균형”을 이루기 위한 도구라고 할 수 있습니다.
이 차이를 이해하는 것은 단순히 운영체제 이론에 머무르지 않고,
실제로 소프트웨어를 설계하거나 성능을 최적화하는 데 큰 도움이 됩니다.