고루틴 실행
go 키워드, 고루틴 수명 주기 및 WaitGroups
고루틴 실행은(는) CoddyKit의 무료 Go Academy 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Go Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Go Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
goroutine이란 무엇인가요
goroutine은 Go 런타임이 관리하는 가볍고 동시 실행되는 함수입니다. goroutine은 운영체제 스레드보다 훨씬 저렴하므로 수천 개를 실행할 수 있습니다:
go키워드로 시작합니다- 초기 스택은 약 2KB이며 동적으로 늘어납니다
- 운영체제가 아니라 Go 런타임이 스케줄링합니다
- 공유 메모리가 아니라 채널을 통해 통신합니다
go 키워드
함수 호출 앞에 go를 붙이면 해당 함수를 goroutine으로 실행할 수 있습니다:
package main
import ("fmt"; "time")
func greet(name string) {
fmt.Printf("Hello, %s!\n", name)
}
func main() {
go greet("Alice") // runs concurrently
go greet("Bob") // runs concurrently
time.Sleep(100 * time.Millisecond) // wait for goroutines
fmt.Println("done")
}goroutine의 수명 주기
goroutine은 go 문이 실행될 때 시작되고 함수가 반환될 때 종료됩니다. main이 반환되면 모든 goroutine이 종료됩니다:
package main
import ("fmt"; "time")
func worker(id int) {
fmt.Printf("Worker %d starting\n", id)
time.Sleep(time.Duration(id) * 50 * time.Millisecond)
fmt.Printf("Worker %d done\n", id)
}
func main() {
for i := 1; i <= 3; i++ {
go worker(i)
}
time.Sleep(300 * time.Millisecond) // naive wait
}동기화를 위한 sync.WaitGroup
goroutine이 완료될 때까지 기다릴 때 대기 대신 sync.WaitGroup을 사용합니다:
package main
import ("fmt"; "sync")
func worker(id int, wg *sync.WaitGroup) {
defer wg.Done() // signal completion
fmt.Printf("Worker %d working\n", id)
}
func main() {
var wg sync.WaitGroup
for i := 1; i <= 5; i++ {
wg.Add(1) // register one goroutine
go worker(i, &wg)
}
wg.Wait() // block until all Done()
fmt.Println("all workers finished")
}익명 goroutine
익명 함수를 직접 goroutine으로 실행할 수 있습니다. 인라인 동시 작업에 유용합니다:
package main
import ("fmt"; "sync")
func main() {
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
i := i // capture loop variable
wg.Add(1)
go func() {
defer wg.Done()
fmt.Printf("goroutine %d\n", i)
}()
}
wg.Wait()
}반복 변수 캡처 시 주의점
반복 변수를 캡처하지 않으면 모든 goroutine이 동일한 (최종) 값을 볼 수 있습니다. 이는 Go에서 발생하는 대표적인 동시성 버그입니다:
package main
import ("fmt"; "sync")
func main() {
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go func(n int) { // pass i as argument — safe
defer wg.Done()
fmt.Println(n) // prints 0, 1, 2 in some order
}(i)
}
wg.Wait()
}goroutine과 스레드 비교
goroutine이 운영체제 스레드보다 선호되는 이유입니다:
- 초기 스택이 2KB로, 운영체제 스레드의 약 1MB보다 작습니다
- 생성에 마이크로초가 걸리며, 운영체제 스레드는 밀리초가 걸립니다
- Go 런타임은 GOMAXPROCS개의 OS 스레드에서 goroutine을 다중화합니다
- goroutine 전환은 협력적이므로 커널이 개입하지 않습니다
- Go가 스케줄링을 처리하므로 개발자는 로직에 집중할 수 있습니다
GOMAXPROCS
runtime.GOMAXPROCS는 병렬로 goroutine을 실행할 OS 스레드 수를 제어합니다(기본값은 CPU 수입니다):
package main
import ("fmt"; "runtime")
func main() {
// Default: number of available CPU cores
fmt.Println("CPUs:", runtime.NumCPU())
fmt.Println("GOMAXPROCS:", runtime.GOMAXPROCS(0)) // 0 = query without changing
// Set to 1 for debugging race conditions:
// runtime.GOMAXPROCS(1)
fmt.Println("Goroutines:", runtime.NumGoroutine())
}goroutine 누수
goroutine이 시작된 후 종료되지 않으면 goroutine 누수가 발생합니다. 일반적인 원인으로는 채널 수신 차단, 뮤텍스 잠금 차단, 취소 기능 부재가 있습니다:
package main
import ("fmt"; "time"; "runtime")
func leaky() {
ch := make(chan int) // nobody sends to ch
go func() {
v := <-ch // blocks forever — goroutine leaked!
fmt.Println(v)
}()
}
func main() {
leaky()
time.Sleep(10 * time.Millisecond)
fmt.Println("goroutines:", runtime.NumGoroutine()) // > 1
}goroutine 사용 모범 사례
goroutine 사용 지침입니다:
- 각 goroutine이 어떻게 종료되는지 항상 알고 있어야 합니다
- 동기화에는 대기가 아니라 WaitGroup이나 채널을 사용합니다
- 반복 변수는 클로저를 통해 전달하지 말고 함수 인수로 전달합니다
- context로 goroutine을 취소하고 실행 중인 채로 남겨 두지 않습니다
- 경쟁 감지기를 사용합니다:
go run -race main.go
빠른 확인
goroutine에서 반복 변수 캡처 버그를 피하는 올바른 방법은 무엇인가요?
복습: goroutine 실행
요약:
go fn()으로 실행하며, 가볍고 비용이 적습니다- 기다릴 때는
sync.WaitGroup을 사용합니다:Add(1),defer Done(),Wait() - 반복 변수는 인수로 전달하거나 다시 선언하여 캡처합니다
- 각 goroutine이 어떻게 종료되는지 항상 파악하여 누수를 방지합니다
- 데이터 경쟁을 감지하려면
-race플래그를 사용합니다
AI 튜터와 함께 Go을(를) 배우세요 — 무료
브라우저에서 실제 코드를 작성하고 실행하며, 24/7 AI 튜터로부터 즉각적인 도움을 받고, 웹이나 앱에서 중단한 부분부터 계속 학습하세요.
- 코스
- 51
- 레슨
- 203
자주 묻는 질문
“고루틴 실행” 강의는 무료인가요?
네 — “고루틴 실행” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Go Academy 강의 전체를 잠금 해제할 수 있습니다. Go Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“고루틴 실행”에서 뭘 배우나요?
go 키워드, 고루틴 수명 주기 및 WaitGroups 브라우저에서 직접 실행하는 실습 코드로 Go Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Go Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Go Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.
“고루틴 실행” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Go Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Go Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.