Go ์ธ์ด๋ ์๋์ ์์ ์ฑ, ๊ทธ๋ฆฌ๊ณ ๋จ์ผ ๋ฐ์ด๋๋ฆฌ ๋ฐฐํฌ์ ๊ฐํธํจ ๋๋ถ์
์ต๊ทผ ๋ฐฑ์๋, ๋ง์ดํฌ๋ก์๋น์ค, DevOps ๋๊ตฌ ๊ฐ๋ฐ์ ๋งค์ฐ ์์ฃผ ์ฌ์ฉ๋๊ณ ์์ต๋๋ค.
์ด๋ฒ ๊ธ์์๋ Go๋ก ๊ฐ๋จํ JSON ๊ธฐ๋ฐ REST API ์๋ฒ๋ฅผ ์ง์ ๋ง๋ค์ด๋ณด๋ฉฐ,
Go์ HTTP ์ฒ๋ฆฌ ๊ตฌ์กฐ์ JSON ์ง๋ ฌํ/์ญ์ง๋ ฌํ(Serialization/Deserialization)๋ฅผ ์ดํดํด๋ด
๋๋ค.
๐งฐ 1. ํ๋ก์ ํธ ์ด๊ธฐ ์ค์
๋จผ์ Go ํ๋ก์ ํธ๋ฅผ ์ด๊ธฐํํฉ๋๋ค.
mkdir go-rest-api
cd go-rest-api
go mod init example.com/go-rest-api
go.mod ํ์ผ์ด ์์ฑ๋ฉ๋๋ค.
Go์ ์์กด์ฑ ๊ด๋ฆฌ ์์คํ
(go mod)์ Node์ package.json๊ณผ ๋น์ทํ ์ญํ ์ ํฉ๋๋ค.
โ๏ธ 2. ๋ฉ์ธ ์๋ฒ ํ์ผ ์์ฑ
main.go ํ์ผ์ ์์ฑํ๊ณ , ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ HTTP ์๋ฒ๋ฅผ ๊ตฌ์ฑํฉ๋๋ค.
package main
import (
"encoding/json"
"log"
"net/http"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
var users = []User{
{ID: 1, Name: "Heejune", Email: "hee@example.com"},
{ID: 2, Name: "Jihyun", Email: "jihyun@example.com"},
}
func main() {
http.HandleFunc("/users", getUsersHandler)
log.Println("โ
Server started on port 8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
func getUsersHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(users)
}
๐งฉ ์ฝ๋ ์ค๋ช
http.HandleFunc: ์์ฒญ ๊ฒฝ๋ก(/users)์ ํธ๋ค๋ฌ๋ฅผ ๋งคํjson.NewEncoder(w).Encode(users): ๊ตฌ์กฐ์ฒด ๋ฐฐ์ด์ JSON์ผ๋ก ๋ณํํด ์๋ตListenAndServe(":8080", nil): 8080 ํฌํธ๋ก HTTP ์๋ฒ ์คํ
์ด์ ์คํํด ๋ด ์๋ค.
go run main.go
๋ธ๋ผ์ฐ์ ๋ Postman์์ http://localhost:8080/users ๋ก ์ ์ํ๋ฉด ๐
[
{ "id": 1, "name": "Heejune", "email": "hee@example.com" },
{ "id": 2, "name": "Jihyun", "email": "jihyun@example.com" }
]
๐งพ 3. POST ์์ฒญ์ผ๋ก JSON ๋ฐ๊ธฐ
์ด๋ฒ์ ์๋ก์ด ์ ์ ๋ฅผ ์ถ๊ฐํ๋ POST /users API๋ฅผ ์ถ๊ฐํด๋ด ์๋ค.
func createUserHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
return
}
var newUser User
if err := json.NewDecoder(r.Body).Decode(&newUser); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
newUser.ID = len(users) + 1
users = append(users, newUser)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(newUser)
}
๊ทธ๋ฆฌ๊ณ ๋ผ์ฐํฐ์ ์ถ๊ฐํฉ๋๋ค.
func main() {
http.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
getUsersHandler(w, r)
case http.MethodPost:
createUserHandler(w, r)
default:
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}
})
log.Println("โ
Server started on port 8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
์ด์ POST /users ๋ก ์๋ JSON์ ์ ์กํ๋ฉด ์๋ก์ด ์ ์ ๊ฐ ์ถ๊ฐ๋ฉ๋๋ค.
{
"name": "Siyu",
"email": "siyu@example.com"
}
๐งฑ 4. Clean Architecture ๊ตฌ์กฐ๋ก ๊ฐ์ ํ๊ธฐ
์ค๋ฌด์์๋ ์ฝ๋๊ฐ ์ ์ ์ปค์ง๊ธฐ ๋๋ฌธ์ ํธ๋ค๋ฌ, ์๋น์ค, ๋ชจ๋ธ, ๋ผ์ฐํฐ๋ฅผ ๋ถ๋ฆฌํฉ๋๋ค.
ํด๋ ๊ตฌ์กฐ๋ฅผ ์๋์ฒ๋ผ ๋ณ๊ฒฝํด๋ณด์ธ์ ๐
go-rest-api/
โโโ main.go
โโโ handler/
โ โโโ user_handler.go
โโโ model/
โ โโโ user.go
โโโ service/
โ โโโ user_service.go
model/user.go
package model
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
service/user_service.go
package service
import "example.com/go-rest-api/model"
var users = []model.User{
{ID: 1, Name: "Heejune", Email: "hee@example.com"},
{ID: 2, Name: "Jihyun", Email: "jihyun@example.com"},
}
func GetAllUsers() []model.User {
return users
}
func AddUser(u model.User) model.User {
u.ID = len(users) + 1
users = append(users, u)
return u
}
handler/user_handler.go
package handler
import (
"encoding/json"
"net/http"
"example.com/go-rest-api/model"
"example.com/go-rest-api/service"
)
func GetUsersHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(service.GetAllUsers())
}
func CreateUserHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
return
}
var user model.User
if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
created := service.AddUser(user)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(created)
}
main.go
package main
import (
"log"
"net/http"
"example.com/go-rest-api/handler"
)
func main() {
http.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
handler.GetUsersHandler(w, r)
case http.MethodPost:
handler.CreateUserHandler(w, r)
default:
http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
}
})
log.Println("๐ Go REST API Server started on port 8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
์ด์ ๊ตฌ์กฐ๊ฐ ๊น๋ํด์ก์ต๋๋ค!
ํธ๋ค๋ฌ โ ์๋น์ค โ ๋ชจ๋ธ ์์ผ๋ก ์ญํ ์ด ๋ถ๋ฆฌ๋์ด ์ ์ง๋ณด์๊ฐ ํจ์ฌ ์ฌ์์ง๋๋ค.
๐ฅ 5. ์คํ ๋ฐ ํ ์คํธ
go run main.go
GET ์์ฒญ
curl http://localhost:8080/users
POST ์์ฒญ
curl -X POST -H "Content-Type: application/json" \
-d '{"name":"Chihyun","email":"chi@example.com"}' \
http://localhost:8080/users
๐งฉ 6. Go์ JSON ์ฒ๋ฆฌ ํน์ง ์์ฝ
| ํญ๋ชฉ | ์ค๋ช |
|---|---|
| ์ง๋ ฌํ | json.Marshal() ์ฌ์ฉ |
| ์ญ์ง๋ ฌํ | json.Unmarshal() ์ฌ์ฉ |
| ๊ตฌ์กฐ์ฒด ํ๊ทธ | json:"name" ์ผ๋ก ํค ๋งคํ |
| ์๋ ๋ณํ | JSON์ ์ซ์๋ float64๋ก ์ธ์ |
| ์ค๋ฅ ์ฒ๋ฆฌ | ๋ช
์์ if err != nil ๋ก ์์ธ ๊ด๋ฆฌ |
Go๋ Python๋ณด๋ค ๋ค์ ๋ณต์กํ์ง๋ง,
๊ทธ๋งํผ ํ์
์์ ์ฑ์ด ๊ฐ๋ ฅํ๊ณ ์ฑ๋ฅ์ด ๋น ๋ฅด๋ฉฐ,
๋๊ท๋ชจ ์๋น์ค์์๋ ์์ธก ๊ฐ๋ฅํ ๋์์ ๋ณด์ฅํฉ๋๋ค.
โ 7. ๋ง๋ฌด๋ฆฌ
์ด๋ฒ ํํ ๋ฆฌ์ผ์์๋
- Go์ ๊ธฐ๋ณธ HTTP ์๋ฒ ๊ตฌ์ถ
- JSON ์์ฒญ/์๋ต ์ฒ๋ฆฌ
- Clean Architecture ๊ตฌ์กฐํ
๋ฅผ ๋ชจ๋ ๋ค๋ค๋ดค์ต๋๋ค.
์ด์ ์ฌ๊ธฐ์ ํ์ฅํด๋ณด์ธ์ ๐
/users/{id}โ ๊ฐ๋ณ ์กฐํ APIPUT/DELETEโ ์์ ๋ฐ ์ญ์ ๊ธฐ๋ฅgorilla/mux๊ฐ์ ๋ผ์ฐํฐ ํ๋ ์์ํฌ ๋์- PostgreSQL, MySQL ์ฐ๋์ผ๋ก ์ค์๋น์ค ์์ค ๊ฐํ
๋๊ธ ๋จ๊ธฐ๊ธฐ