더북(TheBook)

라우터 수정

라우터에서도 패키지 내에서 정의한 HandlerFunc를 사용하도록 다음과 같이 수정하자.

▼ router.go

package main
 
import (
    "net/http"
    "strings"
)
 
type router struct {
    // 키: http 메서드
    // 값: URL 패턴별로 실행할 HandlerFunc
    handlers map[string]map[string]HandlerFunc
}
 
func (r *router) HandleFunc(method, pattern string, h HandlerFunc) {
    // http 메서드로 등록된 맵이 있는지 확인
    m, ok := r.handlers[method]
    if !ok {
        // 등록된 맵이 없으면 새 맵을 생성
        m = make(map[string]HandlerFunc)
        r.handlers[method] = m
    }
    // http 메서드로 등록된 맵에 URL 패턴과 핸들러 함수 등록
    m[pattern] = h
}
 
func (r *router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    // http 메서드에 맞는 모든 handers를 반복하면서 요청 URL에 해당하는 handler를 찾음
    for pattern, handler := range r.handlers[req.Method] {
        if ok, params := match(pattern, req.URL.Path); ok {
            // Context 생성
            c := Context{
                Params:         make(map[string]interface{}),
                ResponseWriter: w,
                Request:        req,
            }
            for k, v := range params {
                c.Params[k] = v
            }
            // 요청 url에 해당하는 handler 수행
            handler(&c)
            return
        }
    }
    // 요청 URL에 해당하는 handler를 찾지 못하면 NotFound 에러 처리
    http.NotFound(w, req)
    return
}
 
func match(pattern, path string) (bool, map[string]string) {
    // ...
}

router의 내부 필드인 handlers 타입을 map[string]map[string]HandlerFunc로 변경했다. 라우터의 ServeHTTP() 메서드에서는 요청 URL에 해당하는 핸들러를 수행하기 전에 Context를 생성해서 매개변수로 전달한다. 이때 match() 함수에서 전달된 동적 URL의 매개변수 정보는 Context에 담는다.

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