서론
Go 언어는 기본적으로 HTTP 구현이 net/http라는 표준 패키지로 제공된다. 표준 패키지는 언어와 함께 관리되어 보안 측면에서도 안정적이며 HTTP 표준을 잘 준수하고 있어 대부분의 상황에서 문제 없이 사용할 수 있다. 그러나 net/http 패키지를 사용해서 서버나 클라이언트가 많은 요청을 빠른 응답 시간으로 처리해야 할 때와 같이 성능이 중요한 상황에서는 외부 패키지인 fasthttp 사용을 고려할 수 있다.
fasthttp는 이름 그대로 빠른 HTTP를 제공하는 패키지로 net/http와 비교했을 때 최대 10배 빠른 성능을 제공한다. 하지만 fasthttp는 net/http와 API가 호환되지 않기 때문에 기존 코드를 다시 작성하거나 사용법을 새로 익혀야 한다. 또한 net/http의 모든 기능을 제공하지는 않고, HTTP 구현을 표준 패키지가 아닌 외부 패키지에 의존해야 한다는 점에서 충분히 검토 후 사용해야 한다.
fasthttp might not be for you!
fasthttp was designed for some high performance edge cases. Unless your server/client needs to handle thousands of small to medium requests per second and needs a consistent low millisecond response time fasthttp might not be for you. For most cases net/http is much better as it's easier to use and can handle more cases. For most cases you won't even notice the performance difference.
설치
go get -u github.com/valyala/fasthttp
fasthttp를 사용하기 위해서는 먼저 Go 모듈에 해당 패키지를 추가해야 한다.
서버 예제
package main
import (
"fmt"
"log"
"github.com/valyala/fasthttp"
)
func main() {
if err := fasthttp.ListenAndServe(":8080", func(ctx *fasthttp.RequestCtx) {
fmt.Fprintf(ctx, "Jae-Sung Example Server\n\n")
fmt.Fprintf(ctx, "Method: %s\n", ctx.Method())
fmt.Fprintf(ctx, "RequestURI: %s\n", ctx.RequestURI())
fmt.Fprintf(ctx, "Path: %s\n", ctx.Path())
fmt.Fprintf(ctx, "Host: %s\n", ctx.Host())
fmt.Fprintf(ctx, "QueryArgs: %s\n", ctx.QueryArgs().String())
fmt.Fprintf(ctx, "User-Agent: %s\n", ctx.UserAgent())
fmt.Fprintf(ctx, "IP: %s\n\n", ctx.RemoteIP().String())
ctx.SetContentType("text/plain; charset=utf8")
}); err != nil {
log.Fatalf("Error in ListenAndServe: %v", err)
}
}
요청 메서드, URI, 쿼리 파라미터, 클라이언트 IP 등의 정보를 응답하는 간단한 서버 예제이다.
클라이언트 예제
package main
import (
"fmt"
"github.com/valyala/fasthttp"
)
func main() {
req := fasthttp.AcquireRequest()
req.SetRequestURI("http://localhost:8080")
req.Header.SetMethod(fasthttp.MethodGet)
resp := fasthttp.AcquireResponse()
err := fasthttp.Do(req, resp)
fasthttp.ReleaseRequest(req)
if err == nil {
fmt.Printf("Response: [%d] %d bytes\n", resp.StatusCode(), len(resp.Body()))
} else {
fmt.Println("Failed to request:", err)
}
fasthttp.ReleaseResponse(resp)
}
로컬 서버에 HTTP 요청을 보내고 응답의 상태 코드와 본문 크기를 출력하는 간단한 클라이언트 예제이다.
마무리
Are there known net/http advantages comparing to fasthttp?
Yes:
- net/http supports HTTP/2.0 starting from go1.6.
- net/http API is stable, while fasthttp API constantly evolves.
- net/http handles more HTTP corner cases.
- net/http can stream both request and response bodies net/http can handle bigger bodies as it doesn't read the whole body into memory
- net/http should contain less bugs, since it is used and tested by much wider audience.
fasthttp는 성능이 가장 중요한 고성능 HTTP 서버나 클라이언트를 구현할 때 강력한 선택지가 될 수 있다. 그러나 모든 상황에서 적합하지는 않다. 예를 들어 net/http는 fasthttp에서 아직 개발 진행 중인 HTTP/2.0을 이미 지원하고 있고 더 다양한 HTTP 예외 상황을 처리할 수 있다. 또한 요청과 응답 본문을 스트리밍 방식으로 처리할 수 있어 전체 본문을 메모리에 읽지 않아 더 큰 본문을 처리하는데도 적합하다. 무엇보다도 더 넓은 사용자 기반과 철저한 테스트 과정을 통해 신뢰성과 안정성이 높다. 결과적으로 fasthttp는 성능이 절대적으로 중요한 경우에 적합하지만 대부분의 일반적인 상황에서는 net/http를 사용하는 것이 더 바람직하다.
'Language > Go' 카테고리의 다른 글
[golang] 타입 스위치(type switch)로 interface{} 값 처리하기 (0) | 2024.11.25 |
---|---|
[golang] panic 없이 interface{} 타입 변환하기 (0) | 2024.11.24 |
[golang] Base64 인코딩과 디코딩 처리하기 (0) | 2024.11.23 |
[golang] 런타임에 콜 스택 출력하기 (1) | 2024.11.22 |
[golang] panic과 recover로 try-catch 따라 하기 (1) | 2024.11.21 |