๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๊ฐœ๋ฐœ/๋Ÿฐ์„ธ๊ถŒ

์„œ๋ฒ„์—์„œ ์ง€์†์ ์ธ OutOfMemory๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

ํ˜„์žฌ ์„œ๋ฒ„์— ๋งค๋ฒˆ OutOfMemory๋กœ ์ธํ•ด์„œ ์„œ๋ฒ„๊ฐ€ ๋‹ค์šด๋˜๊ฑฐ๋‚˜ ‘๋‚ด ์ฃผ๋ณ€ ๋Ÿฌ๋‹ ์ฝ”์Šค ์กฐํšŒ’๊ฐ€ ์•ˆ๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค.
 

 
์ด๋•Œ๋งŒ ํ•ด๋„ ์˜ˆ์ƒํ•˜๋Š” ๋ฌธ์ œ์ ์€ ‘๋‚ด ์ฃผ๋ณ€ ๋Ÿฌ๋‹ ์ฝ”์Šค ์กฐํšŒ’ ์‹œ์— ์ฃผ์–ด์ง„ ๋ฐ˜๊ฒฝ(m)์— ๋งŽ์€ ์ฝ”์Šค๋“ค์ด ์กด์žฌํ•˜๊ณ  ์žˆ์–ด ์ด๋ฅผ ๋ชจ๋‘ ์ฝ์–ด์˜ค๊ธฐ ๋•Œ๋ฌธ์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค. ๋ฌผ๋ก  ํ•œ ๋‘๋ช…์˜ ์‚ฌ์šฉ์ž๊ฐ€ ์š”์ฒญํ–ˆ๋‹ค๋ฉด ๋ฌธ์ œ์—†๊ฒ ์ง€๋งŒ, ์Šค๋ ˆ๋“œ ์ˆ˜๊ฐ€ ๋งŽ์•„์ง€๋Š” ์ˆœ๊ฐ„ ๋ชจ๋“  ์ฝ”์Šค ์กฐํšŒ์™€ ๋น„์Šทํ•œ ๊ฒฝ์šฐ๊ฐ€ ๋˜์–ด๋ฒ„๋ ค OutOfMemory ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค๊ณ  ์ถ”์ธกํ–ˆ๋‹ค. ๊ทธ๋ž˜์„œ mongoDB์—์„œ db.collections.stats().avgObjSize ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด ์ฝ”์Šค ๋ฐ์ดํ„ฐ๊ฐ€ ํ‰๊ท ์ ์œผ๋กœ ์–ผ๋งˆ์˜ ํฌ๊ธฐ๋ฅผ ๊ฐ–๋Š”์ง€ ์กฐ์‚ฌํ•ด๋ดค๋‹ค.
 

 
๋ฐ”์ดํŠธ ๋‹จ์œ„๋กœ ์ถœ๋ ฅ๋˜๋‹ˆ KB๋กœ ๊ณ„์‚ฐํ•ด๋ณด๋ฉด, ์•ฝ 117KB๊ฐ€ ๋œ๋‹ค. ์ด๋“ค ์ค‘ ์ผ๋ถ€๋ฅผ ์ž๋ฐ” ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค๋ฉด ์•ฝ 38๊ฐœ์˜ ์ขŒํ‘œ๊ฐ€ ์žˆ๋Š” 400m ๋Ÿฌ๋‹ ์ฝ”์Šค๋Š” 2.82KB๊ฐ€ ๋œ๋‹ค. 118๊ฐœ์˜ ์ขŒํ‘œ๊ฐ€ ์žˆ๋Š” ์•ฝ 1KM ์ฝ”์Šค๋Š” 6.30KB์ด๋‹ค. ๋Œ€๋ถ€๋ถ„ ๋ฐ์ดํ„ฐ๋“ค์ด 5KM ์ด์ƒ์ธ ๋Ÿฌ๋‹ ์ฝ”์Šค๊ฐ€ ๋งŽ์•„ ๊ฑฐ๋ฆฌ์— ๋”ฐ๋ผ ๋งŽ์€ ์ขŒํ‘œ๊ฐ€ ๋“ค์–ด๊ฐ€๋ฏ€๋กœ ์ด๋Š” ๋”์šฑ ์ปค์งˆ ๊ฒƒ์ด๋‹ค.
 

 
์ด์ œ ์ด๋Ÿฌํ•œ ๋ฉ”๋ชจ๋ฆฌ ๋ฌธ์ œ๊ฐ€ ์ •๋ง ‘๋‚ด ์ฃผ๋ณ€ ๋Ÿฌ๋‹ ์ฝ”์Šค ์กฐํšŒ’๋กœ ์ธํ•ด ๋ฐœ์ƒํ•œ ๊ฒƒ์ธ์ง€ ์•Œ์•„๋ณด๊ธฐ ์œ„ํ•ด์„œ CloudWatch์˜ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ์ง€ํ‘œ๋ฅผ ํ™•์ธํ–ˆ๋‹ค.
 

 
ํ•˜์ง€๋งŒ ์˜์™ธ๋กœ ์ด์œ ๋Š” ๋‹ค๋ฅธ ๊ณณ์— ์žˆ์—ˆ๋‹ค. ์‚ฌ์ง„์„ ๋ณด๋ฉด ํŠน์ • ์ˆœ๊ฐ„์— ์—„์ฒญ๋‚˜๊ฒŒ ์น˜์†Ÿ๋Š” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์‹œ๊ฐ„์„ ๋ณด๋ฉด ๋Œ€๋žต ์ƒˆ๋ฒฝ 2์‹œ์— ๊ฐ‘์ž๊ธฐ ์น˜์†Ÿ๊ธฐ ์‹œ์ž‘ํ•˜๋Š”๋ฐ, ์ด๋ฅผ ๊ณ„์† ์˜ฌ๋ผ๊ฐ”๋‹ค ๋‚ด๋ ค๊ฐ€๋ฉฐ ์œ ์ง€ํ•˜๋‹ค๊ฐ€ ์–ด๋А์ˆœ๊ฐ„ ํ›… ๋–จ์–ด์ง€๋Š” ๋น„์ •์ƒ์ ์ธ ๊ทธ๋ž˜ํ”„๋ฅผ ๋ณด์—ฌ์ฃผ๊ณ  ์žˆ์—ˆ๋‹ค. ๋ณดํ†ต ์ด๋ ‡๊ฒŒ ๋“ค์ญ‰๋‚ ์ญ‰ํ•œ ๊ทธ๋ž˜ํ”„๋Š” ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ๊ฐ€์žฅ ํฐ ์ด์œ ์ด๋‹ค. ๊ทธ๋ž˜์„œ ์ƒˆ๋ฒฝ 2์‹œ์— ์ง„ํ–‰ํ•˜๊ณ  ์žˆ๋Š” Batch ์ž‘์—…์— ๋ญ”๊ฐ€ ๋ฌธ์ œ๊ฐ€ ์žˆ์„ ๊ฒƒ์ด๋ผ ์ƒ๊ฐํ–ˆ๋‹ค.
 

 
ํ•˜์ง€๋งŒ ์ฝ”๋“œ ์ƒ์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜์— ๊ด€ํ•ด์„œ๋Š” ํฐ ๋ฌธ์ œ๊ฐ€ ์—†์—ˆ๋‹ค. ์˜ˆ์™ธ๊ฐ€ ๋˜์ ธ์งˆ ๋•Œ InputStream์ด ๋‹ซํ˜€์ง€์ง€ ์•Š๋Š”๋‹ค๋Š” ์  ๋ฐ–์— ์—†์—ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ์ ‘๊ทผํ•ด๋ณด๋„๋ก ํ–ˆ๋‹ค. ๋ฐ”๋กœ JVM ํž™ ๋ฉ”๋ชจ๋ฆฌ์™€ GC์ด๋‹ค. ์ด๋ ‡๊ฒŒ ์ ‘๊ทผ์„ ํ•˜๊ณ ์ž ํ–ˆ๋˜ ์ด์œ ๋Š” heap space์—์„œ OutOfMemory ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ ํž™ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ• ๋‹น๋˜๊ณ , GC๊ฐ€ ๋Œ์•„๊ฐ€๋Š”์ง€ ํŒŒ์•…ํ•˜๋ฉด ์–ด๋А์ •๋„ ํ•ด์†Œ๋  ๊ฒƒ ๊ฐ™์•˜๋‹ค.
 
๋จผ์ € ์—ฌ๊ธฐ์„œ ๋“œ๋Š” ์˜๋ฌธ์ ์€ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ๋ฌผ๋ฆฌ ๋ฉ”๋ชจ๋ฆฌ + Swap ๋ฉ”๋ชจ๋ฆฌ๋ณด๋‹ค ์ ์€๋ฐ, ์™œ OutOfMemory๊ฐ€ ๋‚˜๋Š”๊ฑธ๊นŒ? ํ˜„์žฌ EC2์˜ ์ŠคํŽ™์€ t4g.micro๋กœ 2์ฝ”์–ด CPU, 1GB ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  Swap ๋ฉ”๋ชจ๋ฆฌ๋กœ๋Š” 8GB๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ Swap ๋ฉ”๋ชจ๋ฆฌ + ๋ฌผ๋ฆฌ ๋ฉ”๋ชจ๋ฆฌ ๊ธฐ์ค€์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹นํ•  ์ค„ ์•Œ์•˜๋‹ค.
 
ํ•˜์ง€๋งŒ JVM์€ ํž™ ์‚ฌ์ด์ฆˆ๋ฅผ ์ •ํ•  ๋•Œ ๋ฌผ๋ฆฌ์  ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๊ฒฐ์ •ํ•œ๋‹ค. Java 8๋ถ€ํ„ฐ๋Š” ๋”ฐ๋กœ JVM ํž™ ์‚ฌ์ด์ฆˆ๋ฅผ ์ •ํ•ด์ฃผ์ง€ ์•Š์œผ๋ฉด ๊ธฐ๋ณธ ํž™ ์‚ฌ์ด์ฆˆ๋Š” ์‹œ์Šคํ…œ ๋ฌผ๋ฆฌ์  ๋ฉ”๋ชจ๋ฆฌ์˜ ์•ฝ 1/64๋กœ ์„ค์ •๋˜๊ณ , ์ตœ๋Œ€ ํž™ ์‚ฌ์ด์ฆˆ๋Š” ์•ฝ 1/4๋กœ ์„ค์ •๋œ๋‹ค.
 

 
์‚ฌ์ง„์„ ๋ณด๋ฉด ํ˜„์žฌ ๋‚ด ์ปดํ“จํ„ฐ์˜ ๋ฉ”๋ชจ๋ฆฌ 16GB์—์„œ ์ตœ๋Œ€ ํž™ ์‚ฌ์ด์ฆˆ๋Š” ์•ฝ 1/4์ธ 4GB๋ฅผ ์ง€์ •ํ•˜๊ณ , ์ตœ์†Œ ํž™์€ ์•ฝ 1/64์ธ 250MB๋ฅผ ํ• ๋‹นํ•œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์„œ๋ฒ„๊ฐ€ ์‹คํ–‰๋˜๊ณ  ์žˆ๋Š” EC2๋Š” ๊ธฐ๋ณธ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ 1GB์ด๋‹ˆ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ฌผ๋ฆฌ ๋ฉ”๋ชจ๋ฆฌ์˜ ์•ฝ 1/64์ธ 16MB๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ณ , ์ตœ๋Œ€ 1/4์ธ 256MB๋ฅผ ํž™ ๋ฉ”๋ชจ๋ฆฌ๋กœ ์‚ฌ์šฉ ์ค‘์ธ ๊ฒƒ์ด๋‹ค.
 

 
๋”๊ตฐ๋‹ค๋‚˜ ํ˜„์žฌ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด 28.1%์ธ๋ฐ๋„ ๋‚จ์€ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ 44.4MB๋ฐ–์— ์•ˆ๋๋‹ค. ๊ทธ๋ž˜์„œ Batch ์ž‘์—…์„ ๋Œ๋ฉด์„œ ์•ฝ 300MB๊นŒ์ง€ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ํ™• ๋Š˜์–ด๋ฒ„๋ฆฌ๋‹ˆ ์ด๋ฅผ ๊ฐ๋‹นํ•˜์ง€ ๋ชปํ•ด ๊ณ„์† OutOfMemory๊ฐ€ ๋œจ๊ฒŒ ๋œ ๊ฒƒ ๊ฐ™๋‹ค. ๊ทธ๋ž˜์„œ ๋จผ์ € JVM์˜ ๊ธฐ๋ณธ ํž™ ์‚ฌ์ด์ฆˆ๋ฅผ ๋Š˜๋ ค๋ณด๋ ค๊ณ  ํ–ˆ๋‹ค. Swap ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‚ฌ์šฉ ์ค‘์ด๊ธฐ์— Swap ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ธฐ์ค€์œผ๋กœ JVM ํž™ ์‚ฌ์ด์ฆˆ ํฌ๊ธฐ๋ฅผ ๋Š˜๋ฆฌ๋ ค๊ณ  ํ–ˆ์œผ๋‚˜ Swap ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ•˜๋ฉด ์ƒ๊ธธ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ๊ฐ€ ์ƒ๋‹นํžˆ ๋งŽ์•˜๋‹ค.
 
๊ฐ€์žฅ ํฌ๊ฒŒ ์ƒ๊ฐํ•œ ๋ฌธ์ œ๋Š” ๋ณด์กฐ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ฃผ ๋ฉ”๋ชจ๋ฆฌ์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ์ ์ด๋‹ค. ์ฃผ ๋ฉ”๋ชจ๋ฆฌ๋ณด๋‹ค 10๋ฐฐ ์ด์ƒ ๋А๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์— ์ „์ฒด ์š”์ฒญ-์‘๋‹ต ๊ณผ์ •์— ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ๊ฒƒ ๊ฐ™์•˜๋‹ค. ๊ทธ๋ฆฌ๊ณ , Swap ๋ฉ”๋ชจ๋ฆฌ๋Š” ์ฃผ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ผ์‹œ์ ์œผ๋กœ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ ๊ฒƒ์ด๊ธฐ์— ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋ถ€์กฑํ•œ ๊ฒฝ์šฐ์— ํ™œ์„ฑ๋œ๋‹ค. ๊ทธ๋ž˜์„œ JVM ํž™ ๋ฉ”๋ชจ๋ฆฌ ์™ธ์— ๋‹ค๋ฅธ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„๋“ค์ด ์–ธ์ œ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š”์ง€ ๋˜๋Š” ์–ผ๋งˆ๋‚˜ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š”์ง€ ์ถ”์ธกํ•˜๊ธฐ๊ฐ€ ์–ด๋ ค์› ๋‹ค. ๊ทธ๋ž˜์„œ ๋‹น์žฅ ํž™ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋ฌด์ž‘์ • ๋Š˜๋ฆฌ๋Š” ๊ฒƒ์€ ํ•ด๊ฒฐ๋ฐฉ์•ˆ์ด ์•„๋‹ˆ๋ผ ์ƒ๊ฐํ–ˆ๋‹ค.
 

 
OutOfMemoryError๋Š” ๋‹จ์ˆœํžˆ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋ถ€์กฑํ•ด์„œ๋งŒ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, GC๊ฐ€ ๋ถˆํ•„์š”ํ•œ ๊ฐ์ฒด๋ฅผ ํšŒ์ˆ˜ํ•˜์ง€ ๋ชปํ•œ ์ƒํƒœ์—์„œ ๋ฉ”๋ชจ๋ฆฌ ์š”์ฒญ์ด ๋“ค์–ด์˜ฌ ๋•Œ ๋ฐœ์ƒํ•œ๋‹ค. ์œ„์˜ ์‚ฌ์ง„ ์† Batch ์ž‘์—…์—์„œ ๋ณด์•˜๋“ฏ์ด ์ง€์†์ ์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์š”๋™์น˜๋Š” ๋ชจ์Šต์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ทธ๋ž˜ํ”„๊ฐ€ 4-5์‹œ๊ฐ„ ๊ฐ€๋Ÿ‰ ์ง€์†๋˜๋Š” ๊ฒƒ์„ ๋ณด๋ฉด GC์˜ ๋™์ž‘์—์„œ๋„ ํžŒํŠธ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค. ๊ทธ๋ž˜์„œ ์šด์˜ ํ™˜๊ฒฝ์œผ๋กœ ๊ตฌ์„ฑํ•˜์—ฌ ์‹คํ—˜์„ ํ•ด๋ณด๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค. ๊ทผ๋ฐ ์•„์‰ฝ๊ฒŒ๋„ ์ด๋ฏธ ์„œ๋ฒ„์˜ ํ”„๋กœ์„ธ์„œ๋ฅผ ์—…๊ทธ๋ ˆ์ด๋“œ ํ•œ ์ƒํƒœ์˜€๋‹ค.
 
์ฒ˜์Œ์—” Test์šฉ ๊ฐ์ฒด๋“ค์„ ๋งŒ๋“ค์–ด EC2์— ๋„์›Œ๋ณด๋ ค๊ณ  ํ–ˆ์œผ๋‚˜, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ธ ๋ฉ”๋ชจ๋ฆฌ๋กœ ํ•˜๊ฒŒ ๋˜๋ฉด ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋กœ ์ธํ•ด ์ •ํ™•ํ•œ ์ธก์ •์ด ๋ถˆ๊ฐ€ํ–ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๊ทธ๋Ÿผ ๋ถ„๋ฆฌํ•œ๋‹ค๊ณ  ํ•ด๋„ ์ด๋ฅผ ์œ„ํ•ด ์šด์˜ ์„œ๋ฒ„ DB๋ฅผ ์—ฐ๊ฒฐํ•˜๊ธฐ์—” ๋„ˆ๋ฌด ์œ„ํ—˜ํ–ˆ๋‹ค. ๊ทธ๋ž˜์„œ EC2์™€ ๋™์ผํ•œ ํ™˜๊ฒฝ์—์„œ ๊ฐ‘์ž‘์Šค๋ ˆ ๋งŽ์€ ๋ฐ์ดํ„ฐ๋“ค์ด ๋“ค์–ด์˜ค๋ฉด ์–ด๋–ป๊ฒŒ ๋˜๋Š”์ง€ ์ •๋„๋งŒ ๋ถ„์„ํ•ด๋ณด๊ธฐ๋กœ ํ–ˆ๋‹ค. ์‚ฌ์šฉํ•œ ์ฝ”๋“œ๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.
 

public class BatchSimulator {
    public static void main(String[] args) throws Exception {
        List<int[]> allocations = new ArrayList<>();
        int counter = 0;
        while (true) {
            // 117KB ํฌ๊ธฐ์˜ int ๋ฐฐ์—ด ๊ณ„์† ์ƒ์„ฑ
            allocations.add(new int[29952]);
            counter++;

            if (counter % 50 == 0) {
                System.out.println("Allocated ~" + (counter) + " MB so far...");
            }
        }
    }
}
FROM openjdk:21-jdk

WORKDIR /app
COPY BatchSimulator.java .

RUN javac BatchSimulator.java

ENV JAVA_OPTS="-Xlog:gc*:file=/logs/gc.log:time,uptime,level,tags"

# JVM ํž™ ์ œํ•œ: ์‹ค์ œ t4g.micro ๊ธฐ๋ณธ๊ฐ’์— ๋งž์ถค
CMD java $JAVA_OPTS BatchSimulator
#!/bin/bash
docker build -t oom-test .

docker run -it --rm \\
  --cpus="2" \\
  --memory="1g" \\
  --memory-swap="8g" \\
  -v ~/gc-logs:/logs \\
  oom-test

 
๊ฐ„๋‹จํ•œ ์ฝ”๋“œ์ด๋‹ค. ๊ธ€์˜ ์ƒ๋‹จ์—์„œ ์•Œ๊ฒŒ ๋œ MongoDB์˜ ํ‰๊ท  ์ฝ”์Šค ํฌ๊ธฐ์ธ 117KB ํฌ๊ธฐ๋กœ ๊ณ„์†ํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋ฆฌ์ŠคํŠธ์— ์ €์žฅํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋„์ปค๋Š” t4g.micro์˜ ์ŠคํŽ™๊ณผ ๋˜‘๊ฐ™์ด ๊ตฌ์„ฑํ–ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ๋Š” 1GB์ด๋ฉฐ ์Šค์™‘ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ 8GB๋กœ ์„ค์ •ํ–ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  CPU๋Š” 2์ฝ”์–ด๋งŒ ์‚ฌ์šฉํ•œ๋‹ค.
 
ํ•ด๋‹น ํ”„๋กœ๊ทธ๋žจ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์‹คํ–‰ํ•ด๋ณด๋ฉด ์ดˆ๊ธฐ ์‹คํ–‰ ์งํ›„ Young Generation์—์„œ์˜ Minor GC๊ฐ€ ์—ฌ๋Ÿฌ์ฐจ๋ก€ ๋ฐœ์ƒํ•œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ์ด๋Š” ์ฃผ๋กœ Eden ์˜์—ญ์—์„œ ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ํ• ๋‹นํ•  ๊ณต๊ฐ„์ด ๋ถ€์กฑํ•  ๋•Œ ๋ฐœ์ƒํ•œ๋‹ค.
 

GC(0) Pause Young (Allocation Failure) 5M->5M(15M) 3.961ms
GC(1) Pause Young (Allocation Failure) 9M->9M(15M) 6.885ms
GC(2) Pause Young (Allocation Failure) 13M->13M(17M) 2.866ms

 
๋˜ํ•œ, ์ž๋ฐ” ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ๋ฆฌ์ŠคํŠธ๊ฐ€ ๊ณ„์†ํ•ด์„œ ์ƒ์„ฑ๋˜๋Š” ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๊ธฐ์— GC๊ฐ€ ์ด๋ฅผ ์ •๋ฆฌํ•˜์ง€ ๋ชปํ•˜๊ณ  Eden๊ณผ Survivor ์˜์—ญ์ด ๋น ๋ฅด๊ฒŒ ์ฐจ๋ฉด์„œ Tenured ์˜์—ญ(Old Generation)์œผ๋กœ ๊ฐ์ฒด๊ฐ€ ์Šน๊ฒฉ๋˜๋Š” ๊ณผ์ •์ด ๋ฐ˜๋ณต๋˜์—ˆ๋‹ค.
 

GC(1) Tenured: 4700K(10944K)->8956K(10944K)
GC(4) Tenured: 13237K(22064K)->20843K(22064K)

 
๊ทธ ํ›„ Minor GC๊ฐ€ ๊ณ„์† ์‹คํŒจํ•˜์ž JVM์€ Full GC๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ฉฐ Tenured ์˜์—ญ์˜ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํšŒ์ˆ˜ํ•˜๋Š” ๊ณผ์ •์„ ๋ฐ˜๋ณตํ–ˆ๋‹ค. ํŠนํžˆ๋‚˜ ๋งˆ์ง€๋ง‰ Full GC์—์„œ๋Š” Tenured ์˜์—ญ์ด ๊ฑฐ์˜ 99% ์‚ฌ์šฉ๋จ๊ณผ ๋™์‹œ์— Eden ๊ณต๊ฐ„ ์—ญ์‹œ ๊ฐ€๋“์ฐฌ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ–ˆ๋‹ค.
 

GC(3) Pause Full (Allocation Failure) 13M->13M(31M) 8.072ms
GC(6) Pause Full (Allocation Failure) 29M->29M(70M) 7.110ms
GC(12) Pause Full (Allocation Failure) 153M->153M(247M) 14.388ms
def new generation total 78656K, used 78611K
tenured generation total 174784K, used 174726K

 
์ข…ํ•ฉ์ ์œผ๋กœ ์ •๋ฆฌํ•˜์ž๋ฉด, ๋ฌผ๋ฆฌ์ ์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋ถ€์กฑํ•œ ์ƒํ™ฉ์ด๋‹ค. ๋ฌผ๋ฆฌ ๋ฉ”๋ชจ๋ฆฌ์˜ ํฌ๊ธฐ๊ฐ€ ์ž‘๊ธฐ ๋•Œ๋ฌธ์— ํž™ ์‚ฌ์ด์ฆˆ์˜ ํฌ๊ธฐ๋„ ์ž‘์„ ์ˆ˜ ๋ฐ–์— ์—†์—ˆ๊ณ  ์ด๋ฅผ ๋Š˜๋ ค์ค€๋‹คํ•ด๋„ ๋‚จ์•„์žˆ๋Š” ๋ฌผ๋ฆฌ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์ด ๊ฑฐ์˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋Š˜๋ฆฌ๊ธฐ ์–ด๋ ค์› ๋‹ค. ๊ฒŒ๋‹ค๊ฐ€ ์ง€๊ธˆ์˜ ์˜ˆ์ œ์ฒ˜๋Ÿผ ์ฝ”์Šค ํŒŒ์ผ๋“ค์„ ๊ณ„์†ํ•ด์„œ ๋ถˆ๋Ÿฌ์˜ค๋Š”๋ฐ, ํž™ ์‚ฌ์ด์ฆˆ๊ฐ€ ์ž‘๋‹ค๋ณด๋‹ˆ Eden ์˜์—ญ๊ณผ Tenured ์˜์—ญ์ด ๊ณ„์†ํ•ด์„œ ๊ฐ€๋“์ฐฌ๋‹ค. ๊ฒฐ๊ตญ ์ด ๋•Œ๋ฌธ์— Full GC๊ฐ€ ๋ฐ˜๋ณต ์‹คํ–‰๋˜๋ฉด์„œ OutOfMemory๊ฐ€ ์ง€์†์ ์œผ๋กœ ๋ฐœ์ƒํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค๋Š” ์ ์„ ์ถ”์ธกํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค.
 
๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ ํŒ€์€ ํ˜„์žฌ EC2์˜ ๋ฌผ๋ฆฌ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋Š˜๋ฆฌ๊ธฐ๋กœ ํ–ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ธฐ์กด์— t4g.micro๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์—ˆ์ง€๋งŒ, ์ด๋ฅผ t4g.small๋กœ ์ฆ๊ฐ€ํ–ˆ๋‹ค. ๋ฌผ๋ฆฌ ๋ฉ”๋ชจ๋ฆฌ๋Š” 2GB์ด๊ธฐ์— ์ด์ œ ํž™ ๋ฉ”๋ชจ๋ฆฌ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ 32MB๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์ตœ๋Œ€ ํž™ ๋ฉ”๋ชจ๋ฆฌ๋Š” ์•ฝ 536MB๊ฐ€ ๋˜์—ˆ๋‹ค. ๊ธฐ์กด์— ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๋˜ ๋ฉ”๋ชจ๋ฆฌ ์ˆ˜์ค€์ด 300MB์ธ ์ ์„ ๊ฐ์•ˆํ–ˆ์„ ๋•Œ ๋”ฐ๋กœ ํž™ ์‚ฌ์ด์ฆˆ๋ฅผ ์กฐ์ •ํ•˜์ง€ ์•Š์•„๋„ ๋ ๊ฑฐ๋ผ ์ƒ๊ฐํ•œ๋‹ค. ๋ฌผ๋ก  ์‚ฌ์šฉ์ž๊ฐ€ ๋งŽ์•„์ง„๋‹ค๋ฉด ์ด๋ฅผ ๋‹ค์‹œ ๊ณ ๋ คํ•ด๋ณผ ๊ฒƒ์ด๋‹ค.

+) 2025.10.24

ํ•ด๋‹น ๋ฌธ์ œ๋ฅผ ํ•ด์†Œํ•˜๊ณ  Batch Job ์ฝ”๋“œ๋ฅผ ๋‹ค์‹œ ํ™•์ธํ•˜๋ฉด์„œ, ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜์˜ ๋ฌธ์ œ๋Š” ์—†์—ˆ์ง€๋งŒ ๊ตฌ๊ธ€ ๋“œ๋ผ์ด๋ธŒ์—์„œ ํŒŒ์ผ๋“ค์„ ์ฝ์–ด์˜ค๋Š” ๊ณผ์ •์ด ๋ฌธ์ œ์ ์ด ๋  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์„ ํŒŒ์•…ํ–ˆ๋‹ค. ๊ทธ ๋ฌธ์ œ๋Š” Batch Job์—์„œ ๊ตฌ๊ธ€ ๋“œ๋ผ์ด๋ธŒ๋กœ๋ถ€ํ„ฐ ์ฝ”์Šค ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์–ด์˜ฌ ๋•Œ, ๋ชจ๋“  ํŒŒ์ผ์„ ํ•œ ๋ฒˆ์— ๋ฉ”๋ชจ๋ฆฌ์— ๋กœ๋“œํ•˜๋Š” ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋˜ ๊ฒƒ์ด๋‹ค.

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๊ตฌ๊ธ€ ๋“œ๋ผ์ด๋ธŒ ํŒŒ์ผ ์ฝ๊ธฐ ๋กœ์ง์— ํŽ˜์ด์ง•(paging)์„ ์ ์šฉํ–ˆ๋‹ค. ๊ธฐ์กด์—๋Š” ๋ชจ๋“  ํŒŒ์ผ ๋ชฉ๋ก์„ ํ•œ ๋ฒˆ์— ๊ฐ€์ ธ์™€์„œ ์ฒ˜๋ฆฌํ–ˆ๋‹ค๋ฉด, ์ด์ œ๋Š” ์ผ์ • ๊ฐœ์ˆ˜(10๊ฐœ)์”ฉ ๋‚˜๋ˆ„์–ด์„œ ์ˆœ์ฐจ์ ์œผ๋กœ ์ฝ์–ด์˜ค๋„๋ก ๋ณ€๊ฒฝํ–ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ํ•œ ๋ฒˆ์— ๋ฉ”๋ชจ๋ฆฌ์— ๋กœ๋“œ๋˜๋Š” ๋ฐ์ดํ„ฐ์˜ ์–‘์„ ์ œํ•œํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

 

 

ํŽ˜์ด์ง• ์ ์šฉ ํ›„ ๋ฐฐ์น˜ ์ž‘์—… ์ค‘ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•œ ๊ฒฐ๊ณผ, ๊ธฐ์กด์— 300MB ์ด์ƒ๊นŒ์ง€ ์น˜์†Ÿ๋˜ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด 120MB ๋‚ด์™ธ๋กœ ์•ˆ์ •ํ™”๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ๋˜ํ•œ ๊ฐ ๋ฐฐ์น˜ ์ฒ˜๋ฆฌ๊ฐ€ ๋๋‚˜๋ฉด ํ•ด๋‹น ๊ฐ์ฒด๋“ค์ด GC์˜ ๋Œ€์ƒ์ด ๋˜์–ด ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํšŒ์ˆ˜ํ•  ์ˆ˜ ์žˆ๋Š” ์—ฌ์œ ๊ฐ€ ์ƒ๊ฒผ๋‹ค. ๊ทธ๋ฆฌ๊ณ  Full GC์˜ ๋ฐœ์ƒ ๋นˆ๋„๋„ ํฌ๊ฒŒ ์ค„์–ด๋“ค์–ด ๋ฐฐ์น˜ ์ž‘์—…์˜ ์ „์ฒด ์ˆ˜ํ–‰ ์‹œ๊ฐ„๋„ ๊ฐœ์„ ๋˜์—ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ ๋ฐฉ์‹์€ ์ธํ”„๋ผ ์ŠคํŽ™ ์—…๊ทธ๋ ˆ์ด๋“œ์™€ ํ•จ๊ป˜ ์‹œ๋„ˆ์ง€๋ฅผ ๋‚ด์–ด OutOfMemory ๋ฌธ์ œ๋ฅผ ์ƒ๋‹น ๋ถ€๋ถ„ ํ•ด์†Œํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.