프로그래밍 일반/Go 프로그래밍

[go] Context 활용하기

지노윈 2024. 11. 7. 20:16
반응형

 

Go 언어로 개발할 때, 단순히 고루틴을 활용하여 동시성 작업을 수행할 수 있지만, 여러 패키지들을 보면 context를 선언하고 고루틴을 관리하는 코드가 빈번히 등장하는 것을 알 수 있습니다. 이 글에서는 context 패키지가 왜 쓰이는지, 그리고 실제 코드를 통해 어떻게 활용하는지 살펴보겠습니다.


왜 context를 사용하는가?

Go 언어는 고루틴을 통해 동시성 작업을 수행합니다. 동시성 프로그램에서는 특정 작업이 시간 초과되거나 취소되어야 하는 경우가 있으며, 시스템 오류로 인해 작업을 선점해야 하는 상황도 발생할 수 있습니다. 이러한 상황을 대비해 고루틴 간에 작업의 상태를 공유하고 관리하기 위해, context 패키지가 Go 1.7 버전부터 표준 라이브러리로 제공되고 있습니다.

기존에는 완료 여부를 확인하기 위해 done 채널과 같은 방식으로 고루틴 간 통신을 했지만, context 패키지를 사용하면 동시성 관리가 보다 간편하고 일관되게 이루어질 수 있습니다.


주요 함수 소개

1. Context 생성

Background() 함수는 가장 기본이 되는 빈 Context를 생성하며, 이 Context는 취소되지 않는 최상위 부모 역할을 합니다.

ctx := context.Background()

2. Context 취소

WithCancel() 함수는 부모 Context를 받아 파생된 Context와 취소 함수(CancelFunc)를 반환합니다.

ctxWithCancel, cancelFunction := context.WithCancel(ctx)
defer cancelFunction()
doWorkContext(ctxWithCancel)

Context를 고루틴이나 중요한 작업 함수에 전달하여 Context 관리를 할 수 있습니다. 명시적으로 cancelFunction()을 호출하여 자원을 회수할 수 있습니다.

3. 타임아웃 및 데드라인 설정

WithTimeout()과 WithDeadline() 함수는 각각 상대적인 기간과 절대적인 시간을 기반으로 Context를 취소하는 데 사용됩니다.

ctxWithTimeout, cancelFunction := context.WithTimeout(ctx, 150 * time.Millisecond)
defer cancelFunction()

타임아웃과 데드라인은 설정된 시간이 지나면 자동으로 CancelFunc을 호출하여 작업을 취소하게 됩니다.

4. CancelFunc 호출 시 처리

고루틴이 작업 중 Context의 CancelFunc이 호출되면, 해당 Context와 모든 파생된 Context는 Done 채널에서 수신을 받아 종료 처리를 진행합니다.

func doWorkContext(ctx context.Context) {
    select {
    case <-ctx.Done():
        // 종료 처리: 파일이나 DB 연결 회수 등
    }
}

이러한 종료 처리를 통해 파일이나 DB 연결 자원을 회수하는 작업을 수행할 수 있습니다.

5. Context에 값 추가하기

WithValue() 함수는 key-value 쌍으로 값을 추가하여, Context를 통해 값을 전달하고 사용할 수 있습니다.

ctx := context.WithValue(context.Background(), "current_user", currentUser)
if v := ctx.Value("current_user"); v != nil {
    // currentUser 사용
}

이를 통해 Context에 특정 값(예: 사용자 정보)을 추가하고 필요한 곳에서 쉽게 꺼내 사용할 수 있습니다.

 

Best Practice

  • Context 전달: 함수를 설계할 때 Context는 첫 번째 파라미터로 전달하는 것이 관례입니다.
  • 취소 및 에러 처리: Done 채널을 통해 취소 신호를 수신받고, 자원 회수와 같은 종료 처리를 진행합니다.
  • 안전한 사용: 모든 파생된 Context는 안전하게 고루틴에서 사용할 수 있습니다.

Golang의 context 패키지를 제대로 활용하면 고루틴 관리가 훨씬 수월해지며, 특히 자원 회수와 종료 처리와 같은 작업을 보다 안정적이고 일관성 있게 할 수 있습니다.