고 중급 #7 표준 라이브러리 투어

5 분 소요

Go의 큰 강점 중 하나는 두꺼운 표준 라이브러리 입니다. 옛 자바스크립트가 작은 표준에 라이브러리로 채우는 모델이라면 — Go는 처음부터 풍부합니다. 이번 글은 자주 쓰이는 것들을 한 번에 훑습니다.

이 글은 깊이보다 — “이 용도에 이 패키지가 있다” 는 인덱스에 가깝습니다. 자세한 사용법은 각 패키지의 공식 문서가 가장 좋습니다.

fmt — 포맷팅 입출력 #

이미 기초 #2에서 다뤘지만 다시.

fmt
fmt.Println("hi")              // 줄바꿈 자동
fmt.Print("줄바꿈 없음")
fmt.Printf("%s = %d\n", "n", 42)
s := fmt.Sprintf("v=%v", x)    // 문자열로
fmt.Errorf("실패: %w", err)     // 에러 만들기

// 자주 쓰는 verb
// %v   기본
// %+v  필드 이름 포함
// %#v  Go 문법으로
// %d %s %t %f %T %q

strings — 문자열 도구 #

strings
strings.Contains("hello", "ell")          // true
strings.HasPrefix("hello", "he")           // true
strings.HasSuffix("hello", "lo")           // true
strings.Index("hello", "ll")               // 2
strings.Replace("hello", "l", "L", -1)     // heLLo (-1은 모두)
strings.ReplaceAll("hello", "l", "L")      // heLLo
strings.ToUpper("hello")                    // HELLO
strings.ToLower("HELLO")                    // hello
strings.TrimSpace("  hello  ")              // "hello"
strings.Trim("---hi---", "-")               // hi
strings.Split("a,b,c", ",")                 // ["a", "b", "c"]
strings.Join([]string{"a", "b"}, ",")       // a,b
strings.Repeat("ab", 3)                     // ababab
strings.Fields("  a  b  c  ")               // ["a", "b", "c"]

strings.Builder — 효율적 문자열 합성 #

Builder
var b strings.Builder
b.WriteString("Hello, ")
b.WriteString("World")
result := b.String()    // "Hello, World"

루프 안에서 s += other로 문자열을 합치면 — 매번 새 메모리 할당이 일어납니다. Builder는 내부 버퍼를 재사용해서 훨씬 효율적입니다.

strconv — 문자열 ↔ 숫자 #

strconv
strconv.Itoa(42)              // "42"
strconv.Atoi("42")             // (42, nil)
strconv.ParseInt("42", 10, 64) // (42, nil) — 진법, 비트 너비
strconv.ParseFloat("3.14", 64)
strconv.FormatFloat(3.14, 'f', 2, 64)  // "3.14"
strconv.Quote("hi\n")          // "\"hi\\n\""

대부분의 경우에는 Itoa / Atoi / ParseFloat만 익혀도 충분합니다.

bytes[]byte도구 #

strings의 byte 슬라이스 버전. API가 거의 평행하게 만들어졌습니다.

bytes
bytes.Contains([]byte("hello"), []byte("ll"))
bytes.Equal(a, b)
bytes.Replace(...)

// Buffer — 가변 byte 버퍼
var buf bytes.Buffer
buf.WriteString("hi")
buf.Write([]byte("!"))
fmt.Println(buf.String())

bytes.Bufferio.Reader/io.Writer를 모두 만족 — IO에서 메모리로 읽거나 쓸 때 자주 등장.

io — IO 인터페이스 #

#1 인터페이스에서 본 핵심 인터페이스들.

io 핵심
type Reader interface { Read(p []byte) (int, error) }
type Writer interface { Write(p []byte) (int, error) }
type Closer interface { Close() error }

io.ReadAll(r)        // 전체 읽어 []byte
io.Copy(dst, src)    // src → dst 복사
io.EOF               // 읽기 끝 sentinel
자주 쓰는 패턴
data, err := io.ReadAll(resp.Body)
defer resp.Body.Close()

os — OS 자원 #

os
os.Args                     // 명령줄 인자
os.Getenv("HOME")
os.Setenv("KEY", "value")
os.Exit(1)                   // 프로그램 종료
os.Stdin / os.Stdout / os.Stderr   // io.Reader/Writer

// 파일
file, err := os.Open("file.txt")        // 읽기
file, err := os.Create("file.txt")      // 쓰기 (덮어쓰기)
defer file.Close()

data, err := os.ReadFile("file.txt")     // 한 번에 모두 읽기
err := os.WriteFile("file.txt", data, 0644)

// 디렉토리
entries, err := os.ReadDir("./")
os.MkdirAll("a/b/c", 0755)
os.Remove("file.txt")
os.RemoveAll("dir")

path/filepath — 경로 다루기 #

filepath
filepath.Join("a", "b", "c")        // a/b/c (OS에 맞게)
filepath.Base("/a/b/c.go")           // c.go
filepath.Dir("/a/b/c.go")            // /a/b
filepath.Ext("c.go")                  // .go
filepath.Abs("./file")                // 절대 경로

OS 별 구분자(Linux의 /, Windows의 \) 차이를 자동 처리.

time — 시간 #

time 기본
now := time.Now()
yesterday := now.Add(-24 * time.Hour)
nextHour := now.Add(time.Hour)

// 차이
elapsed := time.Since(start)         // 경과 시간
duration := time.Until(deadline)      // 남은 시간

// 비교
now.After(other)
now.Before(other)
now.Equal(other)

Duration #

Duration
time.Second
time.Minute
time.Hour
time.Millisecond
time.Microsecond
time.Nanosecond

3 * time.Second                    // 3초
500 * time.Millisecond             // 0.5초

포맷팅 — Go의 독특한 방식 #

time 포맷
now := time.Now()
fmt.Println(now.Format("2006-01-02 15:04:05"))

// Go가 정한 참조 시간
// 2006-01-02 15:04:05.999999999 -0700 MST = Mon Jan 2 15:04:05 MST 2006
// 즉 1 2 3 4 5 6 7

다른 언어(YYYY-MM-DD)와 달리 — 특정 참조 시간(2006-01-02 15:04:05)을 적어 포맷을 표현합니다. 처음엔 어색하지만 익숙해지면 직관적입니다.

자주 쓰는 상수들:

time 상수
time.RFC3339         // "2006-01-02T15:04:05Z07:00"
time.RFC1123
time.DateOnly        // "2006-01-02"
time.TimeOnly        // "15:04:05"

Parse #

Parse
t, err := time.Parse(time.RFC3339, "2026-05-04T10:00:00Z")

encoding/json — JSON #

JSON 기본
type User struct {
	ID   string `json:"id"`
	Name string `json:"name"`
	Age  int    `json:"age,omitempty"`
}

// 직렬화
data, err := json.Marshal(user)
data, err := json.MarshalIndent(user, "", "  ")  // 보기 좋게

// 역직렬화
var u User
err := json.Unmarshal(data, &u)

// 스트림
encoder := json.NewEncoder(os.Stdout)
encoder.Encode(user)

decoder := json.NewDecoder(file)
err := decoder.Decode(&u)

json: 태그가 #6 구조체에서 본 부분입니다. omitempty는 zero value 면 결과에서 빼라는 뜻.

동적 JSON — map[string]any #

스키마를 모르는 JSON을 다룰 때.

동적 JSON
var data map[string]any
json.Unmarshal(rawJSON, &data)

if name, ok := data["name"].(string); ok {
	fmt.Println(name)
}

매번 타입 단언이 필요해 다소 번거롭습니다. 가능하면 struct 정의가 더 깔끔합니다.

sort — 정렬 #

sort 기본
sort.Ints(nums)
sort.Strings(names)
sort.Float64s(values)

// 슬라이스 정렬 — 함수로
sort.Slice(users, func(i, j int) bool {
	return users[i].Age < users[j].Age
})

// 검색 (이미 정렬된 슬라이스에서)
i := sort.SearchInts(nums, target)

Generics가 들어온 후 — slices #

Go 1.21+ 에 slices 패키지가 추가됐습니다. 더 모던한 API.

slices (Go 1.21+)
import "slices"

slices.Sort(nums)
slices.SortFunc(users, func(a, b User) int {
	return a.Age - b.Age
})

slices.Contains([]string{"a", "b"}, "a")
slices.Index([]int{10, 20, 30}, 20)         // 1
slices.Reverse(nums)
slices.Min(nums)
slices.Max(nums)

새 코드에서는 slices 패키지가 점점 더 흔해지고 있습니다.

maps — 맵 도구 #

maps (Go 1.21+)
import "maps"

maps.Keys(m)        // 모든 키 (이터러블, 슬라이스로 모으려면 slices.Collect)
maps.Values(m)
maps.Equal(a, b)
maps.Clone(m)
maps.Delete(m, fn)

errors — 에러 도구 #

#2 에러 처리에서 자세히 다룸.

errors
errors.New("message")
errors.Is(err, target)
errors.As(err, &target)
errors.Join(err1, err2, err3)
errors.Unwrap(err)

net/http — HTTP 클라이언트와 서버 #

HTTP 클라이언트
resp, err := http.Get("https://example.com")
defer resp.Body.Close()
data, _ := io.ReadAll(resp.Body)

// 자기만의 클라이언트
client := &http.Client{Timeout: 5 * time.Second}
req, _ := http.NewRequestWithContext(ctx, "POST", url, body)
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
HTTP 서버
http.HandleFunc("/api/users", func(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "users")
})
http.ListenAndServe(":8080", nil)

실전 시리즈에서 본격적으로 다룹니다.

regexp — 정규식 #

regexp
re := regexp.MustCompile(`(\d{4})-(\d{2})-(\d{2})`)
match := re.FindStringSubmatch("2026-05-04")
// match: ["2026-05-04", "2026", "05", "04"]

re.MatchString("foo")
re.ReplaceAllString("a1 b2", "X")
re.FindAllString("a1 b2 c3", -1)

bufio — 버퍼된 IO #

bufio
scanner := bufio.NewScanner(file)
for scanner.Scan() {
	line := scanner.Text()
	// ...
}
if err := scanner.Err(); err != nil {
	// ...
}

// 또는 Reader
reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('\n')

대용량 파일을 한 줄씩 읽을 때 — os.ReadFile보다 메모리에 안전한 패턴입니다.

loglog/slog — 로깅 #

log는 단순한 출력.

log 옛 패키지
log.Println("info")
log.Fatalf("fatal: %v", err)   // 출력 후 os.Exit(1)

Go 1.21+ 의 log/slog구조적 로깅 (key-value 쌍).

slog (Go 1.21+)
import "log/slog"

slog.Info("user logged in", "user_id", "u1", "ip", "127.0.0.1")
slog.Error("DB 실패", "err", err)

// JSON 출력
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
slog.SetDefault(logger)

JSON 출력은 — 로그 분석 도구(Datadog, Grafana 등)와의 통합이 매우 편합니다. 새 코드에서는 slog가 점점 표준이 되고 있습니다.

flag — 명령줄 플래그 #

flag
import "flag"

var (
	host = flag.String("host", "localhost", "서버 주소")
	port = flag.Int("port", 8080, "포트")
	verbose = flag.Bool("v", false, "verbose")
)

func main() {
	flag.Parse()
	fmt.Println(*host, *port, *verbose)
}
실행
./app --host=0.0.0.0 --port=3000 -v

CLI에 더 풍부한 기능이 필요하면 — cobra, kong 같은 외부 라이브러리. 표준 flag만으로도 작은 도구는 충분합니다.

다른 자주 쓰는 패키지들 — 짧게 #

알아두면 좋은 패키지
crypto/rand        보안 난수
crypto/sha256      해시
encoding/base64
encoding/hex
encoding/csv
encoding/xml
hash/fnv          빠른 해시 (보안 X)
math
math/rand          비보안 난수
net                저수준 네트워킹
net/url            URL 파싱
sync               Mutex, WaitGroup, Once, Map
sync/atomic        원자적 연산
unicode            유니코드 도구
unicode/utf8       UTF-8 인코딩

마무리 #

이번 글은 인덱스에 가까운 글이었습니다. 자세한 사용법은 pkg.go.dev/std에서 각 패키지를 보세요.

자주 만나는 경우:

  • 문자열 → strings, fmt, strconv
  • 시간 → time
  • JSON → encoding/json
  • 정렬 → sort 또는 slices (Go 1.21+)
  • HTTP → net/http
  • 로깅 → log/slog (Go 1.21+)
  • IO → os, io, bufio

중급 시리즈를 마치며 #

7편에서 다룬 내용:

  1. 인터페이스 — 암묵적 구현 (#1)
  2. 에러 처리 — wrap, Is/As, panic (#2)
  3. 고루틴과 채널 — 동시성 입문 (#3)
  4. select와 타임아웃 — 여러 채널 다루기 (#4)
  5. context — 표준 취소/타임아웃 도구 (#5)
  6. 테스팅 — testing 패키지와 table-driven (#6)
  7. 표준 라이브러리 투어 — 자주 만나는 패키지 (이번 글)

여기까지 잡으면 Go로 견고한 코드를 짤 수 있습니다. 다음 고급 시리즈에서는 — 동시성 패턴 깊이, 메모리 모델, 제네릭, reflect 같은 한 단계 위 도구들을 다룹니다.

X