Go에서 여러 Goroutine 대기 방법
카테고리
프로그래밍/소프트웨어 개발
서브카테고리
개발 툴
대상자
Go 언어를 사용하는 중급 이상 개발자(동기화 메커니즘 이해 필요)
핵심 요약
- sync.WaitGroup은 고정된 수의 Goroutine을 대기하는 데 적합하며,
Add()
,Done()
,Wait()
메서드를 사용하여 간단하게 동기화 가능 - 채널은 결과 전달이나 동적 수의 Goroutine 대기 시 유연하지만, 수동 관리가 필요
- context.Context는 취소 또는 타임아웃이 필요한 복잡한 시나리오에 적합하며,
errgroup
과 결합하여 오류 처리 가능 - errgroup은 오류 전파와 컨텍스트 지원을 통해 현대적 애플리케이션에서 강력한 대기 기능 제공
섹션별 세부 요약
1. sync.WaitGroup 사용 예시
wg.Add(1)
로 카운터 증가,wg.Done()
으로 감소,wg.Wait()
로 메인 Goroutine 대기- 예시 코드:
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
// 작업 수행
}()
wg.Wait()
2. 채널 기반 동기화
- 각 Goroutine이
done
채널에 신호 전송, 메인 Goroutine은 신호 수신 후 대기 - 예시 코드:
done := make(chan struct{})
for i := 1; i <= 3; i++ {
go func(id int) {
done <- struct{}{}
}(i)
for i := 0; i < 3; i++ {
<-done
}
3. context.Context 활용
context.WithCancel()
로 취소 신호 전달,select
로 대기 상태 확인- 예시 코드:
ctx, cancel := context.WithCancel(context.Background())
select {
case <-ctx.Done():
// 취소 처리
default:
// 작업 수행
}
4. errgroup 사용
errgroup.Group
을 통해 Goroutine 추가(g.Go()
) 및 오류 전파 가능- 예시 코드:
var g errgroup.Group
g.Go(func() error {
return nil
})
if err := g.Wait(); err != nil {
// 오류 처리
}
결론
- 간단한 작업은
sync.WaitGroup
, 오류 처리가 필요한 경우errgroup
또는context
와 결합 사용 time.Sleep
은 정확한 동기화가 불가능하므로 피해야 함- 도구 선택 시 작업 특성(고정/동적, 오류 처리 필요 여부)을 고려해야 함