Go 언어로 웹 서버를 생성하면 데이터를 저장하여야 하는 경우가 생깁니다. 이러한 경우 DB를 생성하여 데이터를 관리할 수 있습니다. 이번 시간에 Go로 작성된 웹 서버에서 mysql에 CRUD작업을 하는 방법을 기록하겠습니다.
예시 코드는 아래의 github 주소에 올려두었습니다.
https://github.com/rainbow96bear/golang_practice/blob/master/mysql_practice/mysql_practice.go
목차
기본 설정
Create
Read
Update
Delete
기본 설정
Go에서 mysql을 사용하기 위하여 'database/sql', 'github.com/go-sql-driver/mysql' 두 가지 패키지가 필요로 합니다.
'database/sql'은 기본 패키지이지만 'github.com/go-sql-driver/mysql'은 외부 패키지이므로 아래의 명령어를 통하여 받아줍니다.
go get -u github.com/go-sql-driver/mysql
패키지가 받아졌다면 import 해줍니다.
db연결
코드는 사람에 따라 다른 방식으로 작성할 수 있습니다. 저는 공부를 하며 파일 하나에 정리하기 위하여 아래와 같이 작성하였습니다.
var db *sql.DB
func main(){
port := 8080
var err error
db, err = sql.Open("mysql", "root:1q2w3e4r!@tcp(localhost:3333)/Books")
if err != nil {
fmt.Println("DB 열기 실패 :", err)
}
defer db.Close()
router := pat.New()
router.Get("/Books", GetList)
router.Post("/Books", CreateData)
router.Put("/Books", UpdateData)
router.Delete("/Books", DeleteData)
fmt.Println(port, "포트 서버 생성")
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", port), router))
}
mysql과 연결하기 위하여 'sql.Open()'을 사용하였습니다.
매개변수로 'mysql'과 'root:1q2w3e4r!@tcp(localhost:3333)/Books'를 주었습니다.
첫 번째 매개변수는 driver name으로 mysql을 사용한다는 것을 알려줍니다.
두 번째 매개변수는 사용할 계정의 ID, 비밀번호, 통신규약, 주소, 사용할 DataBase이름입니다.
저의 코드는 'root 계정을 사용하고 비밀번호는 1q2w3e4r!이며 tcp를 이용하여 localhost:3333과 통신하고 Books라는 Database를 사용한다'는 의미입니다.
Database와 table
이번 예시에서 사용하는 Database와 table의 구조입니다.
여러 개의 Database 중 저는 Books라는 Database를 사용하겠습니다.
Create
mysql과 연결 설정이 위에서 마무리되었기에 데이터를 저장하는 Create 작업을 작성합니다.
func CreateData(w http.ResponseWriter, r *http.Request){
var bookInfo BookInfo
decoder := json.NewDecoder(r.Body)
if err := decoder.Decode(&bookInfo); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
queryParams := r.URL.Query()
bookInfo.Kind = queryParams.Get("kind")
query := "INSERT INTO books (kind, title, author) VALUES (?, ?, ?)"
_, execErr := db.Exec(query, bookInfo.Kind, bookInfo.Title, bookInfo.Author)
if execErr != nil {
http.Error(w, execErr.Error(), http.StatusInternalServerError)
return
}
res := responseMsg{Status : http.StatusOK, Msg: "저장 완료"}
responseJSON, err := json.Marshal(res)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write(responseJSON)
}
'POST 방식'으로 'JSON'으로 책에 대한 정보를 전달하고 'Query String'으로 책의 종류를 전달하였습니다.
postman을 이용하여 json을 전달하였고 아래와 같은 응답을 받았습니다.
잘 저장된 것이 맞는지 mysql에서 'select * from books'를 사용하여 확인하였고 아래와 같이 저장된 것을 확인할 수 있었습니다.
Read
Create를 하였다면 저장된 정보를 받아올 수 있어야 합니다. 데이터를 불러오는 Read 작업을 작성합니다.
func GetList(w http.ResponseWriter, r *http.Request){
queryParams := r.URL.Query()
kind := queryParams.Get("kind")
query := "SELECT * FROM books WHERE kind = ?"
rows, queryErr := db.Query(query, kind)
if queryErr != nil {
http.Error(w, queryErr.Error(), http.StatusInternalServerError)
return
}
defer rows.Close()
var data []BookInfo
for rows.Next() {
var d BookInfo
if err := rows.Scan(&d.ID, &d.Kind, &d.Title, &d.Author); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
data = append(data, d)
}
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(data); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
Create와는 다르게 'GET 방식'을 사용하였고 'Query String'으로 전달받은 kind 값을 가지는 데이터를 모두 받아옵니다.
postman을 이용하여 요청을 보내었고 아래와 같은 응답을 받았습니다.
Update
저장된 데이터를 수정하여야 하는 경우가 발생할 수 있습니다. 데이터를 수정하는 Update 작업을 작성합니다.
func UpdateData(w http.ResponseWriter, r *http.Request){
var bookInfo BookInfo
decoder := json.NewDecoder(r.Body)
if err := decoder.Decode(&bookInfo); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
queryParams := r.URL.Query()
bookInfo.ID, _ = strconv.Atoi(queryParams.Get("id"))
bookInfo.Kind = queryParams.Get("kind")
query := "UPDATE books SET kind = ?, title = ?, author = ? WHERE id = ?"
_, execErr := db.Exec(query, bookInfo.Kind, bookInfo.Title, bookInfo.Author, bookInfo.ID)
if execErr != nil {
http.Error(w, execErr.Error(), http.StatusInternalServerError)
return
}
res := responseMsg{Status : http.StatusOK, Msg: "수정 완료"}
responseJSON, err := json.Marshal(res)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write(responseJSON)
}
Update의 경우 RESTful 방식인 'PUT 방식'을 사용하였고, 'JSON'을 통하여 수정할 내용을, 'Query String'을 사용하여 책의 종류와 DB에 저장된 정보의 id를 전달하였습니다.
postman을 이용하여 요청을 보내었고 아래와 같은 응답을 받았습니다.
잘 수정된 것이 맞는지 mysql에서 'select * from books'를 용하여 확인하였고 아래와 같이 저장된 것을 확인할 수 있었습니다.
Delete
필요가 없어진 데이터의 경우 삭제할 수 있어야 합니다. 데이터를 삭제하는 Delete 작업을 작성합니다.
func DeleteData(w http.ResponseWriter, r *http.Request){
queryParams := r.URL.Query()
id := queryParams.Get("id")
query := "DELETE FROM books WHERE id = ?"
_, execErr := db.Exec(query, id)
if execErr != nil {
http.Error(w, execErr.Error(), http.StatusInternalServerError)
return
}
res := responseMsg{Status : http.StatusOK, Msg: "삭제 완료"}
responseJSON, err := json.Marshal(res)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write(responseJSON)
}
Delete의 경우 RESTful 방식인 'DELETE 방식'을 사용하였고, 저장된 데이터를 구별할 수 있는 고유 값인 ID를 'Query String'을 통하여 전달하였습니다.
postman을 이용하여 요청을 보내었고 아래와 같은 응답을 받았습니다.
값이 잘 삭제되었는지 mysql에서 'select * from books'를 사용하여 확인하였고, 아래와 같이 삭제된 것을 확인할 수 있었습니다.
'Go language' 카테고리의 다른 글
[Go] GraphQL 사용 및 GraphQL subscription (1) | 2024.12.29 |
---|---|
[Go] cookie와 session 다루기 (0) | 2023.09.14 |
[Go] 웹 서버 테스트하기 (net/http/httptest 패키지) (0) | 2023.09.13 |
[Go] 테스트 코드 작성하기 (테스트, 벤치마크) (0) | 2023.09.13 |
[Go] 데이터 압축하기 (compress/gzip 사용하기) (0) | 2023.09.11 |