공개적으로 최소한의 Go 프레임워크 구축 (v0.1.3)

발행: (2026년 1월 20일 오후 02:58 GMT+9)
6 min read
원문: Dev.to

Source: Dev.to

위에 제공된 텍스트가 없습니다. 번역을 원하는 전체 내용을 알려주시면 한국어로 번역해 드리겠습니다.

소개

대부분의 Go 웹 프레임워크는 수십 개의 의존성을 끌어옵니다—Gin은 직접 의존성이 9개, Echo는 11개, Fiber는 15개—그래서 go.mod 파일이 금방 전화번호부처럼 보이게 됩니다. Marten은 다른 접근 방식을 취합니다: Go가 제공하는 것만 사용합니다(예: net/http, encoding/json). 외부 패키지가 없으며, 벤더 종속성도 없습니다.

전체 API 예제

package main

import (
    "github.com/gomarten/marten"
    "github.com/gomarten/marten/middleware"
)

func main() {
    app := marten.New()

    app.Use(middleware.Logger)
    app.Use(middleware.Recover)

    app.GET("/", func(c *marten.Ctx) error {
        return c.OK(marten.M{"message": "Hello, World!"})
    })

    app.GET("/users/:id", func(c *marten.Ctx) error {
        id := c.ParamInt("id")
        return c.OK(marten.M{"id": id})
    })

    app.Run(":8080")
}

라우터

Marten은 효율적인 경로 매칭을 위해 radix‑tree 라우터를 사용합니다. 다음을 지원합니다:

  • 경로 매개변수 (:id)
  • 와일드카드 (*filepath)
  • 라우트 그룹
api := app.Group("/api/v1")
api.GET("/users", listUsers)
api.GET("/users/:id", getUser)
api.POST("/users", createUser)

미들웨어

Marten에서 미들웨어는 핸들러를 감싸는 함수에 불과합니다:

func Timer(next marten.Handler) marten.Handler {
    return func(c *marten.Ctx) error {
        start := time.Now()
        err := next(c)
        log.Printf("took %v", time.Since(start))
        return err
    }
}

내장 미들웨어

Marten은 14개의 내장 미들웨어 컴포넌트를 제공합니다:

  • Logger
  • Recover
  • CORS
  • RateLimit
  • BasicAuth
  • Timeout
  • Secure
  • BodyLimit
  • Compress
  • ETag
  • RequestID
  • Static
  • NoCache

Context (Ctx) 사용

각 요청은 sync.Pool에서 Ctx 객체를 가져와 할당을 줄이고 메모리 사용량을 낮게 유지합니다:

func handler(c *marten.Ctx) error {
    // Path parameters
    id := c.Param("id")

    // Query parameters
    page := c.QueryInt("page")

    // JSON binding
    var user User
    c.Bind(&user)

    // Response helpers
    return c.OK(user)
}

정적 파일 제공 (v0.1.3)

최신 릴리스에서는 전체 기능 세트를 갖춘 정적 파일 제공을 추가했습니다:

app.Use(middleware.StaticWithConfig(middleware.StaticConfig{
    Root:   "./public",
    Prefix: "/static",
    MaxAge: 3600,
    Browse: false,
}))

기능에는 콘텐츠‑type 감지, HTTP 캐싱(If-Modified-Since), 디렉터리 탐색, 그리고 디렉터리‑트래버설 공격 방지가 포함됩니다.

성능 벤치마크

Gin, Echo, Chi와 비교한 벤치마크에서 Marten은 견고한 성능을 보여줍니다:

벤치마크MartenGinEchoChi
정적 라우트1464 ns/op1336 ns/op1436 ns/op2202 ns/op
파라미터 라우트1564 ns/op1418 ns/op1472 ns/op2559 ns/op
JSON 응답1755 ns/op2050 ns/op1835 ns/op1868 ns/op

가장 빠른 것은 아니지만 경쟁력 있으며, 의존성이 전혀 없습니다.

프로덕션‑레디 API 구축

app := marten.New()

app.Use(
    middleware.RequestID,
    middleware.Logger,
    middleware.Recover,
    middleware.CORS(middleware.DefaultCORSConfig()),
    middleware.RateLimit(middleware.RateLimitConfig{
        Max:    100,
        Window: time.Minute,
    }),
)

api := app.Group("/api/v1")
api.GET("/users", listUsers)
api.POST("/users", createUser, authMiddleware)

SPA 폴백

// API routes
app.GET("/api/users", listUsers)

// Serve static files
app.Use(middleware.Static("./dist"))

// SPA fallback
app.NotFound(func(c *marten.Ctx) error {
    if strings.HasPrefix(c.Path(), "/api/") {
        return c.NotFound("endpoint not found")
    }
    // Serve index.html for client‑side routing
    return c.HTML(200, indexHTML)
})

테스트

Marten v0.1.3은 325개의 테스트와 함께 제공되며, 다음을 포함합니다:

  • 각 구성 요소에 대한 단위 테스트
  • 실제 워크플로우에 대한 통합 테스트
  • 1,000개 이상의 동시 요청을 포함한 스트레스 테스트
  • 경계 사례 및 오류 조건

모든 테스트는 Go의 레이스 탐지기로 통과했으며, 알려진 메모리 누수는 없습니다.

Marten이 제공하지 않는 것

  • ORM 통합database/sql를 직접 사용
  • 템플릿 엔진 – 표준 라이브러리의 html/template 사용
  • 검증 라이브러리 – 직접 작성하거나 서드파티 패키지를 가져와 사용
  • WebSocket 지원 – 향후 릴리스에서 계획 중

철학

표준 라이브러리로 할 수 있다면, 표준 라이브러리를 사용하세요. 더 필요하면 직접 추가하세요—여전히 무의존성 제약을 유지하면서.

향후 릴리스

  • WebSocket 미들웨어
  • 템플릿 렌더링 헬퍼
  • 세션 관리 미들웨어
  • 향상된 정적 파일 제공 옵션

모두 동일한 무의존성 철학을 유지합니다.

설치

go get github.com/gomarten/marten@v0.1.3

CRUD API, JWT 인증, 파일 서버 등 다양한 예제를 확인해 보세요.

결론

Marten은 Gin이나 Echo를 대체하려는 것이 아니라, 최소주의에 대한 실험입니다—전 세계를 끌어들이지 않고도 강력한 웹 프레임워크를 구축할 수 있다는 증명입니다. 때때로, 적은 것이 더 많습니다.

링크

  • GitHub:
  • 문서:
  • 토론:
Back to Blog

관련 글

더 보기 »

Go의 비밀스러운 삶: Context 패키지

런어웨이 goroutine을 멈추고 메모리 누수를 방지하는 방법. 16장: 언제 그만둘지 알기. 아카이브는 조용했으며, 서버 랙의 윙윙거리는 소리만이 코…