Go 에서 context canceled 가 너무 빨리 보인다면 문제는 보통 cancel 자체가 아니라 scope 와 ownership 입니다. parent context 가 실제 작업보다 먼저 끝나거나, timeout 이 실제 경로보다 너무 짧게 잡힌 경우가 많습니다.
짧게 말하면 핵심은 이것입니다. 누가 context 를 소유하고 있고, cancellation 이 어디서 시작되는지 먼저 봐야 합니다. context cancellation 은 runtime 입장에선 보통 정상 동작입니다. 진짜 질문은 올바른 context 가 올바른 작업을 소유하고 있는가입니다.
parent lifetime 과 ownership 부터 본다
많은 context canceled incident 는 사실 lifecycle bug 입니다.
알아야 할 것은 이렇습니다.
- 누가 context 를 만든다
- 누가
cancel을 호출한다 - 어떤 작업이 그 context 에 묶여 있다
- 그 작업이 정말 parent 와 함께 멈춰야 하는가
이 ownership map 이 없으면 context bug 는 랜덤한 실패처럼 보이기 쉽습니다.
early cancellation 은 실전에서 어떻게 보이나
운영 환경에서는 보통 이렇게 보입니다.
- request 가 끝나면서 background work 가 같이 죽는다
- retry 나 fan-out call 이 너무 많은 작업을 일찍 취소한다
- dependency 는 멀쩡해 보이는데 handler 에서
context canceled가 나온다 - shutdown logic 이 끝나도 되는 작업까지 너무 빨리 멈춘다
이런 incident 가 놀랍게 느껴지는 이유는 코드에서 context lifetime 이 충분히 드러나지 않기 때문입니다.
흔한 원인
1. parent context 의 수명이 너무 짧다
request-scoped context 는 팀이 생각하는 것보다 훨씬 짧은 범위만 제어하는 경우가 많습니다.
request 보다 오래 살아야 하는 작업에 r.Context() 를 그대로 쓰는 건 자주 틀립니다.
2. timeout 설정이 너무 공격적이다
configured deadline 이 실제 dependency 또는 worker path 보다 짧을 수 있습니다.
이 경우 cancellation 은 미스터리가 아니라 예측 가능한 결과입니다.
3. background work 가 잘못된 context 를 쓴다
request 하나를 넘어 살아야 하는 task 가 실수로 request cancellation 을 상속받을 수 있습니다.
ctx, cancel := context.WithTimeout(r.Context(), 2*time.Second)
defer cancel()
go runBackgroundJob(ctx) // request 가 끝나면 같이 멈출 수 있음
background work 가 request 보다 오래 살아야 한다면 r.Context() 를 그대로 물리면 안 됩니다.
4. retry 와 fan-out path 가 cancellation pressure 를 키운다
병렬 호출이 많아지면 짧은 parent deadline 하나가 너무 많은 child work 를 한꺼번에 취소할 수 있습니다.
특히 서로 다른 latency profile 을 가진 downstream call 들을 하나의 parent context 가 묶을 때 자주 아픕니다.
5. shutdown flow 의 cancellation boundary 가 불분명하다
graceful drain 되어야 할 worker 가 더 넓은 shutdown path 의 abrupt cancellation 을 상속받을 수 있습니다.
실전 점검 순서
1. 누가 context 를 만들고 누가 cancel 하는지 찾는다
가장 중요한 첫 단계입니다.
owner 를 모르면 모든 cancellation 이 임의적으로 보입니다.
2. 실제 작업 시간과 timeout / deadline 설정을 비교한다
deadline 이 정상 경로보다 짧다면 early cancellation 은 예상된 동작입니다.
3. background task 가 request-scoped context 를 상속받는지 본다
가장 아픈 Go lifecycle bug 들이 여기서 많이 드러납니다.
4. fan-out 과 retry path 에서 parent cancellation 이 너무 이른지 확인한다
짧은 parent deadline 하나가 여러 child 를 함께 과도하게 취소할 수 있습니다.
5. 멈춰야 하는 작업에만 cancellation 이 도달하는지 확인한다
마지막 질문은 cancellation boundary 가 실제 ownership 과 맞는가입니다.
ownership bug 를 찾은 뒤 무엇을 바꾸면 좋나
parent 수명이 너무 짧다면
작업을 올바른 lifecycle 을 가진 context 에 다시 묶어야 합니다.
timeout 이 너무 공격적이라면
현실적인 latency 에 맞게 조정하거나 단계별 deadline 으로 나눠야 합니다.
background work 가 request context 를 상속받는다면
request 바깥의 explicit owner 를 줘야 합니다.
fan-out 이 과도하게 취소된다면
하나의 parent deadline 이 여러 child 를 어떻게 제어하는지 다시 봐야 합니다.
shutdown 이 너무 넓게 cancel 한다면
graceful drain context 와 hard-stop context 를 분리해야 합니다.
장애 중에 던져볼 질문
이 질문이 꽤 유용합니다.
이 작업은 정말 이 parent context 가 끝날 때 같이 멈춰야 하나, 아니면 실제 job 보다 더 짧은 lifetime 을 잘못 상속받은 건가?
이 질문이 error text 만 보는 것보다 훨씬 빨리 real bug 를 드러냅니다.
FAQ
Q. background work 가 request context 를 써도 되나
그 작업이 request 와 함께 멈춰야 할 때만 그렇습니다.
Q. 가장 빠른 첫 단계는 무엇인가
context creator 를 찾고, 그 lifetime 과 제어하는 작업의 길이를 비교하는 것입니다.
Q. early cancellation 은 항상 timeout 문제인가
아닙니다. ownership 과 scope 실수도 매우 흔합니다.
Q. cancellation 이 “정상” 인데 왜 버그인가
runtime 은 정상인데 코드가 잘못된 작업을 잘못된 lifetime 에 묶었을 수 있기 때문입니다.
Read Next
- 증상이 surprising cancel path 보다 hard deadline expiry 에 가깝다면 외부 연동 구간의 지연 시간과 타임아웃 설정을 우선 점검하세요.
- cancellation pressure 가 stuck coordination 으로 번진다면 WaitGroup이나 Channel의 데드락 여부를 확인해 보세요.
- background work 가 clean 하게 멈추지 않고 누적된다면 Golang Goroutine Leak 과 같이 보세요.
- 전체 Go 분기 지도는 Golang Troubleshooting Guide 에서 이어 볼 수 있습니다.
Related Posts
Sources:
먼저 읽어볼 가이드
검색 유입이 많은 핵심 글부터 이어서 보세요.
- 미들웨어 트러블슈팅 가이드: Redis, RabbitMQ, Kafka 중 어디부터 볼까 Redis, RabbitMQ, Kafka가 함께 있는 시스템에서 지금 보이는 장애가 어느 계층에 더 가까운지, 첫 10분 안에 무엇을 확인하고 어떤 글로 들어가야 하는지 정리한 실전 허브 가이드입니다.
- Kubernetes CrashLoopBackOff: 먼저 볼 것들 startup failure, probe, config, resource limit 관점에서 CrashLoopBackOff를 어떻게 나눠서 봐야 하는지 정리한 가이드입니다.
- Astro 기술 블로그 SEO 체크리스트: 트래픽 기다리기 전에 먼저 고칠 것 Astro 기술 블로그를 위한 실전 SEO 체크리스트입니다. 배포 호스트 확인, robots.txt, sitemap, canonical, hreflang, 구조화 데이터, 페이지별 메타데이터, noindex 판단, 검증 명령까지 우선순위대로 정리합니다.
- 다국어 블로그 canonical과 hreflang 설정 가이드: 무엇을 확인하고 어디서 깨질까 다국어 블로그에서 canonical과 hreflang을 어떻게 설정해야 하는지 실전 기준으로 정리합니다. self-canonical, 상호 연결되는 hreflang 묶음, x-default, 카테고리 페이지, 최종 렌더 HTML 점검, 한 언어 버전이 다른 언어 버전을 눌러버리는 실수까지 다룹니다.
- OpenAI Codex CLI 설치 가이드: 설치, 인증, 첫 작업까지 OpenAI Codex CLI를 실전 기준으로 설치하는 방법을 정리했다. 설치, 로그인, 첫 실행, Windows 주의점, 첫 작업을 어떻게 시작하면 좋은지까지 다룬다.