본 게시글은 Go lang 의 공식 튜토리얼에서 소개되는 RESTful API 개발 가이드를 실습하며 재정리한 글이다.
원문은 아래 링크에서 확인 가능하다.
https://go.dev/doc/tutorial/web-service-gin
Tutorial: Developing a RESTful API with Go and Gin - The Go Programming Language
Tutorial: Developing a RESTful API with Go and Gin This tutorial introduces the basics of writing a RESTful web service API with Go and the Gin Web Framework (Gin). You’ll get the most out of this tutorial if you have a basic familiarity with Go and its
go.dev
----------시작----------
Design API endpoints
/albums
- get : 앨범 리스트를 가져온다. 리턴 타입은 json
- post : 새로운 앨범 정보를 생성한다. 데이터 포맷은 json
/albums/:id
- get : 입력한 id 에 해당하는 앨범 정보를 가져온다. 리턴 타입은 json.
Create a folder for your code
$ mkdir web-service-gin
$ cd web-service-gin
$ go mod init example/web-service-gin
=> 이 명령어는 모듈 생성을 위한 과정으로, go.mod 파일을 생성한다. 추후 계속 추적할 디펜던시를 관리하는 목록이 적힌 파일이다.
'example/web-service-gin' 의 위치에 해당하는 텍스트는 모듈의 path로 모듈의 이름을 의미한다. 추후 이 모듈 아래 있는 모듈 경로의 접두사(?prefix) 에 위치하는 이름이다.
Create the data
1. main.go 파일을 만든다.
2. main.go 파일 아래에 패키지를 선언해준다.
package main
3. 'album' 이라는 이름의 구조체를 선언해준다.
type album struct {
ID string `json:"id"`
Title string `json:"title"`
Artist string `json:"artist"`
Price float64 `json:"price"`
}
4. album 구조체의 메모리 저장용 데이터를 생성한다.
var albums = []album{
{ID: "1", Title: "Blue Train", Artist: "John Coltrane", Price: 56.99},
{ID: "2", Title: "Jeru", Artist: "Gerry Mulligan", Price: 17.99},
{ID: "3", Title: "Sarah Vaughan and Clifford Brown", Artist: "Sarah Vaughan", Price: 39.99},
}
Write a handler to return all items
코드를 써보자
1. get /albums 를 위한 펑션을 작성한다.
// getAlbums responds with the list of all albums as JSON.
func getAlbums(c *gin.Context) {
c.IndentedJSON(http.StatusOK, albums)
}
- gin.Context 타입의 인자를 받고 있다. 이 녀석은.. 중요하다.
"... It carries request details, validates and serializes JSON, and more. ..."
- Context.IntendedJson 를 호출했다. 구조체를 json 으로 serialize 하고 이것을 response 에 담기 위해.
2. 핸들러 function 을 endpoint path 에 연결하기 위해 main 펑션을 작성한다.
func main() {
router := gin.Default()
router.GET("/albums", getAlbums)
router.Run("localhost:8080")
}
- gin router 를 디폴트 옵션으로 초기화 하였다.
- get 메소드의 /albums 경로에 연결할 function 의 이름을 적어주었다. (여기서, getAlbums라는 이름만 써준다.)
- Run 명령으로 라우터를 http.Server 에 attach 하고 서버를 시작시킨다.
3. main.go 파일의 상단에 import 구문과 사용된 패키지들이 작성되었을 것이다.
4. 파일 저장하고 이제 실행해보자.
코드를 실행시켜보자
1. Gin 모듈을 받았으니 디펜던시에 추가해보자
go get .
2. 모듈 실행 (main.go 파일이 있는 위치에서 실행)
go run .
3. 다른 터미널을 하나 열어서 아래와 같이 실행해보자.
curl http://localhost:8080/albums
실행결과
ㅊㅋㅊㅋ done.
Write a handler to add a new item
새로운 앨범 추가를 위해 POST 방식의 /albums 를 위한 개발을 할 차례이다.
코드를 써보자
1. post /postAlbums 를 위한 펑션을 작성한다.
func postAlbums(c *gin.Context) {
var newAlbum album
// Call BindJSON to bind the received JSON to
// newAlbum.
if err := c.BindJSON(&newAlbum); err != nil {
return
}
// Add the new album to the slice.
albums = append(albums, newAlbum)
c.IndentedJSON(http.StatusCreated, newAlbum)
}
- Context.BindJSON 을 사용하여 새로운 request body 를 newAlbum 에 바인딩 시킨다.
- albums 슬라이스에 newAlbum 을 더해준다.
- 201 status code 와 새로 추가한 newAlbum 데이터를 리턴값으로 넘겨준다.
2. main 펑션에 post /albums 리퀘스트의 라우터를 추가한다.
func main() {
router := gin.Default()
router.GET("/albums", getAlbums)
router.POST("/albums", postAlbums)
router.Run("localhost:8080")
}
코드를 실행시켜보자
1. 혹시 서버가 실행중이면 일단 끈다.
2. 다시 서버를 실행시킨다. (go run .)
3. 다른 터미널에서 아래와 같이 curl 명령을 날려본다 . 그러면 결과가 아래 이어지듯이 나올 것이다. (나와야 정상)
curl http://localhost:8080/albums \
--include \
--header "Content-Type: application/json" \
--request "POST" \
--data '{"id": "4","title": "The Modern Sound of Betty Carter","artist": "Betty Carter","price": 49.99}'
HTTP/1.1 201 Created
Content-Type: application/json; charset=utf-8
Date: Wed, 02 Jun 2021 00:34:12 GMT
Content-Length: 116
{
"id": "4",
"title": "The Modern Sound of Betty Carter",
"artist": "Betty Carter",
"price": 49.99
}
4. 제대로 추가 됐는지 확인 차 모든 앨범의 리스트를 보여주는 get /albums 명령을 날려본다.
curl http://localhost:8080/albums \
--header "Content-Type: application/json" \
--request "GET"
[
{
"id": "1",
"title": "Blue Train",
"artist": "John Coltrane",
"price": 56.99
},
{
"id": "2",
"title": "Jeru",
"artist": "Gerry Mulligan",
"price": 17.99
},
{
"id": "3",
"title": "Sarah Vaughan and Clifford Brown",
"artist": "Sarah Vaughan",
"price": 39.99
},
{
"id": "4",
"title": "The Modern Sound of Betty Carter",
"artist": "Betty Carter",
"price": 49.99
}
]%
됐다.
Write a handler to return a specific item
이제 id 를 입력했을 때 하나씩 조회하는 기능을 개발해보자.
코드를 써보자
1. 앨범 정보를 하나씩 갖고올 getAlbumByID 펑션을 개발한다.
func getAlbumByID(c *gin.Context) {
id := c.Param("id")
// Loop over the list of albums, looking for
// an album whose ID value matches the parameter.
for _, a := range albums {
if a.ID == id {
c.IndentedJSON(http.StatusOK, a)
return
}
}
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "album not found"})
}
2. main 펑션에 get /albums/:id 를 추가한다.
코드를 실행시켜보자
curl http://localhost:8080/albums/2
{
"id": "2",
"title": "Jeru",
"artist": "Gerry Mulligan",
"price": 17.99
}%
잘 나온다.
끝.