Node.js(V8 엔진)에서 문자열은 불변(Immutable) 데이터 타입입니다.
한 번 생성된 문자열은 메모리상에서 수정될 수 없으며, 수정을 시도할 때마다 새로운 메모리 공간이 할당됩니다.
1. 끊임없는 메모리 할당 (Allocation Overload)
+= 연산자를 사용할 때마다 V8 엔진 내부에서는 다음과 같은 일이 벌어집니다.
- 기존 문자열을 복사합니다.
- 새로 추가될 문자열을 붙입니다.
- 새로운 메모리 주소에 결과물을 저장합니다.
- 기존의 문자열은 더 이상 참조되지 않는 **쓰레기(Garbage)**가 되어 Heap 메모리에 남습니다.
2. GC의 "Stop-the-World" 부하
V8 엔진의 GC는 메모리가 부족해지면 불필요한 객체를 정리하기 위해 실행됩니다.
- Minor GC (Scavenge): 젊은 객체들이 머무는 New Space에서 빈번하게 일어납니다. +=로 생기는 짧은 수명의 문자열들은 여기서 처리됩니다.
- Major GC (Mark-Sweep-Compact): 문자열이 길어지거나 루프 내에서 계속 생성되면 Old Space로 넘어가게 되는데, 이때 Major GC가 발생하면 **애플리케이션의 실행이 일시적으로 중단(Stop-the-world)**됩니다.
쿼리가 수백 줄로 길어지거나 루프 안에서 SQL을 생성하면, GC가 처리해야 할 "죽은 문자열"이 기하급수적으로 늘어나 CPU 점유율이 치솟고 서비스 응답 속도가 느려집니다.
🏗️ 대안: 더 효율적인 방법들
메모리 단편화와 GC 부하를 줄이기 위해 권장되는 방식입니다.
✅ 1. 배열과 join() 사용
가장 간단하면서도 효과적인 방법입니다. 배열에 담아두었다가 마지막에 한 번만 결합합니다.
const queryParts = [];
queryParts.push("SELECT * FROM users");
queryParts.push("WHERE status = 'active'");
// ... 조건 추가
const sql = queryParts.join(" "); // 마지막에 딱 한 번만 새로운 문자열 생성
✅ 2. 템플릿 리터럴 (Template Literals)
코드 가독성을 높여줄 뿐만 아니라, 중간 단계의 불필요한 문자열 생성을 줄여줍니다.
const sql = `
SELECT *
FROM orders
WHERE id = ${orderId}
AND date > '${startDate}'
`;
✅ 3. Query Builder (Knex, Prisma 등)
가장 권장되는 방식입니다. 내부적으로 최적화된 방식으로 문자열을 조합하며, 무엇보다 SQL Injection 보안 위협을 원천 차단합니다.
💡 요약: 한 줄 정리
"+= 연산은 기존 메모리를 수정하는 게 아니라, 매번 새로운 메모리를 사고 버리는 과정입니다.
이 '쓰레기'들을 치우느라 바빠진 GC가 당신의 서버를 멈추게 할 수 있습니다!"
반응형
'IT관련 > Nodejs' 카테고리의 다른 글
| Clinic.js doctor 명령어로 HTML 리포트가 안 만들어질 때 해결 방법 (0) | 2026.03.20 |
|---|---|
| Nodejs에서 sql += "" 방식과 배열(push & join) 방식을 V8 엔진의 메모리 할당 및 GC 관점에서 비교 (0) | 2026.03.20 |
| [Node.js] 성능 최적화의 필수 도구, Clinic.js 완벽 가이드 (0) | 2026.03.18 |
| nodejs에서 mysql 연결시 timezone 셋팅. (0) | 2025.07.07 |