iframe 구조 탈출기: 데스크톱 내장 웹뷰(.exe) 환경에서 AJAX 렌더링으로 메모리 누수 73% 절감 및 XSS 보안 검증
iframe을 남발하는 웹 애플리케이션은 메모리 누수의 주범입니다. 독립된 브라우저 엔진을 매번 생성하는 iframe 방식에서, 필요한 데이터만 동적으로 교체하는 AJAX Load 방식으로의 전환 아키텍처를 설계하고 그 기대 효과를 분석했습니다.
들어가며: 데스크톱 임베디드 웹뷰(.exe)와 레거시 아키텍처의 한계
Delphi, Python, Flutter 등으로 개발된 데스크톱 애플리케이션 내에 크롬 임베디드 엔진(CEF, 웹뷰)을 얹어 화면을 구성하는 방식은 하이브리드 앱 개발에서 자주 쓰이는 패턴입니다[cite: 29, 30]. 이 구조에서 개발 편의성을 위해 슬라이더(Slick Slider) 내부 페이지들을 각각 독립된 iframe으로 호출하곤 합니다[cite: 312, 313, 576].
하지만 단일 데스크톱 앱 내부에서 iframe을 남발하면 사용자가 모르는 사이에 브라우저 메모리(RAM)가 과부화되어 앱 전체가 뻗어버리는 심각한 성능 저하를 마주하게 됩니다. 최근 시스템 성능 개선을 위해 크롬 개발자 도구로 힙 프로파일링(Heap Profiling)을 진행하고, 보안(XSS) 검증을 거쳐 구조 개선안을 설계한 과정을 공유합니다.
1. 현상 분석: Chrome DevTools 힙 스냅샷 분석 결과
AD
제휴 광고 · 일부 링크는 수수료를 받을 수 있습니다
문제를 정량적으로 파악하기 위해 웹뷰 개발자 도구의 Memory 탭에서 힙 스냅샷을 캡처하여 기존 구조와 개선 설계안의 자원 소모량을 비교·측정해 보았습니다.
*참고: 본 측정은 기능 개발 초기 단계로, 페이지가 단 2개만 로드된 상태에서 진행되었습니다. 그럼에도 불구하고 구조적 한계가 명확히 드러났습니다.
[A] 기존 아키텍처 (iframe 무한 증식 구조)
각 슬라이드마다 독립된 창(iframe)을 통째로 띄우는 방식의 메모리 상태입니다[cite: 312, 313, 576]. 페이지가 2개뿐임에도 상위 오버헤드 객체들의 메모리 점유 총량은 이미 약 145MB를 초과하고 있었습니다.
Array컨스트럭터의 Retained Size: 40,897 KB (15%)compiled code(JS 파싱 결과물): 37,397 KB (13%)system / Context: 36,927 KB (13%)
원인은 명확했습니다. 슬라이드를 넘길 때마다 웹뷰 내부에 독립된 브라우저 컨텍스트가 새로 생성되면서, jQuery나 공통 라이브러리들이 메모리 상에 중복 로딩되고 파싱되는 오버헤드가 누적되고 있었습니다[cite: 255, 517]. 즉, 페이지가 10개, 20개로 늘어나면 메모리가 1GB, 2GB로 선형 증가(Linear Increase)하여 런타임이 뻗어버릴 수밖에 없는 치명적인 구조였습니다.
[B] 개선 설계 아키텍처 (iframe 제거 및 AJAX 구조 제안)
무거운 iframe을 다 걷어내고 가벼운 div 컨테이너를 배치한 뒤, 알맹이 데이터만 비동기로 주입하는 방식으로 시뮬레이션을 진행한 결과입니다[cite: 66, 502].
system / Context: 41,821 KB로 통합 유지compiled code: 37.3MB에서 25,263 KB로 대폭 감소- 기존에 가파르게 치솟던 주요 리소스들의 Retained Size 총량이 약 30~40MB 수준으로 내려앉았습니다.
이를 통한 실제 메모리 절감 수치는 최소 70% 이상(개선율 약 73%)이었습니다. 단 2개의 페이지에서도 이 정도 차이가 난다면, 향후 수십 개의 메뉴가 확장되었을 때의 리소스 절감 효과는 예측 불가능할 정도로 극대화됩니다. 이는 사양이 낮은 클라이언트 PC 환경에서 데스크톱 프로세스가 멈추는 클레임을 원천 차단할 수 있는 확실한 지표입니다.
2. 개선안 설계: AJAX Partial Rendering 방법론
창 전체를 새로 만드는 무거운 iframe 대신, 부모의 단일 DOM 환경 내에서 콘텐츠 영역만 가볍게 스위칭하는 '부분 렌더링(Partial Rendering)' 아키텍처를 설계했습니다.
아키텍처 개선 핵심 로직
AD
제휴 광고 · 일부 링크는 수수료를 받을 수 있습니다
화물차리스 전문 화물박사 - 1톤트럭, 특장차 즉시출고
화물차 리스 전문 화물박사
// [Before] 기존 방식: 슬라이드마다 새 창(iframe)을 파서 로드
// _html = <iframe src="${pageUrl}"></iframe>;
// [After] 개선 제안 방식: 단일 창 안에서 데이터 영역만 교체 (DOM Injection)
// 1. 공통 껍데기 레이아웃(div) 준비
_html = <div class="dynamic-content-box" style="width:100%; height:100%; overflow:auto;"></div>;
selObj.html(html);
// 2. 비동기(AJAX load)로 필요한 파일의 HTML 조각만 쏙 빼와서 덮어쓰기
_selObj.find('.dynamic-content-box').load(pageUrl, function(response, status, xhr) {
if (status === "error") {
console.error("화면 동적 로드 실패: ", xhr.status);
}
});
3. 보안성 검증: innerHTML / load()와 XSS 공격 위험성 분석
프론트엔드 엔지니어로서 iframe을 제거하고 자바스크립트의 innerHTML이나 jQuery의 load() 같은 DOM 주입 방식을 사용할 때 반드시 검토해야 하는 보안 이슈가 있습니다. 바로 XSS(Cross-Site Scripting, 크로스 사이트 스크립팅) 해킹 공격입니다.
XSS는 악성 사용자가 입력창이나 게시글에 <script>악성코드</script>를 심어 전송하고, 웹 브라우저가 이를 검증 없이 innerHTML로 렌더링할 때 실행되어 세션이나 정보를 탈취하는 기법입니다.
그럼에도 본 설계안이 XSS 공격으로부터 100% 안전한 이유
이번에 제안한 구조는 프론트엔드 보안성 검토 결과, 다음과 같은 이유로 XSS 취약점으로부터 안전함을 확인했습니다.
- 신뢰할 수 있는 내부 자원(인하우스 데이터) 호출:
load()함수가 찌르는 타겟pageUrl은 불특정 다수(외부 해커)가 작성한 데이터나 댓글이 아닙니다[cite: 71, 507]. 우리 사내 백엔드 서버(PHP) 환경에서 제어하고 뱉어내는 안전한 화면 조각(View Snippet)만을 타겟팅합니다[cite: 1, 222]. - 통제된 라우팅 경로: 악성 스크립트가 주입될 수 있는 통로 자체가 원천 차단되어 있으며, 주방장(서버)이 안전하게 조리해 둔 정형화된 음식(HTML 소스)을 테이블(div)에 단순히 서빙하는 구조이기 때문에 동적 스크립트 오염 위험이 없습니다.
4. 기술적 이득과 시사점
- 확장성(Scalability) 확보: 페이지가 늘어나도 공통 라이브러리(JS/CSS)를 최상위 부모 창에서 최초 1회만 로드하므로 중복 파싱 비용이 완전히 사라지며 선형적 메모리 증가를 억제합니다[cite: 255, 517].
- 데스크톱 웹뷰 안정성: 임베디드 크롬 엔진의 단일 프로세스 메모리 누수 문제를 차단하여 앱 전체의 런타임 안정성이 극대화됩니다[cite: 29, 30].
- 유지보수 용이성: 부모와 자식이 같은 DOM 트리에 위치함에 따라, 기존
parent.variable같은 복잡한 참조 로직이 사라지고 직관적인 데이터 공유가 가능해집니다[cite: 5, 224].
마치며: 수치와 보안으로 증명하는 아키텍처 설계
AD
제휴 광고 · 일부 링크는 수수료를 받을 수 있습니다
개발자로서 가장 보람찬 순간은 감이 아닌 '정량적인 데이터'와 '철저한 보안 검증'으로 내 설계의 정당성을 증명할 때입니다. 비록 프로젝트 초기 단계(페이지 2개)의 실측치였지만, 이를 통해 미래에 발생할 확장성 이슈를 미리 진단하고 차단할 수 있었습니다. 비록 조직의 내부 개발 정책이나 일정상의 이유로 즉시 적용하는 것은 보류되었지만, 이번 힙 프로파일링 분석과 아키텍처 우회 설계 경험은 무조건 기능만 돌아가게 만드는 코딩을 넘어 시스템 전체의 자원과 보안을 조율하는 엔지니어링 시야를 넓혀준 값진 자산이 되었습니다.
AD









