본문 바로가기
카테고리 없음

Go Module을 사용하여 GOROOT 이외의 디렉토리에서 모듈 불러오기

by 노아론 2020. 9. 13.

Go를 이용해 gRPC를 익히면서 Module import에 대한 문제가 생겼다.

프로젝트 내부에 모듈을 두고 싶었으나, import를 하면 Go 컴파일러는 GOROOT 디렉토리에서만 패키지를 찾는 것이었다.

 

문제를 해결하기 위해 코드와 폴더 구조를 살펴보자

golang_module (나의 프로젝트 폴더)
├── main.go
└── my_module
    └── animal.go
// my_module/animal.go
package animals

import "fmt"

// PrintDogSound for used by main package
func PrintDogSound() {
    fmt.Println("bark")
}

// PrintCatSound for used by main package
func PrintCatSound() {
    fmt.Println("meow")
}

Go lint에 의하면 다른 패키지에서 접근 가능한 함수를 만들려면 함수 명의 첫 문자는 반드시 대문자여야 한다

또한, 접근 가능한 함수에는 주석이 있어야 한다

Python에 익숙했던 나는 아래와 같이 작성을 하게 되었다

// main.go
package main

import (
    "./my_module/animal"
    // 문제가 된 지점
)

func main() {
    animal.PrintDogSound()
}

 

하지만, Go에는 relative import가 없다. 이에 아래와 같은 오류가 발생하였다

golang_module [master] % go run main.go
main.go:6:2: cannot find package "." in:
        /project/golang_module/my_module/animal

나만 relative import를 생각한건 아니었나 보다

proposal: Go 2: cmd/go: allow relative imports #20883

파일의 패키지 명을 통해 찾는 것 같아 main.go를 아래와 같이 수정을 해보았다 (마찬가지로 오류가 발생한다)

import (
    animal "my_module/animals"
    // 문제가 된 지점
)
main.go:4:2: package my_module/animals is not in GOROOT (/usr/local/go/src/my_module/animals)

 

 

내가 의도한 my_module/animals의 경로는 golang_module/my_module/animals인데 Go compiler는 전혀 다른 경로인 $GOROOT에서 패키지를 찾고 있었다.

저 경로가 아니면 패키지를 import할 수 없는지, 그럼 결국 매번 패키지를 만들면 $GOROOT에 넣는 것으로 해결을(와... 이 방법은 내키지 않는다;;) 해야 할지 고민하던 중 구글링 삽질을 통해 의존성 관리 도구인 Go Module에 대해 알게 되었다.

Go Module

Go 1.11에 등장해 Go 1.13 버전부터 Module이 기본으로 지정되었다고 한다

Go Module의 기능은 아래와 같다

  • 새로운 모듈 생성
  • 의존성(dependency) 추가
  • 디펜던시 업그레이드
  • 새 메이저 버전에 의존성 추가
  • 새 메이저 버전에 의존성 업그레이드
  • 사용하지 않는 의존성 제거

go mod init roharon/m을 통해 현재 디렉토리에 새 모듈을 생성한다

나는 모듈명을 roharon/m 로 두었으나 자유롭게 지정하면 된다 (roharon.com/m 같은 URL형식도 된다)

golang_module % go mod init roharon/m
go: creating new go.mod: module roharon/m

생성된 go.mod의 내용은 다음과 같다

module roharon/m

go 1.15

지금까지의 나의 프로젝트 구조이다

golang_module (나의 프로젝트 폴더)
├── go.mod
├── main.go
└── my_module
    └── animal.go

마지막으로 animal.go의 함수를 호출하는 main.go파일을 수정해보자

// main.go
package main

import (
    animals "roharon/m/my_module"
    // 모듈명은 roharon/m 이며 animal.go은 my_module폴더에 있다
)

func main() {
    animals.PrintCatSound()
    animals.PrintDogSound()
}
✋내용 수정

위는 패키지 내의 모듈을 import하는 경우이다
다른 패키지를 import하기 위해선 go.mod에 replace 설정이 필요하다

 

이제 go run main.go을 통해 다음과 같이 프린트가 됨을 확인할 수 있다

meow
bark

이상으로 Go module을 이용한 내부 모듈 사용하기에 대해 다뤄보았다.

다음 글로는 Go의 gRPC에 대해 포스팅해보고자 한다

오류 지적은 언제나 환영합니다

 

[참고자료] https://blog.golang.org/using-go-modules

댓글