본문 바로가기
프로그래밍/Golang

Golang Package(패키지) 네이밍 가이드: 효과적인 패키지 이름 짓기 12가지 팁

by slowin 2024. 7. 16.

[go.dev/blog/package-names 포스팅 참고]

좋은 패키지 이름은 짧고 명확해야 합니다.

1. 소문자로 작성되며, 밑줄이나 혼합 대소문자가 없습니다.


좋은 예시:
* time (시간 측정 및 표시 기능 제공)
* list (이중 연결 리스트 구현)
* http (HTTP 클라이언트 및 서버 구현)

 

2. 다른 언어에서 사용되는 일반적인 패턴이 Go에서는 관용적으로 사용되지 않을 수 있습니다.


좋지 않은 예시:
* computeServiceClient
* priority_queue

 

3. 약어는 신중하게 사용되어야 하며, 프로그래머 누구나 쉽게 이해할 수 있는 영역에서는 축약된 단어를 사용할 수 있습니다.


축약 사용 예시:
* strconv (문자열 변환)
* syscall (시스템 호출)
* fmt (형식화된 I/O)


4. 변수로 사용될 만한 단어를 패키지 이름으로 사용하지 마세요.

버퍼 I/O 패키지는 "buf"가 아닌 "bufio"를 사용합니다. 이는 사용자가 "buf"를 변수 이름으로 사용하기 좋기 때문입니다.


5. 반복을 피하세요.

server := &http.Server{
    Addr:    ":8080",  // 서버가 리슨할 주소와 포트
    Handler: mux,      // 요청을 처리할 핸들러
}

위 코드는 `http.Server` 구조체를 사용한 예시입니다. 만약 `"http.HTTPServer"`였다면, 중복 개념이 이름에 노출되고 있는 것입니다. http 패키지 안에 있는 이름이라면, 명확하게 `Server`로 작성하세요.

 

6. 함수 이름을 단순화하세요.

Go 언어는 코드의 가독성, 유지보수성, 그리고 일관성을 중요하게 생각하며, 이를 위해 특정한 코드 스타일과 관용구를 따르도록 권장합니다.

start := time.Now() // start는 time.Time 타입입니다
  • Now 함수는 time 패키지의 함수입니다. 이 함수는 `time.Time` 타입의 값을 반환합니다.
  • 따라서 함수 이름에서 `Time`을 반복할 필요가 없습니다. 클라이언트 코드는 `time.Now()`를 호출하여 `time.Time` 값을 얻습니다.
q := list.New()  // q는 *list.List 타입입니다

New 함수는 특정 타입의 새로운 인스턴스를 생성하는 표준 진입점 역할을 합니다.


7. 다른 패키지의 유형은 같은 이름을 가질 수 있습니다.

Go 표준 라이브러리의 예시로 알아보겠습니다.
`jpeg.Reader`, `bufio.Reader`, `csv.Reader` 처럼 각 패키지의 기능과 잘 어울리는 이름(`Reader`)을 사용할 수 있습니다.


8. 관례에 따라 패키지 경로의 마지막 요소는 패키지 이름입니다.

예시에서 `myproject/util/stringutil` 경로의 마지막 요소인 `stringutil`이 패키지 이름으로 사용되었습니다.
이 규칙은 패키지의 경로와 이름을 일관되게 유지함으로써 코드의 가독성과 유지보수성을 높이는 데 도움을 줍니다.

// main.go
package main

import (
    "fmt"
    "myproject/util/stringutil"
)

func main() {
    reversed := stringutil.Reverse("hello")
    fmt.Println(reversed)
}

 

9. 같은 이름의 패키지를 로컬에서 이름 변경하기

패키지 이름 충돌을 피하기 위해 로컬에서 이름을 변경할 수 있습니다.

package main

import (
    "net/http"
    pprofHttp "net/http/pprof"  // 로컬 이름 변경
    pprofRuntime "runtime/pprof" // 로컬 이름 변경
    "log"
    "os"
)

...


10. Go에서는 디렉터리를 사용하여 관련 패키지들을 그룹화할 수 있습니다.

이 디렉터리 구조는 파일을 정리하는 방법을 제공할 뿐, 디렉터리 내의 패키지 간에는 실제로 관계가 없습니다. 이와 같은 구조 덕분에 같은 이름의 패키지를 다른 디렉터리 내에 만들 수 있습니다.

표준 라이브러리의 crypto 디렉터리에는 여러 패키지가 있습니다. 각 패키지는 암호화 관련 기능을 제공합니다.

  • crypto 디렉터리
    • crypto/sha256: SHA-256 해싱 알고리즘을 제공합니다.
    • crypto/rand: 암호학적으로 안전한 난수를 생성합니다.
package main

import (
    "crypto/rand"
    "crypto/sha256"
    "fmt"
    "io"
)

...

 

11. "빈 식별자(blank identifier)" 가져오기 `_`

`import _ "package"` 형태는 패키지를 가져오지만, 패키지의 이름을 코드 내에서 사용하지 않겠다는 것을 명시합니다. 그러나 이로 인해 패키지의 init 함수는 실행됩니다.

package main

import (
    "net/http"
    "net/http/pprof"       // net/http/pprof 패키지 가져오기
    _ "runtime/pprof"      // runtime/pprof 패키지 가져오기 (직접 사용하지 않더라도 초기화)
    "log"
)
...

 

12. 의미 없는 패키지 이름을 피하세요.

모호한 패키지 이름은 코드를 탐색하고 유지보수하기 어렵게 만듭니다.
util, common, misc와 같은 이름을 가진 패키지는 클라이언트에게 패키지의 내용에 대한 파악을 힘들게 만드는 요인이 됩니다.
이는 클라이언트가 패키지를 사용하는 것을 어렵게 하고, 유지보수에 혼란을 불러일으킬 수 있습니다.

 

관련

Golang 패키지 기본 개념: 구조, 사용법 및 모범 사례 가이드
Golang 패키지 종속성 관리와 모듈화
Golang 모듈 발행 가이드: GitHub에 패키지 배포