메모리(Memory)란? - 메모리를 제어하는 개발자
1. 메모리가 부족해요
[JS]
- "Out of memory: process ran out of memory"
- "RangeError: out of memory"
[SWIFT]
- "Fatal error: Out of memory"
- "Thread 1: EXC_RESOURCE RESOURCE_TYPE_MEMORY (limit=XX MB, unused=0x0)"
[JAVA / KOTLIN]
- "java.lang.OutOfMemoryError: Java heap space"
- "java.lang.OutOfMemoryError: GC overhead limit exceeded"
개발자들에게 "메모리가 부족" 하다는 문제는 친숙하게 느껴진다.
-. 위와 같은 에러메세지로 만나본적도 있고,
-. 유저들로 부터 "로딩이 너무 느려요" 와 같은 문제로 만나본적도 있으며,
-. 어떠한 에러에 대해 "메모리 부족인가?" 와 같은 원인을 추측해보기도 한다.
[메모리] 부족의 문제를 나는 구체적으로 어떻게 해결했는지 생각해보면, 물론 정확하게 원인을 찾아 수정한 경우도 있었지만, 시간이 흘렀거나, 재부팅, 앱을 껏다 키는 행위 등을 통해 문제가 해결되어 버린 경우도 많은 것 같다.
메모리를 정확하게 알고 조작하는 레벨로 오르기를 바라며, [메모리]에 대한 지식을 정리해보려고 한다.
2. 컴퓨터의 작업 방식
1) CPU 와 Memory 의 협업
컴퓨터가 작동하는 방식을 간략하게 표현하자면, 외부에서 들어오는 다양한 입력값(Input)을 CPU가 처리하여 출력(Output)하는 방식이다.
위의 문장을 도식화하면 아래와 같이 나타낼 수 있다.
CPU가 처리하는 것 중 대표적인 2가지로 [Control Unit] 과 [Logic Unit]이 있다.
[Control Unit] 은 정보처리 역할로, 명령어들을 읽고 해석하며 데이터 처리에 대한 순서를 결정한다.
[Logic Unit] 은 계산 또는 연산을 처리하는 역할을 담당한다.
명령어들을 [Control Unit]이 해석하고, 순서를 결정하여 [Logic Unit]을 통해 연산하여 결과를 출력 한다고 보면 된다.
그러나 위와 같이 CPU만 있으면 조금이라도 복잡한 로직은 처리할 수 없게된다.
어떻게 계산할지, 무엇을 계산하지를 CPU는 기억할 수 없기 때문이다.
예를 들어 아래와 같은 코드가 있다고 가정했을 때,
func setCase(a:Int) -> Bool {
if(a === 0){
return false
}else{
return true
}
}
setCase(a:0)
//Swift
setCase 라는 함수를 기억하지 못하면 컴퓨터는 어떻게 계산해야 하는지 알 수 없어 해당 함수를 가진 명령어가 들어와도 처리할 수 없게 된다.
이를 도와주는 것이 [Memory]이며 컴퓨터는 완전한 작동을 위해 아래와 같이 구성된다.
이제 이렇게 생각해볼 수 있을 것 같다.
개발자는 [Memory]에 어떤 방식으로 유저의 입력을 처리할지 저장하는 것이고, CPU는 이를 꺼내서 연산하고 출력하는 것이다.
3. Memory의 종류
좋은 성능을 가지도록 한 개발은 CPU가 빠르게 메모리의 정보를 읽고 쓰도록(access) 하는 개발이라고 볼 수 있는것 같다.
CPU가 상황에 맞게 메모리에 access할 수 있도록 한다면 출력이 원활할 수 있을 것이다.
먼저 종류를 알아보자
1) RAM (Random Access Memory)
- 컴퓨터 시스템에서 가장 일반적으로 사용되는 메모리 형태이다.
- CPU가 데이터와 명령어에 빠르게 엑세스 할 수 있도록 정보를 저장한다.
- 데이터를 읽고 쓰는 데에 높은 속도를 가지며, 임의로 엑세스 할 수 있다는 특징을 가지고 있다.
- 전원이 꺼지면 저장된 데이터가 사라지는 휘발성 메모리이다.
2) ROM (Read-Only Memory)
- 읽기 전용 메모리이다.
- 시스템 초기화 및 부팅 프로세스와 관련된 기본적인 정보를 저장한다.
- 전원이 꺼져도 데이터가 사라지지 않는 비휘발성 메모리이다.
3) Cache Memory
- CPU와 메모리 사이에서 데이터와 명령어를 임시로 저장하는 고속 메모리 이다.
- CPU가 반복적으로 엑세스하는 데이터를 미리 저장하여 엑세스 시간을 단축시키고 성능을 향상 시킬수 있다.
- 하드웨어 수준에서 관리되는 메모리이다.
4) Virtual Memory
- RAM용량을 넘어서는 프로그램 및 데이터를 처리하기 위한 기술이다.
- 물리적인 메모리 제약을 극복하고 다중 프로그램 실행 및 성능 향상을 지원한다.
5) Flash Memory
- 비휘발성 메모리로, 전원이 꺼져도 데이터가 저장된다.
- 데이터를 영구적으로 저장할 수 있는 소형 반도체 기억장치이다.
- 주로 휴대폰, 카메라, USB드라이브, SSD 등에서 사용된다.
메모리 종류와 각각의 특징을 간단하게 정리해 보았다.
이제 개발자가 활용할 수 있는 메모리는 어떤것이 있을까?
나는 iOS와 WEB 서비스를 개발하고 있어, 브라우저의 메모리는 추후 살펴보기로 하고
네이티브 개발자가 다룰 수 있는 메모리를 분류해 보았다.
- RAM
- 생명주기 관리 ( 메모리 누수 방지 / 메모리 사용 최적화 )
- 리소스 관리 (이미지, 동영상 등)
- 캐싱 ( 자주 사용되는 데이터, 중복 계산 결과를 캐싱하여 로딩 속도 최소화 )
- 비동기 처리
- 메모리 프로파일 (메모리 누수, 사용량 분석)
- Virtual Memory
- Java, Kotlin 안드로이드 제어 가능
- Swift iOS 제어 불가능
- Flash Memory
- File System
- Storage Access Framework [AOS]
- 데이터베이스
- SQLite
- [iOS] UserDefaults, CoreData
- [aOS] SharedPreferences
4. 정리
가장 중요한것은 CPU가 빠르게 메모리에 엑세스 할 수 있도록 하는 것이다.
내가 다루는 기술이 접근할 수 있는 메모리의 종류와 특성을 알았으니, 이제 상황에 맞춰 어떻게 CPU가 메모리에 빠르게 접근 할 수 있도록 할지 설계하면 된다.
어떤 상황에 어떤 메모리에 접근해야 하는지 특징과 용어를 알게 되었으니, 메모리에 접근하여 제어하는 명령어들은 검색하면 된다.
큰 틀에 대해서 알아보았으니, 점점 더 깊게 알아보고 정리하려고 한다.
RAM은 개발을 하면서 일반적으로 가장 많이 제어하는 메모리인 만큼 RAM에 대한 정보를 더 알아보는 방향으로 정하였다.