목차

Google App Engine(GAE)에서 go swagger server 실행하기

Intro

[지난번 포스트][last-post]에서 습득한 지식을 바탕으로 go-swagger를 이용해 작성한 서버를 Google App Engine(이하 GAE)에서 실행시켜보자.


spec을 이용해 서버코드 생성하기

[지난번 포스트][last-post]에서 작성한 swagger.yaml을 이용해 서버코드를 생성해보자. swagger.yaml 내용은 아래와 같다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
swagger: "2.0"
info:
  description: hello go swagger
  title: hello world application
  version: 1.0.0
produces:
  - application/json
consumes:
  - application/json
schemes:
  - http
paths:
  /:
    get:
      responses:
        200:
          description: list the todo operations
          schema:
            type: array
            description: "result : helloworld"
            items:
              $ref: "#/definitions/item"
definitions:
  item:
    type: object
    required:
      - result
    properties:
      result:
        type: string

swagger.yaml 파일을 생성했으면 이제 swagger generate 명령을 이용해 실제로 서버에서 구동될 코드를 생성해보자. [지난번 포스트][last-post]와 동일한 명령어지만 --flag-strategy pflag 옵션이 추가됐다. 코드 생성이 완료되었으면 지난번 포스트를 참고하여 /에 접근 시 hello world가 출력되도록 코드를 수정해놓자.

1
swagger generate server -A helloworld -f ./swagger.yml --flag-strategy pflag

swagger generate 명령어를 쓰기전엔 swagger validate 명령어를 이용해 swagger.yaml 파일의 유효성 검사를 진행하는게 보통이지만 이번 예제에선 생략하도록 한다.

flag-strategy pflag 옵션을 주는 이유

이 옵션을 생략하고 generate 명령어를 실행할 경우 생성된 서버코드에 github.com/jessevdk/go-flags에 의존성이 생긴다. 이 패키지에서는 GAE에서 사용할 수 없는 syscall 패키지를 사용하기 때문에 GAE 환경에서는 실행할 수 없다. 그래서 --flag-strategy pflag 옵션을 이용해 위의 패키지 대신 github.com/spf13/pflag를 대신 사용하도록 한다. 좀 더 자세한 내용은 공식 사이트의 문서를 참고하자.


main.go 코드 수정하기

본래 main.go 파일은 수정하지 않는게 원칙이다. 하지만 GAE라는 조금 특수한 상황에서 코드가 동작하게 하려면 수정이 불가피하다. 이 내용은 이 링크에서 얻은 정보를 바탕으로 작성하였다.

  1. 우선 main 함수의 이름을 init로 교체한다.
  2. net/http 패키지를 import 한다.
  3. server.ConfigureAPI() 구문 바로 다음줄에 http.Handle("/", server.GetHandler()) 을 입력한다.
  4. flag와 기타 다른 코드들을 삭제한다.
  5. 위 단계를 모두 수행한 코드의 결과는 아래와 같다.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// Code generated by go-swagger; DO NOT EDIT.

package main

import (
	"log"

	loads "github.com/go-openapi/loads"

	"net/http"
	"test/restapi"
	"test/restapi/operations"
)

// This file was generated by the swagger tool.
// Make sure not to overwrite this file after you generated it because all your edits would be lost!

func init() {

	swaggerSpec, err := loads.Analyzed(restapi.SwaggerJSON, "")
	if err != nil {
		log.Fatalln(err)
	}

	var server *restapi.Server // make sure init is called
	api := operations.NewHelloworldAPI(swaggerSpec)
	// get server with flag values filled out
	server = restapi.NewServer(api)
	defer server.Shutdown()
	server.ConfigureAPI()
	http.Handle("/", server.GetHandler())
}

여기까지 진행했다면 이제 GAE 환경에서 코드를 실행할 준비가 모두 완료된 것이다. 참고로 import된 restapi의 경로는 환경에 따라 달라질 수 있다.


로컬서버를 구동하여 테스트해보기

GAE에서는 개발자의 PC에서 먼저 테스트를 해볼 수 있도록 SDK를 배포하고 있다. 이 곳을 참고하여 우선 GAE 개발환경을 셋팅해보자.(생각보다 되게 간단하다)

환경셋팅이 끝났다면 main.go 파일과 같은 위치에 app.yaml을 생성하자. 내용은 이 파일과 동일하다.

마지막으로 로컬서버를 구동하기 전에 우리가 생성한 코드의 의존 패키지들을 내려받아야 한다. 명령창에서 아래의 명령어들을 실행한다. 참고로 dep를 이용할 시 로컬서버에서는 제대로 동작하지만 deploy가 제대로 되지 않는다. 2017-12-05 현재 원인은 파악하지 못했는데 파악되는대로 내용을 업데이트 하겠다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
go get -u github.com/go-openapi/loads
go get -u github.com/go-openapi/errors
go get -u github.com/go-openapi/runtime
go get -u github.com/go-openapi/runtime/flagext
go get -u github.com/go-openapi/runtime/middleware
go get -u github.com/go-openapi/swag
go get -u github.com/spf13/pflag
go get -u github.com/tylerb/graceful
go get -u github.com/go-openapi/spec
go get -u github.com/go-openapi/strfmt
go get -u github.com/go-openapi/validate

서버 실행 후 http://127.0.0.1:8080에 접근하면 hello world가 json 형태로 제대로 반환되는 모습을 확인할 수 있다.

GAE에 실제로 배포하기

테스트까지 무사히 마쳤으니 이제 실제 GAE에 코드를 올리는 일만 남았다. 아래의 명령어를 실행해서 코드를 배포해보자.

1
gcloud app deploy

GAE 공식 가이드를 잘 따랐다면 위 명령어가 정상동작 할 것이다. 만약에 에러가 발생했다면 GAE quickStart 문서를 보고 다시 시도해보길 바란다.


마치며

이번 포스트는 일단 실행에는 성공했지만 원인을 제대로 파악하지 못한 이슈들이 제법있다. 일단 나는 위 가이드를 따라하며 앱 배포까지 성공했지만 다른사람들도 성공할 수 있을지 솔직히 자신이 없다. 만약 위 가이드에 잘못되거나 추가할 내용이 있다면 작성자에게 메일을 보내주거나 문서를 직접 수정해서 push request를 해주시길 바란다.

[last-post]: {% post_url 2017-10-06-go-swagger01 %}