Menu
Coddy logo textTech

Go의 가비지 컬렉션

Coddy GO 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 107개 중 23번째.

C 또는 C++와 같은 언어와 달리, Go는 가비지 컬렉션(GC)을 통해 메모리 관리를 자동으로 처리합니다. 메모리 사용이 끝났을 때 수동으로 메모리를 해제할 필요가 없습니다. Go 런타임은 어떤 메모리가 여전히 사용 중인지 추적하고 나머지는 회수합니다.

new(), make() 또는 변수 생성을 통해 메모리를 할당하면, Go의 가비지 컬렉터가 이러한 할당을 모니터링합니다. 프로그램의 어떤 부분에서도 값에 더 이상 접근할 수 없게 되면, GC는 자동으로 해당 메모리를 해제합니다.

func createPerson() *Person {
    p := &Person{Name: "Alice", Age: 30}
    return p  // p가 힙으로 이스케이프되며, GC가 이를 관리합니다
}

func main() {
    person := createPerson()
    fmt.Println(person.Name)
    // person이 더 이상 사용되지 않을 때, GC가 메모리를 회수합니다
}

이 예제에서 Person 구조체는 함수에서 반환되기 때문에 힙(heap)에 할당됩니다. Go 컴파일러는 탈출 분석(escape analysis)을 수행하여 변수가 스택에 머무를 수 있는지 아니면 힙으로 이동해야 하는지를 결정합니다. 가비지 컬렉터(garbage collector)는 힙 메모리만 관리합니다.

이러한 자동 메모리 관리는 할당 해제를 잊어버려 발생하는 메모리 누수에 대해 걱정하지 않고 애플리케이션 구축에 집중할 수 있음을 의미합니다. 하지만 GC가 존재한다는 점을 이해하면 성능이 중요한 상황에서 불필요한 할당을 최소화하여 더 효율적인 코드를 작성하는 데 도움이 됩니다.

challenge icon

챌린지

쉬움

Go의 가비지 컬렉터가 힙으로 이스케이프(escape)되는 객체의 메모리를 어떻게 처리하는지 보여주는 세션 관리자를 만들어 보겠습니다. 동적으로 할당되고 함수에서 반환되는 세션을 생성하여, GC가 해당 라이프사이클을 관리하도록 할 것입니다.

코드는 두 개의 파일로 구성됩니다:

  • session.go: ID (string), Username (string), 그리고 Data (문자열 슬라이스) 필드를 가진 Session 구조체를 정의합니다. ID와 사용자 이름을 매개변수로 받아 힙에 새로운 Session을 할당하고(포인터를 반환함으로써), Data 슬라이스를 빈 상태로 초기화하는 NewSession 함수를 만듭니다. 또한 세션의 Data 슬라이스에 문자열을 추가하는 포인터 리시버를 가진 AddData 메서드와, 세션 상세 정보를 보여주는 포맷팅된 문자열을 반환하는 Summary 메서드를 추가합니다.
  • main.go: 입력으로부터 세션 정보를 읽고, 생성자 함수를 사용하여 세션을 생성한 뒤, 몇 가지 데이터 항목을 추가하고 세션 요약을 표시합니다. 세션이 함수 내부에서 생성되어 포인터로 반환되기 때문에, 가비지 컬렉터가 관리하는 힙으로 이스케이프됩니다.

다음 입력값이 제공됩니다:

  • 1행: Session ID
  • 2행: Username
  • 3행: 추가할 첫 번째 데이터 항목
  • 4행: 추가할 두 번째 데이터 항목

Summary 메서드는 다음 형식의 문자열을 반환해야 합니다:

Session [ID] for user [Username]
Data entries: [count]
- [entry1]
- [entry2]

예를 들어, sess-001, alice, login, view_dashboard가 주어지면 출력은 다음과 같아야 합니다:

Session sess-001 for user alice
Data entries: 2
- login
- view_dashboard

여기서 핵심 통찰은 NewSession 함수가 Session을 생성하고 그 포인터를 반환한다는 점입니다. 이로 인해 Session은 스택에 머물지 않고 힙으로 "이스케이프"되며, 더 이상 참조되지 않을 때 가비지 컬렉션의 대상이 됩니다. 이 메모리를 수동으로 해제할 필요가 없으며, Go가 자동으로 처리합니다.

치트 시트

Go는 자동 메모리 관리를 위해 가비지 컬렉션(GC)을 사용합니다. 메모리를 수동으로 해제할 필요가 없습니다.

가비지 컬렉터는 메모리 할당을 추적하고 프로그램에서 더 이상 접근할 수 없는 메모리를 회수합니다.

func createPerson() *Person {
    p := &Person{Name: "Alice", Age: 30}
    return p  // p는 힙으로 이스케이프되며, GC가 이를 관리합니다
}

func main() {
    person := createPerson()
    fmt.Println(person.Name)
    // person이 더 이상 사용되지 않으면, GC가 메모리를 회수합니다
}

Go 컴파일러는 변수가 스택에 남을지 아니면 힙으로 이동할지 결정하기 위해 이스케이프 분석(escape analysis)을 수행합니다. 힙으로 이스케이프되는 변수(반환된 포인터 등)는 가비지 컬렉터에 의해 관리됩니다.

GC는 스택 메모리가 아닌 힙 메모리만 관리합니다. 스택 메모리는 함수가 반환될 때 자동으로 해제됩니다.

직접 해보기

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	// 세션 ID 읽기
	sessionID, _ := reader.ReadString('\n')
	sessionID = sessionID[:len(sessionID)-1]

	// 사용자 이름 읽기
	username, _ := reader.ReadString('\n')
	username = username[:len(username)-1]

	// 첫 번째 데이터 항목 읽기
	data1, _ := reader.ReadString('\n')
	data1 = data1[:len(data1)-1]

	// 두 번째 데이터 항목 읽기
	data2, _ := reader.ReadString('\n')
	data2 = data2[:len(data2)-1]

	// TODO: NewSession 함수를 사용하여 새 세션 생성
	// 포인터를 반환하므로 세션은 힙(heap)으로 이스케이프됩니다

	// TODO: AddData 메서드를 사용하여 세션에 데이터 항목 추가

	// TODO: Summary 메서드를 사용하여 세션 요약 출력
	fmt.Println("")
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨