Skip to content

Latest commit

ย 

History

History
359 lines (286 loc) ยท 15 KB

File metadata and controls

359 lines (286 loc) ยท 15 KB

Martini wercker statusGoDoc

๋งˆํ‹ฐ๋‹ˆ(Martini)๋Š” ๊ฐ•๋ ฅํ•˜๊ณ  ์†์‰ฌ์šด ์›น์• ํ”Œ๋ฆฌ์บ์ด์…˜ / ์›น์„œ๋น„์Šค๊ฐœ๋ฐœ์„ ์œ„ํ•œ Golang ํŒจํ‚ค์ง€์ž…๋‹ˆ๋‹ค.

์‹œ์ž‘ํ•˜๊ธฐ

Go ์ธ์Šคํ†จ ๋ฐ GOPATH ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์„ค์ • ์ดํ›„์—, .go ํŒŒ์ผ ํ•˜๋‚˜๋ฅผ ๋งŒ๋“ค์–ด ๋ณด์ฃ ..ํ ... ์ผ๋‹จ server.go๋ผ๊ณ  ๋ถ€๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

package main

import "github.com/go-martini/martini"

func main() {
  m := martini.Classic()
  m.Get("/", func() string {
    return "Hello, ์„ธ๊ณ„!"
  })
  m.Run()
}

๋งˆํ‹ฐ๋‹ˆ ํŒจํ‚ค์ง€๋ฅผ ์ธ์Šคํ†จ ํ•ฉ๋‹ˆ๋‹ค. (go 1.1 ํ˜น์€ ๊ทธ ์ด์ƒ ๋ฒ„์ ผ ํ•„์š”):

go get github.com/go-martini/martini

์ด์ œ ์„œ๋ฒ„๋ฅผ ๋Œ๋ ค ๋ด…์‹œ๋‹ค:

go run server.go

๋งˆํ‹ฐ๋‹ˆ ์›น์„œ๋ฒ„๊ฐ€ localhost:3000์—์„œ ๋Œ์•„๊ฐ€๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•˜์‹ค ์ˆ˜ ์žˆ์„ ๊ฒ๋‹ˆ๋‹ค.

๋„์›€์ด ํ•„์š”ํ•˜๋‹ค๋ฉด?

๋ฉ”์ผ๋ง ๋ฆฌ์ŠคํŠธ์— ๊ฐ€์ž…ํ•ด ์ฃผ์„ธ์š”

๋ฐ๋ชจ ๋น„๋””์˜ค๋„ ์žˆ์–ด์š”.

ํ˜น์€ Stackoverflow์— ๋งˆํ‹ฐ๋‹ˆ ํƒœํฌ๋ฅผ ์ด์šฉํ•ด์„œ ๋ฌผ์–ด๋ด ์ฃผ์„ธ์š”

GoDoc ๋ฌธ์„œ(documentation)

๋ฌธ์ œ๋Š” ์ „๋ถ€๋‹ค ์˜์–ด๋กœ ๋˜์–ด ์žˆ๋‹ค๋Š” ๊ฑด๋ฐ์š” -_-;;; ๋‚˜๋Š” ํ•œ๊ธ€ ์•„๋‹ˆ๋ฉด ๋ณด๊ธฐ๋‹ค ์‹ซ์–ด! ์ด๋Ÿฐ ๋ถ„๋“ค์€ ์•„๋ž˜ ๋งํฌ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”

  • golang-korea
  • ํ˜น์€ (RexK)์˜ ์ด๋ฉ”์ผ๋กœ ์—ฐ๋ฝ์ฃผ์„ธ์š”.

์ฃผ์š”๊ธฐ๋Šฅ

  • ์‚ฌ์šฉํ•˜๊ธฐ ์—„์ฒญ ์‰ฝ์Šต๋‹ˆ๋‹ค.
  • ๋น„๊ฐ„์„ญ(Non-intrusive) ๋””์ž์ธ
  • ๋‹ค๋ฅธ Golang ํŒจํ‚ค์ง€๋“ค๊ณผ ์ž˜ ์–ด์šธ๋ฆฝ๋‹ˆ๋‹ค.
  • ๋๋‚ด์ฃผ๋Š” ๊ฒฝ๋กœ ๋งค์นญ๊ณผ ๋ผ์šฐํŒ….
  • ๋ชจ๋“ˆ ํ˜• ๋””์ž์ธ - ๊ธฐ๋Šฅ์ถ”๊ฐ€ ์‰ฝ๊ณ , ์ฝ”๋“œ ๊บผ๋‚ด์˜ค๊ธฐ๋„ ์‰ฌ์›€.
  • ์“ธ๋ชจ์žˆ๋Š” ํ•ธ๋“ค๋Ÿฌ์™€ ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ๋งŽ์Œ.
  • ํ›Œ๋ฅ ํ•œ ํŒจํ‚ค์ง€ํ™”(out of the box) ๊ธฐ๋Šฅ๋“ค
  • http.HandlerFunc ์ธํ„ฐํŽ˜์ด์Šค์™€ ํ˜ธํ™˜์œจ 100%

๋ฏธ๋“ค์›จ์–ด(Middleware)

๋ฏธ๋“ค์›จ์–ด๋“ค๊ณผ ์ถ”๊ฐ€๊ธฐ๋Šฅ๋“ค์€ martini-contrib์—์„œ ํ™•์ธํ•ด ์ฃผ์„ธ์š”.

๋ชฉ์ฐจ

Classic Martini

๋งˆํ‹ฐ๋‹ˆ๋ฅผ ์‰ฝ๊ณ  ๋น ๋ฅด๊ฒŒ ์ด์šฉํ•˜์‹œ๋ ค๋ฉด, martini.Classic()๋ฅผ ์ด์šฉํ•ด ๋ณด์„ธ์š”. ๋ณดํ†ต ์›น์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์„ค์ •๋“ค์ด ์ด๋ฏธ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

  m := martini.Classic()
  // ... ๋ฏธ๋“ค์›จ์–ด์™€ ๋ผ์šฐํŒ… ์„ค์ •์€ ์ด๊ณณ์— ์˜ค๋ฉด ์ž‘์„ฑํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
  m.Run()

์•„๋ž˜๋Š” martini.Classic()์˜ ์ž๋™์œผ๋กœ ์žฅ์ฐฉํ•˜๋Š” ๊ธฐ๋ณธ ๊ธฐ๋Šฅ๋“ค์ž…๋‹ˆ๋‹ค.

ํ•ธ๋“ค๋Ÿฌ(Handlers)

ํ•ธ๋“ค๋Ÿฌ(Handlers)๋Š” ๋งˆํ‹ฐ๋‹ˆ์˜ ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค. ํ•ธ๋“ค๋Ÿฌ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“ ํ˜•ํƒœ์˜ ํ•จ์ˆ˜๋“ค์ž…๋‹ˆ๋‹ค.

m.Get("/", func() {
  println("hello ์„ธ๊ณ„")
})

๋ฐ˜ํ™˜ ๊ฐ’ (Return Values)

ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๋ฐ˜ํ™˜์„ ํ•˜๋Š” ํ•จ์ˆ˜๋ผ๋ฉด, ๋งˆํ‹ฐ๋‹ˆ๋Š” ๋ฐ˜ํ™˜ ๊ฐ’์„ http.ResponseWriter์— ์ŠคํŠธ๋ง์œผ๋กœ ์ž…๋ ฅ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

m.Get("/", func() string {
  return "hello ์„ธ๊ณ„" // HTTP 200 : "hello ์„ธ๊ณ„"
})

์›ํ•˜์‹ ๋‹ค๋ฉด, ์„ ํƒ์ ์œผ๋กœ ์ƒํƒœ์ฝ”๋“œ๋„ ํ•จ๊ป˜ ๋ฐ˜ํ™” ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

m.Get("/", func() (int, string) {
  return 418, "๋‚œ ์ฃผ์ „์ž์•ผ!" // HTTP 418 : "๋‚œ ์ฃผ์ „์ž์•ผ!"
})

์„œ๋น„์Šค ์ฃผ์ž…(Service Injection)

ํ•ธ๋“ค๋Ÿฌ๋“ค์€ ๋ฆฌํ”Œ๋ ‰์…˜์„ ํ†ตํ•ด ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ๋งˆํ‹ฐ๋‹ˆ๋Š” ์˜์กด์„ฑ ์ฃผ์ž…์„ ์ด์šฉํ•ด์„œ ํ•ธ๋“ค๋Ÿฌ์˜ ์ธ์ˆ˜๋“ค์„ ์ฃผ์ž…ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๋งˆํ‹ฐ๋‹ˆ๋ฅผ http.HandlerFunc ์ธํ„ฐํŽ˜์ด์Šค์™€ 100% ํ˜ธํ™˜ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.

ํ•ธ๋“ค๋Ÿฌ์˜ ์ธ์ˆ˜๋ฅผ ์ž…๋ ฅํ–ˆ๋‹ค๋ฉด, ๋งˆํ‹ฐ๋‹ˆ๊ฐ€ ์„œ๋น„์Šค ๋ชฉ๋ก๋“ค์„ ์‚ดํŽด๋ณธ ํ›„ ํƒ€์ž…ํ™•์ธ(type assertion)์„ ํ†ตํ•ด ์˜์กด์„ฑ์„ ํ•ด๊ฒฐ์„ ์‹œ๋„ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

m.Get("/", func(res http.ResponseWriter, req *http.Request) { // res์™€ req๋Š” ๋งˆํ‹ฐ๋‹ˆ์— ์˜ํ•ด ์ฃผ์ž…๋˜์—ˆ๋‹ค.
  res.WriteHeader(200) // HTTP 200
})

์•„๋ž˜ ์„œ๋น„์Šค๋“ค์€ martini.Classic():์— ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • *log.Logger - ๋งˆํ‹ฐ๋‹ˆ์˜ ๊ธ€๋Ÿฌ๋ฒŒ(์ „์—ญ) ๋กœ๊ทธ.
  • martini.Context - http ์š”์ฒญ ์ปจํ…์ŠคํŠธ.
  • martini.Params - ๋ฃจํŠธ ๋งค์นญ์œผ๋กœ ์ฐพ์€ ์ธ์ž๋ฅผ map[string]string์œผ๋กœ ๋ณ€ํ˜•.
  • martini.Routes - ๋ฃจํŠธ ๋„์šฐ๋ฏธ ์„œ๋ฏธ์Šค.
  • http.ResponseWriter - http Response writer ์ธํ„ฐํŽ˜์ด์Šค.
  • *http.Request - http ๋ฆฌํ€˜์ŠคํŠธ.

๋ผ์šฐํŒ…(Routing)

๋งˆํ‹ฐ๋‹ˆ์—์„œ ๋ฃจํŠธ๋Š” HTTP ๋ฉ”์†Œ๋“œ์™€ URL๋งค์นญ ํŒจํ„ด์˜ ํŽ˜์–ด์ž…๋‹ˆ๋‹ค. ๊ฐ ๋ฃจํŠธ๋Š” ํ•˜๋‚˜ ํ˜น์€ ๊ทธ ์ด์ƒ์˜ ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์†Œ๋“œ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

m.Get("/", func() {
  // ๋ณด์—ฌ์ค˜ ๋ด
})

m.Patch("/", func() {
  // ์—…๋ฐ์ดํŠธ ์ข€ ํ•ด
})

m.Post("/", func() {
  // ๋งŒ๋“ค์–ด๋ด
})

m.Put("/", func() {
  // ๊ตํ™˜ํ•ด๋ด
})

m.Delete("/", func() {
  // ์—†์• ๋ฒ„๋ ค!
})

m.Options("/", func() {
  // http ์˜ต์…˜ ๋ฉ”์†Œ๋“œ
})

m.NotFound(func() {
  // 404 ํ•ด๊ฒฐํ•˜๊ธฐ
})

๋ฃจํŠธ๋“ค์€ ์ •์˜๋œ ์ˆœ์„œ๋Œ€๋กœ ๋งค์นญ๋œ๋‹ค. ๋“ค์–ด์˜จ ์š”๊ทธ์— ์ฒซ๋ฒˆ์งธ ๋งค์นญ๋œ ๋ฃจํŠธ๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.

๋ฃจํŠธ ํŒจํ„ด์€ martini.Params service๋กœ ์•ก์„ธ์Šค ๊ฐ€๋Šฅํ•œ ์ธ์ž๋“ค์„ ํฌํ•จํ•˜๊ธฐ๋„ ํ•œ๋‹ค:

m.Get("/hello/:name", func(params martini.Params) string {
  return "Hello " + params["name"]			// :name์„ Params์ธ์ž์—์„œ ์ถ”์ถœ
})

๋ฃจํŠธ๋Š” ๋ณ„ํ‘œ์‹(*)์œผ๋กœ ๋งค์นญ ๋  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค:

m.Get("/hello/**", func(params martini.Params) string {
  return "Hello " + params["_1"]
})

Regular expressions can be used as well: ์ •๊ทœ์‹๋„ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค:

m.Get("/hello/(?P<name>[a-zA-Z]+)", func(params martini.Params) string {
  return fmt.Sprintf ("Hello %s", params["name"])
})

์ •๊ทœ์‹์— ๊ด€ํ•˜์—ฌ ๋” ์ž์„ธํžˆ ์•Œ๊ณ  ์‹ถ๋‹ค๋ฉด Go documentation์„ ์ฐธ์กฐํ•ด ์ฃผ์„ธ์š”.

๋ฃจํŠธ ํ•ธ๋“ค๋Ÿฌ๋Š” ์Šคํƒ์„ ์Œ“์•„ ์˜ฌ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ ์œ ์ € ์ธ์ฆ์ž‘์—…์ด๋‚˜, ํ—ˆ๊ฐ€์ž‘์—…์— ์œ ์šฉํžˆ ์“ฐ์ผ ์ˆ˜ ์žˆ์ฃ .

m.Get("/secret", authorize, func() {
  // ์ด ํ•จ์ˆ˜๋Š” authorize ํ•จ์ˆ˜๊ฐ€ resopnse์— ๊ฒฐ๊ณผ๋ฅผ ์“ฐ์ง€ ์•Š๋Š”์ด์ƒ ์‹คํ–‰ ๋  ๊ฑฐ์—์š”.
})

๋ฃจํŠธ๊ทธ๋ฃน์€ ๋ฃจํŠธ๋“ค์„ ํ•œ ๊ณณ์— ๋ชจ์•„ ์ •๋ฆฌํ•˜๋Š”๋ฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

m.Group("/books", func(r martini.Router) {
    r.Get("/:id", GetBooks)
    r.Post("/new", NewBook)
    r.Put("/update/:id", UpdateBook)
    r.Delete("/delete/:id", DeleteBook)
})

ํ•ธ๋“ค๋Ÿฌ์— ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์ง‘์–ด๋„ฃ์„ ์ˆ˜ ์žˆ์—ˆ๋“ฏ์ด, ๊ทธ๋ฃน์—๋„ ๋ฏธ๋“ค์›จ์–ด ์ง‘์–ด๋„ฃ๋Š”๊ฒŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

m.Group("/books", func(r martini.Router) {
    r.Get("/:id", GetBooks)
    r.Post("/new", NewBook)
    r.Put("/update/:id", UpdateBook)
    r.Delete("/delete/:id", DeleteBook)
}, MyMiddleware1, MyMiddleware2)

์„œ๋น„์Šค(Services)

์„œ๋น„์Šค๋Š” ํ•ธ๋“ค๋Ÿฌ์˜ ์ธ์ˆ˜๋ชฉ๋ก์— ์ฃผ์ž…๋ ์ˆ˜ ์žˆ๋Š” ์˜ค๋ธŒ์ ํŠธ๋“ค์„ ๋งํ•ฉ๋‹ˆ๋‹ค. ์„œ๋น„์Šค๋Š” ๊ธ€๋กœ๋ฒŒ ํ˜น์€ ๋ฆฌํ€˜์ŠคํŠธ ๋ ˆ๋ฒจ๋‹จ์œ„๋กœ ์ฃผ์ž…์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๊ธ€๋กœ๋ฒŒ ๋งตํ•‘(Global Mapping)

๋งˆํƒ€๋‹ˆ ์ธ์Šคํ„ด์Šค๋Š” ์„œ๋น„์Šค ๋งตํ•‘์„ ์‰ฝ๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด์„œ inject.Injector ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ฐ˜ํ˜•ํ•ฉ๋‹ˆ๋‹ค:

db := &MyDatabase{}
m := martini.Classic()
m.Map(db) // ์„œ๋น„์Šค๊ฐ€ ๋ชจ๋“  ํ•ธ๋“ค๋Ÿฌ์—์„œ *MyDatabase๋กœ์„œ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
// ...
m.Run()

๋ฆฌํ€˜์ŠคํŠธ ๋ ˆ๋ฒจ ๋งตํ•‘(Request-Level Mapping)

๋ฆฌํ€˜์ŠคํŠธ ๋ ˆ๋ฒจ ๋งตํ•‘์€ ํ•ธ๋“ค๋Ÿฌ์•ˆ์—์„œ martini.Context๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค:

func MyCustomLoggerHandler(c martini.Context, req *http.Request) {
  logger := &MyCustomLogger{req}
  c.Map(logger) // *MyCustomLogger๋กœ์„œ ๋งตํ•‘ ๋จ
}

์ธํ„ฐํŽ˜์ด์Šค๋กœ ๊ฐ’๋“ค ๋งตํ•‘(Mapping values to Interfaces)

์„œ๋น„์Šค์˜ ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์ค‘ ํ•˜๋‚˜๋Š” ์„œ๋น„์Šค๋ฅผ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋งตํ•‘์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ๋“ค์–ด, http.ResponseWriter๋ฅผ ์น˜ํ™˜(override)ํ•ด์„œ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ๋“ค์„ ์ˆ˜ํ–‰ํ•˜๊ฒŒ ํ•˜๊ณ  ์‹ถ์œผ์‹œ๋‹ค๋ฉด, ์•„๋ž˜์™€ ๊ฐ™์€ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ž‘์„ฑ ํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

func WrapResponseWriter(res http.ResponseWriter, c martini.Context) {
  rw := NewSpecialResponseWriter(res)
  c.MapTo(rw, (*http.ResponseWriter)(nil)) // ResponseWriter๋ฅผ NewResponseWriter๋กœ ์น˜ํ™˜(override)
}

์ •์ ํŒŒ์ผ ์„œ๋น™(Serving Static Files)

martini.Classic() ์ธ์Šคํ„ด์Šค๋Š” "public" ํด๋”์•ˆ์— ์žˆ๋Š” ํŒŒ์ผ๋“ค์€ ์ •์ ํŒŒ์ผ๋กœ์„œ ์ž๋™์œผ๋กœ ์„œ๋น™ํ•ฉ๋‹ˆ๋‹ค. ๋” ๋งŽ์€ ํด๋”๋“ค์€ ์ •์ ํŒŒ์ผ ํด๋”์— ํฌํ•จ์‹œํ‚ค์‹œ๋ ค๋ฉด martini.Static ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ด์šฉํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

m.Use(martini.Static("assets")) // "assets" ํด๋”์—์„œ๋„ ์ •์ ํŒŒ์ผ ์„œ๋น™.

๋ฏธ๋“ค์›จ์–ด ํ•ธ๋“ค๋Ÿฌ(Middleware Handlers)

๋ฏธ๋“ค์›จ์–ด ํ•ธ๋“ค๋Ÿฌ๋Š” http request์™€ ๋ผ์šฐํŒ… ์‚ฌ์ด์—์„œ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๋ฏธ๋“ค์›จ์–ด ํ•ธ๋“ค๋Ÿฌ๋Š” ๊ทผ๋ณธ์ ์œผ๋กœ ๋‹ค๋ฅธ ํ•ธ๋“ค๋Ÿฌ๋“ค๊ณผ๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ์‚ฌ์šฉ๋ฐฉ๋ฒ•์€ ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค:

m.Use(func() {
  // ๋ฏธ๋“ค์›จ์–ด ์ž„๋ฌด ์ˆ˜ํ–‰!
})

Handlers๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ฏธ๋“ค์›จ์–ด ์Šคํƒ๋“ค์˜ ์™„์ „ ์ปจํŠธ๋กค์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋งŒ, ์ด๋ ‡๊ฒŒ ์„ค์ •ํ•˜์‹œ๋ฉด ์ด์ „์— Handlers๋ฅผ ์ด์šฉํ•˜์—ฌ ์„ค์ •ํ•œ ํ•ธ๋“ค๋Ÿฌ๋“ค์€ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค:

m.Handlers(
  Middleware1,
  Middleware2,
  Middleware3,
)

๋ฏธ๋“ค์›จ์–ด ํ•ธ๋“ค๋Ÿฌ๋Š” ๋กœ๊น…(logging), ํ—ˆ๊ฐ€(authorization), ์ธ๊ฐ€(authentication), ์„ธ์…˜, ์••์ถ•(gzipping), ์—๋Ÿฌ ํŽ˜์ด์ง€ ๋“ฑ ๋“ฑ, http request์˜ ์ „ํ›„๋กœ ์‹คํ–‰๋˜์–ด์•ผ ํ•  ์ผ๋“ค์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์•„์ฃผ ์ข‹์Šต๋‹ˆ๋‹ค:

// API ํ‚ค ํ™•์ธ์ž‘์—…
m.Use(func(res http.ResponseWriter, req *http.Request) {
  if req.Header.Get("X-API-KEY") != "๋น„๋ฐ€์•”ํ˜ธ!!!" {
    res.WriteHeader(http.StatusUnauthorized)	// HTTP 401
  }
})

Next()

Context.Next()๋Š” ์„ ํƒ์  ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜๋Š” http request๊ฐ€ ๋‹ค ์ž‘๋™ ๋ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.๋”ฐ๋ผ์„œ http request ์ดํ›„์— ์‹คํ–‰ ๋˜์–ด์•ผ ํ•  ์—…๋ฌด๋“ค์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์ข‹์€ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

// log before and after a request
m.Use(func(c martini.Context, log *log.Logger){
  log.Println("request์ „์ž…๋‹ˆ๋‹ค.")

  c.Next()
  
  log.Println("requestํ›„ ์ž…๋‹ˆ๋‹ค.")
})

Martini Env

๋งˆํ‹ฐ๋‹ˆ ํ•ธ๋“ค๋Ÿฌ๋“ค์€ martini.Env ๊ธ€๋กœ๋ฒŒ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐœ๋ฐœํ™˜๊ฒฝ์—์„œ๋Š” ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ ์ž‘๋™ํ•˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, ํ”„๋กœ๋•์…˜ ์„œ๋ฒ„๋กœ ๋งˆํ‹ฐ๋‹ˆ ์„œ๋ณด๋ฅผ ๋ฐฐํฌํ•˜์‹œ๊ฒŒ ๋œ๋‹ค๋ฉด ๊ผญ ํ™˜๊ฒฝ๋ณ€์ˆ˜ MARTINI_ENV=production๋ฅผ ์„ธํŒ…ํ•ด์ฃผ์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

FAQ

๋ฏธ๋“ค์›จ์–ด๋“ค์„ ์–ด๋””์„œ ์ฐพ์•„์•ผ ํ•˜๋‚˜์š”?

๊นƒํ—™์—์„œ martini-contrib ํ”„๋กœ์ ํŠธ๋“ค์„ ํƒ–์•„๋ณด์„ธ์š”. ๋งŒ์•ฝ์— ๋ชป ์ฐพ์œผ์‹œ๊ฒ ์œผ๋ฉด, martini-contrib ํŒ€์›๋“ค์—๊ฒŒ ์—ฐ๋ฝํ•ด์„œ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด ๋‹ฌ๋ผ๊ณ  ํ•ด๋ณด์„ธ์š”.

  • [auth](https: //github.com/martini-contrib/auth) - ์ธ์ฆ์ž‘์—…์„ ๋„์™€์ฃผ๋Š” ํ•ธ๋“ค๋Ÿฌ.
  • binding - request๋ฅผ ๋งตํ•‘ํ•˜๊ณ  ๊ฒ€์‚ฌํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ.
  • gzip - gzip ํ•ธ๋“ค๋Ÿฌ.
  • render - HTML ํ…œํ”Œ๋ ˆ์ดํŠธ๋“ค๊ณผ JSON๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ํŽธํ•˜๊ฒŒ ํ•ด์ฃผ๋Š” ํ•ธ๋“ค๋Ÿฌ.
  • acceptlang - Accept-Language HTTP ํ•ด๋”๋ฅผ ํŒŒ์‹ฑํ• ๋•Œ ์œ ์šฉํ•œ ํ•ธ๋“ค๋Ÿฌ.
  • sessions - ์„ธ์…˜ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ.
  • strip - URL ํ”„๋ฆฌํ‹ฑ์Šค๋ฅผ ์—†์• ์ฃผ๋Š” ํ•ธ๋“ค๋Ÿฌ.
  • method - ํ•ด๋”๋‚˜ ํผํ•„๋“œ๋ฅผ ์ด์šฉํ•œ HTTP ๋ฉ”์†Œ๋“œ ์น˜ํ™˜.
  • secure - ๋ช‡๋ช‡ ๋ณด์•ˆ์„ค์ •์„ ์œ„ํ•œ ํ•ธ๋“ค๋Ÿฌ.
  • encoder - ๋ฐ์ดํ„ฐ ๋ Œ๋”๋ง๊ณผ ์ปจํ…ํŠธ ํƒ€์—ฝ์„์œ„ํ•œ ์ธ์ฝ”๋”ฉ ์„œ๋น„์Šค.
  • cors - CORS ์„œํฌํŠธ๋ฅผ ์œ„ํ•œ ํ•ธ๋“ค๋Ÿฌ.
  • oauth2 - OAuth2.0 ๋กœ๊ทธ์ธ ํ•ธ๋“ค๋Ÿฌ. ํŽ˜์ด์Šค๋ถ, ๊ตฌ๊ธ€, ๊นƒํ—™ ์ง€์›.

ํ˜„์žฌ ์ž‘๋™์ค‘์ธ ์„œ๋ฒ„์— ๋งˆํ‹ฐ๋‹ˆ๋ฅผ ์ ์šฉํ•˜๋ ค๋ฉด?

๋งˆํ‹ฐ๋‹ˆ ์ธ์Šคํ„ด์Šค๋Š” http.Handler ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ฐจ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ Go ์„œ๋ฒ„ ์„œ๋ธŒํŠธ๋ฆฌ๋กœ ์‰ฝ๊ฒŒ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜ ์ฝ”๋“œ๋Š” ๊ตฌ๊ธ€ ์•ฑ ์—”์ง„์—์„œ ์ž‘๋™ํ•˜๋Š” ๋งˆํ‹ฐ๋‹ˆ ์•ฑ์ž…๋‹ˆ๋‹ค:

package hello

import (
  "net/http"
  "github.com/go-martini/martini"
)

func init() {
  m := martini.Classic()
  m.Get("/", func() string {
    return "Hello ์„ธ๊ณ„!"
  })
  http.Handle("/", m)
}

ํฌํŠธ์™€ ํ˜ธ์ŠคํŠธ๋Š” ์–ด๋–ป๊ฒŒ ๋ฐ”๊พธ๋‚˜์š”?

๋งˆํ‹ฐ๋‹ˆ์˜ Run ํ•จ์ˆ˜๋Š” PORT์™€ HOST ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ์ด์šฉํ•˜๋Š”๋ฐ, ์„ค์ •์ด ์•ˆ๋˜์–ด ์žˆ๋‹ค๋ฉด localhost:3000์œผ๋กœ ์„ค์ • ๋˜์–ด ์ง‘๋‹ˆ๋‹ค. ์ข€๋” ์œ ์—ฐํ•˜๊ฒŒ ์„ค์ •์„ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, http.ListenAndServe๋ฅผ ํ™œ์šฉํ•ด ์ฃผ์„ธ์š”.

  m := martini.Classic()
  // ...
  log.Fatal(http.ListenAndServe(":8080", m))

๋ผ์ด๋ธŒ ํฌ๋“œ ๋ฆฌ๋กœ๋“œ?

gin and fresh ๋งˆํ‹ฐ๋‹ˆ ์•ฑ์˜ ๋ผ์ด๋ธŒ ๋ฆฌ๋กœ๋“œ๋ฅผ ๋„์™€์ค๋‹ˆ๋‹ค.

๊ณตํ—Œํ•˜๊ธฐ(Contributing)

๋งˆํ‹ฐ๋‹ˆ๋Š” ๊ฐ„๋‹จํ•˜๊ณ  ๊ฐ€๋ฒผ์šด ํŒจํ‚ค์ง€๋กœ ๋‚จ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ณดํ†ต ๋Œ€๋ถ€๋ถ„์˜ ๊ณตํ—Œ๋“ค์€ martini-contrib ๊ทธ๋ฃน์˜ ์ €์žฅ์†Œ๋กœ ๊ฐ€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๋งˆํ‹ฐ๋‹ˆ ์ฝ”์–ด์— ๊ธฐ์—ฌํ•˜๊ณ  ์‹ถ์œผ์‹œ๋‹ค๋ฉด ์ฃผ์ €์—†์ด Pull Request๋ฅผ ํ•ด์ฃผ์„ธ์š”.

About

express ์™€ sinatra์˜ ์˜ํ–ฅ์„ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค.

๋งˆํ‹ฐ๋‹ˆ๋Š” Code Gangsta๊ฐ€ ๋””์ž์ธ ํ–ˆ์Šต๋‹ˆ๋‹ค.