티스토리 뷰
크롬 : Custom Confirm 만들기 - Remove alert(), confirm(), and prompt for cross origin iframes 이슈
Korean Eagle 2022. 1. 17. 13:19작년 여름인가 잘 되던 서비스가 갑자기 되지 않은 적이 있었다. alert과 confirm이 동작하지 않아 검증로직의 실행에 문제가 생겼기 때문이다. 문제는 크롬 브라우저에서 iframe으로 실행되고 있는 프로그램의 alert, confirm, prompt 기능을 제거해버렸기 때문이다. 우리 시스템은 메인 시스템 외에 별도의 인터넷 서비스를 위해서 공개 홈페이지의 서비스 일부 신청 페이지가 iframe으로 들어가 있다.
하지만 일주일 정도지나 전세계의 수많은 개발자들의 원성으로 다시 크롬은 원상복구 되었다.
그리고 12월 2일에 아래 내용처럼 deprecation 결정을 지연하기로 했지만 언제든지 적용 가능한 상태에 있다.
After talking to developers and considering the options, we have decided to postpone the launch of this deprecation while we investigate adding a feature policy, which may take some time. We will provide several months of advance notice in the future when we decide to re-enable it, and the enterprise policy and origin trial opt-outs will be available at that point.
크롬의 이슈 페이지는 아래와 같다.
해당 이슈에 대한 진행은 아래를 참고 하면 된다.
1. 갑작스럽게 발생한 문제로 인해서 긴급하게 Front End 개발자에게 Custom Alert, Confirm을 만들라는 이야기를 하고, 혹시나 몰라서 나도 가능한 코드를 만들어 보았다.
1-1 사실 alert이나 confirm은 custom으로 구현하기 어렵지 않다.
1-2 하지만, 문제는 confirm인데 우리 시스템의 프로그램의 검증로직의 중간에 사용자의 선택을 기다리는 부분이 있다.
1-3 이걸 callback으로 구현해서 해당 위치에서 confirm 띄우고 yes를 선택하면 callback을 실행하면 될 것 처럼 보이지만 서비스가 4개가 묶여 있는 거라 분리하기도 힘들고 검증로직 역시 너무 복잡해서 조건마다 분기 문을 다시 작성해야 한다.
1-4 즉 진짜 중간에 멈추지 않는 이상 해결책이 너무 복잡한 상황이다.
2. 이 문제가 발생하고 바로 2일도 안 지나서 구글의 정책은 일단 보류가 되어 서버스가 재개되어 상황은 일단 종료되었지만, 근본적인 해결이 필요해서 개발자가 해결하기를 기다렸는데, 브라우저 실행을 중간에 멈추는 건 불가능하다는 이야기를 했다. 주변에서도 해결한 사람이 없다는 이야기만 한다.
2-1 사실 stackoverflow를 검색해도 callback 사용정도만 나와있지 정확하게 해결책을 제대로 제시한 곳은 없어보이긴 한다.
2-2 그런데 이건 이중 async/await으로 검증 로직 중간에 실제 정지하도록 만들 수 있다.
2-3 물론 정지를 해도 브라우저에서 지원하는 alert과 confirm과는 다르게 브라우저를 마우스로 조작할 수 있기 때문에 modal처리를 해야 한다. 이 부분은 단순한 문제가 알아서 해결하길
이전 구조
<style>
스타일 지정
</style>
<script type="text/javascript">
변수블럭
$(document).ready(function(){
온로딩 및 이벤트 함수 부분
$("#btnCvplApply").on("click", function(){
사전 검증로직 블록
// 전자고지(이메일) 유효성 검사
if(checkEmailTyp && checkEmail){
if (!fncEmailRegist(gojiYn)) return;
}
// 전자고지(휴대폰) 유효성 검사
if(checkSmsTyp && checkEmail){
if(!fncSmsRegist(smsGojiYn)) return;
}
사후 검증 및 분기로 서비스 호출블록
});
});
************* 인증함수들 ************
</script>
//이메일고지 유효성 검사
function fncEmailRegist(gojiYn){
검증함수 boolean 돌려줌
}
//문자고지 유효성 검사
function fncSmsRegist(smsGojiYn){
검증함수 boolean 돌려줌
}
변경 구조
0. 실제 코드는 서비스 신청용 2000라인, 별도의 지원 함수를 위한 파일에 1000라인의 코드가 들어 있어 필요한 부분만 남겼다. 좋은 코드는 아니다.
1. 가장 위의 babel, polyfill은 ie11를 지원하기 위해서 넣은 건데 이건 돌아간다는 프로토타입으로 만든 것이기 때문에 실제로 사용할 경우에는 컴파일을 한 소스를 넣어주는 게 좋다.
2. 스타일과 custom confirm 창은 혹시 참고가 될지 몰라 남겨뒀다.
3. 2중 aynch/await으로 브라우저 실행을 멈출 수 있다는 것을 보여주기 위함이다.
4. 비동기 함수 안에서 비동기 함수 ui.confirm가 실행된다. (이부분 빼고 포스트를 작성해서 다시 채워넣었음)
<!-- pilseong, babel, polyfill ES6 async, awake 문법 사용을 위한 라이브러리 import -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.10.4/polyfill.min.js"></script>
<style>
/*숫자목록 스타일 */
.ol_decimal{
display: block;
list-style-type: decimal;
margin-top: 0.2em;
margin-bottom: 0.2em;
margin-left: 0;
margin-right: 0;
padding-left: 20px;
}
/* pilseong customer confirm 모달의 화면 표출 정의 */
.example {
padding: 20px;
}
input[type="button"] {
padding: 5px 10px;
margin: 10px 5px;
border-radius: 5px;
cursor: pointer;
background: #ddd;
border: 1px solid #ccc;
}
/* input[type="button"]:hover {
background: #ccc;
} */
.confirm {
display: none;
}
.confirm > div:first-of-type {
position: fixed;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
top: 0px;
left: 0px;
z-index: 1;
}
.confirm > div:last-of-type {
padding: 10px 20px;
background: white;
position: absolute;
width: auto;
height: auto;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
border-radius: 5px;
border: 1px solid #333;
z-index: 100;
}
.confirm > div:last-of-type div:first-of-type {
min-width: 150px;
padding: 10px;
}
.confirm > div:last-of-type div:last-of-type {
text-align: right;
}
</style>
<!-- pilseong, babel, polyfill ES6 async, awake 문법 사용을 위한 정의-->
<script type="text/babel" data-presets="es2015,stage-2">
변수선언 블록
$(document).ready(function(){
ready 구문 및 이벤트 처리 구문 블록
$("#btnCvplApply").on("click", function(){
// pilseong, 검증로직은 checkRoutine 안에 들어가야 한다.
// pilseong, 버튼을 누르는 실제로는 checkRoutine이 async이기 때문에 바로 종료된다.
checkRoutine();
});
});
// pilseong, custom confirm 함수 정의
const ui = { confirm: async (message) => createConfirm(message) }
const createConfirm = (message) => {
return new Promise((complete, failed)=>{
$('#confirmMessage').text(message)
$('#confirmYes').off('click');
$('#confirmNo').off('click');
$('#confirmYes').on('click', ()=> { $('.confirm').hide(); complete(true); });
$('#confirmNo').on('click', ()=> { $('.confirm').hide(); complete(false); });
// pilseong, 아래의 계산 부분은 스크롤이 있어도 화면 한가운데 confirm이 나오도록 조정
// Get the document offset :
var offset = $(document).scrollTop(),
// Get the window viewport height
viewportHeight = $(window).height(),
// cache your dialog element
$myDialog = $('.confirm > div:last-of-type');
// now set your dialog position
$myDialog.css('top', (offset + (viewportHeight/2)) - ($myDialog.outerHeight()/2));
$('.confirm').show();
});
}
// pilseong, async, await을 사용하기 때문에 비동기함수로 정의한다.
const checkRoutine = async (text, delIdx) => {
검증로직이 여기로 이동되었다. 동일한 코드를 사용하면 된다.
사전 검증 블록
// 전자고지(이메일) 유효성 검사
if(checkEmailTyp && checkEmail){
// pilseong, fncEmailRegist가 종결될 때 까지 대기
if (!(await fncEmailRegist(gojiYn))) return;
}
// 전자고지(휴대폰) 유효성 검사
if(checkSmsTyp && checkEmail){
// pilseong, fncSmsRegist가 종결될 때 까지 대기
if(!(await fncSmsRegist(smsGojiYn))) return;
}
사후 검증 블록
}
검증 함수 블록
</script>
<!-- pilseong, custom confirm html 테그 -->
<div class="confirm">
<div></div>
<div>
<div id="confirmMessage">Confirm text</div>
<div>
<input id="confirmYes" type="button" value="예" />
<input id="confirmNo" type="button" value="아니오" />
</div>
</div>
</div>
// 전자고지 유효성 검사
// pilseong, customer conform을 사용하기 위하여 비동기로 변경
async function fncEmailRegist(gojiYn){
이메일 검증로직 boolean 리턴 검증 블록
var result = await ui.confirm('법인(또는 단체)의 경우 사업자등록증(등기부등본), 신청자 신분증, 위임장(또는 재직증명서)등은 처리담당자가 추가로 서면으로 제출받아야합니다. 그래도 계속 진행하시겠습니까?');
if(result) { //yes
if(saNo.length != 10 ){
alert_msg('법인 사업자번호를 확인하시고 입력하세요.');
$("#saNo").select();
return false;
}
}
검증 블록 추가
}
//문자고지 유효성 검사
// pilseong, customer conform을 사용하기 위하여 비동기로 변경
async function fncSmsRegist(smsGojiYn){
문자고지 검증로직 boolean 리턴
var result = await ui.confirm('법인(또는 단체)의 경우 사업자등록증(등기부등본), 신청자 신분증, 위임장(또는 재직증명서)등은 처리담당자가 추가로 서면으로 제출받아야합니다. 그래도 계속 진행하시겠습니까?');
if(result) { //yes
//alert_msg("saNo.length : " + saNo.length);
if(smsSaNo.length != 10 ){
alert_msg('법인 사업자번호를 확인하시고 입력하세요.');
$("#smsSaNo").select();
return false;
}
}
검증블록 추가
}
'기록' 카테고리의 다른 글
CSS : 글자에 영향을 주지 않고 배경만 흐리게 하기 (0) | 2022.01.23 |
---|---|
Redmine : Redmine Ubuntu 20.04 설치 시 mysql2 오류 (0) | 2022.01.19 |
Spring - XML Schema-based configuration (0) | 2022.01.11 |
Operating System - 사용 중인 포트 확인 (0) | 2022.01.11 |
Database : Database locking (0) | 2022.01.04 |
- Total
- Today
- Yesterday
- 도커 개발환경 참고
- AWS ARN 구조
- Immuability에 관한 설명
- 자바스크립트 멀티 비동기 함수 호출 참고
- WSDL 참고
- SOAP 컨슈머 참고
- MySql dump 사용법
- AWS Lambda with Addon
- NFC 드라이버 linux 설치
- electron IPC
- mifare classic 강의
- go module 관련 상세한 정보
- C 메모리 찍어보기
- C++ Addon 마이그레이션
- JAX WS Header 관련 stackoverflow
- SOAP Custom Header 설정 참고
- SOAP Custom Header
- SOAP BindingProvider
- dispatcher 사용하여 설정
- vagrant kvm으로 사용하기
- git fork, pull request to the …
- vagrant libvirt bridge network
- python, js의 async, await의 차이
- go JSON struct 생성
- Netflix Kinesis 활용 분석
- docker credential problem
- private subnet에서 outbound IP 확…
- 안드로이드 coroutine
- kotlin with, apply, also 등
- 안드로이드 초기로딩이 안되는 경우
- navigation 데이터 보내기
- 레이스 컨디션 navController
- raylib
- 상속
- Spring
- jsp
- 매핑
- 하이버네이트
- MYSQL
- 외부파일
- hibernate
- login
- one-to-one
- spring boot
- 설정하기
- 로그인
- Spring Security
- RestTemplate
- XML
- mapping
- 스프링부트
- Rest
- Angular
- crud
- Many-To-Many
- 설정
- Security
- Validation
- one-to-many
- 스프링
- form
- WebMvc
- 자바