해당 글은 SOPT 30기 활동 중 SOPT 기술 블로그에 제가 작성했던 글입니다.
목차
[에러] JavaScript heap out of memory
무중단 배포를 위해 build 하던 중 터미널에서 아래와 같은 에러가 발생했습니다.
'JavaScript heap out of memory'라는 이 에러는 Heap 메모리가 부족해서 발생한 것입니다.
[해결책 1] 더 큰 메모리 할당
- 현재용량 확인하는 방법
- 용량 늘리는 방법
이 두 코드를 터미널 창에 입력해, 용량을 늘린 후 현재 용량을 다시 확인하면 499.25에서 800으로 용량이 늘어나있음을 확인할 수 있습니다.(800은 예시일 뿐, 용량 크기는 변경해보면서 적절하게 조절하시면 더 좋습니다. 저희는 600, 700, 800 순으로 차례로 테스트해보다 800부터 에러가 해결되는 걸 확인할 수 있었습니다.)
매번 서버를 재배포할 때마다 터미널에 위 코드를 입력하는게 번거로우시다면, .bashrc 파일에 위의 용량 늘리는 코드를 그대로 추가하셔도 됩니다.
저희 서버의 경우, 이 build 에러로 인해 무중단 배포에 실패해 불편함을 겪고 있었습니다,, (400 에러로 서버가 꺼지면 수동으로 다시 직접 켰습니다,,)
빠르게 build 에러를 해결하는 게 중요했기에 [해결책 1]을 우선 사용했고, 무중단 배포를 성공할 수 있었습니다.
그러나 [해결책 1]은 근본적인 해결책이 아닙니다. 어딘가에서 메모리 누수가 발생하고 있는 것일 수 있으므로 메모리 누수를 검사해 봐야합니다.
[해결책 2] 메모리 누수 검사
NodeJS에서 메모리 누수 검사를 하는 방법은 기본 inspector 또는 추가적인 메모리 누수 관측기를 사용하는 것입니다. 이 글에선 '노드 크롬 디버거'를 사용해 메모리 누수를 관측하는 방법 두 가지를 설명드리겠습니다.
방법 1) chrome://inspect로 켜는 노드 크롬 디버거
장점: 과정이 간단함
단점: 활용도 낮음(다른 툴로 확장 x)
요약: 터미널로 서버 키고 chrome://inspect 접속해서 디버거 켬. 디버거에서 직접 스냅샷 촬영하고 내용 확인함.
1. 터미널에서 프로젝트 루트 폴더 열기
2. 터미널에 아래 코드 입력하기 (src/index.ts는 본인 프로젝트의 시작 파일 경로로 수정하기)
- 시작파일이 TypeScript인 경우:
- 시작파일이 JavaScript인 경우:

위와 같이 시작파일이 제대로 동작하는 걸 확인했다면 3으로 넘어갑니다.
3. 크롬으로 chrome://inspect 열기. 조금 기다리다보면 두 번째 사진처럼 구동 중인 서버가 뜹니다.


4. inspect 클릭해서 디버거 켜기.
5. 메모리/프로필에서
1.1kB/초와 같이 나와있는 곳 유심히 살펴 보기. 이 상태에서 메모리 부하 일으키는 작업 실행해봤을 때, 이 수치가 계속해서 크게 증가한다면 누수일 가능성이 큽니다.
6. 스냅샷 촬영 이용해서 아무것도 하지 않은 상태에서 찍은 스냅샷과 부하 일으킨 후 찍은 스냅샷 비교하기.
방법 2) heapdump를 이용해 작동하는 노드 크롬 디버거
장점: heapdump의 활용도가 높음 (다른 툴에서 활용 가능)ex) IBM에서 제공하는 HeapAnalyzer툴은 heapdump를 분석함
단점: 과정이 복잡함
요약: 프로젝트에 heapdump 추가하고 새로 만든 API 이용해서 스냅샷 촬영함. 크롬 개발자 도구 열어서 스냅샷 내용 확인함.
- 프로젝트에 heapdump 모듈 설치하기
만일 설치 시 아래와 같은 error가 난다면?[해결책] node-modules 삭제 후 yarn으로 다시 만들기. 후에 yarn add heapdump 하면 정상적으로 깔림
- package.json에 heapdump 모듈 의존성 추가하기
- index.ts에 아래 코드 추가하기. "C:/Users/choo0/Desktop/" 부분은 각자 본인이 희망하는 snapshot 저장 장소로 바꾸기. (중요!) (저는 제 컴퓨터(choo0)의 바탕화면으로 했습니다)
- http://localhost:8000/heapdump 에 접속하면 지정해둔 장소에 snapshot이 만들어짐. (8000은 본인이 설정한 포트번호로 바꾸기)

(생성된 파일의 연결 프로그램은 중요치 않습니다. 제 컴퓨터에선 워드로 보이는데 무시하셔도 됩니다. 파일 형식만 HEAPSNAPSHOT 파일(.heapsnapshot)이면 됩니다. )
- 메모리 부하를 일으킨 후, 다시 http://localhost:8000/heapdump에 접속해서 snapshot 만들기. (이 snapshot은 현재 node.js가 사용중인 메모리 양이 클수록 추출하는 속도가 느려집니다.)
- 크롬 개발자 도구(오른쪽 상단 더보기(점 3개) > 도구 더보기 > 개발자 도구) 열기.

- 메모리/프로필에서 로드 버튼 눌러 앞서 만든 힙덤프 파일(snapshot) 올리기.
- snapshot 클릭해서 열어서 수없이 반복되는 객체가 있나 확인하기. 이를 통해 어떤 객체들이 메모리를 많이 점유해서 메모리 누수를 유발하는지 찾아낼 수 있습니다.
추가) 아래 코드 중 하나를 Controller에 추가해서 api를 여러 번 반복적으로 돌려보며 변하는 메모리 추이를 보고 간이로 누수를 체크해볼 수도 있습니다. (계속해서 크게 증가한다면 누수 가능성 큼)
참고
inspect -> https://ajh322.tistory.com/243
heapdump -> https://bcho.tistory.com/1097
heapdump -> https://yarnpkg.com/package/heapdump

