PHpullh
학습 라이브러리/Go/Worker Pool 패턴

GO · 패턴

Worker Pool 패턴

고루틴 풀로 동시성을 제어하고 리소스를 효율적으로 사용합니다.

패턴중급worker-poolgoroutinechannelWaitGroup병렬처리

핵심 설명

고루틴 풀로 동시성을 제어하고 리소스를 효율적으로 사용합니다.

Go code

package main

import (
	"fmt"
	"sync"
	"time"
)

type Job struct {
	ID    int
	Input string
}

type Result struct {
	JobID  int
	Output string
	Err    error
}

func worker(id int, jobs <-chan Job, results chan<- Result, wg *sync.WaitGroup) {
	defer wg.Done()
	for job := range jobs {
		// 작업 처리 시뮬레이션
		time.Sleep(100 * time.Millisecond)
		results <- Result{
			JobID:  job.ID,
			Output: fmt.Sprintf("[Worker%d] %s 처리완료", id, job.Input),
		}
	}
}

func WorkerPool(numWorkers, numJobs int) []Result {
	jobs    := make(chan Job, numJobs)
	results := make(chan Result, numJobs)

	var wg sync.WaitGroup

	// Worker 시작
	for i := 1; i <= numWorkers; i++ {
		wg.Add(1)
		go worker(i, jobs, results, &wg)
	}

	// Job 전송
	for i := 1; i <= numJobs; i++ {
		jobs <- Job{ID: i, Input: fmt.Sprintf("task-%d", i)}
	}
	close(jobs) // 전송 완료

	// 모든 워커 완료 대기 후 results 채널 닫기
	go func() {
		wg.Wait()
		close(results)
	}()

	// 결과 수집
	var all []Result
	for r := range results {
		all = append(all, r)
	}
	return all
}

func main() {
	start := time.Now()
	results := WorkerPool(3, 9)
	fmt.Printf("완료: %d개, 소요: %v
",
		len(results), time.Since(start))
	for _, r := range results {
		fmt.Println(r.Output)
	}
}

학습 팁

Worker Pool에서 워커 수를 CPU 코어 수에 맞추면 CPU 바운드 작업에 최적입니다. I/O 바운드 작업은 더 많은 워커가 효과적입니다.

주의할 점

results 채널을 닫지 않으면 for range results가 영원히 블록됩니다. 반드시 모든 워커가 완료된 후 채널을 닫으세요.

자주 묻는 질문

Worker Pool 패턴란 무엇인가요?

고루틴 풀로 동시성을 제어하고 리소스를 효율적으로 사용합니다.

Worker Pool 패턴 학습 시 주의할 점은 무엇인가요?

results 채널을 닫지 않으면 for range results 가 영원히 블록됩니다. 반드시 모든 워커가 완료된 후 채널을 닫으세요.