리다이렉트 이후 window.opener가 null이 되는 문제 해결

커버 이미지

JavaScript에서 window.open() 함수를 사용하면 새 창(팝업) 또는 현재 창에 지정한 URL을 열 수 있습니다. 이때 새로 열린 창에서 window.opener 객체를 사용하면 원래 창의 window 객체에 접근할 수 있습니다. 이를 이용하면 새 창과 원래 창 사이에 데이터를 주고받을 수 있습니다.

문제점 및 원인

이번 프로젝트에서도 위 방식으로 외부 서비스를 이용한 본인 인증을 구현했는데, 인증 후 새 창의 window.openernull이 되어 원래 창에 인증 결과를 전달할 수 없다는 문제가 발견되었습니다.

디버깅해보니, 새 창이 열린 뒤 본인 인증을 위해 외부 도메인으로 리다이렉트되었다가 인증이 끝난 후 다시 우리 도메인으로 돌아오는 과정에서 window.opener 값이 사라지는 것이 원인이었습니다.

해결 방법

MDN 문서에 따르면 window.open()은 두 번째 인자로 name 값을 받습니다. 이 name이 현재 브라우저에서 이미 사용 중이라면 해당 창에 대한 참조를 반환하고, 그렇지 않으면 해당 name을 가진 새 창을 생성합니다.

이를 이용해 window.opener 값을 확인하고, null인 경우 window.open()으로 원래 창을 다시 찾아 window.opener에 재할당하면 됩니다.

// 원래 창
 
const url = 'www.test-url.com';
const options = 'width=400,height=600,scrollbar=yes';
 
// 부모 창의 name 지정
window.name = 'parent';
// 새 창에서 데이터를 받아오게 설정
window.addEventListener("message", receiveMessage, false);
window.open(url, '', options);
 
...
 
// 새 창
if(!window.opener){
  window.opener = window.open('', 'parent'); // 부모 창의 name을 넣어 window.opener 재할당
}
 
window.opener.postMessage(...); // 원래 창에 데이터 전송

주의할 점은 이 방법은 접근이 허용된 창끼리만 사용할 수 있다는 점입니다. 즉, 새 창과 원래 창이 같은 도메인일 때만 사용할 수 있습니다.

따라서 window.open()을 호출하기 전에, 외부 서비스에서 본인 인증이 끝나면 새 창이 다시 우리 도메인으로 리다이렉트되도록 별도 처리가 필요합니다.

참고자료