khumu-comment๋ MSA๋ก ๊ฐ๋ฐ์ค์ธ khumu์ comment ๊ด๋ จ API๋ฅผ ์ ๊ณตํ๋ ์๋ฒ์ด๋ฉฐ Echo
๋ผ๋ Golang์ ์น ํ๋ ์์ํฌ๋ฅผ ๋ฐํ์ผ๋ก ๊ฐ๋ฐ๋๊ณ ์๋ค. ์ฃผ๋ก ์ฌ์ฉ๋๋ ๊ฐ๋ฐ ๋ฐฉ๋ฒ๋ก ์ TDD์ด๋ฉฐ Clean architecture๋ฅผ ๋ฐํ์ผ๋ก ๊ฐ๋ฐ์ ์งํ ์ค์ด๋ค.
API Documentation: https://documenter.getpostman.com/view/13384984/TVsvfkxs
์ค์ ํ์ผ ์ ์ฉ์ Go์ ์ ๋ช
ํ ์ค์ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ spf13/viper์ ์ฟ ๋ฎค ์๋น์ค์์ ์ข ๋ ํธ๋ฆฌํ๊ฒ ์ฌ์ฉํ๊ธฐ ์ํด ํ ๋ฒ ๋ํํ umi0410/ezconfig๋ฅผ ์ด์ฉํ๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก๋ config/default.yaml
์ ์ด์ฉํ๋ฉฐ ํ์์ ๋ฐ๋ผ KHUMU_
prefix๊ฐ ๋ถ์ ํ๊ฒฝ ๋ณ์๋ฅผ ํตํด overrideํ ์๋ ์๊ณ config/{{KHUMU_ENVIRONMENT}}.yaml
์ ์ค์ ํ์ผ๋ก overrideํ ์ ์๋ค. ์์ธํ ์ฌํญ์ umi0410/ezconfig์์ ํ์ธํด๋ณผ ์ ์๋ค.
KHUMU_CONFIG_PATH
ํ๊ฒฝ๋ณ์๋ฅผ ํตํด config
์ด์ธ์ config file์ด ์์นํ path๋ฅผ ์ค์ ํ ์ ์๋ค. ๋จ์ํ config
๋ผ๋ ์๋ ๊ฒฝ๋ก๋ง์ ์ด์ฉํ๋ฉด ๊ฐํน test code๋ฅผ ์งํํ๋ ๊ณผ์ ์ test code๋ฅผ ์คํํ๋ ์์น์ ๋ฐ๋ผ working directory๊ฐ ๋ฌ๋ผ์ง๋ฉด์ ์ฌ๋ฐ๋ฅด๊ฒ config ํ์ผ๋ค์ ์ฐพ์ง ๋ชปํ๋ ๊ฒฝ์ฐ๊ฐ ์๊ธฐ ๋๋ฌธ์ด๋ค.
(์ค์ ์์: KHUMU_CONFIG_PATH=/home/jinsu/khumu-comments/config
)
KHUMU_SECRET
: ํ๊ฒฝ๋ณ์๋ฅผ ํตํด jwt๋ฅผ verifyํ secret์ ์ค์ ํ๋ค.KHUMU_CONFIG_PATH
: ์๋ ๊ฒฝ๋กconfig
์ด์ธ์ ๊ฒฝ๋ก์์ config file์ ์ฐพ์ ์ ์๋๋ก ํ๋ค.- ์ถ๊ฐ์ ์ผ๋ก
KHUMU_
prefix๋ฅผ ํตํด ํ๊ฒฝ ๋ณ์๋ก Config์ ํ๋๋ค์ ์ค๋ฒ๋ผ์ด๋ ํ ์ ์๋ค.
- ํ์ฌ๋ Github Action์์ ๋งค ํธ์๋ง๋ค ์ ์ฒด unit test๋ฅผ ์งํ
- ํ
์คํธ ๋ชจ๋ ํต๊ณผ ์ docker image ๋น๋ ํ ์๋ก ๋น๋๋ ์ด๋ฏธ์ง ํ๊ทธ๋ฅผ private repository๋ก ๊ด๋ฆฌ๋๋
khu-dev/devops
๋ ํฌ์งํ ๋ฆฌ์ ๋ฐ์ ArgoCD
๋ฅผ ํตํด ์๋ ๋ฐฐํฌํ๋ฉฐ ์ด๋kustomize
๋ฅผ ํตํด ์ ์ด๋ฏธ์ง ํ๊ทธ๊ฐ ์ ์ฉ๋จ
# ํ๋ก์ ํธ์ ๋ฃจํธ ๊ฒฝ๋ก์์
$ go test ./...
# ํน์ ์์ธํ ๋ก๊ทธ๋ฅผ ๋ณด๊ณ ์ถ๋ค๋ฉด
$ go test ./... -v
# ํน์ ๊ฐ๋จํ
$ make test
test๋ MySQL์ด ์๋ SQLite3๋ฅผ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ฐํ์ผ๋ก ๊ฐ๋จํ๊ฒ ์ด์ฉํ๋ค.
TODO: Service layer ํ ์คํธ ์์๋ Repository layer๋ ์ธ๋ถ ๋ชจ๋๋ค์ Mockingํ์ฌ ์ ๋ ํ ์คํธ ์งํํ๊ธฐ. ๊ธฐ์กด์๋ ๋น์ฆ๋์ค ๋ก์ง์ ํ ์คํธํ ๋์๋ SQLite3๊ณผ DAO๋ฅผ ์ด์ฉํด ์์ํ๊น์ง ์งํํ๋ ํตํฉ ํ ์คํธ ๊ฐ์ ํํ๋ก ์งํํ์ผ๋ ํ ์คํธ๊ฐ DAO์ ๋ํ ์์กด์ฑ์ ๊ฐ๋ค๋ณด๋ ๋ถํ์ํ ์ด๊ธฐ ๋ฐ์ดํฐ๋ค์ ์์ฑํด์ค์ผํ๋ ๋ถํธ์ด ์์๊ณ ์ด๋ก ์ธํด ๋ง์ ํ ์คํธ ์ผ์ด์ค๋ฅผ ์์ฑํ๋ ๋ฐ์ ๋ถํธ์ ๋๋
- ๊ฐ๋ฐํ ๊ธฐ๋ฅ์ ๋ํ ์ต์ํ์ ๊ธฐ๋ฅ๊ณผ ์ฌ์ฉํ๊ณ ์ํ๋ ํ์
, ๋ค์ด๋ฐ๋ฑ์ ๋ฏธ๋ฆฌ
xxx_test.go
ํ์ผ์ ์์ฑํ๋ค. - ํด๋น ๊ธฐ๋ฅ์
xxx.go
์์ ๊ตฌํํ๋ค. - ๊ตฌํํด๋๊ฐ๋ฉด์ ์๋์ ์ปค๋งจ๋ ์ฝ๋๋ฅผ ํตํด ์๋ก ๊ตฌํํ๋ ๋ด์ฉ์ ๋ํด์๋ง ๊ฐ๋จํ ํ ์คํธ ํด๋ณธ๋ค.
- ๊ตฌํ์ด ๋๋๋ฉด ์ ์ฒด ์ ๋ ํ ์คํธ๋ฅผ ์คํํด๋ณด๊ณ , ์ข ๋ ๋์ ๋ฐฉํฅ์ผ๋ก ๋ฆฌํฉํ ๋งํ๋ค.
- ๋ฆฌํฉํ ๋ง์ด ์๋ฃ๋๋ฉด ๋ค์ ์๋ก์ด ๊ธฐ๋ฅ์ ๋ํด ์ ๋ํ ์คํธ๋ฅผ ์์ฑํ๋ค.
์ด๋ ๊ฒ ์๋ก ๊ตฌํํ ๋ด์ฉ์ ๋ํ ์ ๋ํ ์คํธ๋ฅผ ํตํด ๊ฐ๋ฐ์ ์งํํ๋ฉด ์ ์ฒด ์๋ฒ๋ฅผ ์ฌ์คํํ๋ฉด์ ๊ฐ์ ์์ ์ ๋ฐ๋ณต์ ์ผ๋ก ์ํํ๋ ๋ถํธ์ ์์จ ์ ์๊ณ , ํ ๊ธฐ๋ฅ์ ๋ํ ์ ์ฒด ๊ณ์ธต์ ๊ตฌํํ์ง ์์๋ ๊ฐ๋ฐํ๋ ๋์ ๊ฐ ๊ณ์ธต๋ณ๋ก ๋ฏธ๋ฆฌ ํ ์คํธ๊ฐ ๊ฐ๋ฅํ๋ค.
e.g. TDD ๋ฐฉ์์ ์ด์ฉํ์ง ์๊ณ ๊ฐ๋ฐํ๋ฉด ์ฐ์ repository
๊ณ์ธต๋ง ๋ฏธ๋ฆฌ ๊ตฌํํ๊ณ ํ
์คํธํ๊ณ ์ถ์๋ฐ, http ๊ณ์ธต
๊น์ง ๋ค ๊ตฌํํ ๋ค ์๋ฒ๋ฅผ ๋์ฐ๊ณ ๊ทธ ์๋ํฌ์ธํธ์ ์์ฒญ์ ๋ณด๋ด๊ณ ๋ก๊ทธ๋ฅผ ๊ด์ฐฐํ๋ฉฐ ๊ฐ๋ฐ์ ํด์ผํ์ง๋ง, TDD์ Unit test๋ฅผ
์ด์ฉํด ๊ฐ๋ฐํ๋ฉด unit test์ ๊ฒฐ๊ณผ๋ง ๋ณด๊ณ ๋ ๊ฐ๋ฐ์ด ๊ฐ๋ฅํ๋ค.
# ๊ฐ๋ฐ ์ค์ธ ํ์ผ์ด ์ํ ํจํค์ง์ ๊ฒฝ๋ก์ ๋ํด ์คํํ๊ณ ์ํ๋ ํจ์๋ช
์ ์ ๋ฌํ๋ค.
# ์ด๋ TestSetUp์์ Initialize ๊ด๋ จํ ๋ด์ฉ๋ ํ
์คํธํ๋๋ก ์ค๊ณํ๊ธฐ๋๋ฌธ์ TestSetUp๋ ๊ฐ์ด ์ ๋ฌํ๋ค.
$ go test ./repository/ -run TestSetUp TestLikeCommentRepositoryGorm_Create -v
- go test ๋์ gotest๋ฅผ ์ด์ฉํ๋ฉด ์ข ๋ ๊ฐ์์ฑ ์ข๊ฒ test๋ฅผ ์งํํ ์ ์๋ค.
- Jetbrains์ฌ์ GoLand๋ฅผ ์ด์ฉํ๋ฉด IDE์์ ์ข ๋ ํธ๋ฆฌํ๊ฒ ์ํ๋ unit test๋ฅผ ์คํํ ์ ์๋ค.
{"message": "Not Found"}
์๋ต์ ๋ฐ๋ ๊ฒฝ์ฐecho
๊ฐ ํด๋น ๊ฒฝ๋ก์ ๋ํด route ํ ์ ์์ ๋ ๋ฐ์ํ๋๋ฐ, ์ฃผ๋ก ์ฃผ์์ ๋งจ ๋/
์ ์ฐจ์ด์ธ ๊ฒฝ์ฐ๊ฐ ์์๋ค. ์ด ๋ ํฌ์ ์ปจ๋ฒค์ ์ ๋งจ ๋ค์/
๋ฅผ ์ ๊ฑฐํ๋ ๊ฒ์ ๊ธฐ๋ณธ์ผ๋กํ๋ค.
๊ฐ์ฅ ์์ ๊ณ์ธต๋ถํฐ ๊ฐ์ฅ ํ์ ๊ณ์ธต, ๊ทธ๋ฆฌ๊ณ ๊ณ์ธต๊ณผ ๋ ๋ฆฝ๋ config๋ container ์์ผ๋ก ์ ๋ฆฌํด๋ณด๊ฒ ์ต๋๋ค.
- model ์ญํ ์ ํ๋
ent/schema
- khumu์ comment๋ผ๋ ๋๋ฉ์ธ์์ ์ฌ์ฉํ๋ ๋ชจ๋ธ์ ์ ์ํฉ๋๋ค.
- ์๋ฌด๋ฐ ๋ค๋ฅธ ๊ณ์ธต๋ ์ฐธ์กฐํ์ง ์๋ ์ต์์ ๊ณ์ธต์ ๋๋ค.
- DB Table์ ํ์ฉ๋๊ฑฐ๋ API Response ํฌํจ๋๋ ๋ฑ ๋ค์ํ๊ฒ ์ฌ์ฉ๋ ์ ์์ง๋ง, ์ด ๊ณ์ธต์ ํ์ ๊ณ์ธต๋ค์ด ์์ ์ ์ด๋ป๊ฒ ์ฌ์ฉํ๋์ง ์ ํ ์ ํ์๊ฐ ์์ต๋๋ค.
- usecase ํน์ service
- ๋๋ถ๋ถ์ ๋น์ฆ๋์ค ๋ก์ง์ด ์ด๊ณณ์ ์์นํฉ๋๋ค.
- e.g. ๋๊ธ ์์ฑ ์ message queue์ message๋ฅผ publish. ๋จ ์ด message queue๋ ์ฌ์ค์ kafka๊ฐ ๋ ์๋ ์๊ณ , sqs, sns, redis ๋ฑ์ด ๋ ์๋ ์๋ค. ์ฐ๋ฆฌ๋ ๊ตฌ์ฒดํ๋ ๊ฒ์ ์์กดํ์ง ์๊ณ ์ถ์์ ์ธ ๊ฒ์ ์์กดํ๊ธฐ ๋๋ฌธ์ด๋ค. (ํ์ง๋ง ํ์ฌ๋ ๋ค๋ฅธ message queue๋ฅผ ์ฌ์ฉํ ๊ณํ์ด ์์ด SNS(+SQS์ ์กฐํฉ)์ ์ง์ ์์กดํด ๊ฐ๋ฐ ์ค์ด๋ค.)
- e.g. ์ต๋ช
๋๊ธ์ ์์ฑ์๊ฐ ๋ณธ์ธ์ด๋ฉด
is_author: true
๋ก ๋ณํ - e.g. ์ต๋ช ๋๊ธ์ ๊ฒฝ์ฐ ์์ฑ์์ username์ nickname์ ๊ฐ์ถฅ๋๋ค.
- model๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ์์ ์ฐ๋ฆฌ ๋๋ฉ์ธ์ ์ฝ๋๋ก ์ ์๋์ด ์์ต๋๋ค.
- ํ์ ๊ณ์ธต์ธ repository์ ์์กดํฉ๋๋ค. ํ์ง๋ง ์์กด์ฑ ์ญ์ ์๋ฆฌ(DIP)์ ์ํด ํ์ ๊ณ์ธต์ ๊ตฌํ์ฒด์ ์์กดํ๋ ๊ฒ์ด ์๋๋ผ ์ถ์์ ์ธ repository interface์ ์์กดํฉ๋๋ค.
- ํ์ ๊ณ์ธต์ธ externalํ message queueํน์ aws sns์ ๊ฐ์ ๊ฒ๋ค์ ์์กดํฉ๋๋ค. repository์ ๊ฐ์ด ์์กด์ฑ ์ญ์ ์๋ฆฌ์ ์ํด ๊ตฌํ์ฒด์ ์์กดํ์ง ์๊ณ ์ถ์์ ์ธ interface์ ์์กดํฉ๋๋ค. interface์ ์์กดํ๊ธฐ ๋๋ฌธ์ ์ ๋ ํ ์คํธ ์งํ ์ mocking์ ์ ์ ํ ์ด์ฉํ๊ธฐ ํธํฉ๋๋ค.
- ๋๋ถ๋ถ์ ๋น์ฆ๋์ค ๋ก์ง์ด ์ด๊ณณ์ ์์นํฉ๋๋ค.
- repository (์ผ๋ฐ์ ์ผ๋ก DAO๋ผ๊ณ ๋ถ๋ฅด๋ ๊ณ์ธต)
์ธ๋ถ Data source์ ์ง์ ์์ ์ ํ๋ ๊ณ์ธต์ ๋๋ค.interface
์ ๊ทธ์ ๋ํ ๊ตฌํ์ฒด๋ฅผ ์ ์ํจ์ผ๋ก์จ ์ ์ฐํ๊ฒ ๋์ํฉ๋๋ค. (๋คํ์ฑ๊ณผ ์์กด์ฑ ์ญ์ )inferface
๋ฅผ ์ ์ํจ์ผ๋ก์จMySQL
,SQLite3
,Memory
์array
๋map
๊ทธ ์ด๋ค ๊ฑธ ์ฌ์ฉํ๋ ์ ์ฐํ๊ฒ ๋์ฒํ ์ ์์ต๋๋ค.
repository๋ฅผ ์ด์ฉํ๋ ๊ณ์ธต์ ์ง์ ๊ตฌํ์ฒด๋ฅผ ์ด์ฉํ์ง ์๊ณ interface๋ง์ ์ด์ฉํ๊ธฐ ๋๋ฌธ์ ๊ตฌํ์ฒด๊ฐ ๋ณ๊ฒฝ๋์ด๋ ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ ํ์๊ฐ ์์ต๋๋ค.- ๊ณผ๊ฑฐ gorm์ ์ด์ฉํ ๋ repository ์์ ์ ์ง์ ๊ตฌํํ๋ค๋ณด๋ ์์ ์ทจ์์ ์ผ๋ก ํ์๋ ์์ ๋ค์ด ํ์ํ์ง๋ง ํ์ฌ๋ ent/ent๋ผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด์ฉํ๊ฒ ๋๋ฉด์ repository ๊ณ์ธต์ ๋ํ ์ถ์ํ๊ฐ ์๋์ผ๋ก ์งํ๋๊ณ ํ ์คํธ ๋ํ ๊ฑฐ์ ํ์ ์์ด์ก์.
- http
- ์ฃผ๋ก http ํต์ ์์ฒด์ ๋ํ ๋ก์ง์ ๋ด๊ณ ์์ต๋๋ค. repository์ ํจ๊ป ๊ฐ์ฅ ํ์ ๊ณ์ธต์ ๋๋ค.
- Router, Middleware, Authentication, Authorization ์ ๊ฐ์ ์์ ์ ๋ค๋ฃน๋๋ค.
struct
=>json
์ผ๋กmarshal
ํ ๋ค ๊ทธ ์ ๋ณด๋ฅผ ๋ฐํ์ผ๋ก Response๋ฅผ ๊ตฌ์ฑํ๋ ๋ก์ง์ ๋ด๊ธฐ๋ ํฉ๋๋ค. (e.g.Comment
struct๋ฅผ ๋ฐ์์ json์ผ๋ก ๋ณํํ ๋ค Response์ body๋ฅผ ์์ฑํ๋ ์์ ์ ์งํํฉ๋๋ค.
- ์ฃผ๋ก ์์ฒญ์ ๋ํ ์์ ์ usecase๋ฅผ ํตํด ์งํํฉ๋๋ค.
- container
- ์ปจํ
์ด๋๋ ์์ ๋ชจ๋ ๊ณ์ธต๋ค๊ณผ ๋ฌ๋ฆฌ ์์ ๊ณ์ธต, ํ์ ๊ณ์ธต์ ๊ฐ๋
์ ๊ฐ์ง ์๊ณ ์์กด์ฑ ์ฃผ์
์ ๊ด๋ฆฌํด์ค๋๋ค.
- ๊ฐ๋ฐ์๋ ์์์ ์ผ๋ก ์์กด์ฑ์ ์ฃผ์ ํด์ฃผ๊ฑฐ๋, struct๋ฅผ ์์ฑํ ํ์ ์์ด container๊ฐ type์ ๊ธฐ๋ฐ์ผ๋ก ์์ (container)์ ํด๋น ํ์ ์ ๋ณ์๊ฐ ์กด์ฌํ๋ฉด ๊ทธ๊ฒ์ ์ด์ฉํ ์ ์๊ฒํด์ฃผ๊ณ , ์๋ค๋ฉด ์์ฑํ ๋ค ์ด์ฉํ ์ ์๊ฒ ํด์ค๋๋ค.
- DI framework์ธ dig๊ฐ ์์กด์ฑ ์ฃผ์
์ ์ ์ดํ๋ค๋ ๋ฉด์์ IoC(์ ์ด์ ์ญ์ )์ด ๋ฐ์ํฉ๋๋ค.
- ํ์ฌ๋ uber์
dig
ํจํค์ง๋ฅผ ์์กด์ฑ ์ฃผ์ ํจํค์ง๋ก ์ฌ์ฉ ์ค์ ๋๋ค. ๊ตฌ๊ธ์wire
๊ฐ ๊ฝค ์ ๋ช ํ ๊ฒ ๊ฐ์ง๋ง, ๊ฐ๋ ์ฑ์ ํด์น ๊ฒ ๊ฐ๊ณ , ์ ์ฐํ์ง ์์ ๋ฏํ์ฌ ๋ฐฐ์ ํ์ต๋๋ค. uber์fx
๋dig
๋ฅผ ํ ๋จ๊ณ ๋ ๊ฐ์ผ ํจํค์ง์ธ๋ฏํ๋ฐ, ๋ง์ฐฌ๊ฐ์ง๋ก ์ ์ฐ์ฑ์ด ๋จ์ด์ง๋ ๋๋์ ๋ฐ์์ต๋๋ค.
- ํ์ฌ๋ uber์
- IoC Container์ ๊ด๋ จ๋ ์์ ์ ์ํํ๋ ํจํค์ง์ ๋๋ค.
- ์ปจํ
์ด๋๋ ์์ ๋ชจ๋ ๊ณ์ธต๋ค๊ณผ ๋ฌ๋ฆฌ ์์ ๊ณ์ธต, ํ์ ๊ณ์ธต์ ๊ฐ๋
์ ๊ฐ์ง ์๊ณ ์์กด์ฑ ์ฃผ์
์ ๊ด๋ฆฌํด์ค๋๋ค.
- config : ํ๋ก๊ทธ๋จ์ ๋ํ ์ค์ ์ ๋ณด๋ ๊ทธ ์ ๋ณด๋ฅผ ๋ถ๋ฌ์ค๋ ์์ ์ ๋ด๋นํฉ๋๋ค.
-
ํฐ ์ฅ์ ๋ค
- ์ง์์ ์ธ ๊ฐ๋ฐ์ ๋ํ ์ ๋ขฐ์ ์์ ์ฑ์ด ์์นํ๊ณ , ์ด๋ ์์ฐ์ฑ์ผ๋ก๋ ์ฐ๊ฒฐ๋๋ค.
- ๋ํ ๋น์ฅ์ ๊ฐ๋ฐ์์๋ unit test๋ฅผ ํตํด ๊ณ์ธต์ ๋๋์ด ๊ฐ๋ฐํ๊ธฐ ํธ๋ฆฌํ๊ฒ ๋๋ฌธ์ ์์ฐ์ฑ์ด ์ฆ๊ฐ๋๋ค.
-
์๋๋ ์์กด์ฑ ์ฃผ์ ํจํค์ง๋ฅผ ์ฌ์ฉํ์ง ์์๋๋ฐ, test code๋ฅผ ์ง๊ฒ ๋๋ฉด์ ์๋์ผ๋ก ์์กด์ฑ์ ๋ฃ๋ ๊ฒ์ด ๋ฒ๊ฑฐ๋กญ๊ธฐ๋ ํ๊ณ ๊ฐ๋ ์ฑ๋ ์ ์ข์ ๊ฒ ๊ฐ์ ์์กด์ฑ ์ฃผ์ ํจํค์ง๋ฅผ ์ฌ์ฉํ๊ธฐ ์์ํ๋ค.
-
Mocking ํ๋ ๊ฒฝ์ฐ
- struct ํ ์ธ์๊ฐ ์๋ interface ํ ์ธ์๋ฅผ ์ด์ฉํ๋ฉด ์์กด์ฑ์ ์ฃผ์ ํ ๋ mock type์ ์ฃผ์ ํ ์ ์๋ค.
- mock type์ ์ด์ฉํ๋ฉด ํ์ ๊ณ์ธต์ ๋ด์ฉ๊ณผ ๋ ๋ฆฝ๋๊ฒ ํด๋น ๊ณ์ธต๋ง ํ ์คํธ ํ ์ ์๋ค.
- mock type์ ์ด์ฉํ๋ฉด ํ์ ๊ณ์ธต์ ํ์ ๊ณ์ธต์ ๋ํ ์์กด์ฑ, ๊ทธ ํ์ ๊ณ์ธต์ ๋ ํ์ ๊ณ์ธต์ ๋ํ ์์กด์ฑ์ ๋ชจ๋ ์ฃผ์ ํด ์ค ํ์ ์์ด ๋ด๊ฐ ์ง์ ํ์ํ ๊ณ์ธต๋ง ์ฃผ์ ํ๋ฉด ๋๋ค๋ ์ ์ด ํธ๋ฆฌํ๋ค.
- ๋ค๋ง ํ์ ๊ณ์ธต์ ํ๋ด๋๋ค๋ ์ ์์ ์ค์ ํ์ ๊ณ์ธต์ ๋์๊ณผ ๋ค๋ฅด๊ฒ ๋์ํ ์ ์๋ค๋ ๋ฉด์ด ํด๋น ๊ณ์ธต์ ํ ์คํธ์ ์ ํ์ฑ์ ๋ฎ์ถ ์ ์๋ค.
- ์์กด์ฑ์ ์ฃผ์ ํ๋ ๊ฒ์ด ์คํ๋ ค mock methods๋ฅผ ์ ์ํ๋ ๊ฒ๋ณด๋ค ํธ๋ฆฌํ ๊ฒฝ์ฐ๋ ๋ง๋ค.
-
๊ฐ Test ๋ณ ๋ ๋ฆฝ์ฑ์ด ํ ์คํธ๊ฐ ๊ฐ๋ฅํ๋๋ก ํ์.
-
Java Spring์ BeforeEach์ AfterEach์์ ์์ด๋์ด๋ฅผ ์ป์ด
B
์A
๋ผ๋ ํจ์๋ฅผ ์ ์ํ๊ธฐ๋ก ํ๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ์ด๊ธฐ ๋ฐ์ดํฐ๊ฐ ํ์ํ ํ ์คํธ๋ค์ ๋ชจ๋ ์๋์ ๊ฐ์ด B์ A๋ฅผ ์ด์ฉํด Set up๊ณผ clean up์ ์งํํ๋ค.func TestFoo(t *testing.T) { B() defer A() // some test scenarios. }
-
-
(๊ณ ๋ฏผ ์ค) ๋ถํ์ํ ์ฐธ์กฐ ์ ์ฝ ์กฐ๊ฑด ์ ๊ฑฐ
- ํ์ฌ๋ ๋๊ธ ์ํฐํฐ์ ์ฐธ์กฐ ์ ์ฝ ์กฐ๊ฑด์ผ๋ก ์์ฑ์๋
KhumuUser
, ๊ฒ์๊ธ์Article
์ ์ฐธ์กฐํ๊ฒ ์ค์ ๋์ด์๋ค.- ๋๊ธ์ ํ
์คํธ ํ๊ธฐ ์ํด์๋
KhumuUser
์Article
์ํฐํฐ ๋ฐ์ดํฐ๋ฅผ ๋ง๋ค์ด์ผ ํจ. - ์ถ๊ฐ์ ์ผ๋ก
KhumuUser
์ํฐํฐ๋ฅผ ๋ง๋ค๊ธฐ ์ํด์Group
์ํฐํฐ๋ฅผ ๋ง๋ค์ด์ผ ํจ - ์ถ๊ฐ์ ์ผ๋ก
Article
์ํฐํฐ๋ฅผ ๋ง๋ค๊ธฐ ์ํด์Board
์ํฐํฐ๋ฅผ ๋ง๋ค์ด์ผํจ. - ... ์ด๋ฐ ๊ณผ์ ์ด ๋ง๋ค.
- ๋๊ธ์ ํ
์คํธ ํ๊ธฐ ์ํด์๋
- ์์ ๊ฐ์ ๋ถํธ์ ์์ ๊ธฐ ์ํด ๋ถํ์ํ ์ฐธ์กฐ ์ ์ฝ ์กฐ๊ฑด์ ์์ ๊ณ DB Indexing๋ง ์ ์งํด ๊ฐ๊ฒฐํ๊ฒ ๋ฐ์ดํฐ๋ฅผ ์ ์งํ๊ณ , ํ ์คํธ๋ ์งํํ ์ ์๊ฒ ํ๋ฉด ์ด๋จ๊น ์ถ๋ค.
- ์ ์ด์ ๋ง์ดํฌ๋ก์๋น์ค ๊ฐ์๋ ๋ถ๋ฆฌ๋ DB๋ฅผ ์ด์ฉํ๊ณ ํ์ํ ๊ฒฝ์ฐ message queue ๊ฐ์ ์๋น์ค๋ฅผ ํตํด event๋ฅผ ๋ฐ์ ์๊ธฐ ๋ง์ดํฌ๋ก์๋น์ค DB์ replication์ ์งํํ๋ ๊ฒฝ์ฐ๋ฅผ ๋ง์ด ์ด์ฉํ๋ ๊ฒ ๊ฐ์๋ฐ ์ ์ด์ ์ด๋ฐ ์์ ์ ์ํํ๋ฉด DB์ ์ฐธ์กฐ ์ ์ฝ ์กฐ๊ฑด์ ๊ตณ์ด ๊ฑธ ํ์๊ฐ ์์ง ์์๊น ์ถ๊ธฐ๋ ํ๋ค. ๋๊ธ์ ๊ฒ์๋ฌผ๊ณผ ์ ์ ๋ฅผ ์ฐธ์กฐํ๋๋ฐ ์ฐธ์กฐ ๋ฌด๊ฒฐ์ฑ์ด ์๋ฐฐ๋๋ค๊ณ ํด์ ๊ทธ๋ฅ ๋ฌธ์ ๋ ์๊ธฐ ๋๋ฌธ.
- ํ์ฌ๋ ๋๊ธ ์ํฐํฐ์ ์ฐธ์กฐ ์ ์ฝ ์กฐ๊ฑด์ผ๋ก ์์ฑ์๋
http
๊ณ์ธต์ ๋ํ ํ
์คํธ ์ฝ๋๋ฅผ ์ง ๋ค๊ณ ๊ฐ์ ํ์. http
๋ usecase
๊ณ์ธต์ ์์กด์ ์ด๋ค.
๊ทธ๋ผ ํ
์คํธ ์ฝ๋๋ฅผ ์งค ๋ http
์์ฑ ์ usecase
๋ฅผ ์์ฑํ์ฌ ์ฃผ์
์์ผ์ฃผ์ด์ผํ๋ค. ๊ทผ๋ฐ ๋ฐ๋ณต์ ์ผ๋ก
usecase
๋ repository
์ ์์กด์ ์ด๋ฏ๋ก repository
๋ฅผ ์์ฑํ์ฌ ์ฃผ์
๋ฐ์์ผํ๋ค. ๋ฐ๋ผ์ ์ด๋ฌํ
์์กด ํ์ดํ๋ผ์ธ์ ๋ง์กฑ์์ผ์ฃผ๊ธฐ ๋ฒ๊ฑฐ๋กญ๊ธฐ๋๋ฌธ์ mock type์ ์ด์ฉํด ํ
์คํธ๋ฅผ ํ๊ณ ์ถ๋ค.
๋ง์ฝ ์๋์ ๊ฐ์ ์ฝ๋์์ CommentUseCase์ ๊ดํ mock type์ ์ ์ํ๋ค๋ฉด ์ฌ์ฉ์ด ๊ฐ๋ฅํ ๊น?
func NewCommentRouter(root *RootRouter, uc CommentUseCaseStruct) *CommentRouter {
... ์์
์๋ต
return commentRouter
}
mock type์ ์ด์ฉํ๊ธฐ ๋ถ๊ฐ๋ฅํ๋ค. ์ด์ ๋ CommentUseCase ์ญํ ์ ํ๋ ์ธ์๊ฐ struct ํ์
์ผ๋ก ์ ์๋์ด์๊ธฐ ๋๋ฌธ์ด๋ค.
mock type์ ์ ์ํ๋ค๊ณ ํด๋ ๊ทธ type์ ์์ ์ ์๋ CommentUseCaseStruct
type์ด ๋ ์ ์๋ค.
๋ฐ๋ผ์ ์ฃผ์ ๋ฐ๋ ์ธ์์ type์ concreteํ struct๊ฐ ์๋ abstractํ interface๋ก ์ ์ํด์ฃผ๋ฉด ๋๋ค. ์๋์ฒ๋ผ mock type์ด ํด๋น ์ธํฐํ์ด์ค๊ฐ ๋๊ธฐ ์ํ ๋ฉ์๋๋ค๋ง ํ์ํ ๋งํผ๋ง ์๋ ํ์ ์ ํ๋ด๋ด์ด ๊ตฌํํด์ฃผ๋ฉด๋๋ค.
type CommentUseCaseInterface interface{
List() []*model.Comment
}
type CommentUseCaseMock struct{}
// ๊ฐ๋จํ๊ฒ ํ์ํ ๋งํผ๋ง ์๋์ ๊ธฐ๋ฅ์ ํ๋ด๋ธ๋ค.
func (uc *CommentUseCaseMock) List []*model.Comment{
return []*model.Comment{
&model.Comment{...์๋ต}, &model.Comment{...์๋ต}, &model.Comment{...์๋ต}
}
}
// ์ฃผ์
๋ฐ๋ ์ธ์์ ํ์
์ interfaceํ์ผ๋ก ์ ์ํ๊ธฐ๋๋ฌธ์ ์ค์ ์ ์ธ CommentUseCase์ด๋ ๊ฐ์ง์ CommentUseCaseMock ํ์
์ด๋
// ์๊ด ์์ด ์ฃผ์
๋ฐ์ ์ ์๋ค.
// ์๋ฒ๋ฅผ ๋๋ฆด ๋์๋ CommentUseCase๋ฅผ, ํ
์คํธ ํ ๋๋ ์์กด์ฑ ์ฃผ์
์ด ํธ๋ฆฌํ CommentUseCaseMock์ ์ฌ์ฉํ๋ฉด ๋๋ค.
func NewCommentRouter(root *RootRouter, uc CommentUseCaseInterface) *CommentRouter {
... ์์
์๋ต
return commentRouter
}
$ mockgen -package repository -destination usecase/mock.go \
github.com/khu-dev/khumu-comment/usecase \
CommentUseCaseInterface,LikeCommentUseCaseInterface
(์ถ๊ฐ ์์ ) ์ฐ์ ์ ์์ ๊ฐ์ ์ปค๋งจ๋๋ฅผ ์ด์ฉํด ์๋์ผ๋ก mock type์ ๋ง๋ค ์ ์๋ค.
๊ธฐ์กด์๋ go-gorm์ ์ด์ฉํ์ง๋ง ๋ง์ ๋ถํธ์ ๋๊ผ๊ณ ๋ง์นจ ์ฌ๋ฌ Golang ์ปค๋ฎค๋ํฐ์์ ent/ent๋ฅผ ๊ทน์ฐฌํ๊ธฐ์ ent๋ฅผ ์ด์ฉํ๋ ๋ฐฉ์์ผ๋ก ๊ฐ์ ํ๋ค.
# Comment์ ๋ํ Schema๋ฅผ ์ ์ํ๊ธฐ ์ํ ์ด์
$ go run entgo.io/ent/cmd/ent init Comment
# ํน์ ๊ฐ๋จํ
$ ent init Comment
# Schema ์์ ํ์๋ ํญ์ ์์ง ๋ง๊ณ ์๋ ๋ช
๋ น์ด๋ฅผ ํตํด ๋ณ๊ฒฝ ์ฌํญ์ด ๋ฐ์๋ ์ฝ๋๋ฅผ Generateํ ๊ฒ.
# ๋งค Compile ๋ง๋ค ์ํ์ํฌ ์๋ ์์ง๋ง, ์ง์ฐ์๊ฐ์ด ์ ์ด ๊ฑธ๋ ค์ ๋งค๋ฒ ํ๋ฉด ๋ฒ๊ฑฐ๋ก์ธ ๋ฏ.
$ go generate ./ent
ent๋ ๊ธฐ๋ฅ์ด ๋ง๊ณ ํธ๋ฆฌํ ๋์ ๋ช ๊ฐ์ง ์ปค๋งจ๋๋ฅผ ์ตํ์ผํ๋ค.
ent
์ปค๋งจ๋๋ฅผ ํตํด ์ ์ํ๋ ค๋ schema์ ์ด์์ ๋ง๋ ๋ค.go generate
๋ฅผ ํตํด ํด๋น schema๋ฅผ ๋ฐํ์ผ๋กํ type์ด๋ ๊ธฐ๋ฅ ๋ฑ๋ฑ์ ์๋์ผ๋ก ์ ์ฉํ๋ค.
type์ ๊ธฐ๋ฐ์ผ๋ก ์์กด์ฑ ์ฃผ์
์ ์๋ํํ๋ ์์กด์ฑ ์ฃผ์
ํจํค์ง๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ
๋์ผ ํ์
์ด์ง๋ง ๋ค๋ฅธ ๊ฐ์ฒด๋ฅผ ์ฃผ์
ํ๊ณ ์ถ์ ๊ฒฝ์ฐ ๋๊ฐํ ๊ฒฝ์ฐ๊ฐ ์๋ค. ์ด๋ฐ ๊ฒฝ์ฐ์๋ embedding
์ ํตํด ์๋ ํ์
์
๋ฉ์๋์ ํ๋๋ฅผ ๋ชจ๋ ์ฌ์ฉํ๋ฉด์ ๊ฐ๋ณ์ ์ธ type์ผ๋ก ์ด์ฉํ ์ ์๋ค. ์๋ฅผ ๋ค์ด router์์๋ ์์ router group์ parent router group์
์ธ์๋ก ๋ฐ๊ณ ์ถ์๋ฐ, ๊ทธ๋ฅ *echo.Group
์ ์ฃผ์
๋ฐ๊ฒ ๋ค๊ณ ์ ์ํ๋ฉด, ์ด๋ค *echo.Group
์ ์ฃผ์
๋ฐ๊ฒ ๋ ์ง ๋ชจ๋ฅธ๋ค. ๋ฐ๋ผ์ ์๋์ ๊ฐ์ด
embedding
์ ํตํด ์๋์ ๋ฉ์๋์ ํ๋๋ฅผ ๋ชจ๋ ์ฌ์ฉํ๋ฉด์ ์ฃผ์
๋ฐ์ ์๋ก์ด ํ์
์ ์ ์ํ ์ ์๋ค.
// embedding์ ํตํด *echo.Group์ ๋ฉ์๋, ํ๋๋ฅผ ์ด์ฉํ ์ ์๋ ํ์
์ ์
// ์ด ํ์
์ ์ธ์๋ก ๋ฐ๋ ๋ฉ์๋๋ ์ผ๋ฐ์ ์ธ *echo.Group ํ์
๊ณผ ๊ตฌ๋ณ๋ RootRouter Type์ ์ด์ฉํ ์ ์๋ค.
type RootRouter struct{*echo.Group}
// ํน์ type RootRout echo.Group ๋ ๊ฐ๋ฅ
func NewRootRouter(echoServer *echo.Echo, ... ์ธ์ ์๋ต) *RootRouter{
g := RootRouter{Group: echoServer.Group("/api")}
//... ์์
์๋ต
return &g
}
func NewCommentRouter(root *RootRouter, ... ์ธ์ ์๋ต) *CommentRouter {
// ํน์ดํ๊ฒ Type๋ช
๊ณผ ์ด์ฉํ๊ณ ์ํ๋ ๋ฉ์๋ ๋ช
์ด ๊ฐ์์ ์ด๋ ๊ฒ ์ฌ์ฉํ ๋ฟ ์๋๋ embed ์ root.Group("/comments")๋ก ์ฌ์ฉ ๊ฐ๋ฅ
group := root.Group.Group("/comments")
commentRouter := &CommentRouter{group, ... ์ธ์ ์๋ต}
return commentRouter
}
Redis
๋ฅผ ์ด์ฉํด ์บ์๋ก ํผํฌ๋จผ์ค๋ฅผ ๋์ด๊ณ ์ ์ ๋ฐ์ ์ธ ์ปค๋ฎค๋ํฐ API๋ฅผ ๋ด๋นํ๋ Django ์๋น์ค์ ๋ณธ ๋ ํฌ์งํ ๋ฆฌ์ธ ๋๊ธ ์๋น์ค ๋ชจ๋์ ๋ ๋์ค ์บ์๋ฅผ ์ ์ฉํ๋ค. ํ์ง๋ง Django ์๋น์ค์์๋ ๊ฒ์๊ธ ์ ๋ณด๋ฅผ ์ ๊ณตํ ๋ ํด๋น ๊ฒ์๊ธ์ ๋ํ ๋๊ธ ๊ฐ์๊ฐ ํ์ํ๊ณ ์ด๋ฅผ ์์ฒด์ ์ผ๋ก DB์์ ์ง์ํ๊ฑฐ๋ ์ง์ ํ django์ ๋ถ์ผ ์ ์๋ caching framework์ธ cacheops
๋ฅผ ์ด์ฉํด Redis์ ๋๊ธ ๊ด๋ จ ์บ์๋ฅผ ์ ์ฅํ๋ค. ํ์ง๋ง ๋๊ธ ๊ด๋ จ ๋ฐ์ดํฐ๋ฅผ ๋๊ธ ์๋น์ค๊ฐ ์ ๊ณตํ๋ ๊ฒ์ด ์๋๋ผ Django ์๋น์ค๊ฐ ์ค์ค๋ก ์ง์ํ๋ ๊ฒ์ ์์ ๋๋ฉ์ธ์ ๊ด์ฌ์ฌ๋ฅผ ๋ช
๋ฐฑํ ๋์ด์๋ ํ์์ด๊ณ Context๊ฐ ๋ช
ํํ ๋ถ๋ฆฌ๋์ง ์์ ํํ์๋ค. ๋ณ๊ฐ์ธ ๋ค์์ ์๋น์ค๊ฐ ๋์ผํ ๋ฐ์ดํฐ์ ์ก์ธ์ค ํ ๊ฒฝ์ฐ์ ๋ฐ์ํ๋ ๋ฌธ์ ๋ ๋ค์๊ณผ ๊ฐ์๋ค.
- ๋๊ธ
์์ฑ
,์ญ์
์ด๋ฒคํธ ๋ฐ์ ์ Django ์๋น์ค๋ ๊ทธ ์ด๋ฒคํธ๋ฅผ ๊ฐ์งํ ์ ์์ด Django ์๋น์ค์ cacheops๋ก ์บ์๋ฅผ ์ ๋ฐ์ดํธ ํ ์ ์์. - ๋๊ธ ์๋น์ค๊ฐ ์บ์๋ฅผ invalidateํ ์๋ ์์ง๋ง ์ฌ์ ํ Django ์๋น์ค์ ๋๊ธ ์๋น์ค๋ผ๋ ๋ณ๊ฐ์ ๋ ์๋น์ค๊ฐ Redis์์ ๋์ผํ ๋ฐ์ดํฐ๋ฅผ ์กฐ์ํ๋ ์ํฐ ํจํด์ด ๋ฐ์ํจ.
- ๋๊ธ ์๋น์ค๊ฐ ์บ์๋ฅผ ์ ๋ฐ์ดํธ ํ๋คํด๋ cacheops๊ฐ ์ง๋ ฌํํ๋ ๋ฐฉ์์ ๋ง์ถฐ์ค ์๊ฐ ์๊ธฐ ๋๋ฌธ์ ์ ํจํ ๋ฐ์ดํฐ๋ก ์ ๋ฐ์ดํธํ ์๋ ์๊ณ invalidate ๋ฐ์ ํ ์ ์์. ์ด ๊ฒฝ์ฐ ๋ค์ ์์ฒญ์ ์ํํ๋ ์ ์ ๋ ๊ธด latency๋ฅผ ๊ฒฝํํ๊ฒ ๋จ.
๊ทธ๋์ ์ด๋ ๊ฒ ํด๊ฒฐํ๊ณ ์ํ๋ค.
- Django ์๋น์ค๋ ๋๊ธ ๊ด๋ จ ๋ด์ฉ์ ์ํด์๋ ๋๊ธ ์๋น์ค์๊ฒ๋ง ์ง์ํ๋ค. ๋๊ธ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ์บ์์๋ ์ ๋ ์ ๊ทผํ์ง ์๋๋ค.
- get_comment_count() ๋ฉ์๋๋ฅผ ํตํด ๊ฒ์๊ธ์ ๋๊ธ ๊ฐ์๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฉ์๋๋ฅผ ์ ์ํ ๋ค cache๋ฅผ disable ์ํค๋ ๋ฐฉ๋ฒ์ ์ถ์ฒ.
- ๋๊ธ ๊ด๋ จ ์บ์๋ ๋๊ธ ์๋น์ค๊ฐ ์ฃผ์ธ์ผ๋ก์ ์์์ ๊ด๋ฆฌํ๋ค.
๊ฐ๋จํ ๋ฒค์น๋งํฌ
without Redis | with Redis | |
---|---|---|
๋๊ธ 100๊ฐ ์กฐํ (๋ก์ปฌ ํ๊ฒฝ) | ์ฝ 200 ms | ์ฝ 20 ms |
๋๊ธ 100๊ฐ ์กฐํ (๊ฐ๋ฐ ํ๊ฒฝ) | ์ฝ 300 ms | ์ฝ 70 ms |
Django๊ฐ ๊ฒ์๊ธ ํ๋ ์กฐํ ์ ๊ด๋ จ ๋๊ธ ๊ฐ์๋ฅผ ์ง์ ์กฐํ ํ ์๋ต(๋ก์ปฌ ํ๊ฒฝ) | ์ฝ 60 ms | ์ฝ 15ms |
Django๊ฐ ๊ฒ์๊ธ ํ๋ ์กฐํ ์ ๊ด๋ จ ๋๊ธ ๊ฐ์๋ฅผ ์ง์ ์กฐํ ํ ์๋ต(๊ฐ๋ฐ ํ๊ฒฝ) | ์ฝ 150 ms | ์ฝ 40ms |
๋ฌผ๋ก ๋ง์ ๊ฒฝ์ฐ์ ์๋ง๋ค ๋ค๋ฅด๊ฒ ์ง๋ง ๋์ฒด๋ก Redis๋ฅผ ์ด์ฉํ๋ ๊ฒฝ์ฐ ๊ฑฐ์ 5๋ถ 1 ์ ๋๋ก latency๊ฐ ๊ฐ์ํ๋ ํจ๊ณผ๊ฐ ์์๋ค. ์ด๋ฌ๋ ์บ์๋ฅผ ์ ์ธ ์๊ฐ ์๋ค... Django๊ฐ ๊ฒ์๊ธ ํ๋๋ฅผ ์กฐํ ์ ๊ด๋ จ ๋๊ธ์ ๊ฐ์๋ฅผ ์ง์ ์กฐํํ๋๋ผ๋ Redis๋ฅผ ์ฌ์ฉํ๋ฉด ์์ ๊ฐ์ด latency๊ฐ ์ ์ ๊ฒ์ ์ ์ ์๋ค. ํ์ง๋ง ์์ ์ธ๊ธํ๋ฏ ์ด๋ ์ฑ๋ฅ์ ์ธก๋ฉด์ด ์๋ ๋๋ฉ์ธ์ ๋ถ๋ฆฌํด์ ์ค๊ณํ๋ ์ค๊ณ์ ์ธก๋ฉด์์ ์ข์ง ์์ ํจํด์ด๋ฏ๋ก ๋๊ธ๊ณผ ๊ด๋ จ๋ ๊ธฐ๋ฅ์ ๋๊ธ ์๋น์ค๊ฐ ์ ๋ดํ๊ณ ์ Django๋ ๊ฒ์๊ธ๊ณผ ๊ด๋ จ๋ ๋๊ธ ์ ๋ณด๊ฐ ํ์ํ ์ ์ง์ DB๋ ์บ์์์ ์กฐํํ๋ ๊ฒ์ด ์๋๋ผ ๋๊ธ ์๋น์ค๋ฅผ ํตํด ์กฐํํ๋ ํํ๋ก ๋ณ๊ฒฝํ๋ค.
Maintainer: @umi0410 (dev.umijs@gmail.com)
- ์ด์ ์์ฑ or ๊ฐ์ธ์ ์ธ ์ฐ๋ฝ
- Fork ํ PR ์์ฑ