Golang이 module을 통해 의존성 관리하는 방식에 대해 알아봅니다. Go를 처음 접하는 입문자가 쓴 글이기에 다소 부정확한 내용이 함유되어 있을 수 있습니다.
동아리 내에서 사용중인 코드 채점 서버가 golang(이하 go)로 작성되어 있다. 해당 서버에 대한 이슈 해결을 맡게 되었다. 급한 이슈가 아니기에 go를 공부해가며 이슈를 해결해도 괜찮을 것 같다고 하여 go를 공부하게 되었다. 따라서 Go를 처음 접해보는 입문자이기에 본 포스트에 다소 부정확한 내용이 함유되어 있을 수 있다.
처음 go를 접했을 때 헷갈린 부분이 의존성 관리에 관한 내용이었다. 최신 버전의 Go에서는 의존성을 module을 통해서 관리하고 있다. 그러나 이전 버전들의 경우 GOPATH라는 환경변수를 활용하여 관리한다. 처음 go를 사용할 때 이러한 부분에 대하여 개념이 잡히지 않아 많이 헷갈렸다. 이 부분에 대하여 지금까지 공부한 내용을 정리해보고자 한다.
Go는 소스파일들을 묶어 package로 관리한다. 패키지 내에서 변수들과 함수들(identifier)을 공유한다. 파이썬의 package와 유사하다. 하나의 소스파일 내에서 해당 소스파일이 속한 package 외 다른 package에 속한 identifier들을 참조하여 사용할 수 도 있다. 따라서 go의 의존성 관리는 이러한 package들을 관리하는 것을 의미한다.
하나의 디렉토리에 위치한 여러 소스파일들이 모여 하나의 패키지를 구성한다. 이 디렉토리의 이름, 혹은 위치가 패키지의 이름이 된다. 따라서 다른 패키지에서 해당 패키지의 변수 등을 사용하고 싶으면 디렉토리의 이름이나 경로를 사용하여 import하면 된다.
Go의 소스파일의 최상단에는 package {package_name}을 작성해야 한다. 이러한 패키지 선언은 패키지의 구성 요소를 참조할 때 사용할 일종의 변수와 같은 것이다. 이는 다른 패키지에서 해당 패키지를 import할 때 사용하는 패키지 이름과 같지 않다. 그 때 사용하는 이름은 디렉토리의 이름이다.
main Package최상단에 package main으로 선언된 패키지는 실행가능한 패키지이다. 따라서 go install명령어를 사용하여 컴파일하게 되면 실행가능한 파일이 만들어진다. 이때 package main 밑에 위치한 main함수가 진입점으로써 역할한다.
어떤 패키지안에서 선언된 구분자들이 다른 패키지에서 참조되게 하려면 해당 구분자의 첫 글자를 대문자로 작성해야 한다. C++ 등에서의 private public과 같이, 소문자로 시작하는 구분자는 다른 패키지에서 참조하지 못한다.
다른 패키지, 외부 패키지를 사용하고자 할 때는 go get github.com/example/package_name와 같은 명령을 사용한다. 이 명령어를 사용하면 기존에 설정해 둔 GOPATH 환경변수를 따라 ${GOPATH}/src/ 위치에 해당 패키지의 소스파일이 위치하게 되고 ${GOPATH}/bin에 해당 패키지를 컴파일한 실행파일이 위치하게 된다 (만약, main 패키지라면.).
소스파일은 go get에서 입력한 위치 정보를 따라 배치되게 된다. 따라서 src 아래 github.com 디렉토리가 생성되고, github.com 디렉토리 안에 example/pacakge_name 디렉토리가 생성된다. 따라서 패키지를 만들고 배포하고, import하는 작업이 모두 GOPATH에 따라서 이루어진다. GOPATH를 바꿔가며 작업하면 다른 위치에서도 소스파일을 만들고 배포할 수 있지만 번거롭다는 단점이 있다. 또한 go get을 사용하여 다운로드하는 패키지들은 항상 최신 버전만 다운로드하기 때문에 버전 관리에 어려움이 존재한다. 이러한 문제점을 해결한 것이 go module이다.
모듈은 패키지들을 포함하는 디렉토리다. 모듈을 사용하면 소스 파일의 위치에 제약이 사라지고, 외부 패키지에 대한 버전 관리가 수월해진다. 패키지를 포함한다는 점에서 nested 패키지와 유사하다.
모듈은 go.mod라는 파일을 통해 go와 여러 외부 패키지의 버전을 관리한다. go mod init <module_name>을 실행하면 go.mod가 생성되고 go mod tidy를 입력하면 해당 모듈에 필요한 패키지들이 설치된다.
go.mod에 패키지의 버전 정보를 작성할 수 있는데, 이러한 버전 정보를 이용해 특정 버전에 해당하는 패키지를 이용할 수 있다. go mod tidy를 실행하면 go.sum이라는 파일이 생겨 다운로드한 패키지들의 checksum을 기록한다. 이를 통해 go run등의 작업을 실행할 때 제대로된 패키지를 참조하여 실행하는지 검증하게 된다.