
Go 언어를 사용하다 보면 “작업을 일정 시간 동안만 실행하다가 중단하고 싶다”, 또는 “사용자가 Ctrl+C를 눌렀을 때 우아하게 종료하고 싶다”는 상황이 자주 발생합니다. 예를 들어 웹 서버에서 API 요청에 시간이 너무 오래 걸리면 중단하거나, 백그라운드 작업 도중에 프로그램을 강제 종료하는 상황 등입니다.
이럴 때 유용하게 쓰이는 Go의 기능이 바로 context.WithTimeout
과 os/signal
입니다.
이번 글에서는 이 두 가지를 조합하여 Timeout context with interrupt를 Go 다운 방식으로 제대로 사용하는 방법을 소개합니다.
개념 정리: 무엇을 위한 기능인가?
✅ context.WithTimeout()
- 일정 시간이 지나면 자동으로 취소되는
context
를 생성합니다. - 네트워크 요청, DB 작업 등에 널리 사용됩니다.
✅ os/signal.Notify()
- 운영체제에서 보내는 시그널(예:
SIGINT
,SIGTERM
,Ctrl+C
)을 감지합니다. - 사용자가 프로그램을 강제 종료하려는 신호를 포착할 수 있습니다.
이 조합이 왜 강력한가?
두 기능을 조합하면 다음과 같은 장점이 있습니다:
- 사용자 인터럽트(Ctrl+C)와 타임아웃 모두에 대응 가능
- 하나의 cancel()로 모든 goroutine을 깔끔하게 중단
- 리소스 정리(예: 파일 닫기, DB 연결 종료 등)를 안전하게 처리 가능
실전 예제: Timeout + Interrupt 처리하기
package main
import (
"context"
"fmt"
"os"
"os/signal"
"time"
)
func main() {
// 5초 타임아웃 설정
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
// 인터럽트 감지 채널 생성
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt)
// 인터럽트 발생 시 context 취소
go func() {
<-sigChan
fmt.Println("\n인터럽트 시그널 감지! 취소 신호 보냅니다.")
cancel()
}()
// 작업 수행
fmt.Println("작업을 시작합니다. 최대 5초 동안 실행됩니다.")
select {
case <-time.After(10 * time.Second): // 실제 작업 (10초 걸리는 작업이라고 가정)
fmt.Println("작업 완료!")
case <-ctx.Done():
fmt.Println("작업 취소됨:", ctx.Err())
}
fmt.Println("프로그램 종료")
}
결과 예시
- 프로그램을 실행하고 5초를 넘기면:CopyEdit
작업 취소됨: context deadline exceeded 프로그램 종료
- 실행 도중에 Ctrl+C를 누르면:CopyEdit
인터럽트 시그널 감지! 취소 신호 보냅니다. 작업 취소됨: context canceled 프로그램 종료
실무에서의 활용 예시
상황 | 이 패턴을 적용하는 이유 |
---|---|
API 요청이 너무 오래 걸릴 때 | 클라이언트 타임아웃 설정 |
사용자 작업 중 Ctrl+C 누른 경우 | graceful shutdown 처리 |
CLI 도구 실행 중 타임아웃 제한 필요 | 자동 중단 처리 |
외부 서비스 호출 시 리스크 관리 | 응답 없는 호출 방지 |
흔한 실수
defer cancel()
을 빼먹고 리소스 누수ctx.Done()
을 고루틴 내부에서 체크하지 않음- 시그널 채널을 버퍼 없이 생성하여 시그널 누락 발생
Tip:
signal.Notify(sigChan, os.Interrupt)
이후defer signal.Stop(sigChan)
도 해주면 좋습니다.
마무리: Go다운 종료 방식
Go 언어의 철학은 단순하면서도 강력한 병행성 모델입니다. context
와 os/signal
을 조합하는 이 패턴은 실제 서비스 환경에서 가장 많이 사용되는 안전한 종료 처리 방식 중 하나입니다.
단일 cancel() 호출만으로 타임아웃과 인터럽트 두 가지 상황을 모두 커버할 수 있다는 점에서 매우 유용하고, 코드도 깔끔하게 유지할 수 있습니다.
📌 요약 정리
context.WithTimeout()
→ 일정 시간 후 자동 취소os/signal.Notify()
→ Ctrl+C 등 시스템 시그널 감지cancel()
→ 전체 작업을 종료할 수 있는 제어 지점ctx.Done()
→ 모든 goroutine이 종료 조건을 감지하는 기준