본문 바로가기

[Project] 프로젝트 삽질기42 (feat 테스트 중 node.js 메모리 부족)

어가며

Github action을 활용하여 CICD를 구축하는 과정에서 여러 삽질들을 반복하고 있습니다. 그중, CI 단계에서 테스트 코드를 수행하는 도중 테스트 코드가 제대로 동작하지 않는 문제를 발견했습니다. 이 문제를 다시는 겪지 않기 위해 문제를 정리하고, 이 문제를 어떻게 해결했는지에 대한 과정을 글로 정리합니다.

 

 

 

 

 


 

 

 

 

 

 

 

 

 

 

메모리 관리

Github action으로 테스트 코드를 실행하다 갑자기 테스트가 실패했다는 문구들이 보이기 시작했습니다. 분명 로컬 환경에서는 테스트 코드가 제대로 동작하는데 어떤 문제 때문인지 확인해보니 아래와 같은 알 수 없는 에러를 살펴볼 수 있었습니다.

 

 

 

(node:1363) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 
31 unpipe listeners added to [Console]. Use emitter.setMaxListeners() to increase limit
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory

<--- Last few GCs --->


[26828:0000020CB062E7D0]   706683 ms: Scavenge 7849.4 (8214.7) -> 7839.2 (8214.7) MB, 556.0 / 0.0 ms  (average mu = 0.131, current mu = 0.014) allocation failure 
Writing Node.js report to file: report.20200214.173258.26828.0.001.json[26828:0000020CB062E7D0]   708430 ms: Scavenge 7851.5 (8214.7) -> 7842.8 (8215.7) MB, 1247.6 / 0.0 ms  (average mu = 0.131, current mu = 0.014) allocation failure 
[26828:0000020CB062E7D0]   708535 ms: Scavenge 7855.6 (8215.7) -> 7846.4 (8218.7) MB, 32.1 / 0.0 ms  (average mu = 0.131, current mu = 0.014) allocation failure 


<--- JS stacktrace --->

==== JS stack trace =========================================

    0: ExitFrame [pc: 00007FF742BAB21D]
Security context: 0x0314ac3808d1 <JSObject>
    1: /* anonymous */ [000002D987624109] [C:\Users\Desktop\project\node_modules\jsonparse\jsonparse.js:~127] [pc=000001C121A8459D](this=0x0314ac3b5539 <Parser map = 0000007B595C11A9>,0x02a34c9a8251 <Uint8Array map = 00000236682E5379>)
    2: /* anonymous */ [00000314AC3B0549] [C:\Users\Desktop\project\node_modules\JSONStream\inde...


Node.js report completed
 1: 00007FF741FAF22F napi_wrap+125087
 2: 00007FF741F4FAA6 public: bool __cdecl v8::base::CPU::has_sse(void)const __ptr64+35302
 3: 00007FF741F50776 public: bool __cdecl v8::base::CPU::has_sse(void)const __ptr64+38582
 4: 00007FF742767D4E private: void __cdecl v8::Isolate::ReportExternalAllocationLimitReached(void) __ptr64+94
 5: 00007FF742750371 public: class v8::SharedArrayBuffer::Contents __cdecl v8::SharedArrayBuffer::Externalize(void) __ptr64+833
 6: 00007FF74261BDEC public: static void __cdecl v8::internal::Heap::EphemeronKeyWriteBarrierFromCode(unsigned __int64,unsigned __int64,class v8::internal::Isolate * __ptr64)+1436
 7: 00007FF742627040 public: void __cdecl v8::internal::Heap::ProtectUnprotectedMemoryChunks(void) __ptr64+1312
 8: 00007FF742623B64 public: static bool __cdecl v8::internal::Heap::PageFlagsAreConsistent(class v8::internal::HeapObject)+3204
 9: 00007FF742619373 public: bool __cdecl v8::internal::Heap::CollectGarbage(enum v8::internal::AllocationSpace,enum v8::internal::GarbageCollectionReason,enum v8::GCCallbackFlags) __ptr64+1283
10: 00007FF7426179E4 public: void __cdecl v8::internal::Heap::AddRetainedMap(class v8::internal::Handle<class v8::internal::Map>) __ptr64+2452
11: 00007FF742638C7D public: class v8::internal::Handle<class v8::internal::HeapObject> __cdecl v8::internal::Factory::NewFillerObject(int,bool,enum v8::internal::AllocationType,enum v8::internal::AllocationOrigin) __ptr64+61
12: 00007FF74239CF71 public: class v8::internal::interpreter::JumpTableTargetOffsets::iterator & __ptr64 __cdecl v8::internal::interpreter::JumpTableTargetOffsets::iterator::operator=(class v8::internal::interpreter::JumpTableTargetOffsets::iterator && __ptr64) __ptr64+1681
13: 00007FF742BAB21D public: virtual bool __cdecl v8::internal::SetupIsolateDelegate::SetupHeap(class v8::internal::Heap * __ptr64) __ptr64+544781
14: 000001C121A8459D 

Process finished with exit code 134

 

 

 

 

문제를 살펴보니, 과도한 메모리 점유로 인해 JS 엔진이 버티지 못해 에러를 내보내고 있었습니다. 이 문제를 해결하기 위해서는 Nodejs의 기본 메모리를 올리는 방법과 메모리 누수를 개선하는 방법이 있을 것입니다.

 

테스트 코드를 수행하는 과정에서 어디서 메모리를 많이 잡아먹는지 살펴보는 것이 대단히 중요하겠지만, 현재 개발하고 있는 서비스에서는 사용자를 위해 다양한 기능을 제공하는 것이 우선적이라고 생각하여, 메모리 누수 개선 대신 더 크게 메모리를 할당하는 것으로 문제를 해결했습니다. 

 

 

 

- name: Test with DB
        env:
          NODE_OPTIONS: '--max-old-space-size=8192'
        run: npm run test:report

 

 

테스트를 수행하는 Github Action의 코드에서 NODE_OPTIONS를 활용하여 기본 메모리 사이즈를 늘렸습니다. Node.js의 기본 메모리는 512MB를 초과하면 앱이 종료되기에, 임의로 메모리를 구성했습니다.

 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

마치며

앞으로도 팀의 발전을 돕는 개발자가 되기 위해 노력하려 합니다. 팀에 필요한 부분이 무엇일지 고민하면서, 팀에 도움이 된다면, 열심히 공부해서 실무에 적용할 수 있는 개발자가 되기 위해 노력하고 싶습니다. 팀의 성장에 기여할 수 있는 개발자가 되겠습니다. 

 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

참고 및 출처

 

JavaScript Heap Out Of Memory Error

A quick solution that you can use to fix "Heap Out Of Memory Error" in JavaScript. We lay out the causes and how to prevent them.

blog.openreplay.com

 

 

Nodejs - 메모리 JavaScript heap out of memory

1. 오류 2. 해결방법 1. 오류 노드를 하다 보면 아래와 같은 오류를 만날 수 있다. FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory [26828:0000020CB062E7D0] 706683 ms: Scavenge

ajh322.tistory.com

 

Nodejs - 메모리 누수 확인

1. 개요 2. 메모리 누수란? 3. 메모리 누수 확인 4. 노드 크롬 디버거 5. 누수 발생 확인 수많은 글들이 노드의 메모리 누수에 대한 글들을 설명하고 해결방법, 대안을 포스팅했지만 정말 겉만 번지

ajh322.tistory.com

 

Nodejs - 메모리 할당 사이즈 변경

Nodejs의 기본 메모리 사이즈를 512MB 초과하면 자동으로 앱이 종료된다. 기본 메모리 사이즈를 늘리는 방법에 대해서 알아보자. 커맨드라인 환경에서는 node --max-old-space-size=12000 app.js 로 하면 된다.

ajh322.tistory.com

 

Where do I set 'NODE_OPTIONS="--max-old-space-size=2048"'

When I run "npm start" in application I get the following error - FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory Most of the solu...

stackoverflow.com