golang http server 시작하기

2020. 4. 16. 09:22golang/golang-webServer

golang http server 시작하기

1. 기본 tool 설정

go에서는 네트워크를 다루는 net package를 제공한다. net에는 http가 포함되어 있고 http 요청을 보낼 수 있는 클라이언트도 만들 수 있고 http 서버도 만들 수 있다.

 

http package

 

 

http 요청과 요청을 받을 수 있는 패키지입니다. 다른 언어들과 다르게 http 보안 서버를 만들 수 있게 제공합니다.

 

import "net/http"

 

2. 간단한 http 서버 만들어보기

ListenAndServe 함수

func ListenAndServe(addr string, handler Handler) error

이 함수를 이용하영 http 서버를 시작하고 process를 lock 시킵니다. http 요청을 받을 수 있고 줄수 도 있습니다. 만약 이 함수가 error를 반환하면 서버를 시작할 수 없습니다. 

 

ListenAndServe

 

http - The Go Programming Language

Package http

이 함수를 통해 프로세스가 잠기게 되면 이 함수 아래의 있는 코드들은 실행되지 못합니다. 만약 error가 발생하거나 키보드 인터룹트 ctrl + c를 누르면 프로세스가 종료됩니다.

 

첫번째 파라미터는 string 타입의 addr이다. 이는 "<ip-address>:<port>" IP 주소와 port를 조합해서 제공하면 된다. 우리는 IP 주소 없이 port 번호만 할당합니다. 이러면 모든 주소로 부터 접근할 수 있습니다. 

 

두번째 파라미터는 Handler 인터페이스의 변수이다. Handler는 http 요청을 받는다. 

type Handler interface{
	ServeHTTP(ResponseWriter, *Request)
}

 

우리는 직접 ServeHTTP를 직접 구현함으로써 ListenAndServe에 파라미터로 제공해줄 수 있다. 

 

Handler 인터페이스의 ServeHTTP 메소드

 

들어오는 http 요청은 handler argument의 메소드 ServeHTTP의 시발점이다. ServeHTTP 메소드는 요청 데이터를 받아 응답을 해주는 것이 주요 역할입니다. 

 

ServeHTTP(res http.ResponseWriter, req *http.Request)

res argument는 ResponseWriter 인터페이스이다. 

type ResponseWriter interface{
	Header() Header
    Write([]byte)(int, error)
    WriteHeader(statusCode int)
}

Write 메소드는 HTTP 응답으로 데이터를 쓴다. 또한 다른 메소드를 사용하여 status Code와 response headers를 넣을 수 있다.

 

req argument는 client에 의해 만들어진 HTTP 요청에 의한 정보가 포함되어 있습니다. Request는 구조체이며 포인터입니다. 

 

Writing a "Hello World" server

이제 Hello World라는 텍스트를 반환하는 간단한 Http 서버를 만들어 보겠습니다. 

 

우선 Handler 를 만들어보겠습니다. 

type HttpHandler struct{}

// HttpHandler의 method를 구현한다.
func (h HttpHandler) ServeHTTP(res http.ResponseWriter, req *http.Request){
	data := []byte("Hello World!")
    res.Write(data) // Write로 data내용을 응답해준다.
 }

 

우리의 Handler는 만들어 졌고 이제 http.ListenAndServe method를 만들어 보겠습니다. 

func main(){
	handler := HttpHandler{}
    http.ListenAndServe(":3000", handler)
}

 

우리는 HttpHandler 객체에 아무런 변수를 안만든체 만들었습니다. 

우리는 ListenAndServe 함수에 handler를 arguments로 넘겨주었습니다.

 

아래 명령어를 사용하여 실행

go run 파일 이름.go

만약 다른 url 로 접근을 해도 동일한 결과를 볼 수 있습니다.

 

localhost:9000/blah

어떤 url 조합을 사용해도 동일한 결과를 볼 수 있습니다. 이것은 handler의 메소드 ServerHTTP 때문에 모든 요청에 응답합니다. 

 

Write([]byte) (int ,error)

write는 입력된 byte의 수와 write 함수 사용을 실패하면 에러를 반환한다. 

 

또한 Writer intefrace는 또한 Write method를 정의한다. 그러므로 http.ResponseWriter 인터페이스 객체 res는 Writer 처럼 다룰 수 있다. 즉 다형성을 이용할 수 있다.

그러므로 io의 WriteString, fmt의 Fprintf, Fprint등을 사용하여 응답할 수 있습니다.

 

io 패키지안에 제공하는 WriteString메소드는 Writer 타입의 객체에 String을 쓸 수 있다.

 

func WriteString(w io.Writer, s string) (n int, err error)

또한 fmt 패키지의 Fprint와 Fprintf를 사용하여 Writer object를 쓸 수 있다.

 

func Fprint(w io.Writer, a ...interface{}) (n int, err error)

 

이전의 코드를 바꿔보자

func (h HttpHandler) ServeHTTP(res http.ResponseWriter, req *http.Request) {
    io.WriteString(res, "Hello")
    fmt.Fprint(res, " World! ")
    res.Write([]byte("❤️"))
}

다음 글에서는 직접 라우팅을 적어주어 url을 구분하여 응답하는 코드를 작성해보겠습니다.