더북(TheBook)

미들웨어 체인

그림 8-11처럼 웹 요청이 들어오면 체인으로 연결된 미들웨어가 차례로 수행되고 마지막에 라우터가 동작하도록 구현해 보자.

지금까지는 웹 요청을 라우터가 받아 미들웨어로 묶인 핸들러 함수를 라우터 내부에서 수행했다. 그런데 이제는 서버가 웹 요청을 받아 미들웨어를 차례로 수행한 다음, 마지막에 라우터로 컨텍스트를 넘겨 줄 것이다.

그림 8-11 미들웨어를 차례로 수행한 다음 라우터로 컨텍스트를 넘겨 줌

미들웨어 체인에 라우터를 연결하려면 라우터도 컨텍스트의 값을 매개변수로 받아 처리하는 핸들러 형태가 되어야 한다. 라우터의 ServeHTTP 메서드를 제거하고 핸들러 함수를 반환하는 함수를 새로 정의해 보자.

▼ router.go

func (r *router) handler() HandlerFunc {
    return func(c *Context) {
        // http 메서드에 맞는 모든 handers를 반복하며 요청 URL에 해당하는 handler를 찾음
        for pattern, handler := range r.handlers[c.Request.Method] {
            if ok, params := match(pattern, c.Request.URL.Path); ok {
                for k, v := range params {
                    c.Params[k] = v
                }
                // 요청 URL에 해당하는 handler 수행
                handler(c)
                return
            }
        }
 
        // 요청 URL에 해당하는 handler를 찾지 못하면 NotFound 에러 처리
        http.NotFound(c.ResponseWriter, c.Request)
        return
    }
}

라우터의 ServeHTTP 메서드 로직을 그대로 handler() 메서드에 옮겼다. 차이점은 라우터에서 새로운 컨텍스트를 만드는 것이 아니라, 매개변수로 전달된 컨텍스트를 그대로 사용한다는 점이다. 이제 라우터의 handler 함수로 얻은 라우터 핸들러를 미들웨어 체인의 끝에 연결하면 된다.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.