Outsider's Dev Story

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

Go에서 dep으로 의존성 관리하기

Go로 간단한 프로젝트를 하려고 보니 처음 신경 쓰이는 건 의존성 관리를 어떻게 하는가였다. PackageManagementTools 문서에 패키지 관리 도구가 정리되어 있다.

dep, is an official experiment for the dependency tool. It is currently being implemented, in pre-alpha state and should be used with caution as "Lots of functionality is knowingly missing or broken".

여러 도구가 있지만 dep을 공식 의존성 관리 도구로 언급하고 있다. 아직 실험적으로 구현 중이지만 공식이라고 하니 그냥 dep을 쓰기로 했다. dep 저장소를 보면 프로덕션에서 사용해도 문제없다고 하니(dep is safe for production use.)아직 Go로 뭔가 큰 걸 만들 건 아니지만 써도 괜찮을 것 같다.

dep 설치

dpe은 go 1.8 이상의 버전이 필요하다고 한다. 현재 최신 버전이 1.10이니 나한테는 영향은 없을 것 같다. go get으로 설치해도 되지만(go get -u github.com/golang/dep/cmd/dep) 소스 파일까지는 필요 없을 것 같아서 저장소에 안내된 대로 Homebrew로 설치했다.

$ brew install dep

==> Installing dependencies for dep: go
==> Installing dep dependency: go
==> Downloading https://homebrew.bintray.com/bottles/go-1.10.high_sierra.bottle.tar.gz
######################################################################## 100.0%
==> Pouring go-1.10.high_sierra.bottle.tar.gz
==> Caveats
A valid GOPATH is required to use the `go get` command.
If $GOPATH is not specified, $HOME/go will be used by default:
  https://golang.org/doc/code.html#GOPATH

You may wish to add the GOROOT-based install location to your PATH:
  export PATH=$PATH:/usr/local/opt/go/libexec/bin
==> Summary
  /usr/local/Cellar/go/1.10: 8,150 files, 336.9MB
==> Installing dep
==> Downloading https://homebrew.bintray.com/bottles/dep-0.4.1_1.high_sierra.bottle.tar.gz
######################################################################## 100.0%
==> Pouring dep-0.4.1_1.high_sierra.bottle.tar.gz
  /usr/local/Cellar/dep/0.4.1_1: 7 files, 8.8MB

dep으로 버전을 출력해 볼 수 있으면 잘 설치된 것이다.

$ dep version
dep:
 version     : v0.4.1
 build date  : 2018-01-27
 git hash    : 37d9ea0
 go version  : go1.9.3
 go compiler : gc
 platform    : darwin/amd64

새 버전으로 업그레이드하려면 brew upgrade dep 명령어를 사용하면 된다.

dep으로 의존성 관리하기

go get이 이미 있고 goimports 등을 사용하려고 tools를 설치할 때는 go get으로 설치했다. go get으로 설치하면 $GOPATH/src 아래 소스코드가 들어가는데 이 아래 있으면 로컬에서 import로 불러서 사용할 수 있으므로 go get으로 의존성을 설치해서 사용할 수도 있다.(Go 개발자들이 정확히 어떻게 쓰는지는 아직 잘 모르지만...)

하지만 소스 코드에 import 구문이 있다고 하더라도 go get으로 설치해서 사용하면 본인은 괜찮지만 다른 사람은 의존성을 일일이 찾아서 설치해야 해서 협업하기만 어려우므로 프로젝트의 의존성은 dep같은 도구가 적합하다고 생각한다.

새 프로젝트에서 dep으로 의존성을 관리하는 방법은 dep 문서에 잘 나와 잇다. 처음에 dep으로 의존성을 관리하려면 초기화를 해야 한다.

$ dep init

초기화를 하면 아래처럼 2개의 파일과 1개의 디렉터리가 생성된다.

├── Gopkg.lock
├── Gopkg.toml
└── vendor/


Gopkg.toml

Gopkg.toml은 초기화할 때 생성되는 파일로 dep의 동작을 감시하는 여러 규칙을 담고 있다고 한다.

  • 의존성 규칙: constraints, overrides로 사용자가 적용할 의존성의 버전과 어디서 가져와야 하는지를 지정한다.
  • 패키지 그래프 규칙: required, ignored로 임포트 경로를 추가하거나 제외해서 임포트 그래프를 조작할 수 있다.
  • metadata: 사용자가 정의한 키-값의 맵으로 dep은 무시할 것이다.
  • prune: 어떤 파일과 디렉터리가 불필요하다고 판단할지 설정해서 vendor/에서 자동으로 제거한다.

아래는 dep init했을 때 생긴 Gopkg.toml의 내용이다.

# Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
#   name = "github.com/user/project"
#   version = "1.0.0"
#
# [[constraint]]
#   name = "github.com/user/project2"
#   branch = "dev"
#   source = "github.com/myfork/project2"
#
# [[override]]
#   name = "github.com/x/y"
#   version = "2.4.0"
#
# [prune]
#   non-go = false
#   go-tests = true
#   unused-packages = true


[prune]
  go-tests = true
  unused-packages = true


Gopkg.lock

프로젝트의 의존성 그래프의 스냅숏을 가진 파일이다. 이 파일은 dep ensure 할 때 변경된다.

아래는 생성된 Gopkg.lock 파일의 내용이다.

# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.


[solve-meta]
  analyzer-name = "dep"
  analyzer-version = 1
  inputs-digest = "ab4fef131ee828e96ba67d31a7d690bd5f2f42040c6766b1b12fe856f87e0ff7"
  solver-name = "gps-cdcl"
  solver-version = 1

의존성 추가

웹 프레임워크로 gin을 사용하기 위해 dep ensure로 의존성을 추가해 보자. ensure가 프로젝트에 의존성을 설치하는 명령어고 새로운 의존성을 추가하려면 dep ensure -add를 사용해야 한다.

$ dep ensure -add github.com/gin-gonic/gin
no dirs contained any Go code

현재는 Go 코드를 전혀 작성하지 않아서 오류가 난다. 여기선 Go 코드는 중요하지 않으므로 다음 내용으로 main.go 파일을 만들자.

package main

다시 gin을 추가해 보자.

$ dep ensure -add github.com/gin-gonic/gin
Fetching sources...

"github.com/gin-gonic/gin" is not imported by your project, and has been temporarily added to Gopkg.lock and vendor/.
If you run "dep ensure" again before actually importing it, it will disappear from Gopkg.lock and vendor/.

아까와 달리 추가되었다. 안내 문구를 보면 아직 github.com/gin-gonic/gin를 아직 임포트 한 곳이 없어서 Gopkg.lockvender/에는 추가되었지만 임포트하지 않고 dep ensure를 실행하면 지워질 것이라고 한다.

Gopkg.toml 파일을 보면 하단에 gin이 추가된 것을 볼 수 있다.

[[constraint]]
  name = "github.com/gin-gonic/gin"
  version = "1.2.0"

Gopkg.lock 파일은 아래처럼 의존성의 자세한 정보가 추가되고 [solve-meta]inputs-digest 정보가 변경되게 된다.

[[projects]]
  name = "github.com/gin-gonic/gin"
  packages = [
    ".",
    "binding",
    "render"
  ]
  revision = "d459835d2b077e44f7c9b453505ee29881d5d12d"
  version = "v1.2"


dep 관련 파일 버전 관리

위에서 보았듯이 dep이 생성한 파일은 Gopkg.toml, Gopkg.lockvender 디렉터리다. 좀 찾아봤는데 Gopkg.toml, Gopkg.lock는 둘 다 커밋하는 것 같다. Gopkg.lock가 꼭 필요한지는 확인 안해 봤지만 npm을 생각해 보면 package-lock.json과 같은 역할을 하는 거로 보인다. 내 취향으로는 프로덕션에서 서비스하기 전까지는 lock 파일을 저장소에서 관리하는 편은 아니지만 요즘 추세는 lock 파일도 보통 넣는 것 같고 해서 dep에서도 두 파일을 모두 Git에 넣기로 했다.

vender 디렉터리의 경우 딱 봐도 Git에서 관리할 필요가 없어 보이는데 dep의 FAQ 문서를 보면 이 디렉터리를 커밋해서 관리할 때의 장단점이 나와 있다. 말이 장단점이지 그냥 의존성 파일을 다 저장소에 관리할지 말지의 얘기라서 관례대로 나는 vender 디렉터리는 git에서 제외했다.

의존성 설치

프로젝트를 협업하는 경우 Gopkg.toml, Gopkg.lock를 가진 저장소를 받아서 의존성을 설치해서 개발해야 한다.

$ dep ensure

이때는 dep ensure만 실행해야 한다. 참고로 여기서는 dep만 설명하고 있지만, 앞에서 살펴본 대로 go 소스코드에서 import "github.com/gin-gonic/gin" 처럼 임포트하고 있지 않다면 이 의존성이 지워지게 된다.

2018/02/21 22:33 2018/02/21 22:33

[Book] 인공지능 투자가 퀀트

제목이 인상적인데 아는 사람이 재밌다고 해서 읽게 되었다. 사실 처음 읽을 때는 "인공지능 투자가 퀀트"라고 해서 AI 시대에 인공지능으로 투자하는 알고리즘 얘기로 그 봇의 이름이 "퀀트"인 줄 알았는데 실제로는 "퀀트"는 금융시장에서 알고리즘으로 투자하는 직업의 이름이었다. 퀀트로 일해온 저자가 "퀀트"라는 직업이 어떤 직업인지를 설명하는 글에 가깝다.

인간의 직감이나 감정을 배제하고 오직 수학과 알고리즘만으로 투자하는 사람들, 바로 퀀트(Quant)다.

인공지능을 이용해 투자하는 사람들을 퀀트라 부른다. 퀀트는 모든 것을 숫자로 바꿔서 생각하는 사람이란 뜻을 가진다.

퀀트라는 직업이 어떻게 시작되었는지부터 저자가 실제로 퀀트로 일하면서 겪은 일까지 잘 엮여있어서 재미있게 읽었다. 에드 소프가 카지노에서 승리하는 방법을 연구하다가 금융시장에 관심을 끌게 되고 이후 블랙 숄즈 옵션 거래 알고리즘이 만들어지면서 금융시장이 어떻게 활성화되면서 각 금융시장에 퀀트라는 직업이 생겨나는 과정이 꽤 흥미롭다. 금융시장에 대해 잘 모르는 나조차도 이해하기 쉽게 재밌고 명쾌하게 설명하고 있기는 하지만 에드 소프부터 새로운 알고리즘이 등장하고 이에 따라 변한 시장에 또 새로운 알고리즘이 등장하는 식으로 역사에서 중요한 알고리즘을 하나씩 설명하는데 금융시장이 변해가는 과정을 같이 보는 것 같아서 아주 재미있었다.

소프는 어떤 상황에서도 크게 손해 보는 상황을 막는 울타리 전략 바로, 헤지(Hedge)를 처음 시도하게 된다.

마침내 1971년, 어떤 경우에도 쓸 수 있는 옵션 가격 방정식을 만들어낸다. 현대 금융사에서 뉴턴 방정식이나 아인슈타인 상대성 이론에 비견되는 가장 위대한 발견, 바로 블랙-숄즈 방정식이 완성되는 순간이었다.

두 주식으로 쌍을 만들어 틈이 발생하면 바로 거래하는 알고리즘, 바로 페어(Pair) 트레이딩의 시초이다.

2부에서는 본격적인 퀀트라는 직업을 들여다볼 수 있게 저자의 경험을 설명하고 있다. 퀀트라는 직업을 갖기로 하고 일하면서 퀀트라는 사람들이 어떤 식으로 일하고 있고 자신의 알고리즘을 만들고 지키기 위해 회사끼리 경쟁하는 과정은 긴장감이 정해질 정도로 재미있었다.

이제 시장에서 활동하는 퀀트는 몹시 다양해져 하나로 정의하기도 어려워졌다.

수학자에서 물리학자로, 그 후 금융 공학자에서 네트워크 엔지니어와 소프트웨어 공학자로 옮겨갔던 퀀트의 흐름은 이제 데이터 과학자와 인공지능 전문가로 옮겨가고 있다.

내가 퀀트로 일할 것은 아니지만 아주 재밌게 보았다. 본격적으로 딥러닝과 AI가 발전하고 있는 상황에서 앞으로 어떻게 흘러갈지도 덕분에 궁금해졌고 자신의 직업에 대해서 이 정도로 통찰력을 가지고 있다는 것도 흥미로운 부분이었다.

2018/02/19 23:15 2018/02/19 23:15