회사에서 공식적으로 IE에서 Edge로 브라우저 정책을 바꾸게 되면서 운영 레거시 시스템에 심어진 showModalDialog()가 문제가 되었다.

1. showModalDialog() 란?

showModalDialog()는 JavaScript에서 사용되는 함수 중 하나로, 모달 대화상자를 열 때 사용되었던 오래된 메소드다. 또한 해당 함수는 사용자가 모달 대화상자를 닫을 때까지 다른 작업을 수행하지 못하도록 창을 잠근다.

함수의 구문은 다음과 같다.

showModalDialog(url, argument, options);
  • url: 열려는 대화상자에 표시될 URL 주소.
  • argument: 대화상자에 전달할 인수.
  • options: 대화상자 창의 옵션을 지정하는 객체.

2. 이제와서 문제가 되는 이유?

showModalDialog() 함수는 현재 더 이상 추천되지 않는 Deprecated 메소드다. 심지어 Edge나 Chrome, Firefox에선 제거되었다. 최근까지 IE 브라우저를 쓰고 있었기 때문에 문제가 되지 않았지만, 이젠 실행 자체가 불가능(...is not definded)하여 이슈가 된 것이다. 설상가상으로 꽤 많은 jsp파일에 showModalDialog()가 삽입되어 있어 기존 로직에 최소한의 사이드 이펙트를 위해 Fix가 시급했다.

3. Overriding

해결을 위해 이것 저것 찾아보니 팝업을 열 window.open() 함수를 사용하여 팝업창을 띄우거나, CSS와 Javscript로 모달뷰를 구현해 처리하는 방법이 있었다.

window.open(url, 새창이름, 'dialog');

하지만 운영하는 시스템에서 띄워지는 팝업창엔 값을 포함하여 부모 페이지에 반환해주는 로직이었다. window.open()은 반환 값을 리턴하지 않기에 이것만으론 대체가 힘들어보였는데 아래 글을 발견하게 되었다.

egovframework 요소기술 - showModalDialog 대체 기능

간략히 요약하면 showModalDialog.jsshowModalDialogCallee.js 이 두 JS파일을 사용하여 팝업 호출 및 선택된 값을 부모페이지에 반환 가능하도록 처리할수 있다는 글이다.

3-1. showModalDialog.js

브라우저에 window.showModalDialog()가 없다면 함수를 오버라이드하여 window.open() 로 팝업창을 연다. 반환값의 유무에 따른 콜백 세팅도 가능하다.

...

if (!window.showModalDialog) {
	showModalDialogSupported = false;
	window.showModalDialog = function(arg1, arg2, arg3, callback) {
      ...
		if (callback != null) {
			callbackMethod = callback;
		} else {
			callbackMethod = null;
		}
      ...
		targetWin.focus();
	};

3-2. showModalDialogCallee.js

팝업이 닫힐 때 부모 창으로 콜백 함수를 호출하여 결과를 전달한다.

...
function setReturnValue(obj) {
	if (!window.showModalDialog) {
		if (opener != null && !opener.closed) {
			var callbackMethod = opener.getCallbackMethodName();			
			try {
				if (callbackMethod != null) {
					opener[callbackMethod](obj);
				} else {
					opener.showModalDialogCallback(obj);
				}
			} catch (err) {
				alert('팝업 처리 시 오류가 발생하였습니다. \n오류내용 : ' + err);
			} ...
		} 
	}
}

3-3. 적용 프로세스

  1. 먼저, 새로운 함수를 호출하기 위한 스크립트를 페이지에 추가한다.
<script type="text/javascript" src="showModalDialog.js"></script>
<script type="text/javascript" src="showModalDialogCallee.js"></script>
  1. 팝업창을 띄우는 페이지에서는 다음과 같이 함수를 호출한다.
var url = "popup.html";
var argument = { data: "example data" };
var options = "dialogWidth:600px; dialogHeight:400px; scroll:no; center:yes; resizable:yes;";

showModalDialog(url, argument, options, function(returnValue) {
  console.log("Returned value from popup:", returnValue);
});
// 위 코드에서 `url`은 팝업창으로 띄울 페이지의 URL 주소이며, `argument`는 팝업창으로 전달할 인자이다. 
// `options`는 팝업창의 옵션을 설정하는데 사용되며, 마지막 매개변수는 팝업창이 닫힐 때 호출되는 callback 함수다. 
  1. 팝업창에서는 다음과 같이 window.returnValue을 설정하고 닫는다.
var returnValue = { result: "example result" };
window.returnValue = returnValue; // 팝업창으로부터 반환할 값
window.close();
  1. 마지막으로, callback 함수에서 반환 값을 처리한다.
function callback(returnValue) {
  console.log("Returned value from popup:", returnValue);
}

이러한 단계를 따라 기존 showModalDialog() 함수를 사용한 페이지를 업데이트할 수 있으며 이제 호환성 문제 없이 모든 브라우저에서 페이지가 동작한다.

아래는 showModalDialog를 ReactJS에서 오버라이딩한 예제이다. public/index.html에 showModalDialog.js 유무에 따라 팝업창 출력 여부가 달라진다.

codesandbox 바로가기

4. 마치며

처음에는 showModalDialog()를 대체할 새로운 모달창을 개발하고 연동한다는 답만 보여 많은 비용과 시간이 들 것으로 예상됐다. 그러나 누군가의 지식을 참고하여 더 나은 방향을 찾을 수 있었다.

다만, 개발 및 테스트 범위까진 좁히지 못했다. 항상 개발을 하면서 리팩토링에 대해 중요하게 생각하는데 결국 적용하지 못해 아쉬웠다. 기존 코드를 최대한 활용하여 미래에도 이해하기 쉽고 관리하기 편한 코드를 작성했다는 것에 의의를 둔다.

이번 경험으로 브라우저의 업데이트로도 이슈가 생길 수 있다는 것을 알았다. 시간날 때 프로젝트 내 호출되는 메소드들의 현재 상황을 리스트업하여 대비해보려고 한다. 이것은 당장의 이슈 대응 뿐만 아니라 해당 시스템의 수명을 판단하는데도 도움이 될거라 생각한다.

  • 습득 경험

    • 콜백 함수의 중요성: showModalDialog() 대체 방안에서 추가된 콜백 함수로 대체 기능 구현을 마무리지을 수 있었음

    • 모듈화와 코드 재사용: showModalDialog.js와 showModalDialogCallee.js를 통해 각각의 기능(showModalDialog(), getDialogArguments(), setReturnValue())을 모듈화하여 기존 코드를 재사용함

    • 브라우저 호환: 기존 브라우저에서 지원하지 않는 기능을 대체해보는 경험을 통해 브라우저 호환성에 대한 이해도 증가

profile
late bloomer

0개의 댓글