node.js ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ํ์ธ๊ณผ heap ๋ฉ๋ชจ๋ฆฌ ์ ํ ์ ์ฉํ๊ธฐ
ํ์ฌ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ํ์ธํ๊ธฐ ์ํด์๋ next.js์์ server๋ฅผ ์ปค์คํ
ํ์ฌ ๋ก๊ทธ๋ฅผ ํตํด ํ์ธํ ์ ์๋ค.
๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ์์๋ด๋ ๋ฐฉ๋ฒ์ GPT์ ๋์์ ๋ฐ์ process.memoryUsage()๋ฅผ ํตํด ์ ์ ์๋ค๋ ๊ฒ์ ํ์ธํ๋ค.
1. process.memoryUsage์ ์ค์ ์์
Node.js(Next.js) ์ ํ๋ฆฌ์ผ์ด์
๋ชจ๋ํฐ๋ง์ ์ํ ๋ฉ๋ชจ๋ฆฌ ์ธ์ฌ์ดํธ / if(kakaoAI)2024
ํด๋น ์ปจํผ๋ฐ์ค ๋ด์ฉ์ด ๋ด๊ฐ ๊ณ ๋ฏผํ๊ณ ์๋ ๊ฐ๋
์ ์ธ ๋ถ๋ถ์ ๋ค๋ค์ฃผ๊ณ ์์๋ค.
1-1. ์ฝ๋ ์ ์ฉ
// server.js
const { createServer } = require('http');
const { parse } = require('url');
const next = require('next');
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
app.prepare().then(() => {
const server = createServer((req, res) => {
const parsedUrl = parse(req.url, true);
handle(req, res, parsedUrl);
});
// ๋ฉ๋ชจ๋ฆฌ ๋ก๊น
function logMemoryUsage() {
const memoryUsage = process.memoryUsage();
console.log(`RSS: ${memoryUsage.rss / 1024 / 1024} MB`);
console.log(`Heap Total: ${memoryUsage.heapTotal / 1024 / 1024} MB`);
console.log(`Heap Used: ${memoryUsage.heapUsed / 1024 / 1024} MB`);
console.log(`External: ${memoryUsage.external / 1024 / 1024} MB`);
}
setInterval(logMemoryUsage, 5000);
});
์ปค์คํ ํ server๋ฅผ ํตํด ์๋ฒ๋ฅผ ์์ํ๊ธฐ ์ํด์๋ package.json์ script๋ฅผ node๋ฅผ ํตํด ์คํ์์ผ์ผ ํ๋ค.
{
"scripts": {
"start": "node server.js",
},
2. heap ๋ฉ๋ชจ๋ฆฌ ์ ํ
package.json์ script์คํ ์ ๋ค์๊ณผ ๊ฐ์ด heap ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ ํํ์ฌ ๊ด๋ฆฌํ ์ ์๋ค.
{
"scripts": {
"start": "node --max-old-space-size=4096 server.js"
}
}
ํด๋น ๋ช ๋ น์ด๋ก ์๋ฒ start์ server.js์์ ์์ฑํ console.log๋ฅผ ํตํด ๋ค์๊ณผ ๊ฐ์ ๋ก๊ทธ๊ฐ ์ฐํ๋ ๊ฒ์ ํ์ธํ ์ ์์๋ค.
RSS: 6878.95703125 MB
Heap Total: 3646.2421875 MB
Heap Used: 3577.541633605957 MB
External: 2535.8189821243286 MB
RSS: 6878.97265625 MB
Heap Total: 3646.2421875 MB
Heap Used: 3577.559700012207 MB
External: 2535.819083213806 MB
RSS: 7877.37109375 MB
Heap Total: 3597.78515625 MB
Heap Used: 3515.6298904418945 MB
External: 3877.6123657226562 MB
๊ทธ๋ฌ๋ --max-old-space-size ๋ ํ ๋ฉ๋ชจ๋ฆฌ ์ ๋ํ ์ต๋ ํฌ๊ธฐ๋ฅผ ์ค์ ํ ๋ฟ, ์ ์ฒด ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์๋ ์ํฅ์ ์ฃผ์ง ์๋๋ค๊ณ ํ๋ค.
ํด๋น ๋ก๊ทธ์์ RSS ๋ Resident Set Size ์ฝ์๋ก ํ๋ก์ธ์ค๊ฐ ์ค์ ๋ก ์ฌ์ฉํ๋ ์ ์ฒด ๋ฉ๋ชจ๋ฆฌ์ด๋ค. ์ฌ๊ธฐ์๋ ํ ๋ฉ๋ชจ๋ฆฌ ์ธ์๋ ๋ค์๊ณผ ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ๋ค์ด ํฌํจ๋๋ค.
- External Memory: V8 ์์ง ์ธ๋ถ์์ ์ฌ์ฉํ๋ ๋ฉ๋ชจ๋ฆฌ (e.g., ๋ฒํผ, C++ ํ์ฅ ๋ฑ)
- Code Segment: ์ฝ๋ ์คํ์ ์ํ ๋ฉ๋ชจ๋ฆฌ
- Stack Memory: ํจ์ ํธ์ถ ์คํ ๋ฉ๋ชจ๋ฆฌ
๋ฐ๋ผ์, --max-old-space-size๋ก ์ ํ๋ ๊ฒ์ ํ ๋ฉ๋ชจ๋ฆฌ๋ง์ด๋ฏ๋ก, ํ ์ธ๋ถ ๋ฉ๋ชจ๋ฆฌ(External, Code, Stack)๋ ์ ํ๋์ง ์๋๋ค.
์ ์ฒด ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ ํํ๊ธฐ ์ํด์๋ Node.js ์์ฒด๊ฐ ์๋, ์คํ ํ๊ฒฝ์ด๋ ์ด์ ์ฒด์ ์์ ๋ฉ๋ชจ๋ฆฌ ์ ํ์ ์ค์ ํด์ผ ํ๋ค.
3. node server ํ๊ฒฝ ์ค์
๐ฅ Trouble Shooting
๋ํ, ์์ script๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ฉด build ํ start ์คํ ์ dev๋ชจ๋๋ก ์๋ฒ๊ฐ ์ผ์ง๋ ๊ฒ์ ํ์ธํ๋ค. (์์์ ์ธ๊ธํ ๋ก๊ทธ๋ค๋ dev๋ชจ๋์ ๋ก๊ทธ์์ ์๊ฒ ๋์๋ค.)
์ด์ ์ start ์คํฌ๋ฆฝํธ ์คํ ์ node server.js๋ฅผ ํตํด ์๋ฒ๋ฅผ ์ผ๋๋ก ์ค์ ํ ์ธํ๋ผ ํ๊ฒฝ์ ์ ํ ํ์ ๋ OOM์ด ๋ ์ด์ ๋ ๊ธฐ๋ณธ heap ํฌ๊ธฐ ์ค์ ์ด 2GB์ฌ์ ์๋ค. dev ๋ชจ๋๋ก ์๋ฒ๊ฐ ์ผ์ง๊ฒ ๋๋ฉด ์ต์ ํ๊ฐ ๋์ง ์์ ์ํ๋ผ ํ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ด ๊ทธ ์ด์์ ์ฌ์ฉํ๊ณ ์์ด ๋ฐ์ํ ๋ฌธ์ ๋ก ๋ณด์ธ๋ค.
๐ง๐ Problem Solving
์ฐ๋ฆฌ๋ build ํ production ํ๊ฒฝ์ผ๋ก ์ปค์คํ
ํ ์๋ฒ ์คํํด์ผ ํ๋ค.
๋ฐ๋ผ์, script์์ production ๋ชจ๋๋ก ์๋ฒ๊ฐ ์ผ์ง ์ ์๊ฒ ์ค์ ํด ์ฃผ์ด์ผ ํ๋ค.
production ๋ชจ๋๋ก ์คํ์ํค๊ณ ์ ํ๋ค๋ฉด script์์ NODE_ENV๋ฅผ ๋ช
์ํด์ค์ผ ํ๋ค.
// package.json
"scripts": {
"build": "yarn next build",
"start": "NODE_ENV=production node --max-old-space-size=3072 --max-semi-space-size=64 --optimize-for-size --trace-gc server.js"
}
## ERROR LOG
$ yarn run start
yarn run v1.22.19
$ NODE_ENV=production node --max-old-space-size=3072 --max-semi-space-size=64 --optimize-for-size --trace-gc server.js
'NODE_ENV' is not recognized as an internal or external command,
operable program or batch file.
NODE_ENV๋ฅผ ์ธ์ํ ์ ์์์ ๋ํ๋ด๋ ๋ก๊ทธ๊ฐ ๋์๋ค. (๋์ ํ ์คํธ ํ๊ฒฝ์ ์๋์ฐ์๋ค!)
๐ฅ Trouble Shooting
๊ทธ๋ฌ๋ ํด๋น script๋ก ์คํ ์ Windows ํ๊ฒฝ์์๋ NODE_ENV๋ฅผ ์ธ์ํ ์ ์์๋ค.
๐ง๐ Problem Solving
๋ฐ๋ผ์ ์ฐ๋ฆฌ๋ Windows์ Linux ํ๊ฒฝ์ ๋ํ Cross-env ์ค์ ์ด ํ์ํ๋ค.
## cross-env ์์กด์ฑ ์ถ๊ฐ
yarn add cross-env
## cross-env๋ฅผ ํตํ node ํ๊ฒฝ ์ค์
"scripts": {
"build": "yarn next build",
"start": "cross-env NODE_ENV=production node --optimize-for-size --trace-gc server.js"
}
4. production๋ชจ๋๋ก ์คํ ์ heap ๋ฉ๋ชจ๋ฆฌ ๋ก๊ทธ
์ด์ ์ dev๋ชจ๋๋ก ์๋ฒ startํ ๋์ ๋ค๋ฅด๊ฒ heap ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ด 1/15 ์ด์ ๊ฐ์ํ ๊ฒ๋ ํ์ธํ ์ ์์๋ค.
5. --optimize-for-size ์ค์ ์ฐจ์ด
--optimize-for-size ์ค์ ์ ์ถ๊ฐํ๊ฒ ๋๋ฉด ์ค์ ์ ๋ณด๋ค heap ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ด ๊ฐ์ํ๋ ๊ฒ์ ํ์ธ ๊ฐ๋ฅํ๋ค.
โ ๊ถ๊ธํด์ ๋ ์ฐพ์๋ณธ ๊ฒ
๊ธฐ์กด “next start”์ ํด๋น ์คํฌ๋ฆฝํธ๋ ์ด๋ค ์ฐจ์ด๊ฐ ์์๊น?
- next start vs node server.js ์ฐจ์ด์
ํน์ง | next start | node server.js(์ปค์คํ ์๋ฒ) |
์ค์ ๊ฐ์ํ | Next.js ๊ธฐ๋ณธ ์ ๊ณต ๊ธฐ๋ฅ์ผ๋ก ๊ฐ๋จํ ์คํ ๊ฐ๋ฅ | ์๋ฒ ๋ก์ง ์ถ๊ฐ๋ก ์ค์ ๋ณต์ก๋ ์ฆ๊ฐ |
์ ์ฐ์ฑ | ๊ธฐ๋ณธ ์๋ฒ๋ง ์ฌ์ฉ ๊ฐ๋ฅ | HTTP ์์ฒญ ์ฒ๋ฆฌ, API ํ๋ก์ ๋ฑ ์ ์ฐ |
์ฑ๋ฅ ์ต์ ํ | ๊ธฐ๋ณธ ์ค์ ์ผ๋ก ์ต์ ํ | ์ง์ ์ต์ ํ ๊ฐ๋ฅ (e.g., ์บ์ฑ ๋ก์ง) |
๋ฉ๋ชจ๋ฆฌ ์ค์ ์ ์ด | NODE_OPTIONS๋ก ๊ฐ์ ์ค์ | node ํ๋๊ทธ๋ก ์ง์ ์ค์ ๊ฐ๋ฅ |
next start
- ๋ด์ฅ๋ Next.js ์๋ฒ ์ฌ์ฉ:
- Next.js๊ฐ ๊ธฐ๋ณธ ์ ๊ณตํ๋ ์๋ฒ๋ฅผ ์คํํ๋ค.
- ์ปค์คํ ๋ก์ง์ ์ถ๊ฐํ๊ฑฐ๋ ์ง์ ์๋ฒ๋ฅผ ์ ์ดํ ์๋ ์๋ค.
- ๊ฐ๋จํ ๋ฐฐํฌ:
- Next.js๋ก ์์ฑ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์คํํ๋ ๊ฐ์ฅ ํ์ค์ ์ธ ๋ฐฉ๋ฒ์ด๋ค.
- ๋ฉ๋ชจ๋ฆฌ ์ค์ :
- next start ์์ฒด๋ก๋ Node.js ์คํ ํ๊ฒฝ์ ์ง์ ์ค์ ํ ์ ์๊ธฐ ๋๋ฌธ์, ๋ฉ๋ชจ๋ฆฌ ์ ํ ๋ฑ Node.js ์ต์ ์ ์ ์ดํ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ๋ช ๋ น์ด๋ก ์คํํด์ผ ํ๋ค.
NODE_OPTIONS="--max-old-space-size=4096" next start
node server.js
- ์ปค์คํ
์๋ฒ:
- Next.js์ next() ์ธ์คํด์ค๋ฅผ ํ์ฉํด HTTP ์๋ฒ๋ฅผ ์ง์ ์์ฑํ๊ณ , ์ถ๊ฐ ๋ก์ง์ ์ ์ํ ์ ์๋ค.
- ์๋ฅผ ๋ค์ด, ํน์ API ํ๋ก์ ์ฒ๋ฆฌ, ์ปค์คํ ํค๋ ์ค์ ๋ฑ Next.js ๊ธฐ๋ณธ ์๋ฒ์์ ์ง์ํ์ง ์๋ ๊ธฐ๋ฅ์ ๊ตฌํํ ์ ์๋ค.
- ์ ์ฐ์ฑ:
- HTTP ์์ฒญ์ ์ง์ ์ ์ดํ๊ฑฐ๋ ๋ค์ํ ๋ฏธ๋ค์จ์ด๋ฅผ ์ถ๊ฐํ ์ ์๋ ์ ์ฐ์ฑ์ ์ ๊ณตํ๋ค.
- ๋ฉ๋ชจ๋ฆฌ ์ค์ :
- ์ปค์คํ ์๋ฒ๋ Node.js ํ๊ฒฝ์์ ์คํ๋๋ฏ๋ก, ๋ค์๊ณผ ๊ฐ์ ๋ฐฉ์์ผ๋ก ๋ฉ๋ชจ๋ฆฌ ์ค์ ์ ์ ์ดํ ์ ์๋ค.
node --max-old-space-size=4096 server.js
๐ก ์ฐธ๊ณ ์๋ฃ:
- https://speakerdeck.com/deepu105/v8-memory-usage-stack-and-heap
- https://fe-developers.kakaoent.com/2022/220519-garbage-collection/
- https://velog.io/@seyoung8239/V8-%EC%97%94%EC%A7%84-%EB%82%B4%EB%B6%80%EC%9D%98-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B4%80%EB%A6%AC
- https://gobae.tistory.com/116#V-%EC%--%--%EC%--%-C%EC%-D%--%--%ED%-E%--%--%EB%A-%--%EB%AA%A-%EB%A-%AC
- https://gobae.tistory.com/101
- https://deepu.tech/memory-management-in-v8/
- https://gist.github.com/stormwild/4bd3c1ec50ed055a363012a403b16365
- https://snird.medium.com/do-not-use-node-js-optimization-flags-blindly-3cc8dfdf76fd
- https://blog.heroku.com/node-habits-2016#7-avoid-garbage
- [ttps://devlog.mi.igaw.io/Next.js%EC%97%90%EC%84%9C%20%EB%A9%94%EB%AA%A8%EB%A6%AC%20%EB%88%84%EC%88%98%20%ED%99%95%EC%9D%B8%20%EB%B0%8F%20%EC%88%98%EC%A0%95%ED%95%98%EA%B8%B0](https://devlog.mi.igaw.io/Next.js%EC%97%90%EC%84%9C%20%EB%A9%94%EB%AA%A8%EB%A6%AC%20%EB%88%84%EC%88%98%20%ED%99%95%EC%9D%B8%20%EB%B0%8F%20%EC%88%98%EC%A0%95%ED%95%98%EA%B8%B0)
- https://coffeeandcakeandnewjeong.tistory.com/6
- https://velog.io/@server30sopt/heap-out-of-memory-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0%EA%B3%BC-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%88%84%EC%88%98-%EA%B2%80%EC%82%AC
- https://puterism.com/deploy-next-js-with-ec2/
- https://forums.docker.com/t/build-a-nextjs-project-is-too-heavy-and-some-doubts/138748
https://www.youtube.com/watch?v=p2YFSJaoWWU
https://blog.eunsukim.me/posts/debugging-javascript-memory-leak-with-chrome-devtools
'Development > Next.js' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Next.js] Next.js์ ๊ธฐ๋ณธ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ๊ตฌ์กฐ - node.js v8 (0) | 2024.12.22 |
---|---|
[Next.js] SWC๋ฅผ ํ์ฉํ์ฌ ๋น๋ ์๊ฐ ๋จ์ถํ๊ธฐ (3) | 2024.11.01 |
๋๊ธ