Heap 과 Stack 차이점

김형섭 (Matthew)·2024년 1월 25일
39

개발 팁/테크

목록 보기
10/15
post-thumbnail
post-custom-banner

Why

변수의 값은 메모리에 저장되죠.
프로그램은 결국 변수에 값을 넣고 계산하고 처리하고 다시 보여주는 일들의 반복 입니다.

모든 프로그램은 스택이라는 2가지 메모리 저장소를 사용 하는데요.
차이점이 뭘까요? 아니 왜 구분 할까요?

값을 저장한다는 것

값이란 변수에 담겨있는 데이터 그 자체 입니다.
예를 들어 a 라는 변수에 1 이 들어 있다면 값은 1이죠.

“그렇군, 1을 저장하는 군”, 이라고 넘어가지 말고 한번만 더 생각해 봅시다.
a = 1 인 상황에서 우리가 알 수 있는 것을 말이죠.

먼저, 1 이라는 값을 (내가) 알고 있습니다.
바로, 숫자 라는 것이죠.
1을 저장 할 수 있다면 2도, 3도, 100도 저장할 수 있어야 합니다.

변수의 크기

무엇을 저장할 지 미리 알고 있기 때문에, 얼마까지 저장할 지 한계치의 크기가 필요해지고, 그에 따라 여러개의 타입중 하나를 정해야 합니다.

전통적으로 Int 형(그 형 말고 Type)이 있는데요.

이 타입은 정수를 말하는데 4바이트 용량으로 -2,147,483,648 ~ 2,147,483,647 중 하나를 저장합니다.
최대값이 21.4억 정도로 현실세계에서는 이 값을 넘는 경우가 종종 발생 하죠.

그런데, 요즘은 64비트 CPU가 많기 때문에 기본 타입이 4바이트 Int 가 아니라 8바이트 Int64 도 많이 사용 합니다.
이 경우 비트 수가 2배가 되어, 약 -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 중 하나를 저장하고 현실세계에서 사용하는 숫자 범위 대부분을 커버 하죠.

가끔 64비트 전용으로 개발된 프로그램을 32비트로 실행할 수 있느냐고 묻는 질문들이 있는데,
위와 같은 이유로 불가능 합니다. 숫자 범위가 달라 모든 계산이 틀어질 수 있거든요.

변수 타입과 범위에 대해서는 인터넷에 아주 많은 정보가 있습니다.
오늘의 주제는 변수가 아니고, 변수에는 각각 사용하게 될 byte 크기가 사전에 정해져 있다이기 때문에 여기까지만 알면 됩니다.

변수의 크기가 정해져 있다면

이제 입장을 바꿔보죠. 여러분이 컴퓨터에요.
유저가 제공한 값을 메모리에 저장 하려고 하는데요.

이해하기 쉽게, 값을 A4 용지라고 생각하고, 메모리를 A4 바인더 라고 생각해봐요.
이제 값이 A4 용지로 몇 페이지나 있는지 중요할 것입니다.
너무 크면 A4 바인더에 안 들어가니까요.

아무튼, 잘 차곡 차곡 앞부분 부터 채워 넣고 찾기 쉽게 라벨 스티커도 잘 붙여놓았다고 해봅시다.

값 찾기

유저가 무슨무슨 A4 용지를 달라고 하네요.
그럼 바인더에서 일단 찾아야 겠죠?

라벨링을 잘 해둬서 찾기는 쉽게 찾았어요.
근데 어디까지 꺼내야 할까요?

자세히 보니 문서의 맨 앞에 총 페이지수가 있네요. (값의 크기)
오케이 간단합니다. 찾은 부분 부터, X 페이지를 꺼내면 되네요~
빠르게 찾을수 있고, 빠르게 꺼낼수 있었습니다.

변수의 크기가 정해져 있지 않다면

위 예시는 좋은 사례 입니다.

빨리 찾았고, 몇페이지 인지도 알고 있어서 금방 가져올수 있었죠.
그런데, 문서가 몇페이지 인지 모른다면 어떻게 해야 할까요.

당연히 다음 문서가 나올때까지 한장씩 넘기면서 찾을수 밖에 없겠죠?

찾는건 라벨링을 했으니 빠른데, 정작 꺼내는데 시간이 걸리고 맙니다.

위 예시가 바로 스택과 힙 입니다. (잉?)

쉽게 설명하고자 약간의 비유를 했습니다만, 정확히 저것이 스택과 힙 입니다.

Stack

  • 변수 크기가 고정됨
  • 값을 가져오는 것이 빠름
  • 용량 적음
  • LIFO (후입선출) → 후입선출은 이번 글에서 이해하지 않아도 지장 없어요~

Heap

  • 변수 크기를 모름 (바뀜)
  • 값을 가져오는 것이 느림
  • 용량 큼 (RAM 만큼)

그럼, 항상 더 빠른 스택을 쓰면 되지 않을까요?

아쉽게도, 우리가 개발을 할 때 값의 크기를 알수 없는 경우가 굉장히 많습니다.

간단한 게시글을 입력 받는 다고 해봅시다.
여러분은 이 글의 길이가 얼마나 될지 미리 예상 할 수 있나요?

없죠. 그래서 힙이 필요 합니다.
힙 영역은 미리 크기를 알수 없는 대신, 많은 용량을 저장 할 수 있습니다.

그럼 스택은 왜 굳이 용량을 제한해요?

굳이가 아니라 논리적인 이유 입니다.

스택이 메모리 크기를 미리 어떻게 알 수 있을까요?
바로 소스코드 입니다.

소스코드의 모든 고정 크기 변수의 합이 스택의 용량으로 프로그램마다 사전에 딱! 결정 됩니다.
따라서, 프로그램이 시작 될 때 소스코드에 기반하여 총 스택 용량이 결정되며, 변수 하나하나 마다 제 용량을 갖게 됩니다.

그외의 변수는 모두 가변크기 이므로 프로그램을 실행 한 후 힙에 저장 됩니다.

결국, 논리적인 이유 입니다.

스택은 소스코드를 기반으로 프로그램마다 사용할 용량이 정해져서 부트스트래핑 시 할당 받게 되며,
한번 정해진 크기를 벗어날 수 없습니다.

그 유명한 StackOverflow 아시죠?
스택에 고정된 크기로 할당 했는데, 그 변수의 한계를 넘어가는 바이트를 요청할때 나오는 오류 이름 입니다.

대신, 프로그램은 고정 크기의 변수만 사용 할 수는 없으므로 (미리 알 수가 없으니까)
그런 런타임 동적 변수, 동적 크기는 모두 힙이라는 공간에 저장하므로써 프로그램이 돌아갈 수 있게 되죠.

마무리

오늘은 스택과 힙의 차이점을 알아봤어요.

일반적으로 스택과 힙을 설명하는 글들은 맥락이 없어 다소 어려웠을 겁니다.
조금이나마 이해 하시는데 도움이 되셨기를 바라겠습니다.

  • javanode.js 에서 GC가 도대체 어느 영역에 관여하는 것인지
  • 자바 힙 메모리 설정에서 이름이 왜 힙인지
  • OOM 이 나오면 뭘 봐야 할지 (무슨 변수가 원인인지)

많은 의문이 해결 되실거예요.

오늘도 즐거운 하루 되세요.
다음에도 좋은 글로 찾아뵐께요.

아임웹 CTO
매튜 드림.

profile
CTO at Imweb, 20년차 개발 장인, 전) 플레이오토 CTO/창업자
post-custom-banner

4개의 댓글

comment-user-thumbnail
2024년 1월 25일

좋은 글 감사합니다

답글 달기
comment-user-thumbnail
2024년 1월 30일

잘 읽었습니다

답글 달기
comment-user-thumbnail
2024년 2월 3일

좋은 내용 감사합니다. 혹시 그림은 어느 사이트에서 찾으셨는지 여쭤봐도될까요?
저런 느낌의 이미지를 원하는데 찾기가 어렵네요 ㅠ

1개의 답글