학습
Go 고루틴 (Goroutines)
Go 고루틴 (Goroutines) — 중급
고루틴 (Goroutines)
1. 도입 (왜 배워야 하는가)
고루틴은 Go 언어의 가장 강력한 기능 중 하나로, 동시에 여러 작업을 수행할 수 있게 해줍니다. 실무에서 고루틴을 활용하면, 서버가 여러 클라이언트의 요청을 동시에 처리하거나, 복잡한 계산을 적절히 분산시킬 수 있어 성능을 극대화할 수 있습니다. 만약 고루틴을 모른다면, 동시 처리의 이점을 누릴 수 없으며, 이는 서버 성능 저하나 사용자 경험 악화로 이어질 수 있습니다. 예를 들어, 웹 애플리케이션에서 동시에 여러 사용자의 요청을 처리하지 못하면, 응답 속도가 느려져 사용자 이탈을 초래할 수 있습니다.
2. 핵심 개념 설명
고루틴은 Go의 경량 스레드로, 쉽게 생성하고 관리할 수 있는 비동기 작업을 수행할 수 있습니다. 고루틴은 함수 호출 앞에 go 키워드를 붙여 생성하며, 이는 마치 여러 사람이 동시에 이야기하는 것과 비슷합니다. 한 사람이 말을 하더라도, 다른 사람들은 각자의 이야기를 계속할 수 있습니다.
관련 용어 정리
| 용어 | 설명 |
|---|---|
| 고루틴 | Go 언어의 경량 스레드, 비동기 작업 수행 |
| 채널(Channel) | 고루틴 간의 통신을 위한 데이터 전송 방법 |
3. 기본 코드 예제
package main
import (
"fmt"
"time"
)
func greet(name string) {
fmt.Println("Hello,", name)
}
func main() {
go greet("Alice") // 고루틴으로 greet 함수 호출
go greet("Bob") // 또 다른 고루틴으로 greet 함수 호출
// 메인 함수에서 잠시 대기
time.Sleep(1 * time.Second)
fmt.Println("Main function completed")
}
실행 결과
Hello, Alice
Hello, Bob
Main function completed
코드 한 줄씩 동작 설명
package main- Go 프로그램의 패키지를 정의합니다.import (...)- 필요한 패키지를 가져옵니다. 여기서는fmt와time패키지를 사용합니다.greet(name string)- 이름을 인사하는 함수 정의합니다.main()- 프로그램의 시작점인 메인 함수입니다.go greet("Alice")- 고루틴을 사용해greet함수를 비동기적으로 호출합니다.go greet("Bob")- 또 다른 고루틴을 생성합니다.time.Sleep(1 * time.Second)- 메인 함수가 종료되지 않도록 1초 대기합니다.fmt.Println("Main function completed")- 메인 함수가 완료되었음을 출력합니다.- 고루틴 종료 대기 없이 메인 함수 종료
- 공유 자원 동기화 미비
- 고루틴은 Go 언어의 비동기 작업을 쉽게 수행할 수 있게 해주며, 서버 성능 향상에 기여합니다.
- 고루틴을 사용하려면
go키워드를 앞에 붙여야 하며, 메인 함수가 종료되지 않도록 대기하는 방법을 알아야 합니다. - 다음에 학습하면 좋은 주제로는 채널(Channel), 동기화(Synchronization), 에러 처리(Error Handling) 등이 있습니다. 이를 통해 고루틴을 더욱 효과적으로 활용할 수 있습니다.
4. 실전 활용 예제
4.1 웹 서버에서 클라이언트 요청 처리
쇼핑몰 웹 서버에서 여러 사용자의 장바구니 정보를 동시에 처리해야 할 때, 고루틴을 사용할 수 있습니다.
package main
import (
"fmt"
"net/http"
)
func handleRequest(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Processing request for %s\n", r.URL.Path)
}
func main() {
http.HandleFunc("/", handleRequest)
fmt.Println("Server started at :8080")
http.ListenAndServe(":8080", nil)
}
4.2 데이터 수집 및 처리
여러 API에서 데이터를 동시에 수집할 때, 고루틴을 활용하여 병렬로 요청을 보내고 처리할 수 있습니다.
package main
import (
"fmt"
"sync"
)
func fetchData(url string, wg *sync.WaitGroup) {
defer wg.Done() // 작업이 끝났음을 알림
// 실제 API 호출 로직 필요
fmt.Println("Fetching data from", url)
}
func main() {
var wg sync.WaitGroup
urls := []string{"http://api1.com", "http://api2.com", "http://api3.com"}
for _, url := range urls {
wg.Add(1)
go fetchData(url, &wg) // 고루틴으로 데이터 수집
}
wg.Wait() // 모든 고루틴이 완료될 때까지 대기
fmt.Println("All data fetched")
}
5. 흔한 실수와 주의사항
흔한 실수
- 잘못된 코드:
go greet("Alice")
- 올바른 코드:
go greet("Alice")
time.Sleep(1 * time.Second) // 고루틴 완료 대기
- 고루틴이 동시에 같은 자원에 접근할 경우, 동기화가 필요합니다. sync.Mutex를 사용하여 자원을 안전하게 보호해야 합니다.