다중 iframe 사용 시 발생하는 메모리 누수 문제와 해결 방안

메모리 누수란 무엇인가?

애플리케이션이 실행되기 위해서는 시스템 메모리 자원이 필요합니다. 운영체제나 런타임 환경은 프로그램의 요청에 따라 메모리를 할당하게 되며, 특히 장시간 실행되는 백그라운드 프로세스의 경우 사용하지 않는 메모리를 적절히 해제하지 않으면 점점 리소스를 소모하게 됩니다. 이렇게 더 이상 사용되지 않아야 할 메모리가 해제되지 않고 계속 점유되는 현상을 메모리 누수(memory leak)라고 부릅니다.

메모리 누수가 지속되면 응용 프로그램의 성능 저하뿐 아니라 시스템 전체의 불안정성이나 프로세스 종료로 이어질 수 있습니다. 이를 완화하기 위해 대부분의 현대 언어는 자동 메모리 관리 기능을 제공하며, 대표적인 예로 가비지 컬렉션(garbage collection)이 있습니다.

가비지 컬렉션과 참조 관리

가비지 컬렉터는 더 이상 접근할 수 없는 객체를 찾아 메모리에서 제거합니다. 일반적으로 "참조 계수(reference counting)" 또는 "도달 가능성(reachability)" 기반으로 판단합니다. 하지만 개발자가 명시적으로 참조를 해제하지 않으면, 해당 객체는 여전히 메모리에 남아 있게 됩니다.

즉, 가비지 컬렉션이 있더라도 개발자는依舊 주의해야 합니다. 특히 DOM 요소나 대용량 데이터 구조를 다룰 때는 더 이상 필요하지 않은 참조를 반드시 null 처리하거나 삭제해야 안전한 메모리 관리가 가능합니다.

메모리 누수 진단 방법

Chrome 개발자 도구를 활용하면 웹 애플리케이션의 메모리 사용 추이를 실시간으로 모니터링할 수 있습니다.

  1. 개발자 도구에서 Performance 또는 Memory 탭을 선택합니다.
  2. Memory 옵션을 활성화하고 녹화(record)를 시작합니다.
  3. 페이지에서 사용자 동작을 시뮬레이션합니다 (예: 페이지 전환, 요소 추가/제거).
  4. 일정 시간 후 녹화를 중지하고 그래프를 확인합니다.

녹화된 결과에서 메모리 사용량이 시간이 지남에 따라 일정하게 유지되거나 감소하면 정상입니다. 그러나 반복적인 작업 후에도 지속적으로 증가한다면 메모리 누수가 의심됩니다.

약한 참조를 통한 메모리 관리: WeakMap 활용

ES6에서는 메모리 누수 위험을 줄이기 위해 WeakMapWeakSet이라는 약한 참조(weak reference) 기반의 자료구조를 도입했습니다. 이들은 키로 사용된 객체에 대한 강한 참조를 유지하지 않아, 해당 객체가 다른 곳에서 더 이상 참조되지 않으면 가비지 컬렉션의 대상이 될 수 있습니다.

예를 들어, 특정 DOM 요소에 부가 정보를 연결해야 하는 경우 일반 객체를 사용하면 해당 요소가 제거되어도 정보가 남아 있을 수 있지만, WeakMap을 사용하면 자동으로 정리됩니다.

const elementMetadata = new WeakMap();
const domElement = document.querySelector('#user-panel');

elementMetadata.set(domElement, { loaded: true, timestamp: Date.now() });

// 이후 domElement가 제거되고 참조가 없어지면,
// WeakMap 내의 해당 엔트리는 자동으로 제거됨

이처럼 WeakMap은 메모리 누수를 예방하면서도 객체 확장을 가능하게 해주는 유용한 도구입니다.

다중 iframe에서의 메모리 문제

특히 오래된 브라우저(예: Internet Explorer)에서 <iframe>을 여러 개 동적 생성 및 제거할 경우, 실제 프레임은 닫혔지만 관련 메모리나 객체가 해제되지 않는 문제가 자주 발생합니다. 이는 다음과 같은 원인에서 비롯됩니다:

  • IFrame 창이 닫혀도 JavaScript 참조가 남아 있어 가비지 컬렉션 대상에서 제외됨
  • src 로딩이 완료되기 전에 프레임을 제거하면 상태 불일치 발생
  • 크로스 도메인 콘텐츠 포함 시 보안 제약으로 인해 일부 메서드 호출이 실패함
  • 스크립트 실행 속도보다 UI 종료가 빠를 경우 메모리 정리가 미흡함

안전한 IFrame 제거 전략

다음 함수는 IFrame 요소를 보다 안정적으로 제거하고 메모리 누수를 최소화하기 위한 방법을 제공합니다.

function destroyIframeSafely() {
    const frame = document.getElementById('dynamic-frame');
    
    if (!frame) return;

    // 1. src 초기화로 내부 리소스 로딩 중단
    frame.src = 'about:blank';

    // 2. 내부 문서 및 윈도우 객체 정리 시도
    try {
        if (frame.contentWindow && frame.contentWindow.document) {
            const doc = frame.contentWindow.document;
            doc.open();
            doc.write('');
            doc.close();
            frame.contentWindow.close();
        }
    } catch (error) {
        console.warn('내부 프레임 정리 중 오류 발생:', error.message);
    }

    // 3. DOM에서 완전히 제거
    if (frame.parentNode) {
        frame.parentNode.removeChild(frame);
    }

    // 4. IE 전용 가비지 컬렉션 강제 호출 (비표준)
    try {
        if (typeof window.CollectGarbage === 'function') {
            window.CollectGarbage();
        }
    } catch (e) {
        // 무시
    }

    // 5. 로컬 참조 해제
    frame = null;
}

이 함수는 IFrame의 src를 비우고, 내부 문서를 초기화하며, DOM에서 제거한 후 참조를 명시적으로 null 처리함으로써 메모리 누수 가능성을 크게 줄입니다. 특히 Internet Explorer와 같은 레거시 환경에서 효과적입니다.

태그: JavaScript 메모리 누수 가비지 컬렉션 WeakMap iframe

6월 21일 16:10에 게시됨