Learning Go - Chapter 9. 모듈/패키지/임포트

choko's avatar
Jun 29, 2024
Learning Go - Chapter 9. 모듈/패키지/임포트
 

저장소, 모듈, 패키지

  • 저장소
    • 깃허브와 같은 버전 관리 시스템의 공간이다.
  • 모듈
    • 저장소에 저장된 Go 라이브러리나 응용 프로그램의 최상위 루트이다.
    • 모든 모듈은 전역적으로 유일한 식별자를 가지고 있어야 한다.
  • 패키지
    • 모듈 구성 및 구조를 제공한다. 모듈은 하나 이상의 패키지로 구성되어 있다.
 
 

go.mod

  • 루트 디렉토리에 유효한 go.mod 파일이 있어야 모듈이 된다.
module github.com/my_module_name go 1.19 // Go의 최소 호환 버전 지정 require ( // 해당 모듈이 의존하는 모듈과 각 모듈에 필요한 최소 버전을 나열한다. entgo.io/ent v0.11.4 github.com/cloudflare/cfssl v1.6.3 ... ) // 의존성 있는 모듈이 있는 위치를 재정의한다. replace github.com/my_module_name/common v0.0.0 => ../../common // 툭종 버전의 모듈 사용을 막을 수 있다. exclude MODULE_NAME vx.x.x
 
 

cmd 디렉토리

  • 모듈이 하나 이상의 응용프로그램으로 구성되었다면, 모듈의 루트 드렉터리에 cmd 디렉토리를 만들어 구분할 수 있다. → Go의 관례이다.
notion image
 
 
 
 

내부 패키지 - internal

  • 모듈에서 패키지간의 함수, 타입, 상수를 공유하고 싶지만, API의 일부가 되게는 하고 싶지 않은 경우 internal 패키지 이름을 통해 이것을 지원한다.
  • 패키지를 외부 노출시키고 싶지 않을 때 internal 폴더 안에 패키지를 위치시킨다.
  • internal 패키지와 해당 패키지 안의 식별자들은 internal과 같거나 한 단계 높은 레벨의 디렉터리에서만 접근 가능하다.
 
 
 

패키지 주석과 godoc

  • Go는 자동적으로 문서로 변환해주는 조석을 작성하기 위한 포맷을 가진다. 이를 godoc 이라고 한다.
      1. 항목의 선언과 주석사이에 빈 줄 없이 주석을 작성한다.
      1. 두 개의 슬래시와 항목의 이름으로 주석을 시작한다.
      1. 여러 단락으로 주석을 나누기 위해서는 빈 주석라인을 사용한다.
      // Load will read your env file(s) and load them into ENV for this process. // // Call this function as close as possible to the start of your program (ideally in main) // // If you call Load without any args it will default to loading .env in the current path // // You can otherwise tell it which files to load (there can be more than one) like // // godotenv.Load("fileone", "filetwo") // // It's important to note that it WILL NOT OVERRIDE an env variable that already exists - consider the .env file to set dev vars or sensible defaults func Load(filenames ...string) (err error) { filenames = filenamesOrDefault(filenames) for _, filename := range filenames { err = loadFile(filename, false) if err != nil { return // return early on a spazout } } return }
 
  • godoc 은 go 프로그램의 문서를 생성하게 해준다. → swagger같이
 
 
 
 

init 함수

  • init 함수
    • 명시적으로 아무것도 하지 않아도 패키지에서 상태를 설정하는 방법으로 init 함수을 사용할 수 있다.
    • 다른 패키지가 init이 있는 패키지를 처음 참조하는 순간 수행된다.
    • 주로 데이터베이스 드라이버 등록과 같은, 단일 할당으론 불가능한 패키지 레벨 변수를 초기화 하는 경우에 사용한다.
      • 이 경우, 가져오는 패키지 앞에 밑줄(_)을 이름으로 할당하여 공백 가져오기를 허용한다.
        • init 함수를 수행하지만, 노출된 식별자에 대한 접근은 허용하지 않는다.
        • import ( "database/sql" _ "github.com/lib/pq" )
    • init 함수는 어쩔 수 없는 경우에만 사용하자.
 
 
 

순환 의존성

  • Go는 순환 의존성을 허용하지 않는다.
    • A 패키지가 B 패키지를 직/간접적으로 가져왔다면, B 패키지도 A 패키지를 가져올 수 없다.
    • 이런 경우 두 패키지를 하나로 합치거나, 순한 의존성을 유발하는 항목만 통합하여 새 패키지로 이동시켜 해결하자.
 
 
 

모듈

  • Go는 서드 파티에서 가져온 코드와 본인이 작성한 코드 모두를 컴파일하여 단일 바이너리로 만든다.
  • 서드 파티든 본인의 코드든 모두 import 구문으로 가져온다.
  • 모듈 버전과 mod 명령어
    • 기본적으로 모듈을 프로젝트에 추가하면 의존성의 최신 버전을 선택한다. 하지만 이전 버전도 선택이 가능하여 버전 관리를 유용하게 할 수 있다.
    • go list 명령어를 통해 프로젝트에 사용된 패키지들을 확인할 수 있다.
    • go get 명령어는 모듈과 관련된 작업과 의존성 업데이트를 할 수 있다.
    • go.modgo.sum
      • go.mod 파일에는 현재 모듈에서 사용하고 있는 버전들만 명시되어 있다.
      • 하지만 go.sum 파일에는 이전에 사용했던 모듈들의 버전도 모두 기록되어 있다.
    • go mod tidy
      • 프로젝트에서 모듈 의존성을 정리하고 최적화한다.
      • go.sum 파일에도 해당 모듈의 사용된 버전만 관리되어, 버전 충돌을 방지한다.
    • go mod vendor
      • 해당 모듈에 의존하는 모든 패키지를 프로젝트 내부의 vendor 디렉토리로 복사한다.
      • 인터넷이 연결되어 있지 않는 환경 등에 사용한다.
 
  • pkg.go.dev
    • Go 팀에서 만든, 오픈소스 Go 프로젝트를 자동으로 인덱싱하는 사이트.
    •  
  • 모듈을 위한 프록시 서버
    • go get 명령을 하면, 기본적으로 깃허브와 같은 소스 저장소에서 직접 가져오는게 아니라, 구글에서 수행하는 프록시 서버에서 처리한다.
    • 프록시 서버 외에도 집계 데이터베이스를 관리하는데, 모듈들의 버전과 체크섬을 정보를 포함한다.
      • go build, go get 등의 명령어로 모듈을 다운받을 때마다, 해시를 계산하고 집계 데이터베이스에 접근하여, 해시가 일치하지 않으면 모듈은 설치되지 않는다.
  • 비공개 저장소(GOPRIVATE)
    • 비공개 저장소에 저장된 조직의 코드를 가져오고 싶은 경우, 이 경우 프록시 서버로 모듈을 요청할 수 없다.
      • 이 경우 GOPRIVATE 환경 변수를 사용하여 repo를 지정해주면, 인증된 사용자만이 해당 패키지를 가져올 수 있다.
        • export GOPRIVATE='github.com/{{your private repo}}/'
 
Share article

Tom의 TIL 정리방