Go를 이용해 HTTP 서버를 만드는 법을 포스팅하고자 합니다.
1.Go HTTP Sever 만들기
http 패키지는 HTTP 클라이언트 및 서버를 구현할때 사용되는 패키지 입니다.
HTTP 서버를 만들기 위한 4가지 방법이 있는데
- No request Parsing
- Manual request Parsing
- Multiplexer
- Global multiplexer
이 4가지 중에서 Multiplexer(멀티플렉서)를 사용하는가 안하는가에 따라 두가지로 나뉩니다.
1.No request parsing
가장 기본적인 구성 방법입니다.
어떠한 요청이 와도 동일한 응답을 처리해주는 서버입니다.
package main
import (
"fmt"
"net/http"
)
type database map[string]string
func (d database) ServeHTTP(w http.ResponseWriter, r *http.Request) {
for country, greeting := range d {
fmt.Fprintf(w, "%s: %s\n", country, greeting)
}
}
func main() {
db := database{
"kor": "안돼!",
"eng": "Noooo!",
}
http.ListenAndServe("localhost:8000", db)
}
요청을 받을시 해당 db안에 내용을 출력해주는 서버입니다.
ListenAnServer 함수는 TCP 네트워크에 주소 (addr)에서 수신 대기(Listen)을 한 다음 통신 요청들을 받아
Server(서버) 함수를 통해 handler 함수를 실행시킵니다.
func ListenAndServe(addr string, handler Handler) error
두번째 인자로 Handler 타입을 확인하면 아래와 같습니다.
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
Handler는 HTTP 요청에 대한 응답을 해줍니다.
또한Handler는 ServerHTTP를 가지고 있는 interface역할이고
따라서 위 코드에 ServerHTTP 함수를 가지고 있는 database를 ListenAndServer의
두번째 인자로 넣습니다.
위코드는 어떠 요청에도 관계없이 항상 동일한 읍답을 제공해줍니다.
- http://localhost:8000/
- http://localhost:8000/abc
- http://localhost:8000/kor
2.Manual request parsing
이번에는 ServerHTTP 함수 안에서 요청되는 경로를 구문 분석하도록 메서드를 수정해보겠습니다.
package main
import (
"fmt"
"net/http"
)
type database map[string]string
// func (d database) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// for country, greeting := range d {
// fmt.Fprintf(w, "%s: %s\n", country, greeting)
// }
// }
func (d database) ServeHTTP(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/foo":
fmt.Fprintf(w, "kor: %s\n", d["kor"])
case "/bar":
fmt.Fprintf(w, "eng: %s\n", d["eng"])
default:
http.NotFound(w, r)
}
}
func main() {
db := database{
"kor": "안돼!",
"eng": "Noooo!",
}
http.ListenAndServe("localhost:8000", db)
}
switch 문을 사용해 request 경로 별로 다르게 출력되게 수정했습니다.
case에 없는 경로라면 Not Found를 출력해 404 페이지를 출력합니다.
Not Found 함수는 "404 not found error"로 요청에 대한 응답을 하는 함수입니다.
func NotFound(w ResponseWriter, r *Request)
3.Multiplexer
두 번째 방식으로는 케이스가 증가하면 할 수록 Switch 문이 복잡해지고 관리가 어려워집니다.
이번엔 ServerHTTP 메서드 대신 ServerMux를 사용하는 방법에 대해 알아보겠습니다.
ServerMux는 HTTP 요청 멀티플렉서인데, 패턴에 맞는 핸들러를 등록하고 패턴과 맞는 요청이 올때 패턴에 대한
핸드러를 호출해주게 됩니다.
package main
import (
"fmt"
"net/http"
)
type database map[string]string
func (d database) kor(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "kor: %s\n", d["kor"])
}
func (d database) eng(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "eng: %s\n", d["eng"])
}
func main() {
db := database{
"kor": "안녕!",
"eng": "Hello!",
}
mux := http.NewServeMux()
mux.Handle("/kor", http.HandlerFunc(db.kor))
mux.HandleFunc("/eng", db.eng)
http.ListenAndServe("localhost:8000", mux)
}
NewServeMux 함수를 호출해 새로운 ServerMux를 할당받습니다.
mux := http.NewServeMux()
주어진 패턴에 대한 핸들러를 등록합니다.
mux.Handle("/kor", http.HandleFunc(db.kor))
mux.HandleFunc("/eng", db.eng)
HandlerFunc는 일반 함수를 HTTP 핸들러로 사용할 수 있는 어댑터 역할을 합니다.
type HandlerFunc func(ResponseWriter, *Request)
Handle은 주어진 패턴에 대한 핸들러를 등록해주는 함수입니다.
func Handle(pattern string, handler Handler)
Handle 함수 두 번째 인자로 Handler를 넣어야 하기에 일반 함수를 넣기 위해 HandlerFunc type을 사용해
Handler로 변환해야 합니다.
mux.Handle("/kor", http.HandlerFunc(db.kor))
HandleFunc는 주어진 패턴에 대한 핸들러 함수를 등록하는 함수입니다.
func HandleFunc(pattern string, handler func(ResponseWriter, *Request))
HandleFunc 함수 두 번째 인자는 변환 없이 함수를 직접 등록하시면 됩니다.
mux.HandleFunc("/eng", db.eng)
4.Global multiplexer
일반적으로 코드는 별도의 패키지로 분할됩니다.
라우터 핸들링을 설정해주기 위해 ServerMux 인스턴스를 각 패키지로 전달해줘야 하는 번거로움이 있는데
Global multiplexer 인 DefaultServerMux 인스턴스를 사용한다면
간단하게 사용할 수 있습니다.
package main
import (
"fmt"
"net/http"
)
type database map[string]string
func (d database) kor(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "kor, %s\n", d["kor"])
}
func (d database) eng(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "eng, %s\n", d["eng"])
}
func main() {
db := database{
"kor": "안녕!",
"eng": "Hello!",
}
http.Handle("/kor", http.HandlerFunc(db.kor))
http.HandleFunc("/eng", db.eng)
http.ListenAndServe("localhost:8000", nil)
}
ListenAndServer 함수 두 번째 인자에 nil을 넣어주면 DefaultServeMux를 사용하게 됩니다.
http.ListenAndServe("localhost:8000", nill)
Handle 및 HandleFunc 함수를 사용해 DefaultServeMux에 핸들러를 추가해주면 됩니다.
http.Handle("/kor", http.HandleFunc(db.kor))
http.HandleFunc("/eng", db.eng)
참고자료
'프론트 엔드 > Go' 카테고리의 다른 글
[GO] 리눅스 버전 Go 설치하기 - 헬로우 월드 출력 (0) | 2023.01.09 |
---|---|
[Go] Go 언어 프로그래밍 입문 - Go는 어떤언어 인가? (0) | 2022.02.25 |
[GO] Go - Introduction (0) | 2022.01.30 |