고 에서 context 패키지는 API 나 느린 동작을 다루는데 좋다. ( 특히 서버 리퀘스트 요청에서 )
context 패키지를 이해하려면 고루틴과 채널에 대한 이해가 선행 되어야 하지만 내가 쓸 예시에서는 필요가 없다.
context 를 번역하면 문맥,흐름이라는 걸로 번역이 되는데 쉽게 생각해보면
웹과 서버의 통신을 하는데에 필요한 데이터나 값을 이 context안에 넣고 필요할때 뽑아 쓰는 형식이다.
또한 그 흐름을 컨트롤 해줄수 있는 기능을 한다.
예를들어 3초 이상이 걸리는 http request 가 있다고 가정하자.
하지만 3초이상 걸리는 request 는 무거운 요청에 해당하기에 우리 서버에서는 그걸 허용하지 않고 싶다.
그럴때 고에서는 Context 를 사용한다.
context가 없는 코드를 짜보면
func main() {
req, err := http.NewRequest(http.MethodGet, "http://죤내이오래걸리는데이터가져오는곳", nil)
if err != nil {
panic(err)
}
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
longData , err := ioutil.ReadAll(res.Body)
}
죤내이오래 걸리는곳에서 request 요청을 했다. 물론 여기에서 아무런 에러는 반환하지 않겠지만 ( url이 맞다고 가정하고 )
request 를 던졌는데 그쪽에서 가져오는 시간이 30초라고 생각하면 너무 오래걸린다.
우리는 이걸 미연에 방지 하고 싶다.
context를 추가해서 request 가 2초 이상이 걸리면 에러를 반환하는 코드를 짜보자.
func main() {
timeoutContext , cancel := context.WithTimeout(context.Background() , time.Second * 2 )
defer cancel()
req, err := http.NewRequestWithContext(timeoutContext,http.MethodGet,"http://죤내이오래걸리는데이터가져오는곳", nil)
if err != nil {
panic(err)
}
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
longData , err := ioutil.ReadAll(res.Body)
}
NewRequest를 WithContext 를 추가해 위에서 정의한 2초가 지나면 에러를 반환하는 timeoutContext 를 추가해줬다.
func main() {
r := gin.Default()
r.GET("", func(c *gin.Context) {
req , err := http.NewReqeustWithContext(c.Request.Context() , http.MethodGet, "http://google.com", nil)
if err != nil {
panic(err)
}
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data , err := ioutil.ReadAll(res.Body)
if err != nil {
panic(err)
}
c.Data(200,"text/html", data)
})
}
context 는 기본적으로 cancel을 지원한다. 위의 코드에서 만약 구글을 가져오는데 5초의 시간이 걸려서 사용자가 너무 오래 걸린다 싶어 연결을 취소하면 바로 끊어지게 된다.
이게 무슨말이냐면 아래의 예시를 보자.
아래는 context 가 없을 때 사용자가 cancel 를 보낸 로직이다.
사용자가 request 를 보내고 취소를 해도 서버의 쿼리와 데이터를 반환하는 흐름은 여전히 존재해 서버의 트래픽이 증가한다.
아래는 context 가 있을 때 사용자가 cancel 를 보낸 로직이다.
사용자가 request 를 보내고 취소를 하면 특정 쿼리와 데이터 반환하는 흐름이 없게 되어 서버의 트래픽을 줄여준다.
'Go' 카테고리의 다른 글
golang Gracefully Shutdown (위대한 쇼다운맨 ) (0) | 2022.05.03 |
---|---|
Golang TDD (테스트 주도 개발) 유닛테스트 루트 절대경로 설정 (0) | 2022.04.08 |
고(golang) 메일보내기(google) (0) | 2022.01.13 |
고(golang) 고루틴에 관하여 #2 (0) | 2021.12.23 |
고(golang) 비동기 큐 구현 (0) | 2021.11.29 |