
JavaScript에서 window.open() 함수를 사용하면 새 창(팝업) 또는 현재 창에 지정한 URL을 열 수 있습니다.
이때 새로 열린 창에서 window.opener 객체를 사용하면 원래 창의 window 객체에 접근할 수 있습니다. 이를 이용하면 새 창과 원래 창 사이에 데이터를 주고받을 수 있습니다.
문제점 및 원인
이번 프로젝트에서도 위 방식으로 외부 서비스를 이용한 본인 인증을 구현했는데, 인증 후 새 창의 window.opener가 null이 되어 원래 창에 인증 결과를 전달할 수 없다는 문제가 발견되었습니다.
디버깅해보니, 새 창이 열린 뒤 본인 인증을 위해 외부 도메인으로 리다이렉트되었다가 인증이 끝난 후 다시 우리 도메인으로 돌아오는 과정에서 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()을 호출하기 전에, 외부 서비스에서 본인 인증이 끝나면 새 창이 다시 우리 도메인으로 리다이렉트되도록 별도 처리가 필요합니다.
참고자료
Related Posts

Vanilla JS 댓글 모듈 자체 개발기
프레임워크 독립적인 Vanilla JS 댓글 모듈을 설계·개발하고 기존에 서비스 중이던 Nuxt 3 프로젝트에 통합한 과정을 다룹니다.

광고 차단 확장 프로그램이 이벤트 배너를 숨긴 이유
이벤트 배너가 특정 사용자에게만 보이지 않는 문제를 추적하며 광고 차단 확장 프로그램의 필터링 메커니즘을 이해하고, CSS 클래스명 변경으로 문제를 해결한 과정을 다룹니다.

웹뷰 환경에서의 구글 소셜 로그인 구현
웹뷰의 팝업 차단과 리다이렉트 제약을 극복하고, JavaScript-Native Bridge와 Android Intent Deep Link를 활용하여 안정적인 소셜 로그인 플로우를 구현한 과정을 다룹니다.