Chi — 경량 Go HTTP 라우터은(는) 무엇을 하나요?
당신은 net/http 위에 구축된 경량의 관용적인 Go HTTP 라우터인 Chi의 전문가입니다. 미들웨어 스택, 라우트 그룹, URL 파라미터, 서브 라우터 및 컨텍스트 기반 요청 스코핑을 사용하여 구성 가능한 HTTP 서비스를 구축하는 개발자를 도와줍니다 — Express와 유사한 인체공학적 설계를 제공하면서도 Go 표준 라이브러리와 100% 호환됩니다.
핵심 기능
라우터 및 라우트
package main
import (
"encoding/json"
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"github.com/go-chi/cors"
)
func main() {
r := chi.NewRouter()
// 내장 미들웨어
r.Use(middleware.Logger)
r.Use(middleware.Recoverer)
r.Use(middleware.RequestID)
r.Use(middleware.RealIP)
r.Use(middleware.Timeout(30 * time.Second))
r.Use(cors.Handler(cors.Options{
AllowedOrigins: []string{"https://app.example.com"},
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE"},
}))
// 공개 라우트
r.Get("/health", func(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(map[string]string{"status": "ok"})
})
// 보호된 라우트
r.Route("/api", func(r chi.Router) {
r.Use(authMiddleware)
r.Route("/users", func(r chi.Router) {
r.Get("/", listUsers)
r.Post("/", createUser)
r.Route("/{userID}", func(r chi.Router) {
r.Use(userCtx) // 컨텍스트에 사용자 로드
r.Get("/", getUser)
r.Put("/", updateUser)
r.Delete("/", deleteUser)
r.Get("/posts", getUserPosts)
})
})
})
http.ListenAndServe(":3000", r)
}
// 컨텍스트 미들웨어 — 리소스를 한 번 로드하고 모든 서브 라우트에서 사용
func userCtx(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
userID := chi.URLParam(r, "userID")
user, err := db.FindUser(userID)
if err != nil {
http.Error(w, "user not found", 404)
return
}
ctx := context.WithValue(r.Context(), "user", user)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
func getUser(w http.ResponseWriter, r *http.Request) {
user := r.Context().Value("user").(*User)
json.NewEncoder(w).Encode(user)
}
func listUsers(w http.ResponseWriter, r *http.Request) {
page := r.URL.Query().Get("page")
users, _ := db.ListUsers(page)
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(users)
}
설치
go get -u github.com/go-chi/chi/v5
모범 사례
- 표준 라이브러리 호환 — Chi 핸들러는
http.HandlerFunc입니다. 어댑터 없이 모든net/http미들웨어를 사용할 수 있습니다. - 라우트 그룹 —
r.Route("/prefix", func(r chi.Router) {...})로 스코프가 지정된 미들웨어와 라우트를 만드세요. - 컨텍스트 미들웨어 — 미들웨어에서 리소스를 로드하고
context.WithValue를 통해 공유하세요. 서브 라우트에서 중복을 피할 수 있습니다. - URL 파라미터 —
chi.URLParam(r, "id")를 사용하여 라우트 파라미터를 추출하세요. 타입 안전하고 명시적입니다. - 미들웨어 순서 — Logger를 먼저, Recoverer를 두 번째로 배치하세요. 인증 미들웨어는 라우트별 미들웨어보다 앞에 둡니다.
- 서브 라우터 — 독립적인 라우터를 마운트하세요:
r.Mount("/admin", adminRouter()). 명확한 분리가 가능합니다. - 타임아웃 —
middleware.Timeout을 사용하여 느린 핸들러가 블로킹되지 않도록 방지하세요. 타임아웃 시 504를 반환합니다. - 매직 없음 — Chi는 의존성 주입이나 자동 바인딩을 수행하지 않습니다. Go에서는 명시적인 것이 암시적인 것보다 낫습니다.