golang/go언어 삭제가능한 컨텍스트(Cancellable Context)함수 알아보기

김민영·2023년 12월 30일
0

golang패키지

목록 보기
1/2
post-thumbnail

작성하던 글이 세번이나 날아가 벨로그를 시작하기로 한게 옳은것인가 아주 잠시동안 고민했다.

실무코드를 만지면서 알게된 고랭 컨텍스트의 용도에 대해 간단히 공유해보자 한다.

컨텍스트란?

https://pkg.go.dev/context
Context는 Go1.7에서 표준 패키지에 동참한 라이브러리로,
작업 가능한 시간, 작업 취소 등 작업의 흐름을 제어하는데 사용되는 명세서와 같은 역할을 한다.

기존 go에서는 동시 처리에서는 done 채널을 사용하여 동시 처리를 종료했었다.
그러나 done 채널만을 사용한 방법으로는 취소의 로그 전파나 타임아웃 등 복잡해지는 부분이 있었다고한다!.

거기서 Context가 실험적으로 탄생, 최종적으로 표정 패키지로써 활용되게 되었다고 한다!

컨텍스트의 두 가지 주요 용도

1.고루틴Goroutine의 적절한 취소
2.요청된 정보의 전달, 전파
이 두가지로 볼 수 있다.

고언어를 접한지 한달째, 몇몇의 보수 안건에서 컨텍스트를 넘길 때, Background()?백그라운드면 기본셋이라는 뜻이겠지? 생각해버려 백그라운드를 남발,,, 결국 종료되지않고 남는 고루틴이 존재한다는 에러를 접하게 된다. 나의 미국인 상사는 Cancellabe Context(취소 가능한 컨텍스트)를 사용하라는 지적을 하였고, 그제서야 깨달았다 아.. 취소할 수 있는 컨텍스트도 있어..?


컨텍스트의 두 가지 주요 용도 - 1.고루틴(Goroutine)의 적절한 취소

Context는 시간 초과 및 데드라인을 설정하여 후속 처리가 정체되는 것을 방지, 불필요해진 고루틴(Goroutine)은 취소하고 리소스를 해제하는 역할도 한다.
타임아웃이나 데드라인을 설정하지 않은 경우 접속 등 문제로 느린처리가 돼고, 그 후속 처리를 정체시켜 버린다. Context로 미리 타임아웃 시간 3초등을 설정하면 재시도 처리나 다른 수단을 선택할 수 있게 된다.

그리고 고루틴을 취소하지 않고 프로세스를 끝내게 되면 고루틴은 사라지지 않고 남아 리소스를 소모할 수 있다.(나같은 경우도 unit testing 시 go leak에 의해 리소스가 소모된다는 에러를 접했다.) 이것 또한 Context에서 제대로 취소함으로써 리소스를 해제, 다른처리에 해당 리소스를 사용할 수 있도록 한다.

보통 고루틴(Goroutine)을 취소하려는 패턴이 3개 정도 있다고 생각한다.
1.모든 Goroutine을 취소하려는 경우
2.분기된 대상의 고루틴을 취소하고 싶은 경우
3.블록(느린처리)되어 있는 처리를 취소하고 싶은 경우

내가 남발했었던

ctx := context.Background()

백그라운드 이외에 컨텍스트를 선언하고 지정하는 함수는 다양한 것이 존재한다.
https://pkg.go.dev/context <- 패키지에 있는 함수중 자주 사용하는 함수들에 대해 알아보겠다.

취소가능한 컨텍스트 - withCancel

func WithCancel(parent Context) (ctx Context, cancel CancelFunc)

WithCancel은 parent의 사본을 반환한다.
parent.Done이 닫히거나 취소가 호출되면 복사된 Done 채널도 닫힌다.

이미지로써는 tree 구조로 되어 있어, 생성원의 Context가 캔슬되었을 때에, 거기로부터 파생한 자식 context도 모두 캔슬된다.

취소가능한 컨텍스트 - withDeadline

func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)

withDeadline은 parent의 사본을 반환한다.
parent.Done이 닫히거나 취소가 호출되면 복사된 Done 채널도 닫힌다.

Context의 deadline은 현재시간 +timeout 또는 부모컨텍스트의 기한(트리구조이기 때문에 부모가 우선)의 빠른쪽으로 설정된다.

취소가능한 컨텍스트 - withTimeout

func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)

Context의 타임아웃은 지정한 시간이나 부모 컨텍스트의 기한(트리구조이므로 부모가 우선)의 빠른쪽으로 설정된다.

context.Background()와 context.TODO()

func Backgroune()
func TODO()

backgound나 TODO 어느쪽이든 둘 다 빈 context를 생성한다.
기본적으론 백그라운드쪽을 사용하지만 TODO는 nil처리는 하고싶지 않지만 나중에 무언가를 설정하기 위해 거는,,? 느낌으로 이해할 수 있겠다.

CancelFunc

type CancelFunc = context.CancelFunc

컨텍스트를 캔슬한다.


참고자료 : https://qiita.com/yoshinori_hisakawa/items/a6608b29059a945fbbbd

profile
일본 도쿄에서 2년차 개발자로 일하고 있는 말하는 감자입니다.

0개의 댓글