파이썬의 메모리 할당과 관리
메모리란?
프로그램이 실행되기 위해서는 먼저 프로그램과 프로그램에서 사용될 변수들이 메모리에 로드(load)되어야 한다.
메모리가 무엇인지 아직 개념이 확실하지 않다면, 아래의 포스트를 먼저 읽고 오는 것을 추천한다.
메모리 구조
프로그램이 운영체제로부터 할당받는 대표적인 메모리 공간은 다음과 같이 4개의 영역으로 구분 될 수 있다.
코드(Code) 영역
- 프로그램의 실행 코드가 저장되는 메모리 영역
- 컴파일 된 기계어 형태로 존재하며, CPU에 의해 직접 실행
- 읽기 전용(Read-Only)으로, 프로그램이 실행되는 동안 수정되지 않음
데이터(Data) 영역
- 전역 변수, 정적 변수, 상수 등의 데이터가 저장되는 메모리 영역
- 프로그램 시작 시 할당되며, 프로그램 종료 시까지 유지
- 초기화된 전역 변수와 정적 변수는 초기값으로, 초기화되지 않은 전역 변수와 정적 변수는 0으로 자동 초기화
스택(Stack) 영역
- 함수의 호출과 관련된 지역 변수, 매개변수, 복귀 주소 등이 저장되는 메모리 영역
- 함수가 호출될 때마다 스택 프레임(Stack Frame)이 생성되고, 함수가 종료되면 해당 스택 프레임이 제거
- 후입선출(LIFO, Last-In-First-Out) 구조로 동작하여 함수 호출 순서대로 메모리를 할당하고 해제
힙(Heap) 영역
- 동적으로 할당된 메모리, 즉 런타임에 필요한 메모리가 동적으로 할당되는 메모리 영역
- 사용자가 직접 할당하고 해제해야 하는 메모리 영역으로, 사용자의 조작에 따라 크기가 변화
- 주로 동적으로 생성된 객체나 데이터 구조체가 힙 영역에 할당
메모리 할당 방법
변수 선언과 메모리 할당
파이썬에서 변수를 선언할 때, 해당 변수에 저장될 값의 메모리 공간이 할당된다.
변수는 단지 이름(레퍼런스)일 뿐이며, 변수가 실제 값을 가리키는 메모리 주소를 참조한다.
예를 들어, x = 10을 실행하면 정수형 10의 메모리가 할당되고, 변수 x는 이 메모리 주소를 가리키게 된다.
데이터 타입에 따른 메모리 크기
파이썬은 동적으로 타입을 결정하므로 변수를 선언할 때 데이터 타입을 명시적으로 지정하지 않는다.
데이터 타입은 변수에 할당된 값에 따라 자동으로 결정되며, 해당 데이터 타입에 맞는 메모리 크기가 할당된다.
예를 들어, 정수형 데이터는 4바이트, 실수형 데이터는 8바이트 등의 크기로 메모리를 할당받는다.
# 정수형 데이터는 4바이트 크기로 메모리가 할당된다.
num = 10
# 실수형 데이터는 8바이트 크기로 메모리가 할당된다.
pi = 3.14
# 문자열 데이터는 문자의 개수에 따라 메모리 크기가 달라진다.
name = "Sokuli"
# 리스트 데이터는 리스트의 요소 개수에 따라 메모리 크기가 달라진다.
numbers = [1, 2, 3, 4]
🔮 개발의 편의를 위해 Type Hint를 작성 할 수는 있다.
객체 생성과 메모리 관리 과정
파이썬 객체 생성 과정
1. 객체의 클래스 선택
- 객체를 생성하기 위해 클래스를 선택한다.
- 클래스는 객체의 특성과 동작을 정의하는 템플릿 역할을 한다.
2. 인스턴스화
- 클래스를 이용하여 객체(인스턴스)를 생성한다.
- 이 과정에서 객체의 메모리가 할당되고, 해당 객체의 상태를 초기화한다.
3.__init__ 메서드 호출
- 생성된 객체는 클래스 내의 __init__ 메서드(생성자)를 호출하여 초기화된다.
- 이 메서드는 객체가 생성될 때 한 번 실행되며, 객체의 초기 상태를 설정하는 역할을 한다.
파이썬 메모리 관리 과정
1. 동적 메모리 할당
- 객체가 생성될 때 필요한 메모리 공간을 동적으로 확보한다.
- 이로 인해 개발자가 메모리 할당과 해제에 직접 신경 쓰지 않아도 된다.
2. 가비지 컬렉션 (garbage collection)
- 가비지 컬렉션은 더 이상 사용되지 않는 객체들을 주기적으로 탐지하고 수거한다.
- 객체가 더 이상 사용되지 않으면 해당 객체는 가비지 컬렉션의 대상이 된다.
3. 참조 카운트 (reference count)
- 객체가 생성될 때 해당 객체를 참조하는 변수나 객체들의 개수를 카운트한다.
- 참조하는 변수나 객체의 개수가 0이 되면 해당 객체는 메모리에서 자동으로 제거된다.
4. 순환 참조 탐지
- 가비지 컬렉션은 순환 참조(reference cycle)를 탐지하여 메모리 누수를 방지한다.
- 순환 참조란 서로가 서로를 참조하는 상황을 의미한다.
- 가비지 컬렉션은 순환 참조로 인해 메모리 누수가 발생하는 것을 감지하고 이를 처리한다.
가변객체, 불변 객체의 메모리 비교
가변객체란?
가변 객체는 객체가 생성된 후에도 내부의 데이터를 수정하거나 추가할 수 있다.
예를 들어, 리스트(list)는 가변 객체로, 리스트에 요소를 추가, 삭제, 변경할 수 있다.
my_list = [1, 2, 3]
my_list.append(4) # 리스트에 새로운 요소 추가
my_list[0] = 100 # 리스트의 첫 번째 요소 변경
가변 객체의 메모리 할당 영향
- 메모리 사용량 증가
- 가변 객체는 내용을 변경하거나 추가할 수 있어 메모리 공간이 동적으로 변할 수 있다.
- 객체가 사용하는 메모리 양이 증가할 수 있다.
- 메모리 누수 가능성
- 가변 객체가 계속해서 변화하고 참조되는 경우,
객체가 더 이상 필요하지 않더라도 메모리가 해제되지 않을 수 있다.
- 가변 객체가 계속해서 변화하고 참조되는 경우,
🔮 메모리 누수(Memory Leak)란?
: 프로그램에서 더 이상 사용되지 않는 메모리가 해제되지 않고 계속해서 쌓이는 현상
불변객체란?
불변 객체는 객체가 생성된 후에는 해당 객체의 내부 데이터를 수정할 수 없다.
예를 들어, 정수(int), 실수(float), 문자열(str)은 불변 객체이다.
파이썬에서 불변 객체의 값을 변경하려고 하면 해당 객체를 새로 생성하여 값을 할당하는 방식으로 처리한다.
my_int = 10
my_str = "Hello"
# 아래와 같이 불변 객체의 값을 변경하려고 하면 오류 발생
# my_int = 20
# my_str[0] = "X"
불변 객체의 메모리 할당 영향
- 메모리 사용량 고정
- 객체가 생성될 때 할당된 메모리 공간이 변하지 않으며, 객체가 사용하는 메모리 양이 고정된다.
- 안정적인 공유 가능
- 불변 객체는 여러 변수 또는 함수에서 안전하게 공유될 수 있다.
- 동일한 값을 갖는 불변 객체는 메모리에 하나만 생성되고,
이후에는 같은 값을 가진 변수들이 해당 객체를 참조한다. - 불필요한 중복 메모리 할당을 피할 수 있다.
- 스레드 안정성 보장
- 불변 객체는 여러 스레드에서 안전하게 공유될 수 있다.
- 변경이 불가능하므로 여러 스레드에서 동시에 접근하더라도 객체의 내용이 변하지 않는다.
- 스레드 간의 동기화 문제가 발생하지 않는다.
마무리
이 글에서는 메모리란 무엇이며, 파이썬은 어떻게 메모리를 구조화하고 관리하는지 알아보았다. 메모리 할당 방법을 살펴보고, 파이썬에서 객체가 생성되고 메모리가 관리되는 과정을 이해했다. 또한 가변 객체와 불변 객체 사이의 메모리를 비교해보았다. 언어의 메모리 관리를 이해하고 사용하면 코드를 최적화하고 더 효율적으로 만드는데 도움이 된다.
'# Language > Python' 카테고리의 다른 글
[Python] 파이썬 입력 함수 비교: input() VS sys.stdin.readline() (0) | 2023.07.25 |
---|---|
[Pyhon] 파이썬 vars() 함수: 객체 속성을 다루는 도구 (0) | 2023.07.24 |
[Python] 파이썬 Type Annotation / Type Hinting (0) | 2023.03.24 |
[Python] 파이썬 에러 핸들링: Exceptions (0) | 2023.01.26 |