티스토리 뷰

반응형

JavaScript에서 opener를 호출할 때 안전하게 다루는 방법

웹 개발에서 부모 창(opener)과 자식 창 간 데이터를 주고받는 작업은 흔히 발생합니다. 하지만 opener를 호출할 때, 해당 요소가 존재하지 않는 경우 오류가 발생할 수 있습니다. 이런 문제를 방지하려면 어떻게 해야 할까요? 오늘은 학생이 이해하기 쉽도록, 부모 창과 자식 창의 관계를 비유로 설명드리겠습니다.

 


부모 창과 자식 창의 관계란?

부모 창(opener)은 웹 페이지 간 데이터를 교환할 수 있도록 자식 창과 연결된 창입니다. 마치 선생님(부모 창)이 학생(자식 창)에게 데이터를 전달하는 것과 같습니다. 학생이 어떤 정보를 요청할 때, 선생님이 자료를 정확히 준비했는지 확인하지 않고 무작정 전달하려고 하면 문제가 생기겠죠? 웹 개발에서도 같은 원리입니다. 데이터를 보내기 전에 반드시 부모 창에 해당 요소가 존재하는지 확인해야 합니다.


opener를 호출할 때 왜 오류가 발생할까요?

자식 창에서 opener의 특정 요소에 접근하려고 할 때, 그 요소가 부모 창에 없다면 자바스크립트는 다음과 같은 오류를 반환합니다:

Uncaught TypeError: Cannot read properties of null

이는 자식 창이 존재하지 않는 요소를 참조하려고 하기 때문입니다. 마치 선생님이 없는 자료를 찾으려고 하는 학생처럼 말이죠.


오류를 방지하려면?

자바스크립트에서 opener로 특정 요소를 참조하기 전에, 그 요소가 존재하는지 확인하는 것이 중요합니다. 이를 통해 불필요한 오류를 예방할 수 있습니다.


1. 요소 존재 여부 확인

다음 코드를 보면, 특정 요소가 존재할 경우에만 작업을 수행하도록 조건문을 추가한 예입니다:

if ($("#prodcodechange", opener.document).length) {
    $("#prodcodechange", opener.document).val(code);
}

여기서 $("#prodcodechange", opener.document).length는 해당 요소가 존재하는지 확인합니다. 요소가 있으면 .val(code)를 통해 값을 설정합니다.


2. AJAX 요청 시 안전하게 다루기

AJAX 요청에서도 응답을 처리할 때, 요소가 존재하는지 반드시 확인해야 합니다. 아래는 수정된 AJAX 코드입니다:

if ($("#order_CUST", opener.document).length) {
    $("#order_CUST", opener.document).val(data["codenum"]);
}
if ($("#order_CUST_DES", opener.document).length) {
    $("#order_CUST_DES", opener.document).val(data["comname"]);
}

이 코드는 AJAX 응답에서 order_CUST와 order_CUST_DES 요소가 존재할 경우에만 데이터를 입력합니다. 존재하지 않을 경우 오류를 방지합니다.


3. 부모 창의 함수 호출 시 확인

자식 창에서 부모 창의 특정 함수를 호출할 때도 동일한 방식으로 안전하게 호출해야 합니다:

if (typeof opener.changeordergridcode === "function") {
    opener.changeordergridcode();
}

typeof를 사용하여 함수가 정의되어 있는지 확인한 후 호출합니다. 이는 정의되지 않은 함수를 호출하려는 시도를 방지합니다.


완성된 코드

위의 원칙을 모두 적용한 최종 코드는 다음과 같습니다:

function intoval(code, name, des, outputunitprice, company_name, company_code) {
    if ($("#prodcodechange", opener.document).length) {
        $("#prodcodechange", opener.document).val(code);
    }
    if ($("#proddeschange", opener.document).length) {
        $("#proddeschange", opener.document).val(name);
    }

    var params = "?comname=" + encodeURIComponent(company_name);
    console.log('params ' + params);

    if (company_code == null || company_code == '') {
        if (ajaxRequest !== null) {
            ajaxRequest.abort();
        }

        ajaxRequest = $.ajax({
            url: "search_cust.php" + params,
            type: "post",
            success: function (data) {
                if ($("#order_CUST", opener.document).length) {
                    $("#order_CUST", opener.document).val(data["codenum"]);
                }
                if ($("#order_CUST_DES", opener.document).length) {
                    $("#order_CUST_DES", opener.document).val(data["comname"]);
                }
                setTimeout(function () {
                    if (typeof opener.changeordergridcode === "function") {
                        opener.changeordergridcode();
                    }
                    self.close();
                }, 500);
            },
            error: function (jqxhr, status, error) {
                console.log(jqxhr, status, error);
            }
        });
    } else {
        setTimeout(function () {
            if (typeof opener.changeordergridcode === "function") {
                opener.changeordergridcode();
            }
            self.close();
        }, 500);
    }
}

안전한 코딩의 중요성

우리는 코드를 작성할 때, 예상치 못한 상황을 고려해야 합니다. opener를 호출할 때 요소가 없을 수 있다는 가능성을 항상 염두에 두고 작업을 진행하는 것이 중요합니다. 이러한 안전한 코딩 습관은 단순히 오류를 줄이는 것을 넘어, 협업 시 동료 개발자들에게 신뢰를 주고, 유지보수를 쉽게 만들어 줍니다.

따라서 우리는 **"항상 확인하고 신중하게 행동하라"**는 자세를 가져야 합니다. 이는 코딩뿐 아니라 우리의 삶에서도 유용한 원칙이 될 것입니다.

 

JavaScript에서 opener를 안전하게 사용하는 방법과 대안

웹 개발에서 opener는 부모 창과 자식 창 간 데이터를 주고받는 중요한 역할을 합니다. 오늘은 opener의 필요성과 사용 이유를 살펴보고, 더 안전하고 현대적인 대안으로 모달 창을 활용하는 방법도 함께 알아보겠습니다.


1. opener란 무엇인가?

opener는 자바스크립트에서 자식 창과 부모 창을 연결하는 객체입니다. 부모 창에서 window.open()을 통해 새 창(자식 창)을 열면, 자식 창은 부모 창의 window 객체에 접근할 수 있습니다.

opener의 역할

  • 부모 창의 데이터를 자식 창에서 참조하거나 수정할 수 있음.
  • 자식 창에서 부모 창의 특정 함수를 호출할 수 있음.
  • 두 창 간 데이터를 동기화하여 작업을 효율적으로 처리 가능.

opener 사용 예제

// 부모 창에서 자식 창 열기
const childWindow = window.open('child.html', 'Child Window');

// 자식 창에서 부모 창에 접근
console.log(opener.document.title); // 부모 창의 제목 출력

2. opener는 왜 사용할까?

opener는 여러 창 간 데이터를 공유하거나, 부모 창에서 특정 동작을 수행하도록 지시할 때 유용합니다.

사용 사례

  1. 데이터 전송: 자식 창에서 입력된 데이터를 부모 창으로 전달하여, 실시간 업데이트나 저장 처리를 수행합니다.
  2. opener.document.getElementById('inputField').value = '자식 창 데이터';
  3. 상호작용: 자식 창이 특정 작업(예: 고객 정보 조회)을 수행한 후, 부모 창에서 화면을 갱신합니다.
  4. opener.refreshCustomerList();
  5. 상태 유지: 자식 창에서 설정한 상태를 부모 창의 UI에 반영합니다.

3. opener의 문제점과 한계

opener는 강력한 기능을 제공하지만, 몇 가지 단점이 있습니다:

  1. 존재하지 않는 요소 참조: 부모 창에 특정 요소가 없으면 오류가 발생합니다.
  2. // 부모 창에 #inputField 요소가 없는 경우 오류 발생 opener.document.getElementById('inputField').value = '값';
  3. 보안 문제: 부모와 자식 창이 동일한 출처(Same-Origin Policy)를 따라야만 opener를 사용할 수 있습니다. 그렇지 않으면 오류가 발생하거나 데이터를 주고받을 수 없습니다.
  4. 유지보수 어려움: 창 간의 의존성이 높아질수록 코드가 복잡해지고, 유지보수가 어려워질 수 있습니다.

4. 모달 창을 활용한 대안

모달 창은 opener를 대체할 수 있는 현대적인 방법입니다. 모달 창은 같은 페이지 안에서 팝업 형태로 작동하며, 부모 창과 동일한 DOM을 공유하므로 opener 없이 데이터를 직접 교환할 수 있습니다.

모달 창의 장점

  1. 동일한 DOM 사용: 부모 창과 자식 창이 동일한 페이지 안에서 작업하므로 데이터 교환이 간단합니다.
  2. 보안 문제 없음: 동일한 출처 제한 없이 동작합니다.
  3. UI 통합: 별도의 새 창이 아니라 동일한 화면에서 팝업으로 동작하므로 사용자 경험이 개선됩니다.

모달 창 사용 예제

HTML 모달

<!-- Bootstrap 모달 -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="exampleModalLabel">모달 제목</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        모달 내용
        <input type="text" id="modalInput" class="form-control">
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-primary" id="saveData">저장</button>
      </div>
    </div>
  </div>
</div>

JavaScript로 데이터 전송

// 모달 열기
$('#exampleModal').modal('show');

// 데이터 저장 버튼 클릭 이벤트
document.getElementById('saveData').addEventListener('click', function () {
    const inputData = document.getElementById('modalInput').value;

    // 부모 창의 요소에 데이터 반영
    document.getElementById('parentInputField').value = inputData;

    // 모달 닫기
    $('#exampleModal').modal('hide');
});

5. opener와 모달의 비교

특징 opener 모달 창

데이터 교환 방식 부모와 자식 창 간 데이터 전달 동일 DOM 내에서 직접 데이터 공유
사용 편의성 새 창을 열고 닫아야 함 동일 화면에서 팝업으로 처리
보안 동일 출처 정책 필요 동일 출처 문제 없음
UI/UX 통합 별도의 창으로 사용자 경험 단절 가능 사용자 경험 통합 가능

결론: 언제 opener를 사용하고, 언제 모달을 사용할까?

  1. opener 사용이 적합한 경우:
    • 부모 창과 자식 창이 별도의 독립된 작업을 수행해야 할 때.
    • 새 창에서 많은 양의 데이터를 처리하고, 그 결과만 부모 창에 반영할 때.
  2. 모달 창이 적합한 경우:
    • 데이터를 교환할 때 부모 창과 자식 창이 동일한 페이지에서 작업할 수 있을 때.
    • 별도의 새 창을 띄우는 것이 사용자 경험을 저해할 가능성이 있을 때.

선택과 집중

opener와 모달 창 모두 각각의 장단점을 가지고 있습니다. 중요한 것은 상황에 맞는 도구를 선택하여 사용하는 것입니다. 이는 우리가 매일의 삶에서도 마찬가지입니다. 모든 선택에는 적절한 시기와 방법이 있습니다. 우리가 상황을 정확히 판단하고, 가장 적합한 도구를 사용할 때 비로소 효율적이고 아름다운 결과를 만들어낼 수 있습니다. 현명한 선택과 집중이야말로 우리의 삶을 더 나은 방향으로 이끌어 줄 것입니다.

반응형
댓글