[Golang] Module

2021-11-02 hit count image

Golang에서 Module(모듈)에 대해서 알아보고 어떻게 사용하는지에 대해서 알아보도록 하겠습니다.

개요

이번 블로그 포스트에서는 Golang에서 Module(모듈)을 사용하는 방법에 대해서 살펴보려고 합니다. 이 블로그 포스트에서 소개하는 코드는 다음 링크를 통해 확인하실 수 있습니다.

모듈

Golang의 버전 1.11 이전에는 모듈이라는 기능이 존재하지 않았습니다. 1.11 버전에서 처음 모듈이 소개되었으며, 1.13에서 모듈 기능이 완성되었습니다. 1.13때에 모듈은 선택 사항이였습니다. 1.16 버전에서 모듈은 Golang의 기본 사양이 되었습니다.

Golang에서 모듈은 패키지(Package)의 모음으로써, 한 개의 모듈은 다수의 패키지를 포함할 수 있습니다. 이런 모듈을 통해 Golang은 패키지들의 종속성을 관리할 수 있으며, 모듈은 패키지 관리 시스템으로써 활용이 됩니다.

모듈은 패키지를 트리 형식으로 관리하며, 루트(root) 폴더에 go.mod 파일을 생성하여 모듈을 정의하고, 종속성 정보를 관리하게 됩니다.

go mod init

Golang에서는 다음 명령어를 사용하여 모듈을 생성할 수 있습니다.

go mod init MODULE_NAME

이때 모듈의 이름은 유니크해야 합니다. 따라서 보통 GitHub 저장소 주소를 활용하거나 URL을 모듈 이름으로 사용하게 됩니다.

go mod init github.com/dev-yakuza/study-golang/module/greeting

greeting 모듈

그럼 예제를 만들어 보면서 Golang의 모듈을 이해해 보도록 하겠습니다. 먼저 다른 모듈에서 참조하는 greeting 모듈을 만들어보도록 하겠습니다.

mkdir greeting
cd greeting
touch main.go

greeting 모듈을 만들기 위해 greeting 폴더를 생성하고 greeting 폴더안에 main.go 파일을 생성하고 다음과 같이 수정합니다.

package greeting

import "fmt"

func Hello(name string) string {
  message := fmt.Sprintf("Hello, %s", name)
  return message
}

greeting 모듈은 greeting이라는 패키지를 포함하고 있습니다.

package greeting

greeting 패키지에는 Hello라는 함수가 있으며, 해당 함수는 다른 패키지에서도 사용할 수 있도록 Public 함수로(대문자로 시작) 제작하였습니다.

func Hello(name string) string {
  message := fmt.Sprintf("Hello, %s", name)
  return message
}

Hello 함수는 name 인자를 받아서 Hello, NAME으로 문자열을 반환합니다.

greeting 모듈 생성

이제 이렇게 제작한 greeting 패키지를 다음 명령어를 사용하여 모듈을 생성합니다.

# cd greeting
go mod init github.com/dev-yakuza/study-golang/module/greeting

명령어를 실행하면, 해당 폴더에 go.mod 파일이 생성되는 것을 확인할 수 있습니다.

module github.com/dev-yakuza/study-golang/module/greeting

go 1.17

hello 모듈

다음으로 greeting 모듈을 사용하는 hello 모듈을 생성해 보도록 하겠습니다.

# cd ..
mkdir hello
cd hello
touch main.go

greeting 폴더와 동일한 위치에 hello 폴더를 생성합니다. 그리고 생성한 폴더에 main.go 파일을 생성하고 다음과 같이 수정합니다.

package main

import (
  "fmt"

  "github.com/dev-yakuza/study-golang/module/greeting"
)

func main() {
  message := greeting.Hello("John")
  fmt.Println(message)
}

이렇게 만든 hello 모듈은 main 패키지와 main 함수를 포함하고 있습니다. 즉, 프로그램의 시작점을 의미합니다. 이 프로그램은 우리가 미리 만들어둔 greeting 모듈을 사용할 예정입니다. greeting 모듈을 사용하기 위해서는 앞에서 만든 모듈 이름을 사용합니다.

import (
  "fmt"

  "github.com/dev-yakuza/study-golang/module/greeting"
)

그런 다음 greeting 모듈이 제공하는 Hello 함수를 사용하여 메시지를 출력합니다.

func main() {
  message := greeting.Hello("John")
  fmt.Println(message)
}

이렇게 프로그램을 제작하면 다음과 같이 greeting 패키지를 찾을 수 없어 에러가 발생합니다.

could not import github.com/dev-yakuza/study-golang/module/greeting (cannot find package "github.com/dev-yakuza/study-golang/module/greeting" in any of
  /usr/local/Cellar/go/1.17/libexec/src/github.com/dev-yakuza/study-golang/module/greeting (from $GOROOT)
  /Users/jeonghean/go/src/github.com/dev-yakuza/study-golang/module/greeting (from $GOPATH))compilerBrokenImport

이제 hello 모듈을 제작하여, greeting 모듈을 사용할 수 있도록 수정해 봅시다.

hello 모듈 생성

이제 다음 명령어를 사용하여 hello 모듈을 생성합니다.

go mod init github.com/dev-yakuza/study-golang/module/hello

명령어를 실행하면, hello 폴더안에 go.mod 파일이 다음과 같이 생성된 것을 확인할 수 있습니다.

module github.com/dev-yakuza/study-golang/module/hello

go 1.17

go mod tidy

Golang에서 기본적으로 제공하는 패키지가 아닌, 외부 패키지를 사용할 때, 해당 패키지를 다운로드할 필요가 있습니다. 이때, 모듈 안에서 다음 명령어를 실행하여 외부 패키지를 다운로드합니다.

go mod tidy

하지만, 우리가 만든 greeting 패키지는 아직 공개되지 않았기 때문에(GitHub 등과 같은 곳에 소스 코드를 공개하지 않았기 때문에), 다음과 같은 메시지가 표시됩니다.

go: finding module for package github.com/dev-yakuza/study-golang/module/greeting
github.com/dev-yakuza/study-golang/module/hello imports
        github.com/dev-yakuza/study-golang/module/greeting: module github.com/dev-yakuza/[email protected] found (v0.0.0-20211026013945-559aef3c74a0), but does not contain package github.com/dev-yakuza/study-golang/module/greeting

이런 경우, greeting 모듈을 GitHub에 올리고, 외부에 공유해서 해결할 수도 있습니다. 다른 방법으로는 go.mod를 사용하여 로컬 패키지를 참조하게 변경할 수 있습니다.

go mod edit -replace

그럼 이제 go.mod를 사용하여 로컬 패키지를 참조하게 변경해 봅시다. 다음 명령어를 실행하여, 로컬 패키지를 참조하도록 변경합니다.

go mod edit -replace github.com/dev-yakuza/study-golang/module/greeting=../greeting

그리고 다시 다음 명령어를 실행하여 패키지를 설정합니다.

go mod tidy

실행

이제 모든 준비가 끝났습니다. 지금까지 작업한 내용을 확인하기 위해 hello 폴더 안에서 다음 명령어를 실행해 봅니다.

# cd hello
go run main.go

이렇게 실행하면, 다음과 같은 결과가 출력됩니다.

Hello, John

외부 모듈 폴더

Golang에서 다음 명령어를 실행하면 외부에서 제작된 모듈 다운로드하여, 프로그램에서 사용하는 것이 가능합니다.

go mod tidy

이렇게 다운로드된 모듈은 GOPATH/pkg에 저장되게 됩니다.

go env

위에 명령어를 실행하면 다음과 같이 GOPATH의 경로를 알 수 있으며, 해당 폴더로 이동하면 pkg 폴더를 확인할 수 있습니다.

...
GOOS="darwin"
GOPATH="/Users/dev-yakuza/go"
GOPRIVATE=""
...

완료

이것으로 Golang에서 모듈이 무엇인지, 어떻게 사용하는지에 대해서 알아보았습니다. 이제 모듈을 사용하여 외부 패키지를 사용하거나, 외부에서 사용할 수 있도록 패키지를 제공해 보시기 바랍니다.

제 블로그가 도움이 되셨나요? 하단의 댓글을 달아주시면 저에게 큰 힘이 됩니다!

책 홍보

스무디 한 잔 마시며 끝내는 React Native 책을 출판한지 벌써 2년이 다되었네요.
이번에도 좋은 기회가 있어서 스무디 한 잔 마시며 끝내는 리액트 + TDD 책을 출판하게 되었습니다.

아래 링크를 통해 제가 쓴 책을 구매하실 수 있습니다.
많은 분들에게 도움이 되면 좋겠네요.

스무디 한 잔 마시며 끝내는 React Native, 비제이퍼블릭
스무디 한 잔 마시며 끝내는 리액트 + TDD, 비제이퍼블릭
Posts