# docker run --name wiki -e MYSQL_ROOT_PASSWORD=1234 -d mysql
wiki 데이터베이스를 만들었다.
# mysql -u root -p -h 172.17.0.2
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.17 MySQL Community Server - GPL
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> CREATEDATABASE wiki;
GORM을 이용한 데이터베이스 연결
현재 애플리케이션 구조는 아래와 같다.
.
├── db
├── main.go
├── go.mod
├── go.sum
├── handler
│ └── handler.go
├── model
│ └── wiki.go
├── router
│ └── router.go
├── store
│ └── wiki.go
└── wiki
└── wiki.go
gorm 패키지를 import 한다. gorm패키지는 golang 생태계에서는 가장 많이 사용하는 ORM이다.
mysql driver를 임포트 했다.
New()메서드는 데이터베이스에 연결하고 gorm.DB 객체를 리턴한다.
AutoMigration()메서드는 데이터베이스를 마이그레이션 하기 위해서 사용한다.
가장 중요한 wiki model 스트럭처는(model/wiki.go) 아래와 같다.
package model
import (
"github.com/jinzhu/gorm"
)
// Wiki ...
type Wiki struct {
gorm.Model
Name string `gorm:"column:name;size:160"`
Title string `gorm:"column:title;size:160"`
Author string `gorom:"size:80"`
Contents string `gorm:"column:contents"`
}
gorm.DB 객체는 main 함수에서 생성해서, 앞서 만들어 놓은 Store로 넘긴다. 아래는 완전한 main.go의 코드다.
package main
import (
"fmt"
"os"
"joinc.co.kr/jwiki/db"
"joinc.co.kr/jwiki/handler"
"joinc.co.kr/jwiki/router"
"joinc.co.kr/jwiki/store"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
func main() {
r := router.New()
d, err := db.New()
if err != nil {
fmt.Println("DB Error", err.Error())
os.Exit(1)
}
db.AutoMigration(d)
api := r.Group("/api")
ws := store.NewWikiStore(d)
h := handler.NewHandler(ws)
h.Register(api)
fmt.Println(api)
r.Logger.Fatal(r.Start(":8888"))
}
db.New() 메서드를 호출 데이터베이스에 연결한다.
db.AutoMigraion() 메서드를 실행해서, wiki.model에 따라서 데이터베이스를 마이그레이션 한다. 뭔가 대단한건 아니다. 테이블이 없으면 자동으로 만들어주고, (모델이 변경되면) 테이블 스키마를 업데이트 해주겠다는 얘기다. 이렇게 해서 소프트웨어 객체와 데이터를 통합할 수 있다.
wiki model을 위한 bind 스트럭처 개발
HTTP Handler가 유저의 요청(Request)를 받아서 처리한다. 요청 데이터의 컨텐츠 타입(Contents-Type)은 application/json일 테고, wiki.model 스트럭처로 bind 하면 된다. wiki model 스트럭처는 아래와 같다. model/wiki.go 다.
package model
import (
"github.com/jinzhu/gorm"
)
// Wiki ...
type Wiki struct {
gorm.Model
Name string `gorm:"column:name;size:160"`
Title string `gorm:"column:title;size:160"`
Author string `gorom:"size:80"`
Contents string `gorm:"column:contents"`
}
model 스트럭처를 핸들러에서 직접 바인드하는 방법도 있지만, model 과 비지니스로직은 분리하는게 좋을 것 같아서 bind 스트럭처를 따로 만들었다. handler/request.go 파일이다.
package handler
import (
"fmt"
"github.com/labstack/echo/v4"
"joinc.co.kr/jwiki/model"
)
type wikiCreateRequest struct {
Wiki struct {
Name string `json:"name" validate: "required"`
Title string `json:"title" validate: "required"`
Author string `json:"author" validate: "required"`
Contents string `json:"contents" validate: "required"`
} `json:"wiki"`
}
// Data ...
type Data struct {
Name string `json:"name"`
Title string `json:"title`
Author string `json:"author"`
Contents string `json:"contents"`
}
func (w *wikiCreateRequest) bind(c echo.Context, a *model.Wiki) error {
if err := c.Bind(&w.Wiki); err != nil {
fmt.Println("Bind", w)
return err
}
a.Name = w.Wiki.Name
a.Title = w.Wiki.Title
a.Author = w.Wiki.Author
a.Contents = w.Wiki.Contents
return nil
}
비즈니스 로직의 구현을 위해서 유저의 요청을 wiki 모델에 바인딩 하기 위한 스트럭처와 bind 메서드를 만들었다. 이제 개발자는 모델의 수정 없이, 유저 요청을 처리할 수 있게 된다.
CreateWiki 핸들러는 아래와 같이 유저 요청을 바인딩 한다.
mysql> SELECT * FROM wikis\G
*************************** 1. row ***************************
id: 3
created_at: 2020-09-20 07:41:36
updated_at: 2020-09-20 07:41:36
deleted_at: NULL
name: my page
title: Hello World
author: yundream
contents: What's your name
1 row in set (0.00 sec)
미들웨어 만들기
이렇게 해서 유저 요청을 데이터베이스에 저장하는 기본적인 웹 애플리케이션 서버를 만들었다. 그러나 유저의 요청의 종류에 상관없이 모든 요청의 전후에 일부코드의 실행이 필요 할 수도 있다. 예를 들어 서버에 대한 모든 요청에 대한 로깅, 보안 검증 코드를 호출, 사용자가 인증이 되어었는지를 확인을 해야 할 수 있다. 이런 코드들을 각 핸들러에 두는 것은 비효율적이다. 미들웨어를 사용하면 이러한 공통작업을 효율적으로 수행 할 수 있다.
echo 프레임워크는 그룹(group)별로 미들웨어를 설치 할 수 있다. 예를 들어 admin과 관련된 페이지는 아래와 같이 인증모듈이 실행되도록 할 수 있다.
e := echo.New()
admin := e.Group("/admin". middleware.BasicAuth())
middleware 패키지를 만들기로 했다. 패키지의 위치는 meddleware/meddleware.go 다.
Contents
소개
MySQL 데이터베이스 실행 과 준비
GORM을 이용한 데이터베이스 연결
wiki model을 위한 bind 스트럭처 개발
테스트
미들웨어 만들기
Logging 미들웨어
정리
Recent Posts
Archive Posts
Tags