
๋ค์ด๊ฐ๋ฉฐ
Gin์ Go ์ธ์ด ๊ธฐ๋ฐ์ ๊ณ ์ฑ๋ฅ ์น ํ๋ ์์ํฌ์ ๋๋ค. ๊ฐ๋ณ๊ณ ์ ์ฐํ๋ฉฐ ๋ฏธ๋ค์จ์ด, ๋ผ์ฐํ , ์ ํจ์ฑ ๊ฒ์ฌ ๋ฑ ๋ค์ํ ๊ธฐ๋ฅ์ ์ง์ํฉ๋๋ค. ์์ธํ ๋จ๊ณ๋ณ๋ก ์ดํด๋ณด๋ ค๊ณ ํฉ๋๋ค. ํน์ง → ์ฅ๋จ์ → ์ค๋ฌด ์ฌ์ฉ ์์ → ์ด์ ํ ์์๋ก ์ ๋ฆฌํด๋ณด๊ฒ ์ต๋๋ค.
1) ๊ฐ์
- Gin์ Go๋ก ์์ฑ๋ ๊ฒฝ๋(ํ์ง๋ง ๊ธฐ๋ฅ ํ๋ถ) ์น ํ๋ ์์ํฌ๋ก, ์์ฐ์ฑ(๊ฐ๋จํ API)๊ณผ ์ฑ๋ฅ(๋น ๋ฅธ ๋ผ์ฐํ )์ ๋์์ ๋ ธ๋ฆฌ๋ ์๋น์ค์ ์ ํฉํฉ๋๋ค. (Gin Web Framework)
- ์ฃผ ์ฌ์ฉ ์ฌ๋ก: REST API, ๋ง์ดํฌ๋ก์๋น์ค, ๋ด๋ถ ํด/๊ด๋ฆฌ ์ฝ์ ๋ฑ — JSON ๋ฐ์ธ๋ฉ๊ณผ ๋ฏธ๋ค์จ์ด ์กฐํฉ์ผ๋ก ๋น ๋ฅด๊ฒ ๊ฐ๋ฐํ๊ณ ์ด์ํ๊ณ ์ถ์ ๋ ์ ํฉํฉ๋๋ค. (Gin Web Framework)
2) ์ฃผ์ ํน์ง
- ๋น ๋ฅธ ๋ผ์ฐํฐ(Zero-allocation / radix tree ๊ธฐ๋ฐ): ๋ผ์ฐํ ์ด ๋งค์ฐ ํจ์จ์ ์ผ๋ก ์ค๊ณ๋์ด ์์ต๋๋ค. (Gin Web Framework)
- ๋ฏธ๋ค์จ์ด ์ฒด์ธ ์ง์(๋ก๊น , ๋ฆฌ์ปค๋ฒ๋ฆฌ, ์ธ์ฆ, GZIP ๋ฑ) — ๊ธฐ๋ณธ ์ ๊ณต ๋ฏธ๋ค์จ์ด์ ํ์ฅ ์ํ๊ณ๊ฐ ํ๋ถํฉ๋๋ค. (GitHub)
- ๋ฐ์ธ๋ฉ/๊ฒ์ฆ ํตํฉ: JSON/XML/Form ๋ฐ์ธ๋ฉ๊ณผ go-playground/validator ๊ธฐ๋ฐ์ ๊ฒ์ฆ์ ์ฝ๊ฒ ์ฌ์ฉํฉ๋๋ค. (Gin Web Framework)
- ๋ผ์ฐํธ ๊ทธ๋ฃนํ, ์๋ฌ ๊ด๋ฆฌ, ํ ํ๋ฆฟ ๋ ๋๋ง ๋ฑ ์ค์ ๊ธฐ๋ฅ ๋ด์ฅ. (GitHub)
3) ์ฅ์
- ์ฅ์
- ๊ฐ๋ฐ ์์ฐ์ฑ — ์ง๊ด์ ์ธ API์ ๋ฌธ์, ์์ ๊ฐ ๋ง์ ์ด๊ธฐ ๊ฐ๋ฐ ์๋๊ฐ ๋น ๋ฆ ๋๋ค. (Gin Web Framework)
- ์ฑ๋ฅ์ด ์ฐ์ — net/http ๊ธฐ๋ฐ ํ๋ ์์ํฌ ์ค ๋น ๋ฅธ ํธ์ด๋ฉฐ ์ค ์๋น์ค์์ ์ถฉ๋ถํ ์ฒ๋ฆฌ๋์ ์ ๊ณตํฉ๋๋ค. (Gin Web Framework)
- ์ ๋ ฅ ๋ฐ์ธ๋ฉ๊ณผ ๊ฒ์ฆ์ด ๊ฐํธ → DTO/Struct์ ํ๊ทธ๋ง ๋ฌ์๋๋ฉด ์๋ ๋ฐ์ธ๋ฉ/๊ฒ์ฆ์ด ๋ฉ๋๋ค. (Gin Web Framework)
- ํ๋ถํ ๋ฏธ๋ค์จ์ด·์ปค๋ฎค๋ํฐ → ๋ก๊น ·๋ฆฌ์ปค๋ฒ๋ฆฌ ๋ฑ ๊ธฐ๋ณธ ๊ตฌ์ฑ์ผ๋ก ๋ฐ๋ก ์ฌ์ฉ ๊ฐ๋ฅ. (GitHub)
- ๋จ์ / ๊ณ ๋ ค์ฌํญ
- ๊ทนํ์ ๋ฒค์น๋งํฌ ํ๊ฒฝ์์๋ fasthttp ๊ธฐ๋ฐ ํ๋ ์์ํฌ(Fiber ๋ฑ)์ ์ฐ์๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค — ์ค ํธ๋ํฝ/IO๊ฐ ๋ง์ ์๋น์ค์์ ๋ฏธ์ธ ์ฐจ์ด๋ฅผ ๊ฒํ ํด์ผ ํฉ๋๋ค. (๊ทธ๋ฌ๋ ๋๋ถ๋ถ์ ํ์ค์ ์๋น์ค์์๋ ์ฐจ์ด๊ฐ ํฌ์ง ์์ต๋๋ค). (Medium)
- WebSocket/ํ์ด์ฌํน๋ ์ฐ๊ฒฐ์ graceful shutdown์์ ์ถ๊ฐ ๊ด๋ฆฌ ํ์ — http.Server.Shutdown()์ hijacked ์ฐ๊ฒฐ(์: WebSocket)์ ์๋์ผ๋ก ์ ๋ฆฌํ์ง ์์ผ๋ฏ๋ก ๋ณ๋ ์ข ๋ฃ ๋ก์ง์ด ํ์ํฉ๋๋ค. (VictoriaMetrics)
- ๋๋ฒ๊ทธ/๋ฆด๋ฆฌ์ค ๋ชจ๋ ๊ด๋ฆฌ ํ์ — ๊ฐ๋ฐ ์ค ๋๋ฒ๊ทธ ๋ก๊ทธ๊ฐ ๋ง์ด ์ถ๋ ฅ๋ ์ ์์ด, ์ด์ํ๊ฒฝ์์๋ gin.SetMode(gin.ReleaseMode) ์ค์ ์ ๊ถ์ฅํฉ๋๋ค. (Go Packages)
4) ๋จ๊ณ๋ณ ์ฌ์ฉ ์์ (์ค์ ์ฝ๋ · ์ค๋ช )
์๋ ์์ ๋ค์ ์ค์ ๋ก ๋ฐ๋ก ๋ถ์ฌ ์จ๋ณผ ์ ์๊ฒ ๊ตฌ์ฑํ์ต๋๋ค.
์ค๋น(ํ๋ก์ ํธ ์ด๊ธฐํ)
mkdir mygin && cd mygin
go mod init example.com/mygin
go get github.com/gin-gonic/gin
(๊ณต์ Quickstart ์ฐธ์กฐ). (Gin Web Framework)
1. Hello world (๊ธฐ๋ณธ ๋ผ์ฐํ )
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default() // Logger + Recovery ํฌํจ
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "pong"})
})
r.Run(":8080")
}
- gin.Default()๋ Logger/Recovery ๋ฏธ๋ค์จ์ด๊ฐ ํฌํจ๋์ด ์์ด ๊ฐ๋ฐ ํธ์์ฑ์ด ๋์. (GitHub)
2. JSON ๋ฐ์ธ๋ฉ + ๊ฒ์ฆ ์์
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
type CreateUserReq struct {
Name string `json:"name" binding:"required"`
Email string `json:"email" binding:"required,email"`
Age int `json:"age" binding:"gte=0,lte=130"`
}
func main() {
r := gin.Default()
r.POST("/users", func(c *gin.Context) {
var req CreateUserReq
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// ๊ฒ์ฆ ํต๊ณผ
c.JSON(http.StatusCreated, gin.H{"user": req})
})
r.Run(":8080")
}
- Gin์ go-playground/validator๋ฅผ ์ฌ์ฉํด binding ํ๊ทธ ๊ธฐ๋ฐ ๊ฒ์ฆ์ ์ ๊ณตํฉ๋๋ค. (Gin Web Framework)
3. ๋ฏธ๋ค์จ์ด·๋ผ์ฐํธ ๊ทธ๋ฃน ํ์ฉ
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func authMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
token := c.GetHeader("X-Api-Key")
if token != "secret" {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error":"unauthorized"})
return
}
c.Next()
}
}
func main() {
r := gin.New()
r.Use(gin.Logger(), gin.Recovery())
api := r.Group("/api")
{
v1 := api.Group("/v1")
v1.Use(authMiddleware())
v1.GET("/profile", func(c *gin.Context) {
c.JSON(200, gin.H{"name":"alice"})
})
}
r.Run(":8080")
}
- Group์ผ๋ก ๊ณตํต ๊ฒฝ๋ก·๋ฏธ๋ค์จ์ด๋ฅผ ๋ฌถ์ด ๊ด๋ฆฌ → ๋๊ท๋ชจ API ๊ตฌ์กฐํ์ ์ ๋ฆฌํฉ๋๋ค. (GitHub)
4. Graceful shutdown ์์
package main
import (
"context"
"log"
"net/http"
"os"
"os/signal"
"time"
"github.com/gin-gonic/gin"
)
func main() {
gin.SetMode(gin.ReleaseMode) // ์ด์ ์ ๊ถ์ฅ
r := gin.New()
r.Use(gin.Logger(), gin.Recovery())
r.GET("/ping", func(c *gin.Context){ c.String(200, "pong") })
srv := &http.Server{
Addr: ":8080",
Handler: r,
}
go func() {
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen: %s\n", err)
}
}()
// ์๊ทธ๋ ๋๊ธฐ (Ctrl+C, SIGTERM)
quit := make(chan os.Signal, 1)
signal.Notify(quit, os.Interrupt)
<-quit
log.Println("Shutdown Server ...")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
log.Fatal("Server Shutdown:", err)
}
log.Println("Server exiting")
}
- http.Server.Shutdown() ํจํด์ผ๋ก ๊ธฐ์กด ์์ฒญ์ ๋ง์น ๋ค ์ข ๋ฃ. ๋ค๋ง WebSocket ๋ฑ ํ์ด์ฌํน๋ ์ฐ๊ฒฐ์ ๋ณ๋ ์ ๋ฆฌ ๋ก์ง ํ์. (Gin Web Framework)
5) ์ด์ ํ / ๊ด๋ จ ๊ฐ๋
- ๋ฆด๋ฆฌ์ค ๋ชจ๋: ์ด์์์ ๋ก๊ทธ ์ก์์ ์ ๊ฑฐํ๋ ค๋ฉด gin.SetMode(gin.ReleaseMode) ์ฌ์ฉ. (Go Packages)
- ํ๋กํ์ผ๋ง: net/http/pprof๋ก CPU/๋ฉ๋ชจ๋ฆฌ ๋ถ์ — ๋ณ๋ชฉ ์์ธ์ ๋จผ์ ์ฐพ๊ณ ์ต์ ํํ์ธ์.
- ๋ฏธ๋ค์จ์ด ๋น์ฉ ๊ด๋ฆฌ: ๋ฏธ๋ค์จ์ด๊ฐ ๋ง์์ง์๋ก per-request ์ค๋ฒํค๋ ์ฆ๊ฐ → ํ์ํ ๊ฒ๋ง ์ ์ฉํ๊ณ , ํซ์คํ์ ํ๋กํ์ผ๋ง ํ ์ต์ ํ.
- ์ฑ๋ฅ ์ต์ ํ ์ ํ์ง: ์ ๋ ์ต๋ RPS/์ด์ ์ง์ฐ์ด ๋ชฉํ๋ผ๋ฉด fasthttp ๊ธฐ๋ฐ ํ๋ ์์ํฌ(Fiber ๋ฑ)๋ฅผ ๊ฒํ ํ๋, ์ํ๊ณ·๊ฐ๋ฐ ํธ์์ฑ๊ณผ trade-off๋ฅผ ๋ฐ์ ธ ๊ฒฐ์ ํ์ธ์. (Medium)
- ์ปจํ ์ด๋·K8s ๋ฐฐํฌ: readiness/liveness probe, SIGTERM ์ฒ๋ฆฌ(Graceful shutdown) ํ์. (Medium)
6) ๊ฒฐ๋ก
- ๋น ๋ฅด๊ฒ API๋ฅผ ๊ฐ๋ฐํ๊ณ ์ด์๊น์ง ๊ณ ๋ คํ ์์ ์ฑ์ ์ํ๋ฉด Gin์ด ์ข์ ์ ํ์ ๋๋ค(๋ฐ์ธ๋ฉ·๋ฏธ๋ค์จ์ด·๋ฌธ์·์ปค๋ฎค๋ํฐ์ ์ฅ์ ). (GitHub)
- ๊ทน๋จ์ ์ฑ๋ฅ(๋ฒค์น๋งํฌ ์ฐ์)๊ฐ ์ต์ฐ์ ์ด๋ผ๋ฉด fasthttp ๊ณ์ด์ ๊ฒํ ํ๋, ์ค์ ์๋น์ค์์ IO/DB์ ๋ฌถ์ด๋ ๊ฒฝ์ฐ ์ฐจ์ด๋ ์์ต๋๋ค. (Medium)
'ํ๋ก๊ทธ๋๋ฐ ์ธ์ด > Go' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [Go] ์ฌ๋ผ์ด์ค(slice)์๋ ํฌ์ธํฐ๊ฐ ์๋ค (0) | 2025.10.14 |
|---|---|
| [Go] ๊ณ ๋ฃจํด(Goroutine) (0) | 2025.10.13 |
| [Go] ํจ์ ๊ณ ๊ธ(๊ฐ๋ณ ์ธ์, defer, ๋๋คํจ์, ํจ์ํ์ ๋ณ์) (0) | 2025.09.19 |
| [Go] Mordern Go ๊ธฐ๋ณธ2(ํจ์, ์ธํฐํ์ด์ค, ๋ฉ์๋, ์๋ฌ) (2) | 2025.05.21 |
| [Go] Modern Go ๊ธฐ๋ณธ (0) | 2025.05.21 |
๋๊ธ