[GoLang] Context가 뭘까요?

2023. 12. 2. 20:09· Go Lang/Study
목차
  1. Context 정의
  2. 함수 및 타입들
  3. WithCancel
  4. WithCancelCause
  5. WithDeadline
  6. WithTimeOut
  7. WithValue

최근 면접에서 Go의 Context가 뭐냐고 물으셨다.

가장 중요할 때 기억이 나지 않는 게 세상의 규칙인 건가.. 라는 생각이 들었다

 

그렇게  백수의 기간이 늘었다

 

Context 정의

context 패키지에서 제공하는 걸로 간단하게 생각하면 작업 명세서라 할 수 있다.

"10시부터 12시는 네가 일해, 그리고 중간에 냉장고 정리를 하고 에어컨을 꺼야 돼, 나는 여기서 청소하고 있을게"와 어떻게 하지를 정의해주는 작업 명세서다.

 

새로운 고루틴을 시작할 때 시간을 지정해주기도 하고 외부의 작업을 취소할 때도 사용할 수 있다.

거기에 작업 설정에 대한 정보도 전달이 가능하다.

 

이게 가능해진 버전은 Go 1.7 버전(2016-08-15일)부터로 그때부터 기본으로 탑재가 됐다.

Context 단어 뜻을 그대로 직역하면 "맥락"으로 대충 맥락을 책임진다 생각해도 될 것 같다.

 

https://pkg.go.dev/context#pkg-index

 

context package - context - Go Packages

Discover Packages Standard library context Version: go1.21.4 Opens a new window with list of versions in this module. Published: Nov 7, 2023 License: BSD-3-Clause Opens a new window with license information. Imports: 5 Opens a new window with list of impor

pkg.go.dev

문서에는 아래와 같은 다양한 함수와 타입을 제공한다고 알려주는데

Context가 파라미터로 있고 반환에도 Context가 있는 경우는 상위 Context를 Context로 감싸 신규 Context로 만들 수 있다는 걸 알려준다.

와 다양하다


함수 및 타입들

당연히 문서를 보는 게 좋지만 진짜 간단히 정리하자면 아래와 같다

명칭 설명
func AfterFunc Context가 완료 또는 종료, 취소시 설정한 함수가 실행, 이미 완료시는 바로 함수 실행
func Cause Context가 취소된 원인을 0이 아닌 오류 반환
func WithCancel 해당 Context에 CancelFunc를 받을 수 있음
func WithCancelCause CancelFunc 대신 CancelCauseFunc으로 Context Cause 설정, Cause로 탐색 가능
func WithDeadline 제한 기간을 지정하는데 제한 기간뿐만아니라 상위 Context가 종료시에도 종료 됨
func WithDeadlineCause 반환된 CancleFunc은 Cause를 기록하지 않고 기한 초과시에 Context Cause 설정
func WithTimeout 얼마나 유지할 지를 결정할 때 사용하며 Conext 취소시 관련 리소스를 해제하므로 Defer를 통한 취소가 필요
func WithTimeoutCause 시간 만료시 Context Cause를 설정
type CacnelFuc 작업 중단을 지시 
type CancelCauseFunc CancelFunc와 동일하지만 Cause 설정

 

정독하면은 Context에 대한 느낌이 올 것이다.

하지만 이걸 고루틴에 적용하고 사용할지는 막막합니다.

 

예제를 코딩해봅시다.


WithCancel

작업 취소가 가능한 컨텍스트로 아래가 예제입니다.

cancel을 실행함으로써 ctx.Done을 찾는 select문이 실행되어 wg.Done으로 wg.Wait가 종료되는 것이죠.

package main

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

var wg sync.WaitGroup

func main() {
	wg.Add(1)

	ctx, cancel := context.WithCancel(context.Background())
	go printTick(ctx)
	time.Sleep(5 * time.Second)

	cancel() // cancel을 실행함으로써 ctx에 done 신호가 들어감

	wg.Wait()
}

func printTick(ctx context.Context) {
	// 초당 한번씩 이벤트 생성
	tick := time.Tick(1 * time.Second)
	for {
		select {
		case <-ctx.Done(): // ctx에 done 신호가 들어오면
			fmt.Println("cancel() 실행으로 ctx.Done()이 실행됨")
			wg.Done() // waitGroup을 종료
			return
		case <-tick:
			fmt.Println("tick")
		}
	}
}

다음과 같은 출력이 나와야 함

tick
tick
tick
tick
tick
cancel() 실행으로 ctx.Done()이 실행됨

WithCancelCause

위에 WithCancel 코드에서 main 부분만 아래로 바꾸면 되고

둘은 기능은 똑같으나 Cause 키워드가 붙은 것들은 Cause를 통해 취소나 완료된 이유를 알 수 있다.

func main() {
	wg.Add(1)

	ctx, cancel := context.WithCancelCause(context.Background())
	go printTick(ctx)
	time.Sleep(5 * time.Second)

	cancel(errors.New("정상 종료")) // cancel을 실행함으로써 ctx에 done 신호가 들어감

	// 해당 context 에 cause 로 에러 확인
	err := context.Cause(ctx)
	fmt.Println("Error:", err)
	wg.Wait()
}

결과

tick
tick
tick
tick
tick
Error: 정상 종료
cancel() 실행으로 ctx.Done()이 실행됨

WithDeadline

데드라인은 특정 시기까지 유지되다가 지나면 만료되는 함수이다

cancel을 받을 경우 특정 시기에 만료되는 걸 취소할 수 있다

 

main 함수 로직만 아래로 수정하면 된다

func main() {
	wg.Add(1)

	ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(5*time.Second))
	go printTick(ctx)

	defer cancel()
	wg.Wait()
}

결과

tick
tick
tick
tick
tick
cancel() 실행으로 ctx.Done()이 실행됨

WithTimeOut

WithTimeOut은 특정 시간 후에 종료할 수 있고

예제는 WithDeadline 부분을 아래로 바꾸면 바로 적용 가능합니다.

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)

결과 값도 동일한대

 

이 둘의 차이점은 

DeadLine은 특정 시각을 설정, timeOut은 일정시간을 설정한다고 봐야죠


WithValue

Context 설명 중 작업 지시 뿐만 아니라 값의 전달도 있었는데

값의 전달은 WithValue를 사용하면 된다

package main

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

var wg sync.WaitGroup

func main() {
	wg.Add(1)

	// 컨텍스트 랩핑
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	ctx = context.WithValue(ctx, "hello", "world")
	
	go printTick(ctx)

	defer cancel()
	wg.Wait()
}

func printTick(ctx context.Context) {
	// 초당 한번씩 이벤트 생성
	tick := time.Tick(1 * time.Second)
	for {
		select {
		case <-ctx.Done(): // ctx에 done 신호가 들어오면
			fmt.Println("cancel() 실행으로 ctx.Done()이 실행됨")
			wg.Done() // waitGroup을 종료
			return
		case <-tick:
			fmt.Println(ctx.Value("hello"), "tick")
		}
	}
}

 

반응형

'Go Lang > Study' 카테고리의 다른 글

[GoLang] Go에서 동시성이란  (1) 2024.01.15
[GoLang] 데드락, 라이브락, 기아상태 이해하기 (Deadlock, Livelock, Starvation)  (1) 2024.01.02
[GoLang] Markdown을 HTML로 변환하기 (고도화)  (1) 2023.11.12
[GoLang] Markdown을 HTML로 변환하기  (0) 2023.11.05
[GoLang] Interface와 덕 타이핑  (0) 2023.11.05
  1. Context 정의
  2. 함수 및 타입들
  3. WithCancel
  4. WithCancelCause
  5. WithDeadline
  6. WithTimeOut
  7. WithValue
'Go Lang/Study' 카테고리의 다른 글
  • [GoLang] Go에서 동시성이란
  • [GoLang] 데드락, 라이브락, 기아상태 이해하기 (Deadlock, Livelock, Starvation)
  • [GoLang] Markdown을 HTML로 변환하기 (고도화)
  • [GoLang] Markdown을 HTML로 변환하기
DSeung
DSeung
DSeung
Dev log
DSeung
  • 분류 전체보기 (193)
    • PHP (62)
      • Laravel (31)
      • Error (5)
      • Setting (11)
      • Modern PHP (15)
    • Go Lang (51)
      • Study (30)
      • Algorithm (17)
      • Setting (1)
      • Error (3)
    • Java (11)
      • Spring (3)
      • JSP (0)
      • Error (2)
      • Setting (2)
      • 단축키 (2)
    • JavaScript (6)
      • Modern JavaScript (4)
      • Node (1)
    • Android Kotlin (5)
      • Study (4)
      • Error (1)
    • 컴퓨팅 기술 (12)
      • 데이터베이스시스템 (4)
      • Docker (2)
      • 크롤링 & 스크래핑 (1)
      • API (1)
      • 클라우드 (1)
      • 네트워크 (1)
    • MySQL (7)
    • AWS (1)
    • Git (5)
      • GItLab (1)
      • GitHub (4)
    • 도메인 (2)
      • 안과 (2)
    • 자격증 (7)
      • SQLD (1)
      • 정보처리기사 (6)
    • Mac os (1)
    • 나머지 (13)
      • tistory (1)
      • 기타 (9)
      • 일기 (3)
    • 독서 (10)

인기 글

최근 글

블로그 메뉴

  • 홈
  • 태그
전체
오늘
어제
hELLO · Designed By 정상우.v4.2.0
DSeung
[GoLang] Context가 뭘까요?
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.