변수의 기록

(OS) Thread Per Request vs Thread Pool 모델 정리 (쓰레드 비교) 본문

CS지식/운영체제 (Operating System)

(OS) Thread Per Request vs Thread Pool 모델 정리 (쓰레드 비교)

불광동 물주먹 2025. 4. 15. 22:48

 Thread Per Request vs Thread Pool 모델 정리

1. Thread Per Request 모델

서버에 요청이 들어올 때마다 새로운 스레드를 생성해 처리하고, 요청 처리가 끝나면 해당 스레드를 버리는 방식입니다.

 

⚠️ 문제점

  • 스레드 생성 비용: 스레드 생성과 소멸은 커널 개입이 필요한 작업으로 비용이 큽니다. (컨텍스트 구조 초기화, 스택 메모리 확보 등)
  • 요청 폭주 시 병목: 요청이 처리 속도보다 빠르게 들어올 경우, 새로운 스레드가 계속 생성되고 이로 인해 스레드 수 급증.
    • 컨텍스트 스위칭 빈도 증가 → CPU 오버헤드 발생
    • 메모리 고갈 가능성 → OutOfMemoryError 또는 서버 응답 불능
  • 예측 불가능성: 자원 소모가 요청 수에 비례하여 늘어나므로, 대량 요청에 대한 대비가 어렵다.

사진 출처 - 유튜브 쉬운코드


2. Thread Pool 모델

요청마다 새 스레드를 생성하는 대신, 미리 생성된 일정 수의 스레드들을 재사용하는 방식입니다.

 작동 방식

  1. 들어오는 요청은 내부 큐에 적재
  2. 사용 가능한 스레드가 큐에서 작업을 꺼내 실행
  3. 작업 종료 후 해당 스레드는 풀로 복귀되어 대기

 장점

  • 스레드 재사용으로 생성/소멸 비용 절감
  • 자원 사용량을 제어하여 안정적인 서버 운영 가능
  • 과도한 컨텍스트 스위칭 방지 → CPU 효율 개선


사진 출처 - 유튜브 쉬운코드


3. 실전 적용 시 고려사항

 1) 스레드 풀 크기 설정 기준

  • CPU Bound Task
    계산 중심 로직 → CPU 사용 비중 큼
    → 코어 수와 동일하거나 소폭 많은 값 권장
    예: Runtime.getRuntime().availableProcessors()
  • IO Bound Task
    DB/네트워크 등 외부 자원을 기다리는 시간이 많음
    → 스레드 수를 더 많이 설정해도 무방
    예: 코어 수의 2~4배 (경험적으로 튜닝 필요)


💡 Java의 Executors.newFixedThreadPool(n) 또는 ThreadPoolExecutor 사용 시, 명시적으로 설정할 수 있음.

java 예시 


newFixedThreadPool 메서드로  쓰레드풀 10개  생성




큐사이즈는???

 

1. corePoolSize와 maximumPoolSize가 동일하게 nThreads로 설정 → 고정된 수의 스레드를 사용하는 풀 (Fixed Thread Pool)
2. 큐는 new LinkedBlockingQueue<>() → 기본 생성자 사용
3. LinkedBlockingQueue 자기 자신을 호출하는 생성자 오버로딩 (this() 사용)
4. capacity 값을 Integer.MAX_VALUE로 설정
   → 약 21억(2^31 - 1) 개의 작업을 저장할 수 있는 사실상 무제한 큐

 주의점!!!!

  • Executors.newFixedThreadPool() 사용 시:
    • 스레드 개수는 제한되어 있지만
    • 큐는 사실상 무제한 (Integer.MAX_VALUE)
  • 즉, 요청이 과도하게 밀릴 경우 메모리 과다 사용으로 인해 OOM(Out Of Memory) 발생 위험 있음

 

대안 (큐 개수 설정)

ExecutorService pool = new ThreadPoolExecutor(
    10,                    // corePoolSize
    10,                    // maximumPoolSize
    0L, TimeUnit.MILLISECONDS,
    new ArrayBlockingQueue<>(1000), // 제한된 큐 크기
    new ThreadPoolExecutor.CallerRunsPolicy() // 거절 정책 설정
);

 

 

 


 

 

 2) 작업 큐(Work Queue)의 크기 제한

  • 큐 사이즈가 무제한이면:
    요청이 폭주할 경우 큐에 계속 쌓이면서 메모리 부족 위험 발생
  • 큐 사이즈가 제한되면:
    큐가 가득 찼을 때 RejectedExecutionHandler로 대처 가능
    • 예: CallerRunsPolicy, AbortPolicy, DiscardPolicy 등

큐 정책과 함께 백프레셔(Backpressure) 또는 최대 요청 수 제한 등의 보호 장치도 고려 필요

 

 

 


 정리

항목 Thread per Request Thread Pool
스레드 생성 시점 요청마다 생성 미리 생성 후 재사용
성능 요청 많아지면 하락 일정 수준에서 안정적
자원 관리 어렵고 예측 불가 자원 제한 및 관리 용이
적용 예 간단한 서버/테스트 실 서비스, 고부하 처리