GoLand
세팅mkdir bin
mkdir pkg
mkdir src
위의 세 폴더 중 소스코드를 보관할 곳은 src
입니다.
src
안에는 소스를 작성할 main.go
파일을 생성해주세요.
package main // package가 main으로 되어 있지 않다면 실행할 수가 없습니다.
func main() {
}
go module
등록cd src
go mod init noah.io/ark/rest
src
폴더로 들어가 go module
을 등록합니다.
root
├── bin
├── pkg
├── src
└── main.go
└── go.mod
CR(UD) api
생성REST API
의 CRUD
중 create
와 read
의 작업만 하는 REST API
를 만들어보겠습니다.
routing
해보기package main
import "net/http"
func main() {
http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
writer.Write([]byte("hello"))
})
http.ListenAndServe(":8000", nil)
}
위의 코드는 go
서버를 localhost:8000
에 띄울 수 있게 해줍니다.
http.ListenAndServe(":8000", nil)
의 nil
이란 값이 없음을 뜻합니다.
ListenAndServe
의 두 번째 인수에는 실행할 핸들러를 적는데 값이 nil
이기 때문에 맨 마지막에 정의된 핸들러가 실행되게 됩니다.
포스트맨에서 테스트를 하면 hello
가 잘 출력되는 것을 확인할 수 있습니다.
Create, Read api
생성package main
import (
"encoding/json"
"net/http"
)
// 사용자의 이메일을 키로 정보를 저장하는 맵입니다.
var users = map[string]*User{}
// User 구조체
// 각각 nickname과 email의 타입이 문자열(string)입니다.
type User struct {
Nickname string `json:"nickname"`
Email string `json:"email"`
}
func main() {
http.HandleFunc("/users", func(writer http.ResponseWriter, request *http.Request) {
switch request.Method {
case http.MethodGet: // 조회
json.NewEncoder(writer).Encode(users) // 인코딩
case http.MethodPost: // 등록
var user User
json.NewDecoder(request.Body).Decode(&user) // 디코딩
users[user.Email] = &user
json.NewEncoder(writer).Encode(user) // 인코딩
}
})
http.ListenAndServe(":8080", nil)
}
위의 코드는 localhost:8000/users
의 서버에 들어온 request.Method
가 get
인지 post
인지를 판단하여 유저의 정보를 조회하거나 등록할 수 있는 REST API
입니다.
만약 request.Method
가 http.MethodGet
이라면 users
의 정보를 json
형태로 변환하여 출력해줄 것입니다.
만약 request.Method
가 http.MethodPost
라면 json
형식으로 들어온 request
를 디코딩하여 user
에 정보를 저장할 수 있도록 한 다음,
사용자의 email
을 키로 사용하여 user
의 정보를 저장한 뒤 다시 json
형태로 정보를 인코딩하여 출력해줍니다.
포스트맨으로 실행하면 이렇게 값이 잘 나오는 것을 볼 수 있습니다.
middleware
로 header
에 content-type
을 추가하기그런데 포스트맨의 response
가 뭔가 이상합니다.
json
형태이나 text
로 출력이 되고 있습니다.
이는 header
에 있는 content-type
에 application/json
을 등록해주지 않았기 때문입니다.
따라서 기본값인 text
로 출력되는 것입니다.
이번에는 미들웨어를 활용하여 response
의 header
의 content-type
을 json
형식으로 추가해보겠습니다.
package main
import (
"encoding/json"
"net/http"
)
var users = map[string]*User{}
type User struct {
Nickname string `json:"nickname"`
Email string `json:"email"`
}
// 4. 요청이 들어온 Response Header에 ContentType을 추가하고 전달받은 HandleFunc타입의 함수에 ResponseWriter와 Request를 넘겨줍니다.
// next는 미들웨어의 변수입니다.
func jsonContentTypeMiddleware(next http.Handler) http.Handler {
// 들어오는 요청의 Response Header에 Content-type을 json으로 설정해준다.
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
writer.Header().Add("Content-Type", "application/json")
// 전달받은 http.Handler 호출
next.ServeHTTP(writer, request)
})
}
func main() {
// 1. 새로운 mux를 만듭니다.
// mux는 요청 경로와 핸들러를 매핑하는 역할을 합니다.
mux := http.NewServeMux()
// 2. 기존에 만들어놓은 HandleFunc를 HandlerFunc로 변경 ("/users" 삭제)
// 원하는 경로를 함수와 연결시킬 수 있습니다.
userHandler := http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
switch request.Method {
case http.MethodGet: // 조회
json.NewEncoder(writer).Encode(users)
case http.MethodPost: // 삽입
var user User
json.NewDecoder(request.Body).Decode(&user) // 디코딩
users[user.Email] = &user
json.NewEncoder(writer).Encode(user)
}
})
// 3. 만들어놓은 미들웨어에 파라미터로 넘깁니다. ("/users"는 이 때 사용)
mux.Handle("/users", jsonContentTypeMiddleware(userHandler))
http.ListenAndServe(":8000", mux)
}
이렇게 jsonContentTypeMiddleware()
미들웨어로 요청이 들어온 response
의 header
에 content-type
을 application/json
으로 줌으로써 응답을 json
형태로 볼 수 있게 됩니다.
아래는 포스트맨에서 확인한 응답 결과입니다.
이렇게 간단한 REST API
를 만들어보았는데
아무런 db
를 연결하지 않아 map
을 사용하였지만 다음에는 mongodb
를 활용하여 값을 db
에 저장해보겠습니다.