Skip to content

Commit

Permalink
[1119] section75
Browse files Browse the repository at this point in the history
  • Loading branch information
myeunee committed Nov 19, 2024
1 parent 5aa034e commit fa4f211
Show file tree
Hide file tree
Showing 35 changed files with 1,080 additions and 0 deletions.
33 changes: 33 additions & 0 deletions chapter19/section75/.air.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
root = "."
tmp_dir = "tmp"

[build]
cmd = "go build -o ./tmp/main ."
# 'cmd'에서 바이너리 파일 지정
bin = "tmp/main"

# 80번 포트를 사용하도록 실행 시 인수를 지정
full_bin = "APP_ENV=dev APP_USER=air ./tmp/main 80"

include_ext = ["go", "tpl", "tmpl", "html"]
exclude_dir = ["assets", "tmp", "vendor", "frontend/node_modules", "_tools", "cert", "testutil"]
exclude_regex = ["_test.go"]
exclude_unchanged = true
follow_symlink = true
log = "air.log"
delay = 1000
stop_on_error = true
send_interrupt = false
kill_delay = 500

[log]
time = false

[color]
main = "magenta"
watcher = "cyan"
build = "yellow"
runner = "green"

[misc]
clean_on_exit = true
2 changes: 2 additions & 0 deletions chapter19/section75/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.git
.DS_Store
36 changes: 36 additions & 0 deletions chapter19/section75/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Build stage
# 최신 버전으로 수정 ******
FROM golang:1.23.1 AS deploy-builder

WORKDIR /app

# go.mod, go.sum 파일 복사 및 의존성 다운로드
COPY go.mod go.sum ./
RUN go mod download

COPY . .
# 바이너리 빌드
RUN go build -trimpath -ldflags "-w -s" -o app

#--------------------------------
# Deployment stage
# 최신 GLIBC 버전을 사용하기 위해 우분투로 교체

FROM ubuntu:latest as deploy

RUN apt-get update && apt-get install -y libgcc-s1

# 빌드된 바이너리를 복사
COPY --from=deploy-builder /app/app .

# 실행 명령
CMD ["./app"]

#--------------------------------
# Development stage with Air for live reloading

# ******** 최신 버전으로 수정 ***********
FROM golang:1.23.1 as dev
WORKDIR /app
RUN go install github.com/air-verse/air@latest
CMD ["air"]
34 changes: 34 additions & 0 deletions chapter19/section75/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
.PHONY: help build build-local up down logs ps test
.DEFAULT_GOAL := help

DOCKER_TAG := latest
build: ## 배포용 도커 이미지 빌드 + 내 모듈 이름에 맞게 수정 **********
docker build -t myeunee/golangstudy-chapter19-section75:${DOCKER_TAG} --target deploy ./

build-local: ## 로컬 환경용 도커 이미지 빌드
docker compose build --no-cache

up: ## 자동 새로고침을 사용한 도커 컴포즈 실행
docker compose up -d

down: ## 도커 컴포즈 종료
docker compose down

logs: ## 도커 컴포즈 로그 출력
docker compose logs -f

ps: ## 컨테이너 상태 확인
docker compose ps

test: ## 테스트 실행
go test -race -shuffle=on ./...

help: ## 옵션 보기
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'

dry-migrate: ## Try migration
mysqldef -u todo -p todo -h 127.0.0.1 -P 33306 todo --dry-run < ./_tools/mysql/schema.sql

migrate: ## Execute migration
mysqldef -u todo -p todo -h 127.0.0.1 -P 33306 todo < ./_tools/mysql/schema.sql
2 changes: 2 additions & 0 deletions chapter19/section75/_tools/mysql/conf.d/mysql.cnf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[mysql]
default_character_set=utf8mb4
4 changes: 4 additions & 0 deletions chapter19/section75/_tools/mysql/conf.d/mysqld.cnf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[mysqld]
default-authentication-plugin=mysql_native_password
character_set_server=utf8mb4
sql_mode=TRADITIONAL,NO_AUTO_VALUE_ON_ZERO,ONLY_FULL_GROUP_BY
21 changes: 21 additions & 0 deletions chapter19/section75/_tools/mysql/schema.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
CREATE TABLE `user`
(
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '사용자 식별자',
`name` varchar(20) NOT NULL COMMENT '사용자명',
`password` VARCHAR(80) NOT NULL COMMENT '패스워드 해시',
`role` VARCHAR(80) NOT NULL COMMENT '역할',
`created` DATETIME(6) NOT NULL COMMENT '레코드 작성 시간',
`modified` DATETIME(6) NOT NULL COMMENT '레코드 수정 시간',
PRIMARY KEY (`id`),
UNIQUE KEY `uix_name` (`name`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='사용자';

CREATE TABLE `task`
(
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '태스크 식별자',
`title` VARCHAR(128) NOT NULL COMMENT '태스크 타이틀',
`status` VARCHAR(20) NOT NULL COMMENT '태스크 상태',
`created` DATETIME(6) NOT NULL COMMENT '태스크 작성 시간',
`modified` DATETIME(6) NOT NULL COMMENT '태스크 수정 시간',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='태스크';
21 changes: 21 additions & 0 deletions chapter19/section75/clock/clock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package clock

import (
"time"
)

type Clocker interface {
Now() time.Time
}

type RealClocker struct{}

func (r RealClocker) Now() time.Time {
return time.Now()
}

type FixedClocker struct{}

func (fc FixedClocker) Now() time.Time {
return time.Date(2022, 5, 10, 12, 34, 56, 0, time.UTC)
}
23 changes: 23 additions & 0 deletions chapter19/section75/config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package config

import (
"github.com/caarlos0/env/v6"
)

type Config struct {
Env string `env:"TODO_ENV" envDefault:"dev"`
Port int `env:"PORT" envDefault:"80"`
DBHost string `env:"TODO_DB_HOST" envDefault:"127.0.0.1"`
DBPort int `env:"TODO_DB_PORT" envDefault:"33306"`
DBUser string `env:"TODO_DB_USER" envDefault:"todo"`
DBPassword string `env:"TODO_DB_PASSWORD" envDefault:"todo"`
DBName string `env:"TODO_DB_NAME" envDefault:"todo"`
}

func New() (*Config, error) {
cfg := &Config{}
if err := env.Parse(cfg); err != nil {
return nil, err
}
return cfg, nil
}
23 changes: 23 additions & 0 deletions chapter19/section75/config/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package config

import (
"fmt"
"testing"
)

func TestNew(t *testing.T) {
wantPort := 3333
t.Setenv("PORT", fmt.Sprint(wantPort))

got, err := New()
if err != nil {
t.Fatalf("cannot create config: %v", err)
}
if got.Port != wantPort {
t.Errorf("want %d, but %d", wantPort, got.Port)
}
wantEnv := "dev"
if got.Env != wantEnv {
t.Errorf("want %s, but %s", wantEnv, got.Env)
}
}
35 changes: 35 additions & 0 deletions chapter19/section75/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
version: "3.9"
services:
app:
image: gotodo
build:
args:
- target=dev
environment:
TODO_ENV: dev
PORT: 8080
TODO_DB_HOST: todo-db
TODO_DB_PORT: 3306
TODO_DB_USER: todo
TODO_DB_PASSWORD: todo
TODO_DB_NAME: todo
volumes:
- .:/app
ports:
- "18000:8080"
todo-db:
image: mysql:8.0.29
platform: linux/amd64
container_name: todo-db
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
MYSQL_USER: todo
MYSQL_PASSWORD: todo
MYSQL_DATABASE: todo
volumes:
- todo-db-data:/var/lib/mysql
- $PWD/_tools/mysql/conf.d:/etc/mysql/conf.d:cached
ports:
- "33306:3306"
volumes:
todo-db-data:
22 changes: 22 additions & 0 deletions chapter19/section75/entity/task.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package entity

import "time"

type TaskID int64
type TaskStatus string

const (
TaskStatusTodo TaskStatus = "todo"
TaskStatusDoing TaskStatus = "doing"
TaskStatusDone TaskStatus = "done"
)

type Task struct {
ID TaskID `json:"id"`
Title string `json:"title"`
Status TaskStatus `json:"status" `
Created time.Time `json:"created"`
Modified time.Time `json:"modified" db:"modified"`
}

type Tasks []*Task
30 changes: 30 additions & 0 deletions chapter19/section75/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module github.com/myeunee/GolangStudy/chapter19/section75

go 1.23.1

require (
github.com/caarlos0/env/v6 v6.10.1
github.com/go-chi/chi/v5 v5.1.0
github.com/go-playground/validator/v10 v10.22.1
github.com/google/go-cmp v0.6.0
golang.org/x/sync v0.8.0
)

require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/stretchr/testify v1.9.0 // indirect
)

require (
github.com/DATA-DOG/go-sqlmock v1.5.2
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-sql-driver/mysql v1.8.1
github.com/jmoiron/sqlx v1.4.0
github.com/leodido/go-urn v1.4.0 // indirect
golang.org/x/crypto v0.19.0 // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/sys v0.23.0 // indirect
golang.org/x/text v0.14.0 // indirect
)
49 changes: 49 additions & 0 deletions chapter19/section75/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
github.com/caarlos0/env/v6 v6.10.1 h1:t1mPSxNpei6M5yAeu1qtRdPAK29Nbcf/n3G7x+b3/II=
github.com/caarlos0/env/v6 v6.10.1/go.mod h1:hvp/ryKXKipEkcuYjs9mI4bBCg+UI0Yhgm5Zu0ddvwc=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA=
github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Loading

0 comments on commit fa4f211

Please sign in to comment.