4주차 Unit 1.2 — 프로세스와 스레드

Psj·2026년 5월 20일

F-lab

목록 보기
121/240

Unit 1.2 — 프로세스와 스레드

F-LAB JAVA · 4주차 · Phase 1 · 동시성의 기초


📌 학습 목표

이 Unit을 끝내면 다음을 답할 수 있어야 한다.

  • 프로세스 (Process) 의 정의와 특징은?
  • 스레드 (Thread) 의 정의와 특징은?
  • 프로세스의 메모리 구성 (코드/데이터/힙/스택) 은?
  • 스레드가 공유하는 것 vs 개별인 것 은?
  • 스레드가 힙은 공유하고 스택은 따로 갖는 이유는?
  • 프로세스 vs 스레드 를 클래스/인스턴스에 비유하면?
  • PCB (Process Control Block) 와 TCB 는?
  • 멀티프로세스 vs 멀티스레드 의 장단점은?
  • 스레드 안전 (Thread Safety) 의 근원은?

🎯 핵심 한 문장

프로세스 (Process) 는 실행 중인 프로그램으로 독립적인 메모리 공간을 가지며, 스레드 (Thread) 는 프로세스 안에서 코드를 한 줄씩 실행하는 흐름이다.
하나의 프로세스는 최소 1개 이상의 스레드 를 반드시 포함 (메인 스레드).
프로세스의 메모리 중 코드/데이터/힙 (Heap) 은 모든 스레드가 공유 하고, 스택 (Stack) 은 스레드마다 개별 할당된다.
스택이 개별인 이유는 각 스레드가 독립적인 실행 흐름 (메서드 호출, 지역 변수) 을 가져야 하기 때문이고, 힙이 공유인 이유는 스레드들이 협력하며 데이터를 주고받기 위함.
바로 이 공유 메모리 (힙) 때문에 동시성 문제 (데이터 불일치) 가 발생하며, 이것이 4주차의 핵심 주제다.

비유 — 회사와 직원

프로세스 = 독립된 회사 (건물)
  - 각 회사는 독립된 사무실 공간 (메모리)
  - 다른 회사의 자료에 직접 접근 X
  - 회사 간 소통은 별도 절차 (IPC)

스레드 = 회사 안의 직원들
  - 같은 회사 자료실 (힙) 공유
  - 각자 개인 책상 (스택)
  - 자료실에서 협력
  - 같은 자료 동시 수정 시 충돌 (동시성 문제)

공유 자료실 (힙):
  - 직원들이 함께 사용
  - 동시에 같은 문서 수정하면? → 충돌
  - 규칙 (동기화) 필요

개인 책상 (스택):
  - 각자 개인 작업
  - 충돌 없음 (스레드 안전)

→ 프로세스 = 회사, 스레드 = 직원, 힙 = 공유 자료실, 스택 = 개인 책상.


🧭 9개 섹션 로드맵

1. 프로세스의 정의와 특징
2. 스레드의 정의와 특징
3. 프로세스의 메모리 구성
4. 스레드의 공유 vs 개별
5. 스택이 개별인 이유
6. 클래스/인스턴스 비유
7. PCB와 TCB
8. 멀티프로세스 vs 멀티스레드
9. 면접 + 자기 점검

1️⃣ 프로세스의 정의와 특징

1.1 프로세스의 정의

프로세스 (Process):

  실행 중인 프로그램.
  디스크의 프로그램 파일이 메모리에 올라와
  실행되고 있는 상태.

특징:
  - 독립적인 메모리 공간
  - OS 가 작업 단위로 관리
  - 최소 1개 스레드 포함

1.2 프로그램 vs 프로세스

프로그램 (Program):
  - 디스크의 정적 파일
  - 실행 코드 + 데이터
  - 예: shipment.jar

프로세스 (Process):
  - 실행 중인 프로그램
  - 메모리에 로드됨
  - 동적 (실행 상태)
  - 예: java -jar shipment.jar 실행 중

비유:
  - 프로그램 = 요리 레시피 (종이)
  - 프로세스 = 실제 요리하는 중

1.3 프로세스의 독립성

프로세스의 독립적 메모리:

  프로세스 A          프로세스 B
  ┌──────────┐      ┌──────────┐
  │ 코드      │      │ 코드      │
  │ 데이터    │      │ 데이터    │
  │ 힙        │      │ 힙        │
  │ 스택      │      │ 스택      │
  └──────────┘      └──────────┘
  
  서로 직접 접근 X
  - A 가 B 의 메모리 못 봄
  - OS 가 보호 (메모리 격리)

장점:
  - 안정성 (한 프로세스 죽어도 다른 건 OK)
  - 보안

단점:
  - 통신 비용 (IPC 필요)
  - 생성 비용 큼

1.4 프로세스 간 통신 (IPC)

IPC (Inter-Process Communication):

  프로세스들이 데이터를 주고받는 방법.

종류:
  - 파이프 (Pipe)
  - 소켓 (Socket)
  - 공유 메모리 (Shared Memory)
  - 메시지 큐 (Message Queue)
  - 시그널 (Signal)

특징:
  - 별도 메커니즘 필요
  - 스레드 간 통신보다 비용 ↑

1.5 프로세스의 생성

프로세스 생성:

  fork() (Unix):
    - 부모 프로세스 복제
    - 자식 프로세스 생성

  비용:
    - 메모리 공간 할당
    - 자원 복사
    - 큼

자바 프로세스:
  - JVM 하나가 1 프로세스
  - java -jar app.jar = 1 프로세스

1.6 ILIC 의 맥락

// ILIC 서버는 1개 JVM 프로세스
// java -jar ilic.jar

// 외부 프로세스 실행 (드물게)
public class ExternalProcessExample {
    
    public void runConverter(Path input, Path output) throws IOException, InterruptedException {
        // 별도 프로세스 실행 (PDF 변환 등)
        ProcessBuilder pb = new ProcessBuilder(
            "wkhtmltopdf", input.toString(), output.toString());
        
        Process process = pb.start();   // 새 프로세스
        int exitCode = process.waitFor();   // 완료 대기
        
        if (exitCode != 0) {
            throw new IOException("Conversion failed");
        }
    }
}

// 하지만 대부분의 동시 처리는
// 같은 프로세스 안의 멀티스레드로

1.7 자기 점검 답변

프로세스의 정의와 특징은?

:
1. 정의:

  • 실행 중인 프로그램
  • 메모리에 로드
  1. 프로그램 vs 프로세스:

    • 프로그램: 정적 파일
    • 프로세스: 실행 중
  2. 독립성:

    • 독립 메모리
    • 서로 직접 접근 X
    • OS 보호
  3. 통신:

    • IPC (파이프, 소켓 등)
    • 비용 ↑
  4. 특징:

    • 안정성, 보안
    • 생성 비용 큼

2️⃣ 스레드의 정의와 특징

2.1 스레드의 정의

스레드 (Thread):

  프로세스 안에서 코드를 한 줄씩 실행하는 흐름.
  "실 (thread)" 이 코드를 위에서 아래로 꿰는 것.

특징:
  - 프로세스의 자원 공유 (힙, 코드, 데이터)
  - 자체 스택 보유
  - 실행의 최소 단위

2.2 실행 흐름으로서의 스레드

스레드 = 실행 흐름:

  코드:
    line 1: int x = 10;
    line 2: process(x);
    line 3: return x;

  스레드:
    - line 1 → line 2 → line 3 순차 실행
    - "실" 이 코드를 꿰는 것

멀티스레드:
    스레드 A: line 1 실행 중
    스레드 B: line 5 실행 중
    → 같은 코드를 여러 흐름이 동시 진행

2.3 메인 스레드

메인 스레드 (Main Thread):

  프로세스 시작 시 자동 생성되는 첫 스레드.

자바:
  public static void main(String[] args) {
      // 이 코드는 메인 스레드에서 실행
  }

특징:
  - 모든 프로세스는 메인 스레드로 시작
  - 추가 스레드는 메인에서 생성
  - 메인 스레드 종료 ≠ 프로세스 종료 (다른 스레드 있으면)

2.4 스레드의 생성 비용

스레드 생성 비용 (프로세스보다 적음):

  프로세스 생성:
    - 새 메모리 공간
    - 자원 복사
    - 큼

  스레드 생성:
    - 스택만 새로 (약 1MB)
    - 힙, 코드 공유
    - 상대적으로 적음
    - 하지만 여전히 비용 있음 (Phase 7 에서 풀)

2.5 스레드의 장점

멀티스레드의 장점:

1. 자원 공유
   - 힙, 코드 공유
   - 메모리 효율

2. 통신 쉬움
   - 공유 메모리로 직접
   - IPC 불필요

3. 생성 비용 적음
   - 프로세스보다

4. 컨텍스트 스위칭 빠름
   - 같은 프로세스 내
   - 메모리 공간 유지

단점:
  - 동기화 문제 (공유 자원)
  - 한 스레드 오류가 전체 영향

2.6 ILIC 의 맥락

// 자바 스레드 생성
public class ShipmentThreadExample {
    
    public void demonstrateThreads() {
        // 메인 스레드에서 실행 중
        System.out.println("Main: " + Thread.currentThread().getName());
        // "Main: main"
        
        // 새 스레드 생성
        Thread worker = new Thread(() -> {
            System.out.println("Worker: " + Thread.currentThread().getName());
            processShipments();
        });
        worker.start();   // 새 흐름 시작
        
        // 메인 스레드는 계속 진행
        System.out.println("Main continues");
    }
    
    private void processShipments() {
        // 별도 스레드에서 실행
    }
    
    // 현재 스레드 정보
    public void printThreadInfo() {
        Thread current = Thread.currentThread();
        System.out.println("Name: " + current.getName());
        System.out.println("ID: " + current.threadId());
        System.out.println("State: " + current.getState());
        System.out.println("Priority: " + current.getPriority());
    }
}

2.7 자기 점검 답변

스레드의 정의와 특징은?

:
1. 정의:

  • 프로세스 안 실행 흐름
  • 코드를 한 줄씩
  1. 메인 스레드:

    • 첫 스레드 (자동)
    • main() 실행
  2. 장점:

    • 자원 공유 (힙, 코드)
    • 통신 쉬움
    • 생성 비용 적음
  3. 단점:

    • 동기화 문제
    • 한 스레드 오류 전체 영향
  4. 본질:

    • 실행의 최소 단위
    • 자체 스택

3️⃣ 프로세스의 메모리 구성

3.1 4가지 메모리 영역

프로세스 메모리 구성:

┌─────────────────────┐
│   코드 섹션 (Code)    │  ← 실행 코드 (읽기 전용)
├─────────────────────┤
│   데이터 섹션 (Data)  │  ← 전역/static 변수
├─────────────────────┤
│   힙 (Heap)          │  ← 동적 할당 (new)
│         ↓            │
│                      │
│         ↑            │
│   스택 (Stack)       │  ← 메서드 호출, 지역 변수
└─────────────────────┘

3.2 코드 섹션

코드 섹션 (Code/Text Section):

  - 실행할 프로그램의 기계어 코드
  - 읽기 전용 (수정 불가)
  - 모든 스레드 공유

자바:
  - Method Area 의 일부
  - 클래스의 바이트코드
  - JIT 컴파일된 네이티브 코드

3.3 데이터 섹션

데이터 섹션 (Data Section):

  - 전역 변수
  - static 변수
  - 모든 스레드 공유

자바:
  - Method Area (Metaspace)
  - static 필드
  - 상수 풀

멀티스레드:
  - 공유됨 → 동기화 필요

3.4 힙 (Heap)

힙 (Heap):

  - 동적 메모리 할당
  - new 로 생성한 객체
  - 모든 스레드 공유

자바:
  - 모든 객체 (인스턴스)
  - 인스턴스 변수
  - 배열

멀티스레드:
  - 공유됨 → 동기화 필요 (★ 핵심)
  - GC 대상

3.5 스택 (Stack)

스택 (Stack):

  - 메서드 호출 정보 (스택 프레임)
  - 지역 변수
  - 매개변수
  - 리턴 주소
  - 스레드마다 개별 ★

자바:
  - 스레드 1개 = 스택 1개
  - 메서드 호출마다 스택 프레임
  - 메서드 종료 시 프레임 제거

멀티스레드:
  - 개별 → 동기화 불필요 (스레드 안전)

3.6 시각화 — 공유 vs 개별

프로세스 메모리 (3 스레드):

┌────────────────────────────────┐
│  코드 섹션 (공유)                │
├────────────────────────────────┤
│  데이터 섹션 (공유, static)      │
├────────────────────────────────┤
│  힙 (공유, 객체들)               │  ★ 동기화 필요
│    Shipment, Company, List...   │
├────────────────────────────────┤
│  스택1   │  스택2   │  스택3      │  ★ 개별 (스레드 안전)
│ (스레드A)│ (스레드B)│ (스레드C)   │
└────────────────────────────────┘

3.7 ILIC 의 메모리 매핑

public class ShipmentService {
    
    // 데이터 섹션 (static, 공유)
    private static final BigDecimal FUEL_RATE = BigDecimal.valueOf(0.15);
    private static int totalProcessed = 0;   // 공유 → 동기화 필요
    
    // 힙 (인스턴스, 공유)
    private final ShipmentRepository repository;   // 객체 참조
    private List<Shipment> cache = new ArrayList<>();   // 공유 → 위험
    
    public Shipment process(Long id) {
        // 스택 (지역 변수, 스레드별 — 안전)
        Shipment shipment = repository.findById(id);   // 지역 변수 (스택)
        BigDecimal freight = calculate(shipment);       // 지역 변수 (스택)
        
        // 객체 자체는 힙에 (shipment 가 가리키는 것)
        // shipment 참조는 스택에
        
        return shipment;
    }
    
    private BigDecimal calculate(Shipment s) {
        BigDecimal weight = s.getWeight();   // 지역 (스택)
        return weight.multiply(FUEL_RATE);   // FUEL_RATE 는 공유 (읽기만, 안전)
    }
}

3.8 자기 점검 답변

프로세스의 메모리 구성은?

:
1. 4가지 영역:

  • 코드 섹션
  • 데이터 섹션 (static)
  • 힙 (객체)
  • 스택 (지역 변수)
  1. 공유 (스레드 간):

    • 코드, 데이터, 힙
  2. 개별 (스레드별):

    • 스택
  3. 동기화 필요:

    • 힙, 데이터 (공유)
    • 스택은 불필요 (개별)

4️⃣ 스레드의 공유 vs 개별

4.1 공유하는 것

스레드가 공유하는 것:

1. 코드 섹션
   - 같은 코드 실행

2. 데이터 섹션
   - static 변수
   - 전역 변수

3. 힙
   - 모든 객체
   - 인스턴스 변수

→ 협력의 기반
→ 동시성 문제의 근원

4.2 개별인 것

스레드가 개별로 갖는 것:

1. 스택
   - 메서드 호출 정보
   - 지역 변수
   - 매개변수

2. PC (Program Counter)
   - 다음 실행 명령 주소

3. 레지스터
   - CPU 레지스터 상태

→ 독립적 실행 흐름
→ 스레드 안전

4.3 공유의 양면성

공유의 장점:
  - 협력 (데이터 주고받기)
  - 메모리 효율
  - 빠른 통신

공유의 단점:
  - 동시성 문제
  - 데이터 불일치
  - 동기화 필요

핵심:
  - "스레드 안전한가?"
  - = "공유되는가?"
  - 공유되면 동기화 고려

4.4 변수별 안전성

변수 종류와 스레드 안전성:

지역 변수 (스택):
  - 스레드별 개별
  - 스레드 안전 ✓

인스턴스 변수 (힙):
  - 객체 공유 시 공유
  - 동기화 필요 (조건부)

static 변수 (데이터):
  - 항상 공유
  - 동기화 필요

매개변수 (스택):
  - 스레드별
  - 안전 (단, 참조 객체는 공유 가능)

4.5 참조의 함정

// 지역 변수지만 위험한 경우
public void process() {
    // 지역 변수 (스택) — 안전?
    List<Shipment> list = sharedList;   // ★ 공유 객체 참조!
    list.add(shipment);   // 위험! (sharedList 가 공유)
    
    // list 참조 자체는 스택 (안전)
    // 하지만 list 가 가리키는 객체는 공유 (힙)
}

// 진짜 안전한 경우
public void processSafe() {
    List<Shipment> list = new ArrayList<>();   // 새 객체 (지역)
    list.add(shipment);   // 안전 (이 스레드만 접근)
}

4.6 시각화

스레드 A 와 B 의 메모리:

힙 (공유):
  ┌────────────────────┐
  │ Shipment 객체       │  ← A, B 모두 접근 가능
  │ List 객체           │  ← 동시 수정 위험
  └────────────────────┘
       ↑          ↑
       │          │
  스택 A       스택 B
  ┌──────┐    ┌──────┐
  │참조 →│    │참조 →│  ← 같은 객체 가리킬 수 있음
  │지역x │    │지역y │  ← 각자 개별 (안전)
  └──────┘    └──────┘

4.7 ILIC 의 맥락

public class ShipmentCounter {
    
    // ❌ 공유 변수 (위험)
    private int count = 0;   // 인스턴스 변수 (힙, 공유)
    
    public void increment() {
        count++;   // 여러 스레드 동시 → 데이터 손실
    }
    
    // ✓ 동기화
    public synchronized void incrementSafe() {
        count++;
    }
    
    // ✓ Atomic (Phase 후반)
    private final AtomicInteger atomicCount = new AtomicInteger();
    public void incrementAtomic() {
        atomicCount.incrementAndGet();
    }
    
    // ✓ 지역 변수 (안전)
    public int calculate(List<Shipment> shipments) {
        int localSum = 0;   // 지역 변수 (스택, 안전)
        for (Shipment s : shipments) {
            localSum += s.getQuantity();
        }
        return localSum;
        // localSum 은 이 스레드만 접근
    }
}

4.8 자기 점검 답변

스레드의 공유 vs 개별은?

:
1. 공유:

  • 코드, 데이터 (static), 힙 (객체)
  • 협력의 기반
  • 동시성 문제 근원
  1. 개별:

    • 스택 (지역 변수)
    • PC, 레지스터
    • 스레드 안전
  2. 핵심 원칙:

    • 스레드 안전 = 공유 안 됨
    • 공유되면 동기화
  3. 함정:

    • 지역 변수가 공유 객체 참조 시 위험
    • 참조 ≠ 객체

5️⃣ 스택이 개별인 이유

5.1 핵심 질문

질문:
  왜 스레드들이 힙은 공유하고
  스택은 따로 갖는가?

답:
  - 스택: 독립적 실행 흐름 필요
  - 힙: 협력 (데이터 공유) 필요

5.2 스택이 개별이어야 하는 이유

스택 = 실행 흐름:

  각 스레드는 독립적으로 코드 실행:
    - 자기만의 메서드 호출 순서
    - 자기만의 지역 변수
    - 자기만의 실행 위치 (PC)

  만약 스택을 공유한다면?
    - 스레드 A 의 메서드 호출과
    - 스레드 B 의 메서드 호출이
    - 같은 스택에 섞임
    - → 완전히 망가짐

  따라서:
    - 스택은 반드시 개별
    - 독립적 실행 보장

5.3 시각화 — 개별 스택

스레드 A 의 스택:
  ┌────────────────┐
  │ calculate()    │  ← 현재 실행 중
  │  - weight      │
  ├────────────────┤
  │ process()      │
  │  - shipment    │
  ├────────────────┤
  │ main()         │
  └────────────────┘

스레드 B 의 스택 (완전 독립):
  ┌────────────────┐
  │ validate()     │  ← 다른 메서드
  │  - result      │
  ├────────────────┤
  │ handleRequest()│
  └────────────────┘

각자 독립적 호출 스택
서로 영향 X

5.4 힙이 공유여야 하는 이유

힙 = 협력의 공간:

  스레드들이 협력하려면 데이터 공유 필요:
    - 생산자가 만든 데이터를
    - 소비자가 사용
    - 공유 큐 (힙)

  만약 힙도 개별이라면?
    - 데이터 공유 불가
    - IPC 같은 비싼 통신 필요
    - 멀티스레드의 장점 상실

  따라서:
    - 힙은 공유
    - 협력 가능
    - 단, 동시성 문제 (트레이드오프)

5.5 트레이드오프

공유 vs 개별의 트레이드오프:

스택 개별:
  + 독립 실행 흐름
  + 스레드 안전
  - 공유 불가 (지역 변수)

힙 공유:
  + 협력 가능
  + 메모리 효율
  - 동시성 문제

설계 의도:
  - 실행 흐름은 독립 (스택)
  - 데이터는 공유 (힙)
  - 균형

5.6 스택 크기

// 스택 크기 설정
// -Xss 옵션 (기본 약 512KB ~ 1MB)
// java -Xss1m App

// 스택 오버플로우
public void recursive(int n) {
    recursive(n + 1);   // 무한 재귀
    // StackOverflowError
    // 스택 크기 초과
}

// 스레드마다 스택
// 스레드 1만 개 = 약 1만 MB (1MB씩)
// → 메모리 부족 가능
// → 스레드 풀 (Phase 7)

5.7 ILIC 의 맥락

public class StackHeapExample {
    
    // 힙 — 공유 (동기화 필요)
    private final Map<Long, Shipment> sharedCache = new ConcurrentHashMap<>();
    
    public void process(Long id) {
        // 스택 — 이 스레드의 독립 실행
        Shipment local = sharedCache.get(id);   // local 참조는 스택
        // local 이 가리키는 객체는 힙 (공유)
        
        // 지역 변수 (스택, 안전)
        BigDecimal weight = local.getWeight();
        boolean isHeavy = weight.compareTo(BigDecimal.valueOf(1000)) > 0;
        
        // 다른 스레드의 스택과 완전 독립
        // weight, isHeavy 는 이 스레드만
        
        if (isHeavy) {
            handleHeavy(local);   // 새 스택 프레임
        }
    }
    
    private void handleHeavy(Shipment s) {
        // 새 스택 프레임 (이 스레드)
        String message = "Heavy: " + s.getBlNo();   // 지역
        log.info(message);
    }
}

5.8 자기 점검 답변

스택이 개별인 이유는?

:
1. 스택 = 실행 흐름:

  • 독립적 메서드 호출
  • 독립적 지역 변수
  • 공유하면 망가짐
  1. 힙 = 협력 공간:

    • 데이터 공유
    • 협력 가능
    • 개별이면 통신 비용
  2. 트레이드오프:

    • 스택 개별: 안전, 독립
    • 힙 공유: 협력, 동시성 문제
  3. 설계 의도:

    • 실행은 독립 (스택)
    • 데이터는 공유 (힙)

6️⃣ 클래스/인스턴스 비유

6.1 비유의 핵심

프로세스 ↔ 인스턴스
스레드 ↔ ? (다양한 관점)

여러 비유가 있지만 가장 흔한:

프로세스 = 인스턴스 (객체)
  - 독립된 상태 (메모리)
  - 각자 자기 데이터

스레드 = 메서드 실행
  - 인스턴스 안에서 동작
  - 같은 인스턴스 데이터 접근

6.2 회사-직원 비유 (재정리)

프로세스 = 회사:
  - 독립된 건물 (메모리)
  - 다른 회사와 격리
  - 회사 간 소통은 절차 (IPC)

스레드 = 직원:
  - 같은 회사 자료실 (힙) 공유
  - 각자 책상 (스택)
  - 직원 간 소통 쉬움 (공유)

공유 자료실 (힙):
  - 동시 수정 충돌 (동시성)
  - 규칙 필요 (동기화)

6.3 다양한 비유

주방 비유:
  프로세스 = 주방 (독립 공간)
  스레드 = 요리사 (같은 주방 도구 공유)
  도구 (힙) = 공유, 충돌 가능
  손 (스택) = 개별

도로 비유:
  프로세스 = 도로
  스레드 = 차선
  여러 차선이 같은 도로에서

책 비유:
  프로세스 = 책 (전체)
  스레드 = 책갈피 (읽는 위치)
  여러 책갈피가 같은 책을

6.4 비유의 한계

비유의 주의:

  비유는 이해를 돕지만 완벽하지 않음.

  예:
    - 회사-직원: IPC 부분 부정확
    - 클래스-인스턴스: 1:N 관계 다름

  핵심은:
    - 프로세스 = 독립 메모리
    - 스레드 = 공유 + 개별 스택
    - 정확한 메모리 모델 이해

6.5 ILIC 의 맥락

// ILIC 서버 = 1개 프로세스 (회사)
// 여러 요청 처리 스레드 (직원)

@Service
public class ShipmentService {
    
    // 공유 자료실 (힙) — 모든 스레드 접근
    private final ShipmentRepository repository;
    private final Map<Long, Shipment> cache = new ConcurrentHashMap<>();
    
    // 여러 스레드 (직원) 가 동시 호출
    public Shipment process(Long id) {
        // 각 스레드는 자기 책상 (스택)
        // 지역 변수는 독립
        Shipment local = cache.computeIfAbsent(id, repository::findById);
        // cache 는 공유 (자료실)
        // local 참조는 스택 (책상)
        return local;
    }
}

6.6 자기 점검 답변

프로세스/스레드를 비유하면?

:
1. 회사-직원 비유:

  • 프로세스 = 회사 (독립 건물)
  • 스레드 = 직원
  • 힙 = 공유 자료실
  • 스택 = 개인 책상
  1. 클래스-인스턴스:

    • 프로세스 = 인스턴스
    • 스레드 = 메서드 실행
  2. 비유의 한계:

    • 완벽하지 않음
    • 정확한 메모리 모델 이해 중요
  3. 핵심:

    • 프로세스 = 독립 메모리
    • 스레드 = 공유 (힙) + 개별 (스택)

7️⃣ PCB와 TCB

7.1 PCB (Process Control Block)

PCB (Process Control Block):

  OS 가 프로세스를 관리하기 위한 정보 구조.

포함 정보:
  - 프로세스 ID (PID)
  - 프로세스 상태
  - PC (Program Counter)
  - 레지스터 값
  - 메모리 정보
  - 열린 파일 목록
  - 우선순위
  ...

7.2 TCB (Thread Control Block)

TCB (Thread Control Block):

  OS 가 스레드를 관리하기 위한 정보 구조.

포함 정보:
  - 스레드 ID
  - 스레드 상태
  - PC
  - 레지스터 값
  - 스택 포인터
  ...

PCB 와 차이:
  - TCB 는 더 가벼움
  - 스레드는 프로세스 자원 공유
  - PCB 의 일부 정보 공유

7.3 컨텍스트 스위칭과 PCB/TCB

컨텍스트 스위칭 시:

프로세스 전환 (PCB):
  - 현재 PCB 에 상태 저장
  - 다음 PCB 에서 복원
  - 메모리 공간 전환 (TLB 플러시)
  - 비용 큼

스레드 전환 (TCB):
  - TCB 에 상태 저장/복원
  - 같은 프로세스면 메모리 유지
  - 비용 적음

핵심:
  - 스레드 전환 < 프로세스 전환

7.4 자바와 TCB

// 자바 Thread 객체는 TCB 추상화
Thread t = new Thread(task);
t.threadId();         // 스레드 ID
t.getState();         // 상태
t.getName();          // 이름
t.getPriority();      // 우선순위

// 실제 OS TCB 와 매핑 (1:1 모델)
// Virtual Thread 는 다름 (M:N)

7.5 스레드 로컬 (ThreadLocal)

// 스레드별 독립 데이터 (TCB 관련 개념)
public class ShipmentContext {
    
    private static final ThreadLocal<String> currentUser = new ThreadLocal<>();
    
    public static void setUser(String user) {
        currentUser.set(user);   // 이 스레드만의 값
    }
    
    public static String getUser() {
        return currentUser.get();   // 이 스레드의 값
    }
    
    public static void clear() {
        currentUser.remove();   // ★ 메모리 누수 방지
    }
}

// 각 스레드가 독립적 값
// 스택과 유사하게 스레드별 격리
// 단, 메모리 누수 주의 (remove 필수)

7.6 ILIC 의 맥락

// 요청별 컨텍스트 (스레드 로컬)
@Component
public class RequestContext {
    
    private static final ThreadLocal<RequestInfo> context = new ThreadLocal<>();
    
    public void setCurrentRequest(RequestInfo info) {
        context.set(info);   // 현재 스레드 (요청)
    }
    
    public RequestInfo getCurrentRequest() {
        return context.get();
    }
    
    public void clear() {
        context.remove();   // 요청 끝나면 정리
    }
    
    record RequestInfo(String userId, String requestId, Instant startTime) {}
}

// 주의:
// - 스레드 풀에서 스레드 재사용
// - 이전 요청의 값이 남을 수 있음
// - 반드시 clear (remove)

7.7 자기 점검 답변

PCB와 TCB는?

:
1. PCB:

  • 프로세스 관리 정보
  • PID, 상태, 메모리 등
  1. TCB:

    • 스레드 관리 정보
    • 더 가벼움
    • 프로세스 자원 공유
  2. 컨텍스트 스위칭:

    • 프로세스 전환 (PCB): 비용 큼
    • 스레드 전환 (TCB): 적음
  3. 자바:

    • Thread 객체 = TCB 추상화
    • ThreadLocal: 스레드별 데이터

8️⃣ 멀티프로세스 vs 멀티스레드

8.1 비교 표

항목멀티프로세스멀티스레드
메모리독립공유 (힙)
통신IPC (느림)공유 메모리 (빠름)
생성 비용적음
컨텍스트 스위칭비쌈
안정성높음 (격리)낮음 (전파)
동기화덜 필요필요

8.2 멀티프로세스의 장단점

멀티프로세스:

장점:
  - 안정성 (한 프로세스 죽어도 다른 건 OK)
  - 보안 (격리)
  - 독립성

단점:
  - 통신 비용 (IPC)
  - 생성 비용 큼
  - 메모리 많이

예:
  - Chrome 브라우저 (탭마다 프로세스)
  - 한 탭 죽어도 다른 탭 OK

8.3 멀티스레드의 장단점

멀티스레드:

장점:
  - 통신 쉬움 (공유 메모리)
  - 생성 비용 적음
  - 메모리 효율

단점:
  - 동기화 문제
  - 한 스레드 오류 전체 영향
  - 디버깅 어려움

예:
  - 웹 서버 (요청마다 스레드)
  - 게임 (렌더링, 물리, 입력 스레드)

8.4 Chrome 의 예

Chrome 브라우저의 멀티프로세스:

  - 각 탭 = 별도 프로세스
  - 한 탭이 크래시 → 그 탭만
  - 다른 탭 영향 X

이유:
  - 안정성 우선
  - 보안 (탭 간 격리)
  - 메모리 비용 감수

대조:
  - 옛 브라우저 (멀티스레드)
  - 한 탭 멈추면 전체 멈춤

8.5 선택 기준

멀티프로세스 선택:
  ✓ 안정성 최우선
  ✓ 격리 필요
  ✓ 독립 실행

멀티스레드 선택:
  ✓ 빠른 통신
  ✓ 자원 공유
  ✓ 효율 우선

대부분의 서버 앱:
  - 멀티스레드 (효율)
  - + 프로세스 격리는 컨테이너로 (Docker)

8.6 ILIC 의 선택

// ILIC 는 멀티스레드 (단일 JVM)
// 톰캣 스레드 풀로 요청 처리

// server.tomcat.threads.max=200
// 200 스레드가 요청 처리 (멀티스레드)

// 격리는 컨테이너 레벨
// - Docker 컨테이너마다 별도 JVM 프로세스
// - 한 컨테이너 죽어도 다른 건 OK
// - Kubernetes 가 관리

// 외부 프로세스는 드물게
@Service
public class DocumentConverter {
    
    public Path convertToPdf(Path html) throws IOException, InterruptedException {
        // 별도 프로세스 (격리)
        Process process = new ProcessBuilder(
            "wkhtmltopdf", html.toString(), "output.pdf")
            .start();
        process.waitFor();
        // 변환 도구 크래시해도 메인 JVM 영향 X
        return Path.of("output.pdf");
    }
}

8.7 자기 점검 답변

멀티프로세스 vs 멀티스레드는?

:
1. 멀티프로세스:

  • 독립 메모리
  • 안정성, 보안
  • 통신 비용 (IPC)
  • 예: Chrome
  1. 멀티스레드:

    • 공유 메모리
    • 빠른 통신
    • 동기화 문제
    • 예: 웹 서버
  2. 선택:

    • 안정성: 멀티프로세스
    • 효율: 멀티스레드
  3. 현대:

    • 멀티스레드 (효율)
    • 격리는 컨테이너 (Docker)

9️⃣ 면접 + 자기 점검

9.1 면접 단골 질문 매핑

Q핵심 답변
프로세스?실행 중인 프로그램, 독립 메모리
스레드?프로세스 내 실행 흐름
프로그램 vs 프로세스?정적 파일 vs 실행 중
메모리 구성?코드/데이터/힙/스택
공유하는 것?코드, 데이터, 힙
개별인 것?스택
스택 개별 이유?독립 실행 흐름
힙 공유 이유?협력 (데이터 공유)
IPC?프로세스 간 통신
PCB vs TCB?프로세스 vs 스레드 관리 정보
멀티프로세스 vs 멀티스레드?안정성 vs 효율
스레드 안전 근원?공유 여부

9.2 자기 점검 체크리스트

프로세스

  • 정의 (실행 중 프로그램)
  • 독립 메모리
  • IPC

스레드

  • 정의 (실행 흐름)
  • 메인 스레드
  • 생성 비용

메모리

  • 4가지 영역
  • 공유 (코드/데이터/힙)
  • 개별 (스택)

공유 vs 개별

  • 스택 개별 이유
  • 힙 공유 이유
  • 참조 함정

PCB/TCB

  • 정의
  • 컨텍스트 스위칭
  • ThreadLocal

멀티프로세스 vs 멀티스레드

  • 비교
  • 선택 기준
  • Chrome 예

9.3 추가 심화 질문

Q1: 스레드 1개당 1MB 의 의미?

답:

  • 스택 크기 (-Xss, 기본 약 512KB~1MB)
  • 1만 스레드 = 약 10GB
  • 무한 생성 불가
  • 스레드 풀 필요 (Phase 7)

Q2: 자바의 스레드는 OS 스레드?

답:

  • 전통 (1:1 모델): 자바 스레드 = OS 스레드
  • OS 가 스케줄링
  • Virtual Thread (Java 21+): M:N 모델
  • 다수 가상 = 소수 OS

Q3: ThreadLocal 의 메모리 누수?

답:

  • 스레드 풀에서 스레드 재사용
  • ThreadLocal 값이 남음
  • remove() 안 하면 누수
  • 요청 끝나면 반드시 clear

Q4: 데이터 섹션 vs 힙 차이?

답:

  • 데이터: static, 전역 (컴파일 시 결정)
  • 힙: 동적 (런타임 new)
  • 둘 다 공유
  • 자바: 데이터 = Metaspace, 힙 = Heap

Q5: 스택 오버플로우 vs 힙 OOM?

답:

  • StackOverflowError: 스택 초과 (깊은 재귀)
  • OutOfMemoryError: 힙 초과 (객체 많음)
  • 스택은 스레드별, 힙은 공유

🎯 핵심 요약 — 3줄 정리

1. 프로세스 vs 스레드

  • 프로세스: 실행 중 프로그램, 독립 메모리
  • 스레드: 프로세스 내 실행 흐름

2. 메모리

  • 공유: 코드, 데이터, 힙 (동기화 필요)
  • 개별: 스택 (스레드 안전)

3. 핵심 원칙

  • 스택 개별: 독립 실행
  • 힙 공유: 협력 + 동시성 문제
  • 스레드 안전 = 공유 안 됨

📚 다음으로...

Unit 1.3 — 변수 종류와 메모리 위치 (4주차 관점)

이번 Unit에서 프로세스/스레드의 메모리를 봤다면, 다음은 변수별 메모리 위치와 스레드 안전성.

  • 지역/인스턴스/static 변수의 위치
  • 멀티스레드 관점의 안전성
  • "스레드 안전 = 공유되는가?"

Phase 1 진행 상황

🚀 Phase 1 — 동시성의 기초
  ✅ Unit 1.1 멀티태스킹 vs 멀티프로세싱
  ✅ Unit 1.2 프로세스와 스레드 ← 여기
  ⏭ Unit 1.3 변수 종류와 메모리 위치
  ⏭ Unit 1.4 스케줄링 큐와 컨텍스트 스위칭

4주차 누적 진행

🚀 Phase 1 — 동시성의 기초 (2/4 진행)

총: 2/35 Unit
profile
Software Developer

0개의 댓글