JavaScript에서 대규모 숫자의 경우 스프레드 연산자가 실패하는 이유를 분석하고 테스트해보며 stack size 이해하기

Description: 스프레드 연산자의 크기가 너무 커지는 경우 동일한 로직이더라도 문제가 생기는 특수한 경우를 알아보고 해결해봅시다.

현재 노트: KR-010.40 b
상위 분류: KR-010.40

#JavaScript

Why? 왜 이 글을 쓰게 되었나요?

JavaScript에서 당연하게 사용하던 스프레드연산자가 배열크기로 인해 런타임에러가 발생하였습니다.
단순히 다루는 수의 크기가 커지는 것만으로 발생할 수 있는 문제라는 점이 신선했었고, JavaScript를 깊게 이해하기 위한 부분이라 생각하여 트러블슈팅과 테스트 과정을 글로 작성하기로 했습니다.

What? 어떤 문제가 있었나요?

프로그래머스 퍼즐챌린지를 풀 던 도중 런타임 에러가 자꾸발생하였습니다.
런타엠 에러라길래 보통의 배열의 잘못된 인덱스 접근인줄 알고 로직으로 해결하려고하였으나, 계속 에러가 생겨서 포기하였습니다.
그래서 질문하기 코너를 찾아보았는데 그 중에 해당 문제를 언급한 글이 있었습니다.

런타임 에러의 원인은 스프레드 연산자의 배열크기 때문이라는 것.
이를 확인하기 위해 로컬 환경에서 에러를 구현해보기로 하였습니다.

How 어떻게 해결하셨나요?

검색 결과 약 10~15만 사이의 값이 상한선이라는 정보를 파악하여 처음에는 배열의 형태로 범위를 확인하였습니다. 처음에는 대략적인 값의 범위를 러프하게 좁히기 위해 5만, 1만, 1천단위로 상한선을 테스트한 후, 5천 정도의 범위가 확정이되면 프로그래밍으로 세밀한 값을 얻었습니다.

이후 좀더 정밀한 수치조절을 위해 값을 변경하였습니다.
Pasted image 20250407140954.png

좀더 정밀하게 1000단위로 대략적인 값을 측정하였습니다 최대 126000사이즈에서 에러확인.

이후 범위가 125000~126000이기에 iterator한 배열 형태로값을 측정해 정밀한 값을 얻었ㅅ브니다.
최대 크기 125064

하지만 여기서 더 나아가 "스프레드 연산자 배열의 최대 크기" 를 구해보면 어떨까 하는 생각에 테스트를 수행해보았습니다.
cm에서 다음과 같은 명령어를 통해 node의 기본 스펙을 확인할 수 있었습니다.
node --v8-options | findstr stack


C:\Users\User>node --v8-options | findstr stack
	...
  --stack-size (default size of stack region v8 is allowed to use (in kBytes))
        type: int  default: --stack-size=984
	...

여기서 984kB가 스택의 기본값인 것을 알았고,
Node.js의 숫자는 Number형을 사용하며 데이터당 8B를사용하기에 984kB기준으로 가능한 스택 사이즈를 계산한다면

984kB / 8 => 123000

즉 테스트에서 나왔던 125064와 유사한 값을 얻은 것을 확인할 수 있었습니다.

즉 Node.js의 stack-size의 기본값이 984kB에 가까운 값이기에 약 123000보다 큰 Number 데이터를 가지지못하는 것이었습니다.
(에러가 발생했던 프로그래머스 테스트는 입력이 최대 30만)

그렇다면 해당 사이즈만 크기를 키워준다면 동일한 로직일지라도 문제가 해결되는 것은 아닌가?라는 생각으로 테스트를 수행하였습니다. 그 결과 30만 배열의 크기일지라도 문제없이 동작하였습니다!
$ node --stack-size=4000 callstackSize.js

Retrospective 무엇을 배웠고, 어떻게 활용할까요?

가장 중요한 부분은 숫자가 커지는 것만으로 문제가 발생할 수 있는상황을 깨달은 점입니다.
흔히 대규모 트래픽과 같은 경우 기존의 아키텍처, 로직으로 감당히 불가능한 상황이 나오는 것으로 알고있습니다. 그런 상황을 이번 트러블 슈팅을 통해 느꼈습니다.

물론 추가적으로 stack의 사이즈를 직접 조사하는 방법과 그 크기를 예상하는 방법 등 좀 더 깊은레벨의 JavaScript 정확히는 Node.js의 구조를 이해하게됐습니다.