0Pricing
Go Academy · 강의

정상적인 종료

작업자를 깔끔하게 중지하기

정상적인 종료은(는) CoddyKit의 무료 Go Academy 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Go Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Go Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

우아한 종료가 필요한 이유

오래 실행되는 고루틴에는 중지 시점을 알려야 합니다. 우아한 종료를 사용하면 worker가 현재 작업을 마치고 리소스를 해제한 뒤, 누수나 데이터 손실 없이 종료할 수 있습니다.

  • 고루틴 누수가 없습니다
  • 반쯤 완료된 쓰기가 없습니다
  • 프로세스가 깔끔하게 종료됩니다

done 채널 패턴

전형적인 방법은 done 채널을 사용하는 것입니다. 이 채널을 닫으면 이를 수신하는 모든 고루틴에 중지 신호를 알립니다. 닫힌 채널은 수신할 때 즉시 반환되기 때문입니다.

done := make(chan struct{})
// ... later
close(done)

중지 신호에 select 사용

worker는 select를 사용하여 작업을 처리하거나 done 채널을 감지합니다. done이 닫히면 해당 case가 실행되고 worker가 반환됩니다.

for {
    select {
    case <-done:
        return
    case j := <-jobs:
        process(j)
    }
}

context.Context

관용적인 최신 도구는 context입니다. context.WithCancel은 컨텍스트와 취소 함수를 제공합니다. cancel을 호출하면 컨텍스트의 Done 채널이 닫힙니다.

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

ctx.Done() 수신하기

worker는 ctx.Done()을 대상으로 select를 수행합니다. cancel이 호출되거나 기한이 지나면 채널이 닫히고 worker가 종료됩니다.

select {
case <-ctx.Done():
    return ctx.Err()
case j := <-jobs:
    process(j)
}

worker 기다리기

중지 신호를 보내는 것만으로는 충분하지 않습니다. worker가 실제로 작업을 마칠 때까지 기다려야 합니다. sync.WaitGroup이 worker를 추적하므로 main은 수가 0이 될 때까지 차단될 수 있습니다.

var wg sync.WaitGroup
wg.Add(1)
go func() {
    defer wg.Done()
    runWorker(ctx)
}()
// ... later
cancel()
wg.Wait()

context를 사용한 시간 제한

context.WithTimeout은 일정 시간이 지나면 자동으로 취소합니다. 따라서 강제 종료하기 전에 종료에 걸리는 시간을 제한할 수 있습니다.

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

완전한 우아한 종료

이 프로그램은 두 worker를 실행하고 컨텍스트를 취소한 다음, 두 worker가 깔끔하게 종료할 때까지 기다린 후 완료를 출력합니다.

package main

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

func worker(ctx context.Context, id int, wg *sync.WaitGroup) {
    defer wg.Done()
    for {
        select {
        case <-ctx.Done():
            fmt.Printf("worker %d stopping\n", id)
            return
        case <-time.After(50 * time.Millisecond):
        }
    }
}

func main() {
    ctx, cancel := context.WithCancel(context.Background())
    var wg sync.WaitGroup
    for i := 1; i <= 2; i++ {
        wg.Add(1)
        go worker(ctx, i, &wg)
    }
    time.Sleep(120 * time.Millisecond)
    cancel()
    wg.Wait()
    fmt.Println("all workers stopped")
}

진행 중인 작업 마무리하기

종료할 때는 이미 시작한 작업을 worker가 마치도록 하는 경우가 많습니다. 마지막 반복문에서 남은 작업을 읽거나, 새 작업은 받지 않으면서 현재 작업이 완료되도록 하세요.

OS 신호 받기

실제 서버에서는 signal.NotifyContext를 SIGINT 및 SIGTERM에 연결하여 취소를 처리합니다. Ctrl+C를 누르면 수동으로 취소했을 때와 같은 우아한 종료 경로가 실행됩니다.

ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()

cancel()을 잊지 마세요

defer cancel()은 WithTimeout을 사용할 때도 항상 적용하세요. cancel을 호출하지 않으면 기한이 만료될 때까지 컨텍스트의 내부 고루틴과 타이머가 누수됩니다.

빠른 확인

종료 처리에 대한 지식을 확인해 보세요.

복습

우아한 종료를 배웠습니다:

  • context.WithCancel 또는 done 채널을 사용하여 중지를 알립니다
  • worker는 ctx.Done()을 대상으로 select를 수행합니다
  • WaitGroup은 모든 worker가 실제로 종료되도록 보장합니다
  • 실제 서버에서는 취소를 OS 신호에 연결합니다
  • 항상 cancel()을 defer로 호출합니다

자주 묻는 질문

“정상적인 종료” 강의는 무료인가요?

네 — “정상적인 종료” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Go Academy 강의 전체를 잠금 해제할 수 있습니다. Go Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“정상적인 종료”에서 뭘 배우나요?

작업자를 깔끔하게 중지하기 브라우저에서 직접 실행하는 실습 코드로 Go Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Go Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Go Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.

“정상적인 종료” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Go Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Go Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 작업자 풀 패턴
  2. 팬아웃과 팬인
  3. 파이프라인 단계
  4. 정상적인 종료
← Go Academy(으)로 돌아가기