사전 메모리
개념

메모리

gabury1

메모리는 프로세서가 지금 처리하는 명령어와 데이터를 올려 두고 곧바로 꺼내 쓰게 해 줍니다. 프로그램을 실행하면 디스크에 있던 내용이 먼저 메모리로 올라옵니다. 전원이 꺼지면 메모리에 담긴 내용은 사라집니다. 휴대폰의 저장 공간도 흔히 메모리라고 부르지만 이 항목은 실행 중인 데이터를 담는 쪽을 다룹니다.

쉽고 빠른 이해

메모리는 실행 중인 프로그램이 쓰는 작업 공간입니다. 서버에서 돌고 있는 애플리케이션의 객체, 요청을 처리하는 동안 만든 변수, 캐시에 올려 둔 값이 전부 메모리에 있습니다.

왜 따로 두는지는 속도 때문입니다. 디스크는 큽니다. 전원이 꺼져도 내용이 남습니다. 대신 프로세서가 명령 하나마다 디스크를 기다리면 너무 느립니다. 그래서 당장 쓰는 것만 빠른 메모리로 옮겨 놓고 씁니다.

어떻게 도는가:

  1. 운영체제가 프로그램을 디스크에서 읽어 메모리에 올립니다
  2. 프로세서는 메모리에서 명령어를 하나씩 가져와 실행합니다
  3. 실행하다 필요한 데이터도 메모리에서 읽고 메모리에 씁니다

대가도 있습니다. 메모리는 디스크보다 작고 비쌉니다. 전원이 꺼지면 내용도 날아갑니다. 남겨야 할 데이터는 따로 디스크에 적어야 합니다. 다 쓰고 나면 프로그램이 느려지거나 강제로 종료됩니다.

상세

메모리를 일하는 사람의 책상에 빗대 봅니다. 책장에는 책이 많이 꽂혀 있지만 한 권 꺼내려면 일어나 걸어가야 합니다. 그래서 지금 보는 책만 책상에 펼쳐 둡니다.

비유에서 책상은 메모리입니다. 책장은 디스크입니다. 앞에서 말한 프로세서를 흔히 CPU(Central Processing Unit, 중앙처리장치)라고 부릅니다. 이 항목도 여기부터 CPU 라고 적습니다.

메모리는 CPU 가 지금 실행하는 명령어와 그 명령어가 다루는 데이터를 담는 저장 장치입니다. 교과서에서는 주기억장치라고 부릅니다. 파일을 오래 보관하는 디스크는 보조기억장치라고 부릅니다.

주소로 찾아가는 저장 공간

메모리는 바이트 단위의 칸이 길게 늘어선 모양입니다. 칸마다 0 부터 시작하는 번호가 붙습니다. 이 번호를 메모리 주소라고 합니다. CPU 는 「몇 번 주소의 값을 읽어라」「몇 번 주소에 이 값을 써라」로 메모리를 씁니다.

block-beta
columns 5
  a0["주소 0"] a1["주소 1"] a2["주소 2"] a3["주소 3"] a4["…"]
  v0["0x48"] v1["0x69"] v2["0x00"] v3["0x2A"] v4["…"]

그림 윗줄은 주소입니다. 아랫줄은 그 칸에 든 값입니다. 칸 하나에는 한 바이트가 들어갑니다. 큰 값은 이어진 여러 칸에 나눠 담깁니다.

어느 주소든 번호만 알면 곧장 찾아갑니다. 앞 칸부터 차례로 훑지 않아도 됩니다. 그래서 메모리를 RAM(Random Access Memory, 임의 접근 메모리)이라고도 부릅니다. 「임의 접근」은 아무 칸이나 골라서 같은 시간에 닿는다는 뜻입니다.

메모리를 따로 두는 이유

저장 장치는 빠를수록 작고 비쌉니다. 한 장치로 빠르기와 크기를 다 얻을 수 없습니다. 그래서 컴퓨터는 성격이 다른 저장 장치를 겹겹이 둡니다. 이 구성을 메모리 계층이라고 합니다.

표에 메모리보다 빠른 장치가 둘 나옵니다. 레지스터는 CPU 안에 있는 아주 작은 저장 칸으로, 지금 계산하는 값을 담습니다. CPU 캐시는 CPU 바로 곁에 붙은 작은 저장 장치로, 메모리에서 자주 읽는 내용을 복사해 둡니다.

저장 장치 속도 크기 전원이 꺼지면
레지스터 가장 빠릅니다 가장 작습니다 사라집니다
CPU 캐시 매우 빠릅니다 작습니다 사라집니다
메모리 빠릅니다 중간입니다 사라집니다
디스크 느립니다 큽니다 남습니다

표에서 볼 것은 메모리가 가운데에 있다는 점입니다. 레지스터와 CPU 캐시는 CPU 에 붙어 있어 아주 빠릅니다. 대신 프로그램 하나를 다 담기에도 작습니다. 디스크는 넉넉합니다. 하지만 CPU 가 기다리기에는 느립니다.

메모리는 이 둘 사이를 메웁니다. 실행 중인 프로그램 전체를 담을 만큼 큽니다. CPU 가 명령어마다 읽어도 버틸 만큼 빠릅니다.

전원이 꺼지면 사라지는 성질

메모리는 휘발성 저장 장치입니다. 전기가 들어오는 동안에만 값을 붙들고 있습니다. 서버가 갑자기 꺼지면 메모리에만 있던 데이터는 되살릴 방법이 없습니다.

백엔드에서 이 성질은 설계에 바로 드러납니다. 데이터베이스는 바뀐 내용을 메모리에서 먼저 처리합니다. 그러면서 같은 변경을 디스크의 로그에도 적습니다. 서버가 죽어도 로그를 다시 읽어 되살리기 위해서입니다.

캐시는 사정이 다릅니다. 캐시에는 원본이 따로 있는 값만 담습니다. 서버가 꺼져 캐시가 비어도 원본에서 다시 가져오면 됩니다. 그래서 메모리에만 둬도 괜찮습니다.

프로그램이 메모리에서 도는 흐름

프로그램 파일은 평소 디스크에 있습니다. 디스크에 있는 채로는 CPU 가 실행할 수 없습니다. CPU 는 메모리에 있는 명령어만 가져와 실행하기 때문입니다.

flowchart TD
    A["디스크의 프로그램 파일"] --> B["운영체제가 메모리에 올린다"]
    B --> C["CPU 가 메모리에서 명령어를 가져온다"]
    C --> D["명령어를 실행하며 메모리의 데이터를 읽고 쓴다"]
    D --> C

그림의 되돌아가는 화살표가 프로그램이 도는 동안 되풀이되는 부분입니다. 명령어 하나를 끝내면 다음 명령어를 다시 메모리에서 가져옵니다.

프로세스마다 나눠 쓰는 메모리

한 컴퓨터에서 여러 프로세스가 동시에 돕니다. 이들이 같은 주소를 마구 쓰면 서로의 값을 덮어씁니다. 그래서 운영체제는 프로세스마다 자기만의 주소 범위를 줍니다. 이 범위를 주소 공간이라고 합니다.

프로세스가 보는 주소는 실제 메모리 칸의 번호와 다릅니다. 운영체제와 CPU 가 둘을 짝지어 바꿔 줍니다. 이 방식을 가상 메모리라고 합니다. 덕분에 한 프로세스는 다른 프로세스의 메모리를 볼 수 없습니다.

프로세스 하나의 주소 공간은 쓰임에 따라 몇 구역으로 나뉩니다.

block-beta
columns 1
  s["스택 영역 · 함수 호출마다 쌓였다 빠진다"]
  g["비어 있는 구간"]
  h["힙 영역 · 실행 중에 요청해서 받는다"]
  d["데이터 영역 · 전역 변수"]
  c["코드 영역 · 실행할 명령어"]

그림의 영역을 아래부터 하나씩 봅니다.

  • 코드 영역에는 CPU 가 실행할 명령어가 들어갑니다.
  • 데이터 영역에는 프로그램이 끝날 때까지 살아 있는 전역 변수가 들어갑니다.
  • 힙 영역은 실행 중에 필요한 만큼 요청해서 받는 곳입니다. 객체를 새로 만들면 대개 여기 놓입니다.
  • 스택 영역은 함수를 부를 때마다 지역 변수를 쌓고, 함수가 끝나면 걷어 내는 곳입니다.

힙과 스택은 실행하는 동안 크기가 늘었다 줄었다 합니다. 그래서 둘 사이를 비워 두고 서로 그 빈 구간 쪽으로 자라게 합니다. 그림의 「비어 있는 구간」이 그 여유 공간입니다.

힙에서 받은 메모리는 다 쓰면 돌려줘야 합니다. 돌려주는 일을 사람이 코드로 하는 언어가 있습니다. 가비지 컬렉션이 알아서 거둬 가는 언어도 있습니다. 안 쓰는데 돌려주지 않고 계속 쥐고 있으면 메모리 누수가 됩니다.

메모리가 모자랄 때

프로세스들이 요청한 양이 실제 메모리보다 커지는 때가 옵니다. 운영체제는 한동안 안 쓴 내용을 디스크로 내려 보내 칸을 비웁니다. 이 일을 스와핑이라고 합니다. 나중에 그 내용이 다시 필요하면 디스크에서 읽어 올립니다.

스와핑은 프로그램을 멈추지 않게 해 줍니다. 대가는 속도입니다. 메모리에서 읽던 것을 디스크에서 읽게 됩니다. 그만큼 프로그램 전체가 눈에 띄게 느려집니다.

디스크로 내리는 것으로도 모자라면 운영체제는 프로세스 하나를 골라 강제로 끝냅니다. 리눅스 커널에서는 메모리 부족 킬러가 이 일을 맡습니다. 서버에서 애플리케이션이 로그 한 줄 없이 사라졌다면 이것부터 의심합니다.

컨테이너로 서비스를 돌리면 이 한계가 기계 전체가 아니라 묶음 단위로 걸립니다. cgroup이 프로세스 묶음마다 쓸 수 있는 메모리의 상한을 정하기 때문입니다. 기계에 메모리가 남아 있어도 그 묶음이 상한을 넘으면 강제로 종료됩니다.

메모리라는 낱말이 가리키는 범위

일상에서는 이 낱말이 더 넓게 쓰입니다. 휴대폰이나 휴대용 저장 장치의 용량을 메모리라고 부르기도 합니다. 그쪽은 전원이 꺼져도 남는 플래시 메모리입니다. 이 항목의 메모리와는 역할이 다릅니다.

「메모리 사용량」이라고 할 때는 대개 이 항목의 메모리를 말합니다. 그래픽 카드에 따로 달린 메모리도 있습니다. 화면과 계산에 쓸 데이터를 그래픽 처리 장치 곁에 둡니다. 쓰임은 같습니다. 놓인 장치만 다릅니다.

관련 항목

메모리와 함께 메모리 계층을 이루는 저장 장치

레지스터 · CPU 캐시 · 디스크 · SSD · 플래시 메모리 · 메모리 계층

메모리를 이루는 부품과 단위

바이트 · 메모리 주소 · DRAM · SRAM · 메모리 모듈 · 메모리 버스

메모리를 읽고 쓰는 장치와 소프트웨어

CPU · 운영체제 · MMU · 커널 · 메모리 할당자

운영체제가 메모리를 나눠 주는 방식

가상 메모리 · 주소 공간 · 페이지 · 페이지 테이블 · 페이지 폴트 · 스와핑 · 메모리 매핑

프로세스 주소 공간을 이루는 구역

코드 영역 · 데이터 영역 · 힙 · 스택

메모리에서 자주 나는 오류와 장애

메모리 누수 · 메모리 부족 킬러 · 메모리 부족 · 버퍼 오버플로 · 세그멘테이션 폴트 · 스래싱

메모리 사용을 묶고 제한하는 수단

cgroup · 컨테이너 · 프로세스 · 가비지 컬렉션 · 메모리 사용량 · 힙 크기

메모리에 올려 두고 쓰는 저장 방식

캐싱 · 인메모리 데이터베이스 · 페이지 캐시 · 버퍼

메모리가 지닌 성질과 그 반대 성질

휘발성 · 비휘발성 · 영속성 · 임의 접근

메모리 대신 데이터를 오래 남기는 수단

로그 · 선행 기록 로그 · 데이터베이스 · 파일 시스템

다른 이름: memory · 주기억장치 · 주 메모리 · main memory · RAM · 램