웹 서버를 만들기 위해서 하나하나 공부했던 부분에 대해서 정리를 하였습니다.
이전에 주로 다루었던 Node.js
와의 차이점과 동일한 문법 적인 부분을 비교하면서 적어보았습니다.
실제 실습 영상은 Youtube에서 다루고 있습니다.
package main
import (
"fmt"
"net/http"
)
func basic(w http.ResponseWriter, r *http.Request) {
// node.js에서 req,res를 받는것처럼 반드시 두개의 인자를 받아야 한다.
// Request부분 즉 r에는 클라이언트에서 보낸 메서드. 헤더, 바디 등등 정보가 담겨있다.
// 이와 반대로 ResponseWriter은 출력을 담당하고 있습니다.
fmt.Fprint(w, "hello world")
}
func main() {
http.HandleFunc("/", basic)
http.ListenAndServe(":3000", nil)
}
기본적인 웹 서버 입니다.
경로는 localhost:3000
으로 들어오는 경로만을 설정한 매우 간단한 서버 입니다.
단순히 화면에 Fprint를 통해서 보여주는?? 역할만을 수행하고 있습니다.
주석에도 적어둔것과 같이 Node.js와 비교를 해보자면
Node.js에서 express미들웨어를 사용하여 구성한 서버에서도 인자값을 두개 받게 됩니다.
req
, res
로 사용을 합니다.golang에서도 반드시 인자값을 두개 받게 되며 이를 http.ResponseWriter, Request
라고 합니다.
이때 Request
는 Node.js에서 req
와 같이 클라이언트에서 보내는 데이터를 담고 있고
ResponseWriter
부분은 Node.js에서 res
와 같이 클라이언트에게 보내는 데이터를 담게 됩니다.
이전과는 다르게 Request
를 통해서 요청을 받는 서버를 구현해 보았습니다.
package main
import (
"fmt"
"net/http"
"strconv"
)
func basic(w http.ResponseWriter, r *http.Request) {
values := r.URL.Query() // 쿼리 인수를 받게 됩니다.
name := values.Get("name") //특정 키값이 있는지를 확인합니다.
if name == "" {
name = "world" // 만약 키값이 없다면 새로 만들어 줍니다.
}
id, _ := strconv.Atoi(values.Get("id")) // 쿼리 인자에서 키값이 id인 값을 가져오고 int타입으로 변환시켜 줍니다.
fmt.Fprintf(w, "hello %s! id: %d", name, id) //그후 화면에 출력합니다.
}
func main() {
http.HandleFunc("/bar", basic)
http.ListenAndServe(":3000", nil)
}
url에 담기는 쿼리 메시지를 가져오는 방법입니다.
r.URL.Query()
를 통해 모든 쿼리 인자들을 가져올수 있고
이후 Get(키값)
을 통해서 쿼리 값에 접근이 가능합니다.
또한 부가적으로 들어오는 쿼리값들은 모두 string
타입이기 떄문에 strconv.Atoi()
를 통해서 string값을 int타입으로 변형시켜 줍니다.
이전 예시에 비해서 쿼리값을 받아올수 있는 부분만 변경이 되었기 떄문에 이해하기는 어렵지 않을것이라고 생각합니다.
사실 이러한 인스턴스가 정확하게 어떠한 방식으로 구동이 되는지는 아직은 이해하지 못하였습니다.
하지만 기능적인 부분을 추가할떄 어려운 문제점이 있고 단순히 DefaultServerMux
를 사용하기 보다는 인스턴스를 만들어서 사용을 하는 것이 좀더 기능적 추가에 유용하다고 인식만을 하고 있는 시점입니다.
DefaultServerMux라는 용어는 ListenAndServer부분에 nil이 들어가는 서버를 말합니다.
package main
import (
"fmt"
"net/http"
"strconv"
)
func basic(w http.ResponseWriter, r *http.Request) {
values := r.URL.Query() // 쿼리 인수를 받게 됩니다.
name := values.Get("name") //특정 키값이 있는지를 확인합니다.
if name == "" {
name = "world" // 만약 키값이 없다면 새로 만들어 줍니다.
}
id, _ := strconv.Atoi(values.Get("id")) // 쿼리 인자에서 키값이 id인 값을 가져오고 int타입으로 변환시켜 줍니다.
fmt.Fprintf(w, "hello %s! id: %d", name, id) //그후 화면에 출력합니다.
}
func test(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "이곳은 / 입니다.")
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/bar", basic)
mux.HandleFunc("/", test)
http.ListenAndServe(":3000", mux)
}
두개의 URL을 처리할수 있는 서버입니다.
두 경우 모두 이전에 사용하였던 코드 그대로 사용을 하였고 문제 없이 작동을 하고 있습니다.
굉장히 간단하지만 Node.js에서도 안해보았던 작업을 해보았습니다.
제목 그대로 파일을 제공하는 서버를 구축할수 있는 방법 입니다.
package main
import (
"net/http"
)
func main() {
mux := http.NewServeMux()
mux.Handle("/", http.FileServer(http.Dir("폴더명")))
http.ListenAndServe(":3000", mux)
}
일단 기본 셋팅을 위해서 같은 경로에 폴더가 필요합니다.
이후 해당 폴더에 접근을 한뒤에 폴더 안에 있는 이미지 파일 이름을 url에 입력해 주면 됩니다.
localhost:3000/img.jpg
package main
import (
"encoding/json"
"fmt"
"net/http"
)
type Student struct {
Name string
Age int
Score int
}
func MakeWebHandler() http.Handler {
mux := http.NewServeMux()
mux.HandleFunc("/student", StudentHandler)
return mux
}
func StudentHandler(w http.ResponseWriter, r *http.Request) {
var student = Student{"aaa", 16, 8}
data, _ := json.Marshal(student)
w.Header().Add("contetnt-type", "application/json")
w.WriteHeader(http.StatusOK)
fmt.Fprint(w, string(data))
}
func main() {
http.ListenAndServe(":3000", MakeWebHandler())
}
이번에는 이전과 다른 방식으로 서버를 구현해 보았습니다.
ListenAndServer
의 두번쨰 인자로 함수를 넘겨주는 방식입니다.이전과는 다르게 Header
부분에 어떠한 데이터를 넘겨주는지 타입을 정해주게 됩니다.
객체 형식의 데이터를 json으로 넘기기 위해서 일단 []byte
로 변환을 시켜 줍니다.
json.Marshal()
에서 이러한 역할을 처리하고 있습니다.이후 string으로 변환해 준뒤에 출력에 담아서 보내게 됩니다.