-
[Golang] net/http 패키지개발언어/Go 2020. 9. 30. 23:58
1. net/http 기본사용
net/http 패키지는 HTTP 클라이언트와 서버를 작성하는 데 필요한 모든 기능을 제공한다.
package main import ( "fmt" "net/http" ) func main() { port := 8080 http.HandleFunc("/index", indexHandler) http.ListenAndServe(fmt.Sprintf(":%v", port),nil) } func indexHandler(resp http.ResponseWriter, req *http.Request) { fmt.Fprint(resp, "Index Page\n") }
net/http 패키지를 사용할 때, 첫 번째로 하는 작업은 http 패키지에서 HandleFunc 메서드를 호출하는 것이다. 이 때, HandleFunc 메서드는 첫 번째 매개 변수로 요청이 들어오면, 두 번째 매개 변수의 함수로 매핑시켜주며, 이 과정에서 DefaultServeMux 핸들러에 Handler 타입을 만든다. 함수의 원형은 아래와 같다.
func HandleFunc(pattern string, handler func(ResponseWriter, *Request))
HandleFunc 함수를 만들었다면, 그 다음에는 ListenAndServe를 통해 HTTP 서버를 시작한다. ListenAndServe를 통해 서버를 바인드 할 TCP 네트워크 주소와 요청을 라우팅하는 데 사용할 핸들러라는 두 가지 매개변수를 사용한다. 함수의 원형은 다음과 같다.
func ListenAndServe(addr string, handler Handler) error
2. JSON 다루기
내장 표준 라이브러리인 encoding/json 패키지를 사용하면 JSON형태의 데이터를 다룰 수 있게되며, JSON을 다룰 때에는 마샬(Marshal)과 언마샬(Unmarshal) 함수를 구현한다. 여기서 마샬이란, JSON 데이터의 형태를 바이너리 형태로 변환하는 것을 의미하며, 언마샬이란, 반대로 바이너리의 데이터를 JSON 형태(또는 다른 데이터 형태)로 변환하는 것을 의미한다.
2.1 마샬(Marshal)
func Marshal(v interface{})([]byte, error)
Marshal 함수는 interface 타입의 매개 변수를 하나 입력받는데, interface는 Go의 모든 타입을 나타내기 때문에 모든 타입을 매개 변수로 사용할 수 있다.
Marshal이 사용되는 예제를 보도록 하자.
code)
package main import ( "encoding/json" "fmt" "net/http" ) type indexResponse struct { Message string } func main() { http.HandleFunc("/index", indexHandler) http.ListenAndServe(fmt.Sprintf(":%v", 8080),nil) } func indexHandler(resp http.ResponseWriter, req *http.Request) { response := indexResponse{Message: "This is Index Page"} data, err := json.Marshal(response) if err != nil { panic("error!") } // 참고) fmt.Fprint 함수는 첫번째 객체에 두 번째 이후의 데이터를 담는다고 보면됨. fmt.Fprint(resp, data, "\n") fmt.Fprint(resp, string(data)) }
실행결과)
indexHandler함수의 fmt.Fprint(resp, data, "\n") 결과 데이터가 byte로 나온 것을 보면, JSON데이터를 json.Marshal함수를 통해 변형하면, 바이트 형의 데이터가 나온다는 것을 알 수 있다. 그리고 역의 과정으로 해당 byte를 string 형태로 역변환 했을 때, 다시금 JSON 형태의 데이터로 돌아간다는 것을 알 수 있다.
2.2 언마샬(Unmarshal)
언마샬은 마샬링되어 바이트화 된 데이터를 다른 데이터 형태로 변환시키는 것을 의미한다.
코드)
package main import ( "encoding/json" "fmt" "io/ioutil" "net/http" ) type indexResponse struct { Message string `json:"message"` } type indexRequest struct { Request string } func main() { port := 8080 http.HandleFunc("/index", indexHandler) http.ListenAndServe(fmt.Sprintf(":%v", port), nil) } func indexHandler(resp http.ResponseWriter, req *http.Request) { body, err := ioutil.ReadAll(req.Body) if err != nil { http.Error(resp, "Bad request(body)", http.StatusBadRequest) return } var request indexRequest err = json.Unmarshal(body, &request) if err != nil { http.Error(resp, "Bad request(json unmarshal)", http.StatusBadRequest) return } response := indexResponse{Message: request.Request} encoder := json.NewEncoder(resp) encoder.Encode(response) }
실행결과)
3. 컨텍스트(Context)
golang은 Context 패키지를 기본적으로 포함하고 있다. Context는 함수가 요청을 받을 때 API와 API 사이, 프로세스 사이에서 값들을 가지고 다닌다. 서버에 요청이 들어오면 Context가 생성이 되고, 함수가 다른 함수를 호출할 때 반드시 Context가 전파된다. 이 경우 Background, WithCancel, WithDeadline, WithTimeout, WithValue메서드로 Context의 값을 변경할 수 있으며 Context가 취소되는 경우 해당 Context로부터 파생된 Context도 삭제된다.
여기서 Background 메서드는 값이 없는 빈 Context를 반환하며, 일반적으로 main 함수에서 최상위 Context로 사용된다.
func Background() Context
WithCancel 메서드는 cancel 함수를 가지고 있는 부모 컨텍스트의 복사본을 리턴한다.
func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
WithDeadline 메서드는 제한 시간이 지난 경우 만료되는 부모 컨텍스트의 복사본을 리턴한다.
func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc)
WithTimeout 메서드는 Context 타입의 지속시간(duration)을 매개 변수로 전달한다는 점을 제외하고는 WithDeadline과 유사하다. 매개변수로 전달한 지속시간이 지나면 완료 채널이 닫히고 컨텍스트와 연관된 리소스가 해제된다.
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
WithValue 메서드는 매개 변수로 전달받은 key, value 쌍을 가지고 있는 부모 Context의 복사본을 리턴한다. 이렇게 설정된 컨텍스트 값은 요청 범위 데이터로 사용하기에 적합하다.
func WithValue(parent Context, key interface{}, val interface{}) Context
'개발언어 > Go' 카테고리의 다른 글
[Golang] 마이크로서비스 공통패턴 (0) 2020.10.14 [Golang] RPC API (0) 2020.10.12 [Golang] go에서 RPC 다루기 (0) 2020.10.11 [golang] 마샬링(Marshaling) (0) 2020.09.26 [golang] 인터페이스(Interface) (0) 2020.09.24