Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.

Go 언어의 웹 프레임워크 Gin 사용하기

1월부터 하는 Kubernetes에서 실제로 서비스를 구축하기 위해 간단한 마이크로 서비스를 만들어 보고 있다. 주로 Node.js로 하는 게 편하지만 다른 언어도 배워보고 싶어서 Golang을 선택했다. 아주 간단한 API 서버라서 웹 프레임워크가 필요했는데 Go 언어에 대해 아는 게 없어서 좀 찾아봤다.

Top 6 web frameworks for Go as of 2017같은 글을 참고했는데 본격적으로 사용해 보지 않으면 감이 잘 안와서 선택이 쉽지는 않았다. 웹 MVC 프레임워크로는 beegoBuffalo가 있었지만 주로 마이크로 웹 프레임워크를 더 선호하는 편이라서 Gin이나 echo, Iris에 관심이 갔다.

Go My Way #1 - 웹 프레임워크를 보다 보니 일부러 프로젝트가 활발한 것처럼 보이려고 속이던 행동이 발견된 Iris는 일찌감치 제외하고 Gin와 echo 중에서 고민하다가 크게 차이는 없는 것 같아서(특히 지금 내 용도에서는...) 좀 더 스타가 많은 Gin을 선택했다.

Gin

저장소의 README에 나온 내용대로 main.go 파일을 생성한다.

// main.go
package main

import "github.com/gin-gonic/gin"

func main() {
  r := gin.Default()
  r.GET("/ping", func(c *gin.Context) {
    c.JSON(200, gin.H{
      "message": "pong",
    })
  })
  r.Run() // listen and serve on 0.0.0.0:8080
}

Go 언어에서 dep으로 의존성 관리를 하고 있어서 dep을 초기화한다.

$ dep init

초기화 후 만들어진 Gopkg.toml 파일에 gin을 사용하기 위해 다음 내용을 추가한다.

[[constraint]]
  name = "github.com/gin-gonic/gin"
  branch = "master"

이제 추가한 의존성을 설치한다.

$ dep ensure

의존성 설치도 완료되었으면 Hello World 식 예제 애플리케이션을 실행할 수 있다.

$ go run main.go
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env: export GIN_MODE=release
 - using code:  gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /ping                     --> main.main.func1 (3 handlers)
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on :8080

Gin 서버가 http://localhost:8080에 떴으므로 이 서버에 요청을 보내면 정상적으로 뜬 것을 확인할 수 있다.

$ curl -i http://localhost:8080/ping
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Sun, 29 Apr 2018 16:45:36 GMT
Content-Length: 18

{"message":"pong"}

실제 웹 애플리케이션을 작성하려면 데이터베이스 라이브러리도 필요하고 프로젝트 폴더 구조도 만들어야 하지만 이 글에서는 Gin에 대한 설정만 얘기하고 있으므로 간단히 Gin의 라우팅만 살펴보자.

// main.go
package main

import (
  "net/http"

  "github.com/gin-gonic/gin"
)

func main() {
  r := gin.Default()

  v1 := r.Group("/v1")
  {
    v1.GET("/health", health)
    v1.POST("/signup", signup)
    v1.POST("/login", login)
  }
  r.Run()
}

func health(c *gin.Context) {
  c.JSON(http.StatusOK, gin.H{
    "message": "ok",
  })
}

func signup(c *gin.Context) {
  c.JSON(http.StatusCreated, gin.H{
    "message": "signed up",
  })
}

func login(c *gin.Context) {
  c.JSON(http.StatusOK, gin.H{
    "message": "logged in",
  })
}

보통 API 서버는 URL에 접두사가 붙으므로 r.Group("/v1")을 사용하면 반복해서 사용하지 않아도 된다. 위 설정은 http://localhost:3000/v1/health로 요청을 받게 된다. 상태 코드를 숫자로 적어도 되지만 net/http에서 상수를 가져와서 HTTP 상태 코드로 사용할 수 있다.

$ PORT=3000 go run main.go
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env: export GIN_MODE=release
 - using code:  gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /v1/health                --> main.health (3 handlers)
[GIN-debug] POST   /v1/signup                --> main.signup (3 handlers)
[GIN-debug] POST   /v1/login                 --> main.login (3 handlers)
[GIN-debug] Environment variable PORT="3000"
[GIN-debug] Listening and serving HTTP on :3000

그리고 gin은 기본 포트로 8080을 사용하지만 PORT 환경변수를 지정하면 해당 포트로 서버를 실행하게 된다.

2018/04/30 02:53 2018/04/30 02:53

[Book] 에어비앤비 스토리

에어비앤비 스토리

에어비앤비 스토리 - 8점
레이 갤러거 지음
유정식 옮김
다산북스


제목대로 Airbnb가 창업하고 성장한 과정에 관한 책이다. Airbnb를 무척 좋아하지만(서비스와 회사 둘 다) 성장 과정은 단편적으로만 알고 전체적으로 알지는 못해서 읽게 되었다. Airbnb가 창업된 지 9년이 되었고 엄청나게 성장하고 있지만, 공동창업자인 체스키(Brian Chesky), 게비아(Joe Gebbia), 블레차르지크(Nathan Blecharczyk) 세 명이 계속 운영하는 부분도 인상적인 부분이다.

무엇보다도 홈어웨이homeaway, VRBO, 카우치서핑couchsurfing, 베드앤블랙퍼스트bedandbreakfast 등 이미 집이나 공간을 대여하는 온라인 서비스 기업들의 이름도 줄줄이 꿰고 있었다. 그래서 나는 이 신출내기 회사가 대체 무엇을 차별화할 수 있을지 강한 의문이 들었다. 진부하고 독창적이지 않은 아이디어로 뭘 어쩌겠냐는 거냐며 동료들에게 투덜거리기까지 했다.

"웹사이트만 깔끔하고 번드르르하게 디자인한 다음에 마치 새로운 것인 양 시장에 내놓겠다고?"

당연히 처음에는 세 창업자가 어떻게 만나고 아이디어를 구현하려고 얼마나 고생했는지 얘기가 나온다. 하마터면 세 창업자의 조합이 깨지거나 아이디어를 포기할 뻔한 순간까지 어쩌면 뻔할 수도 있는 창업 이야기지만 관심 있는 회사라 그런지 재미있게 읽었다.

이미 비슷한 공간 임대 사이트가 그토록 많은데 왜 유독 에어비앤비만 ‘떴냐’는 것이다. 어떻게 에어비앤비는 단기 임대를 대중화하는 데 성공했을까? 반면 왜 다른 회사들은 성공하지 못했을까?

가장 큰 차이는 ‘제품’ 그 자체에 있다.

기본적으로 창업에 대한 어떤 통찰력을 준다기보다는 Airbnb의 역사를 설명하고 있지만, 성공으로 이끌고 위기를 이겨나가는 부분에서 인상적인 부분은 꽤 있었다. 이런 책이 어느 정도는 긍정적인 견해로 쓰게 마련이기는 하지만 CEO인 체스키는 돈을 벌기 위해서라기보다 Airbnb라는 서비스에 사명에 가깝게 집중하고 있다는 생각이 들었다. 물론 성공한 뒤에 정리하면 대부분의 스타트업이 그렇기는 하지만 결과적으로 Airbnb는 성공과 팬에 가까운 사용자 둘 다 가졌고 성장하면서 법적 이슈나 사고 등 위기에 처했을 때 대처하는 부분을 보면 단순히 회사를 살리기 위한 선택을 하지 않으려고 노력했다는 느낌이 들어서 인상적이었다.

에어비앤비의 이사회 멤버 제프 조던Jeff Jordan은 “성공하면 거의 항상 합법성 문제가 떠오릅니다”라고 말했다

초기의 창업단계를 지나서 안정적인 상태가 되고 나서는 성장 과정에 대해서 나오는데 이때는 호텔 산업과의 관계, Airbnb와 비슷한 공간 대여 산업, Airbnb로 파생된 산업에 대해서 나오는데 이런 관계는 잘 모르는 부분이라서 재미가 있었다. 2012년부터 여행 갈 때마다 Airbnb를 주로 이용했기 때문에 Airbnb가 성장하면서 서비스의 방향이 발전하는 이야기도 내 경험과 연결되어서 더 재미있게 읽었다.

체스키와 게비아, 블레차르지크는 아직까지 사이좋게 지내고 있으며, 9년이 지난 지금도 자신들이 띄워 올린 로켓을 직접 조종하고 있다. 지난 몇 년 동안 그들의 역할은 각자가 가진 강점에 적합하도록 진화를 거듭했다.

“문화를 망치는 것은 제품을 생산하는 기계를 망가뜨리는 것이다”라고 선언했다. 또 조직 문화가 강할수록 직원들이 ‘나는 세상에 이로운 일을 수행하고 있다’는 믿음을 갖게 되어, 공식적인 규칙과 프로세스 없이도 알아서 잘 움직이게 된다고 말했다. 실제로 프로세스가 줄어들고 관리 감독이 용이해지면 혁신을 위한 더 나은 조건이 형성된다.

뒷부분에는 세 창업자에 관한 얘기가 나온다. 보통은 회사가 성장하면서 일부 창업자가 교체되는 데 반해 엄청난 성장과 함께 세 창업자도 각자의 역할을 하고 있다는 부분이 인상적이다. 세 창업자는 각기 다른 역할로 균형을 잘 맞추고 있고 자신의 위치에서 그 역할을 하기 위해서 노력을 많이 해왔다는 걸 알 수 있고 창업자들이 회사와 직원에 대해 어떤 생각을 하고 있는지 다양한 관점으로 볼 수 있어서 재미있었다.

마지막으로 스티브 잡스가 한 말인 "세상을 바꿀 수 있다고 생각할 정도로 미친 사람만이 세상을 바꿀 수 있다"와 같은 의미이지만 이 책에 나온 다음 말이 나한테는 더 와닿았다.

“이성적인 사람은 자신을 환경에 적응시킨다. 비이성적인 사람은 환경을 자신에게 적응시킨다. 그러므로 모든 진보는 비이성적인 사람들에게 달려 있다.”

“비관론자들은 대개 옳다. 그러나 세상을 바꾸는 자는 낙관론자들이다.”

2018/04/28 23:10 2018/04/28 23:10