SSR ํ๊ฒฝ(Node.js) ๋ฉ๋ชจ๋ฆฌ ๋์ ๋๋ฒ๊น ๊ฐ์ด๋ (2)
SSR ํ๊ฒฝ(Node.js) ๋ฉ๋ชจ๋ฆฌ ๋์ ๋๋ฒ๊น ๊ฐ์ด๋ (2) ๊ด๋ จ
[FEConf2023์์ ๋ฐํํ SSR ํ๊ฒฝ(Node.js) ๋ฉ๋ชจ๋ฆฌ ๋์ ๋๋ฒ๊น ๊ฐ์ด๋][1]๋ฅผ ์ ๋ฆฌํ ๊ธ์ ๋๋ค. ๋ฐํ ๋ด์ฉ์ 2ํ๋ก ๋๋์ด ๋ฐํํฉ๋๋ค. 1ํ์์๋ ๋ฉ๋ชจ๋ฆฌ ๋์์ ๋ํด ์์๋ณด๊ณ , ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ๋ชจ๋ํฐ๋ง ๋๊ตฌ๋ฅผ ํตํด ํ์ธํด๋ณด๊ฒ ์ต๋๋ค. 2ํ์์๋ ๋ฉ๋ชจ๋ฆฌ ๋์ ํ์์ ์ง์ ๋๋ฒ๊น ํด๋ณด๊ณ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ์์๋ด ๋๋ค. ๋ณธ๋ฌธ์ ์ฝ์ ๋ ์ด๋ฏธ์ง์ ์ถ์ฒ๋ ๋ชจ๋ ์ด ์ฝํ ์ธ ์ ๊ฐ์ ์ ๋ชฉ์ ๋ฐํ ์๋ฃ๋ก, ๋ฐ๋ก ์ถ์ฒ๋ฅผ ํ๊ธฐํ์ง ์์์ต๋๋ค. ๋ฐํ ์๋ฃ๋ FEConf2023 ํํ์ด์ง์์ ๋ค์ด๋ก๋ํ ์ ์์ต๋๋ค.
์ด๋ฒ ๊ธ์์๋ ์์ ๊ธ์์์ ๋ฉ๋ชจ๋ฆฌ ๋์ ํ์์ ์ง์ ๋๋ฒ๊น ํด๋ณด๊ณ ํด๊ฒฐํด ๋ณด๊ฒ ์ต๋๋ค.
๋ฉ๋ชจ๋ฆฌ ๋์ ํด๊ฒฐํ๊ธฐ
์ฐ๋ฆฌ๋ ์์ ์๋ฆฌ๋ฒ ์ดํฐ ์์ ์์ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ๋ฐฉ๋ฒ 2๊ฐ์ง๋ฅผ ์์๋ดค์ต๋๋ค.
- ํ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋๋ ค์ฃผ๊ฑฐ๋
- ๋ฉ๋ชจ๋ฆฌ ๋์์ ๋ฒ์ธ์ ๋๋ฒ๊น ํ๋ค.
๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ ๋ํด ์์ธํ๊ฒ ์์๋ณด๊ฒ ์ต๋๋ค.
ํ ๋ฉ๋ชจ๋ฆฌ ๋๋ฆฌ๊ธฐ
๋จผ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋๋ฆฌ๋ ๋ฐฉ๋ฒ์ ๋ํด ์ดํด๋ณด๊ฒ ์ต๋๋ค. '๋ฉ๋ชจ๋ฆฌ๊ฐ ๋ถ์กฑํ๋๊น ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋๋ฆฐ๋ค.'๋ผ๋ ์๊ฐ์ ์์ฃผ ๋น์ฐํ ์๊ฐ์ ํ๋ฆ์ ๋๋ค. ๊ทธ๋ฌ๋ ๊ณผ์ฐ ํ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋๋ฆฌ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋ชจ๋ฆฌ ๋์๊ฐ ํด๊ฒฐ๋ ๊น์?
const listItems = [];
function memoryLeakFunction() {
for (let i=0; i<1_000_000; ++i) {
listItem.push(i);
}
console.log(`${process.memoryUsage().heapUsed / 1024 / 1024} MB`);
}
๊ทธ๋ ์ง ์์ต๋๋ค. ํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋๋ ค์ค๋ ์ด ์ฝ๋๋ ๊ณ์ํด์ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ์ผ์ผํค๊ณ ์๋ฒ๊ฐ ์ฃฝ๊ฒ ๋ฉ๋๋ค. ์์ผ๊น์? Node.js์ V8 ์์ง์ด ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ด๋ฆฌํ๋ ๋ฐฉ์์ ์๋ฉด ์ดํดํ ์ ์์ต๋๋ค. V8 ์์ง์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ ๊ด๋ฆฌํ๊ธฐ ์ํด '๋งํฌ ์ค ์ค์'์ด๋ผ๋ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํฉ๋๋ค. ์ฌ์ฉํ๋ ๊ฒ์ ๋งํฌํ๊ณ ์ฌ์ฉํ์ง ์๋ ๊ฒ์ ์ธ์ด์ ์ฒญ์ํด๋ฒ๋ฆฐ๋ค๋ ๋ป์ ๋๋ค.
๋ฐฐ์ด์ด๋ ์ค๋ธ์ ํธ, ํ์ ๊ณผ ๊ฐ์ ๋ฐ์ดํฐ ํ์ ์ ํ๋ฉ๋ชจ๋ฆฌ๋ก๋ถํฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋น๋ฐ์ ๋์ํฉ๋๋ค. ์ด๋ฌํ ํ์ ์ ๊ฐ์ฒด๋ผ๊ณ ๋ถ๋ฅด๊ฒ ์ต๋๋ค. ๊ฐ๋น์ง ์ปฌ๋ ํฐ๋ ์ด๋ฌํ ๊ฐ์ฒด๊ฐ ์์ฉ๋๊ณ ์๋์ง ์๋์ง ๋ฃจํธ๋ก๋ถํฐ ์์ํด์ ์ฌ๊ท์ ์ผ๋ก ๊ณ์ ์ฒดํฌ๋ฅผ ํ๊ณ ์๋ค๊ฐ ๋ ์ด์ ์ฌ์ฉํ์ง ์๋ ๋ถํ์ํ ๊ฐ์ฒด๋ฅผ ์๊ฑฐํ์ฌ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ํ๋ณดํฉ๋๋ค. ์ด๊ฒ ๋ฐ๋ก '๋งํฌ ์ค ์ค์' ์๊ณ ๋ฆฌ์ฆ์ ๋๋ค.
๊ทธ๋ฌ๋ ์ด๋๊ฐ์์ ๊ณ์ ์ฐธ์กฐ๋ฅผ ํ๊ณ ์๋ ๊ฐ์ฒด๊ฐ ์๋ค๋ฉด ๊ทธ ๊ฐ์ฒด๋ค์ ๊ณ์ํด์ ํ๋ฉ๋ชจ๋ฆฌ์ ์กด์ฌํ๊ฒ ๋ฉ๋๋ค. ์ด๋ ๊ฒ ๊ฐ์ฒด๊ฐ ๊ณ์ํด์ ์กด์ฌํ๋ฉด ์ด๋ป๊ฒ ๋ ๊น์? ์ด๋ฅผ ์ดํดํ๊ธฐ ์ํด ํ ๋ฉ๋ชจ๋ฆฌ์ ๋ํด ์ ํ์๊ฐ ์์ต๋๋ค.
ํ ๋ฉ๋ชจ๋ฆฌ
Node.js์ V8 ์์ง์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ ๊ด๋ฆฌํ๊ธฐ ์ํด ์์ญ์ ๋๋์ด ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ด๋ฆฌํฉ๋๋ค. ์๋๋ V8 ์์ง์ ๋ผ์ดํ ์ฌ์ดํด์ ์ค๋ช ํ๊ธฐ ์ํด ํํํ ๊ฐ๋จํ ๊ฐ๋น์ง ์ฝ๋ ํฐ์ ๊ตฌ์กฐ์ ๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก ์ ์ ๋ค๋ ์ด์ (Young Generation)๊ณผ ์ฌ๋ ์ ๋ค๋ ์ด์ (Old Generation)์ผ๋ก ๋๋์ด์ ธ ์๊ณ , ๊ฐ๋น์ง์ฝ๋ ํฐ๋ ๋ง์ด๋ ๊ฐ๋น์ง ์ฝ๋ ํฐ์ ๋ฉ์ด์ ๊ฐ๋น์ง ์ฝ๋ ํฐ๋ก ๋๋์ด์ ธ ์์ต๋๋ค. ๋ง์ฝ์ ์ฒ์ ์ ์ธ๋ ์ด๋ค ๊ฐ์ฒด๊ฐ ์๋ค๋ฉด ์ด ๊ฐ์ฒด๋ ๋ณดํต nursery(์ ์๊ธฐ) ๋ผ๋ ์์ญ์ ๋ฉ๋ชจ๋ฆฌ ํ ๋น์ด ๋ฉ๋๋ค. ๊ฐ๋น์ง ์ฝ๋ ํฐ๊ฐ ํ๋ฒ ์์ ์ ์ํํ๋๋ฐ ํด๋น ๊ฐ์ฒด๊ฐ ์ด์๋จ์๋ค๋ฉด ์ด ๊ฐ์ฒด๋ intermediate(์ค๊ฐ๊ธฐ) ๋ผ๋ ์์ญ์ผ๋ก ๋์ด๊ฐ๋๋ค. ๋ค์ ๊ฐ๋น์ง ์ฝ๋ ํฐ๊ฐ ์์ ์ ์ํํ๋๋ฐ ๋ ์ด ๊ฐ์ฒด๊ฐ ์ด์๋จ์๋ค๋ฉด ์ด ๊ฐ์ฒด๋ ๊ฒฐ๊ตญ ์ฌ๋ ์ ๋ค๋ ์ด์ ์์ญ์ผ๋ก ๋์ด๊ฐ๋๋ค. V8 ๋ฌธ์์์๋ ์ด ์์ญ๊น์ง ๋์ด๊ฐ๋ ๊ฐ์ฒด๋ ๊ฑฐ์ ์๋ค๊ณ ์ค๋ช ์ ํฉ๋๋ค.
๊ทธ๋ ๋ค๋ฉด ์ด ์ฌ๋ ์ ๋ค๋ ์ด์ ์์ญ์ ์ด์๋จ์ ๊ฐ์ฒด๊ฐ ๋ ๋ง์์ง๋ฉด ์ด๋ป๊ฒ ๋ ๊น์? V8 ์์ง์ ๋ ๊ฐ์ง ์์ญ์ ์กฐ์ ํ๋ฉด์ ์ดํ๋ฆฌ์ผ์ด์ ์ ๋์์ํต๋๋ค. ๊ทธ๋ฌ๋ ํ ๋ฉ๋ชจ๋ฆฌ๋ ์ ํ๋ ์ฉ๋์ ๊ฐ์ง๊ธฐ ๋๋ฌธ์ ๊ฒฐ๊ตญ ๊ฝ ์ฐจ๊ฒ ๋ ๊ฒ์ด๊ณ ์๋ฒ๊ฐ ์ฃฝ๊ฒ ๋ฉ๋๋ค.
listItems
๋ฐฐ์ด์ ์ ์ญ ๋ณ์๋ก ์ ์ธ๋์๊ธฐ ๋๋ฌธ์ ๊ฐ๋น์ง ์ฝ๋ ํฐ๊ฐ ์๊ฑฐํ์ง ๋ชปํ๊ณ ์ฌ๋ ์ ๋ค๋ ์ด์
์ ์กด์ฌํ๊ฒ ๋ฉ๋๋ค. ์ฒ์์๋ ์ฒซ ๋ฒ์งธ ๊ทธ๋ฆผ์ฒ๋ผ ์์ ์์ญ๋ง ์ฐจ์งํ๊ณ ์์ ๊ฒ๋๋ค. ๊ทธ๋ฌ๊ณ ๋์ ์๋ฒ์ ํด๋น ์์ฒญ์ด ์ค๋ฉด 100๋ง ๋ฒ์ ๋ฐ๋ณต๋ฌธ์ ์ํํ๋ฉด์ listItems
์ ๊ธธ์ด๊ฐ ๋์ด๋๊ณ ์ด๊ฒ ๋ฐ๋ณต๋๋ค ๋ณด๋ฉด ๋ ๋ฒ์งธ ๊ทธ๋ฆผ์ฒ๋ผ ๋ง์ ์ฉ๋์ ์ฐจ์งํ๊ฒ ๋ ๊ฒ์
๋๋ค. ๊ทธ๋ฌ๋ค๊ฐ ๊ฒฐ๊ตญ ํ ๋ฉ๋ชจ๋ฆฌ๊ฐ ๊ฝ ์ฐจ๋ ์๊ฐ์ด ์ค๊ฒ ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ฉด ์๋ฒ๊ฐ ์ฃฝ๊ฒ ๋ฉ๋๋ค.
์ ์์ ๋ ๋จ์ํ์ง๋ง ์ค์ ์ฝ๋๋ฅผ ์์ฑํ ๋ ์ด๋ฐ ๋ฌธ์ ๋ฅผ ๋ง๋๊ฒ ๋์์ ๋ ํ ๋ฉ๋ชจ๋ฆฌ๋ง ๋๋ฆฌ๋ฉด ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋ ๊น์? ์ด๋ฐ ๋ฌธ์ ๋ฅผ ๋ง๋ฌ์ ๋ ๊ตฌ๊ธ๋ง์ ํด๋ณด๋ฉด ์๋์ ๊ฐ์ด max-old-space-size
๋ฅผ ๋๋ฆฌ๋ผ๋ ๋ต๋ณ์ ์ฝ๊ฒ ๋ง๋ ์ ์์ต๋๋ค.
์ฌ๊ธฐ์ max-old-space-size
๋ Node.js์ ์ฌ๋ ์ ๋ค๋ ์ด์
์ ์ฉ๋์ ์กฐ์ ํ๋ ์ต์
์
๋๋ค. ์ฆ, ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ์ผ์ผํจ ๋๋ถ๋ถ์ ๊ฐ์ฒด๋ ์ฌ๋ ์ ๋ค๋ ์ด์
์์ญ์ ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ์์ ์ค๋ช
๋๋ฆฐ ๊ฐ๋น์ง ์ฝ๋ ํฐ์ ๊ตฌ์กฐ์์ ์ฌ๋ ์ ๋ค๋ ์ด์
์ ์ฉ๋์ ๋๋ฆฌ๋ผ๋ ๋ต๋ณ์ ๋ง์ด ๋ง๋๊ฒ ๋ฉ๋๋ค.
๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ์ผ์ผํค๋ ์์ธ์ ์ด์ธ์๋ ๋ค์ํ๊ฒ ์กด์ฌํฉ๋๋ค. ์์๋ก ์ค๋ช
๋๋ฆฐ ์ ์ญ ๋ณ์ ๋ฟ๋ง ์๋๋ผ, setTimeout
, setInterval
๊ณผ ๊ฐ์ ํจ์๋ฅผ ์ฌ์ฉ ํ ํด๋ฆฌ์ด๋ฅผ ํ์ง ์์ ๊ฒฝ์ฐ์ ํด๋ก์ ๊ฐ ๋ํ์ ์
๋๋ค. ํด๋ก์ ์ ๊ฒฝ์ฐ๋ ์คํ ์ปจํ
์คํธ ์์์ ๊ฐ์ฒด๋ ๋ณ์์ ์ ์ธ๊ณผ ์ฐธ์กฐ, ์ด์ ๋ฐ๋ฅธ ๋ ๋ค๋ฅธ ์ฐธ์กฐ๊ฐ ์๋ ๊ฒฝ์ฐ ๋ฑ ๋ค์ํ ๊ฒฝ์ฐ์์ ํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ง์ด ํ ๋นํ๋ ๊ฒฝ์ฐ๋ ๋ฐ์ํฉ๋๋ค.
์ด๋ฌํ ๋ค์ํ ๊ฒฝ์ฐ์์ ํ ๋ฉ๋ชจ๋ฆฌ๊ฐ ๊ต์ฅํ ๋ง์ด ํ์ํ ์ํฉ์ด ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ ๋ฌด์์ ํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋๋ฆฌ๋ ๊ฒ๋ง์ด ํด๊ฒฐ์ฑ ์ด ์๋ ์๋ ์์ต๋๋ค.
๋ฉ๋ชจ๋ฆฌ ๋์ ๋๋ฒ๊น ํ๊ธฐ
๋๋ฒ๊น ๋ฐฉ๋ฒ
์ด์ ๋๋ฒ๊น
์ ํตํด ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์์๋ณด๊ฒ ์ต๋๋ค. node -โinspect index.js
์ ๊ฐ์ด inspect๋ผ๋ ์ต์
์ ์ฌ์ฉํด์ Node.js๋ฅผ ์คํ์ํค๊ณ ๋ธ๋ผ์ฐ์ ์ ๊ด๋ฆฌ์ ๋๊ตฌ๋ฅผ ์ด๋ฉด ์ด๋ก์ Node.js ๋ฒํผ์ ๋ณผ ์ ์์ต๋๋ค. ์ ๋ ์ฃผ๋ก ํฌ๋กฌ์ ์ธ์คํํธ ๋ฉ๋ด๋ฅผ ํ์ฉํฉ๋๋ค. ์ด ๋ฉ๋ด์๋ ํ์ฌ ์คํ ์ค์ธ ๋ก์ปฌ ์๋ฒ๋ค์ ๋ชฉ๋ก์ ๋ณผ ์ ์๊ณ ์ํ๋ ์๋ฒ๋ฅผ ์ ํํ์ฌ ์ธ์คํํธ ์ฐฝ์ ์ด์ด ์ฌ์ฉํฉ๋๋ค.
๋๋ฒ๊น ์ ์ํด ์ธ์คํํธ ์ฐฝ์ ์ด๋ฉด ์๋์ ๊ฐ์ ์ฐฝ์ด ๋ฐ ๊ฒ๋๋ค. ์ข์ธก ํจ๋์ ๋ณด๋ฉด ๋๊ทธ๋ผ๋ฏธ ๋๊ฐ๊ฐ ๊ฒน์ณ์ง ๋ชจ์์ ํ๋กํ์ผ๋ง ๋ นํ ๋ฒํผ์ด ์์ต๋๋ค. ํน์ ๊ตฌ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ๋ฑ์ ํ์ธํ๊ธฐ ์ํด ๋ นํ๋ฅผ ์์ํ๊ณ ์ข ๋ฃํด์ผ ํ๋๋ฐ, ์ด ๋ฒํผ์ผ๋ก ๋ นํ์ ์์๊ณผ ์ข ๋ฃ๋ฅผ ํ ์ ์์ต๋๋ค.
๊ทธ ์์ ๊ธ์ง ๋ชจ์์ ๋ฒํผ๊ณผ ์๋์๋ ๋ นํ๊ฐ ๋๋ ํ๋กํ์ผ๋ง ๊ฒฐ๊ณผ ํ์ผ ๋ชฉ๋ก์ด ์์ต๋๋ค. ๊ธ์ง ๋ชจ์์ ๋ฒํผ์ ํ๋กํ์ผ๋ง ๋ นํ์ ๊ฒฐ๊ณผ ํ์ผ ๋ชฉ๋ก์ ๋ชจ๋ ์ญ์ ํ๋ ๋ฒํผ์ ๋๋ค.
๋ง์ง๋ง์ผ๋ก ์ฐ๋ ๊ธฐํต ๋ชจ์์ ๋ฒํผ์ด ์๊ณ ์ด๋ ์๋์ผ๋ก ๊ฐ๋น์ง ์ปฌ๋ ํฐ๋ฅผ ์๋์ํค๋ ๋ฒํผ์ ๋๋ค. ๋ณดํต ๋ฉ๋ชจ๋ฆฌ ํ๋กํ์ผ๋ง์ ํ๊ธฐ ์ ์ ๊ฐ๋น์ง ์ปฌ๋ ํฐ๋ฅผ ๋์์์ผ ์์ ํ๋ฅผ ์ํจ ๋ค์์ ํ๋กํ์ผ๋ง์ ํ๋ ๋ฐฉ์์ผ๋ก ์ฌ์ฉํฉ๋๋ค.
๋ค์์ผ๋ก ๊ฐ์ฅ ์ค์ํ ์์ญ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ํฌ๋กฌ์์๋ ์ธ ๊ฐ์ง ํ๋กํ์ผ๋ง ํ์
์ ์ง์ํฉ๋๋ค. ์ฒซ ๋ฒ์งธ๋ ํ ์ค๋
์ท์
๋๋ค. ์ง๊ธ ์ด ์๊ฐ์ ํ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ๊ธฐ๋กํ๋ ํ์
์
๋๋ค. ์ด ํ์
์ ์ ํํ๋ฉด ์๋์ [take snapshot]
๋ฒํผ์ด ํ์ฑํ๋ฉ๋๋ค. ๋ฒํผ์ ๋๋ฅด๋ฉด ๊ทธ ์๊ฐ๋ถํฐ ํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ธฐ์ตํ๊ฒ ๋ฉ๋๋ค. ๋ด๊ฐ ์ ๋ง ์์ง ์ฝ๋๊ฐ ์์ด์ ๋ฉ๋ชจ๋ฆฌ์ ์ผ๋ก๋ ์ฑ๋ฅ์ ์ผ๋ก ๊ฐ์ ํ ๋ถ๋ถ์ด ์๋ค๋ฉด ๊ทธ ์ ํ๋ฅผ ๊ธฐ๋กํ๋ฉด ๋ ๊ฐ์ง ๊ฒฝ์ฐ๋ฅผ ๋น๊ตํ ์ ์์ต๋๋ค. ์ฆ, ์ด๋ค ๋ถ๋ถ์์ ๋ฉ๋ชจ๋ฆฌ ๋์๊ฐ ๋ฐ์ํ๋์ง ์ ํํ ์๊ณ ์์ ๋ ํด๋น ๋ถ๋ถ์ ๋๋ฒ๊น
ํ ์ ์์ต๋๋ค.
๋ ๋ฒ์งธ ํ์ ์ ๋ง์ด ์ฌ์ฉํ๋ ์ ์ฉํ ๊ธฐ๋ฅ์ ๋๋ค. ์ฃผ๊ธฐ์ ์ผ๋ก ํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ธฐ๋กํ๊ณ ๋ นํํ๋ ๋์ ํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ผ๋ง๋ ์ฐ๊ณ ์๋์ง ๊ทธ๋ํ๋ก ๋ณด์ฌ์ฃผ๋ ํ์ ์ ๋๋ค. ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ๊นจ๋ซ๊ณ ๋๋ฒ๊น ํ๋ ๊ฒฝ์ฐ ํ์๋ผ์ธ์ ํตํด ์๊ฐ์ด ์ง๋๋ฉด์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ด ์ด๋ป๊ฒ ๋ณํ๋์ง๋ฅผ ์ดํด๋ณผ ๋ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ณดํต ๋ฉ๋ชจ๋ฆฌ ๋์๊ฐ ์ด๋์ ๋ฐ์ํ๋์ง ์๊ธฐ ์ฝ์ง ์์ต๋๋ค. ์ด๋ด ๋ ์ฌ์ฉํ๋ฉด ์ ์ฉํ ๊ธฐ๋ฅ์ ๋๋ค.
๋ง์ง๋ง ํ์ ์ ์ํ๋ง ํ์ ์ ๋๋ค. ๋ ๋ฒ์งธ ํ์ ๊ณผ ๋น์ทํ์ง๋ง ํจ์ฌ ๊ธด ์๊ฐ์ ๋ นํํด์ผ ํ๋ ๊ฒฝ์ฐ์ ์ฃผ๋ก ์ฌ์ฉํฉ๋๋ค. ๋ชจ๋ ์๊ฐ์ ๋ค ๊ธฐ๋กํ๋ฉด ์ค๋ฒํค๋๊ฐ ๋ฐ์ํ ์ ์๊ธฐ ๋๋ฌธ์ ์ข ๋ ๊ธด ์๊ฐ ๋์ ์ํ๋ง์ ํ ์ ๋ณด๋ก ๋๋ฒ๊น ํ๋ ๋ฐฉ์์ ๋๋ค. ๋ นํ ๋ฒํผ์ ๋๋ฅด๋ฉด ๋ณํ๊ฐ ์์ด ๋ณด์ด์ง๋ง ๊ธฐ๋ก ์ค์ธ ์ํ๊ฐ ๋๊ณ , ๋ นํ๋ฅผ ์ข ๋ฃํ๋ฉด ์ํ๋ง๋ ์ ๋ณด๋ฅผ ๋ณด์ฌ์ค๋๋ค.
์ธ ๊ฐ์ง ํ์ ์ ๋๋ฒ๊น ๋ฐฉ๋ฒ์ ๋ํด ๊ฐ๋จํ๊ฒ ์์๋ดค์ต๋๋ค. ๊ฐ์์ ๊ฒฝ์ฐ์ ๋ง๊ฒ ํ์ ์ ์ ํํด์ ์ฌ์ฉํ๋ฉด ๋์ง๋ง, ๋ณดํต ๋ ๋ฒ์งธ ํ์ ์ ๋ง์ด ์ฌ์ฉํ๊ฒ ๋ฉ๋๋ค. ๋ฉ๋ชจ๋ฆฌ ๋์ ์๋ฌ๋ฅผ ๋ง๋ฌ์ ๋ ๋ ๋ฒ์งธ ํ์ ์ผ๋ก ๋จผ์ ๋๋ฒ๊น ์ ํ๋ฉด ๋ฌธ์ ์ ์ ๋น ๋ฅด๊ฒ ํ์ธํ ์ ์์ ๊ฒ์ ๋๋ค.
๋ฉ๋ชจ๋ฆฌ ๋์ ๋ฒ์ธ ์ฐพ๊ธฐ
๋๋ฒ๊น ์ ์์ํ๋ฉด ์์ 2๋ฒ์งธ ๋๋ฒ๊น ๋ฐฉ๋ฒ์ ์ค๋ช ์ฒ๋ผ ์๋จ์ ๊ทธ๋ํ๊ฐ ๋ํ๋ฉ๋๋ค.
์ ๊ทธ๋ํ์ ๋์ด๋ ๊ทธ ์๊ฐ์ ํ๋ฉ๋ชจ๋ฆฌ์ ํ ๋น๋ ์ด๋์ ๋ปํฉ๋๋ค. ํ์ ๋ถ๋ถ์ ๊ฐ๋น์ง ์ฝ๋ ํฐ๊ฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์๊ฑฐํ ๋ถ๋ถ์ด๊ณ , ํ๋์์ ํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฐจ์งํ๊ณ ์๋ ๋ถ๋ถ์ ๋๋ค. ์ฆ, ํ๋์์ด ๋ง์ผ๋ฉด ๋์๊ฐ ๋ง๋ค๊ณ ํ ์ ์์ต๋๋ค. ๊ทธ ์๊ฐ์ ํ์ ๋ถ๋ถ์ด ๋ง๋ค๋ฉด ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ๊ฑฑ์ ํ ํ์๊ฐ ์๋ค๋ ๋ป์ ๋๋ค.
๊ทธ๋ํ ์์ญ์ ๋๋๊ทธํ๋ฉด ์ผ๋ถ ๊ตฌ๊ฐ๋ง ์ ํํด์ ๋ณผ ์๋ ์์ต๋๋ค. ๋จผ์ ์ ์ฒด ์์ญ์ ํ์ธํ๊ณ ํ๋์ ๊ทธ๋ํ๊ฐ ์๋ ์์ญ์ ์ ํํด์ ๋ณด๋ฉด ๊ต์งํฉ์ฒ๋ผ ๊ณตํต์ผ๋ก ๋ณด์ด๋ ๊ฐ์ฒด๋ค์ด ์์ ๊ฒ์ ๋๋ค. ์ด๋ฐ ๋ถ๋ถ๋ค์ ์ง์ค์ ์ผ๋ก ๋๋ฒ๊น ํ๋ฉด ์๊ฐ์ ๋จ์ถ์ํฌ ์ ์์ต๋๋ค.
๊ทธ๋ํ๋ฅผ ํตํด ์ด๋ ์์ ์ ๋ฉ๋ชจ๋ฆฌ ๋์๊ฐ ๋ฐ์ํ๋์ง๋ฅผ ์ฝ๊ฒ ์ ์ ์๋๋ฐ, ๋๊ฐ ๋ฉ๋ชจ๋ฆฌ ๋์์ ๋ฒ์ธ์ธ์ง๋ ๊ทธ๋ํ๊ฐ ์๋ ค์ฃผ์ง ์์ต๋๋ค.
๋ฐ๋ก ์๋ก์ฐ ์ฌ์ด์ฆ์ ๋ฆฌํ ์ธ๋ ์ฌ์ด์ฆ์ ๋๋ค. ์๋ก์ฐ ์ฌ์ด์ฆ๋ ๊ฐ์ฒด ์์ ์ ํฌ๊ธฐ๋ฅผ bytes๋ก ํ์ํ ๊ฒ์ด๊ณ , ๋ฆฌํ ์ธ๋ ์ฌ์ด์ฆ๋ ๊ฐ์ฒด ์์ ์ด ์กด์ฌํ๊ธฐ ์ํด ์์ ์ด ์ฐธ์กฐํ๊ณ ์๋ ๋ชจ๋ ๊ฐ์ฒด๋ค์ ๋ค ๋ํ ํฌ๊ธฐ์ ๋๋ค. ์ถ๊ฐ์ ์ผ๋ก ๋์คํด์ค๋ผ๋ ์งํ๋ ์๋๋ฐ, ์ด ์งํ๋ ๊ฐ๋น์ง ์ฝ๋ ํฐ์ ๋ฃจํธ๋ก๋ถํฐ ์ผ๋ง๋ ๋จ์ด์ ธ ์๋์ง ๋ํ๋ด๋ ๊ฐ์ ๋๋ค. ์ด ๊ฐ์ด ํฌ๋ฉด ๋ฉ๋ชจ๋ฆฌ ๋์๊ฐ ์ผ์ด๋ ๊ฐ๋ฅ์ฑ์ด ๋๋ค๊ณ ์ ์ถํ ์ ์์ต๋๋ค. ์ ํํ๊ฒ ๋๋ฒ๊น ํ๋ ์งํ๋ผ๊ธฐ๋ณด๋ค๋ ๊ฐ๋จํ๊ฒ ์ฐธ๊ณ ์งํ๋ก ํ์ฉํ์๋ฉด ์ข์ ๊ฒ ๊ฐ์ต๋๋ค.
์์ ์์ ์ฝ๋์์ ์ ์ญ ๋ณ์์ ์ ์ธํ listItems
๋ฅผ ํจ์ ์์์ ์ฐธ์กฐํ๊ณ ์์์ต๋๋ค. ๊ฐ๋น์ง ์ฝ๋ ํฐ๋ ์ด ๋ณ์๋ฅผ ์๊ฑฐํ์ง ๋ชปํ๊ณ ํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ณ์ ์ฐจ์งํ๊ฒ ๋ฉ๋๋ค. ํจ์ ์์ฒด๋ ๊ฐ๋จํ ์ฝ๋์ด์ง๋ง ์ค์ ์คํ ์ปจํ
์คํธ ์์์ ์ด ๋ณ์๋ ์์ฃผ ๊ธด ๊ธธ์ด๋ฅผ ๊ฐ์ง๊ธฐ ๋๋ฌธ์ ํ ๋ฉ๋ชจ๋ฆฌ๊ฐ ๊ต์ฅํ ๋ง์ด ํ์ํ ์ํฉ์ด ๋ฐ์ํฉ๋๋ค. ๋ค์ ๋งํด ์๋ก์ฐ ์ฌ์ด์ฆ ํฌ๊ธฐ์ ๋นํด ๋ฆฌํ
์ธ๋ ์ฌ์ด์ฆ๊ฐ ๊ต์ฅํ ํฌ๋ค๊ณ ํ ์ ์์ต๋๋ค.
์์ ์์ฑํ ์ฝ๋์ ์ธ์คํํธ ๋ฉ๋ด์์ ๋ฆฌํ
์ธ๋ ์ฌ์ด์ฆ๋ฅผ ๋ด๋ฆผ์ฐจ์์ผ๋ก ์ ๋ ฌํ๊ณ ์ดํด๋ณด๋ฉด ์ ๊ฐ ์์ฑํ memoryLeakFunction
์ ๋ณผ ์ ์์ต๋๋ค. ์ด ๊ฐ์ฒด๋ฅผ ์ ํํ๊ณ ์๋์ชฝ์ ๋ณด๋ฉด Retainers ํญ์ ํตํด ์ด ๊ฐ์ฒด๊ฐ ์ด๋ค ์ฐธ์กฐ ์์๋ก ํ ๋ฉ๋ชจ๋ฆฌ์ ํ ๋น๋์๋์ง ์ ์ ์์ต๋๋ค.
์๋๋ก ์ญ ๋์ด์ค๋ฉด listItems
๊ฐ ๋ณด์
๋๋ค. ๊ทธ๋ฆผ์ ์ค๋ฅธ์ชฝ ์๋๋ฅผ ๋ณด๋ฉด listItems
์ ์๋ก์ฐ ์ฌ์ด์ฆ๋ณด๋ค ๋ฆฌํ
์ธ๋ ์ฌ์ด์ฆ๊ฐ ๊ต์ฅํ ํฌ๋ค๋ ๊ฑธ ์ ์ ์์ต๋๋ค. ์ง๋ฃจํ ๊ณผ์ ์ด ๋ ์๋ ์์ง๋ง ์ด๋ฐ ๊ฐ์ฒด๋ค์ ํ๋์ฉ ์ฐพ๊ณ ์์ ํ๋ฉด์ ์ด ์์น๋ฅผ ์ค์ฌ๊ฐ๋ฉด ๋ฉ๋ชจ๋ฆฌ ๋์ ๋ฒ์ธ์ ์ฐพ๊ณ ์ด๋ฅผ ํด๊ฒฐํ ์ ์๊ฒ ๋ฉ๋๋ค.
์๋ ๊ทธ๋ฆผ์ ์ ๊ฐ ์ค์ ๋ก ๊ฒฝํํ ์ธ์คํํธ ํ๋ฉด์
๋๋ค. ๋ถํ์ํ ๋ถ๋ถ์ ์ ์ธํ๊ณ ๋ณด๋ ์๋์ ๊ฐ์ ๋ถ๋ถ์ ์ฐพ์์ต๋๋ค. ๋ณดํต์ node_modules
๋ผ๋ ๊ฒฝ๋ก๋ก ๋ณด์ผ ํ
๋ฐ ์ ์ ๊ฒฝ์ฐ yarn berry
๋ก ๋
ธ๋ ํจํค์ง ๊ด๋ฆฌ๋ฅผ ํ๊ธฐ ๋๋ฌธ์ โ.yarn
โ ๋ผ๋ ๊ฒฝ๋ก๋ฅผ ๋ณผ ์ ์์ต๋๋ค. ์ด ๊ฒฝ๋ก์ ์ด๋ค ํ์ผ์ธ์ง ํ์ธํ ์ ์์๊ณ , ์ด ํ์ผ์์ ๋ฉ๋ชจ๋ฆฌ ๋์๊ฐ ๋ฐ์ํ๋ค๋ ๊ฒ์ ํ์ธํ๊ณ ์์ ํ์ฌ ๋ฐฐํฌํ๋๋ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ํด๊ฒฐํ ์ ์์์ต๋๋ค.
๋ฐฐํฌ ์ด์ ๊ทธ๋ํ๋ ์์ ์ค๋ช ๋๋ฆฐ ์ฐ ๋ชจ์์ ๊ทธ๋ํ์๋๋ฐ, ๋ฐฐํฌ ์ดํ์๋ ์๋์ฒ๋ผ ์์ํ ๊ทธ๋ํ๋ก ๋ฐ๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
using
- ๊ณ ํต์ ๋์ด์ค ํค์๋
๋ง์ง๋ง์ผ๋ก ์๊ฐํ๊ณ ์ถ์ ํค์๋๊ฐ ์์ต๋๋ค. ๋ฐ๋ก using
์ด๋ผ๋ ํค์๋์
๋๋ค. C#์ ์ฌ์ฉํด ๋ดค๋ค๋ฉด ์ต์ํ ๊ฒ ๊ฐ์ต๋๋ค. ํ์ด์ฌ์์๋ ๋น์ทํ ๊ฐ๋
์ด ์์ต๋๋ค. ์ต๊ทผ ํ์
์คํฌ๋ฆฝํธ 5.2 ๋ฒ์ ์ด ๊ณต์ง๋๋ฉด์ ๋ง์ ๋ถ๋ค์ด ๋ดค๊ฒ ์ง๋ง ์ฌ์ค ์๋ก์ด ๊ฐ๋
์ ์๋๋๋ค.
C#์์๋ ์ด๋ฏธ ์๋ ๊ฐ๋ ์ด๊ณ , ์๋ฐ์คํฌ๋ฆฝํธ TC39 (์๋ฐ ์คํฌ๋ฆฝํธ ํ์ค์ ๊ด๋ฆฌํ๋ ๊ทธ๋ฃน) ์์ ์ด๋ฏธ ์คํ ์ด์ง 3๊น์ง ์งํ๋ ์ํ์ด๊ธฐ ๋๋ฌธ์ ์ด์ฉ๋ฉด ๊ณง ๋ง๋๋ณผ ์๋ ์์ ๊ฒ ๊ฐ์ต๋๋ค.
๊ฐ๋จํ๊ฒ ์ค๋ช
ํ๋ฉด ๊ธฐ์กด์ ๋ณ์๋ฅผ ์ฌ์ฉํ ๋ ์ ์ธํ๋ var
, let
, const
๋์ ์ using
์ ์ ์ธํ๋ฉด ์ด ๋ณ์์ ์ค์ฝํ ๋์์ Symbol.dispose()
๋ฅผ ๋ง๋ค์ด๋๊ณ ์ด๋ฅผ ํธ์ถํ์ฌ ํด๋ฆฐ์
์ ํ ์ ์์ต๋๋ค. ์ ์ธ๋ ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ฅผ ์ ๊ฑฐํ ์๋ ์๊ณ , DB ์ฐ๊ฒฐ์ ํ๋ค๋ฉด ์ด ์ฐ๊ฒฐ์ ํด์ ํ ์๋ ์์ต๋๋ค. ๋, ์คํธ๋ฆผ์ ์ฐ๊ฒฐ์ ํ๋ค๊ฐ ๋์ด์ผ ํ๋ ๊ฒฝ์ฐ๋ ์ด๋ฅผ ํ์ฉํด ๋ผ์ดํ ์ฌ์ดํด์ ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
์์ ์์ ์ฝ๋๋ฅผ using
์ ์ฌ์ฉํด์ ๋ฐ๊ฟ ๋ณด๋ฉด ์๋์ ๊ฐ์ต๋๋ค. const
๋์ using
์ ์ ์ธํ๊ณ , using
์ ์ฌ์ฉํ๊ธฐ ์ํด Disposable์ implements ํ์ต๋๋ค. ํจ์์ ๋ด์ฉ์ ๋์ผํ๊ณ ๋ง์ง๋ง ๋ถ๋ถ์ dispose
๋ฅผ ํตํด ํด๋ฆฐ์
ํ๋ ๋ถ๋ถ์ ์ถ๊ฐํ์ต๋๋ค.
const server = http.createServer((req,res) => {
if (req.url === '/memory-leak') {
using func = new MemoryLeakFunction();
func.exec();
}
res.writeHead(200, { 'Content-Type': 'text/html' });
res.write(`
<!DOCTYPE html>
<html lang="en">
<head>
<title>Hello World</title>
</head>
<body>
<h1>Content</h1>
</body>
</html>
`);
res.end();
});
let listItems: number[] = [];
export class MemoryLeakFunction implements Disposable {
exec() {
for (let i=0; i<1_000_000; ++i) {
listItem.push(i);
}
console.log(`${process.memoryUsage().heapUsed / 1024 / 1024} MB`);
}
[Symbol.dispose]() {
listItems = [];
console.log("ํด๋ฆฐ์
!");
}
}
๋ง์น๋ฉฐ
์ง๊ธ๊น์ง ์ค๋ช
ํ ๊ฒ๋ค์ ์์ฝํ๋ฉด์ ๊ธ์ ๋ง๋ฌด๋ฆฌํ๊ฒ ์ต๋๋ค. ์๋ฒ ํ๊ฒฝ๊ณผ ํด๋ผ์ด์ธํธ ํ๊ฒฝ์ ๋๋ ์ ๋๋ฒ๊น
ํ๋ ๋ฐฉ๋ฒ, ์๋ฒ ํ๊ฒฝ์์ ์ธ์คํํธ ์ต์
์ ์ฌ์ฉํ๊ณ ํ์๋ผ์ธ์ผ๋ก ํ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ํ๋กํ์ผ๋ง ํ๋ ๋ฐฉ๋ฒ, ์๋ก์ฐ ์ฌ์ด์ฆ์ ๋ฆฌํ
์ธ๋ ์ฌ์ด์ฆ์ ํฌ๊ธฐ๋ฅผ ํตํด ๋ฉ๋ชจ๋ฆฌ ๋์์ ์์ธ์ธ ๊ฐ์ฒด๋ฅผ ์ฐพ๋ ๋ฐฉ๋ฒ, ๊ทธ๋ฆฌ๊ณ ๋ง์ง๋ง์ผ๋ก using
์ ์ฌ์ฉํ์ฌ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ๋ฐฉ์งํ๋ ๋ฐฉ๋ฒ ๋ฑ ์ ์์๋ดค์ต๋๋ค.
ํ์ ์์ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ๊ฒฝํํ ๋ ์ค๋ ์ค๋ช ๋๋ฆฐ ๋ฐฉ๋ฒ์ ํตํด ๋๋ฒ๊น ํด๋ณด๊ณ , ์์ธ์ ์ฐพ์ ์ฑ๋ฅ์ ๊ฐ์ ํด ๋ณผ ์ ์๋ ๊ธฐํ๊ฐ ๋์ผ๋ฉด ์ข๊ฒ ์ต๋๋ค.
๊ฐ์ฌํฉ๋๋ค.
FEConf2023์์ ๋ฐํ๋ 'SSR ํ๊ฒฝ(Node.js) ๋ฉ๋ชจ๋ฆฌ ๋์ ๋๋ฒ๊น ๊ฐ์ด๋'/๋ฐ์งํ ํ ์ค ํ๋ ์ด์ค ํ๋ก ํธ์๋ ์์ง๋์ด โฉ๏ธ